14 #if defined (AJALinux) || defined (AJAMac) 15 #include <arpa/inet.h> 21 #if !defined (AJAMac) && !defined (AJALinux) && !defined(AJABareMetal) 42 if (mMCSFileStream.is_open())
43 mMCSFileStream.close();
46 mBaseELARLocation = mCurrentLocation = mFileLines.end();
47 mCommentString = mMCSInfoString = mCurrentRecord = mBitfileDate = mBitfileTime = mBitfileDesignName = mBitfilePartName =
"";
65 if (!mLastError.empty())
77 ::stat(inMCSFileName.c_str(), &fsinfo);
78 mFileSize = uint32_t(fsinfo.st_size);
80 struct tm * fileTimeInfo = localtime(&fsinfo.st_ctime);
82 time_t rawGenerationTime;
83 time(&rawGenerationTime);
84 struct tm * generationTimeInfo = localtime(&rawGenerationTime);
85 ostringstream comment;
86 comment <<
"Generation Time: " << asctime(generationTimeInfo) <<
" Original MCS Time: " << asctime(fileTimeInfo) << endl;
87 mCommentString = comment.str();
89 mMCSFileStream.open(inMCSFileName.c_str(), std::ios::in);
90 if (mMCSFileStream.fail())
96 if (mMCSFileStream.is_open())
97 mMCSFileStream.close();
106 mMCSFileStream.open(inMCSFileName.c_str(), std::ios::in);
107 if (mMCSFileStream.fail())
110 GetFileByteStream(50);
116 void CNTV2MCSfile::GetMCSInfo()
118 uint16_t mainPartitionAddress = 0x0000, mainPartitionOffset = 0x0000;
120 GetPartition(mainBitfilePartition, mainPartitionAddress, mainPartitionOffset,
false);
121 if (mainBitfilePartition.size() > 0)
125 mBitfileDate = bitfileInfo.
GetDate();
128 mBitfileTime = bitfileInfo.
GetTime();
131 mMCSInfoString = mFileLines[0];
137 const size_t pkgNumPos(mMCSInfoString.find(
"PACKAGE_NUMBER"));
138 const size_t datePos(mMCSInfoString.find(
"DATE"));
139 if (pkgNumPos == string::npos || datePos == string::npos)
141 if (datePos <= pkgNumPos)
143 return mMCSInfoString.substr(pkgNumPos, datePos - pkgNumPos - 1);
148 const size_t datePos(mMCSInfoString.find(
"DATE"));
149 if (datePos == string::npos)
151 return mMCSInfoString.substr(datePos + 5, mMCSInfoString.npos - datePos + 5);
161 uint64_t recordSize = 0;
162 UWord baseAddress = 0x0000;
163 UWord ExtendedBaseAddress = 0x0000;
165 UByte recordType = 0x00;
167 if (!Open(inMCSFileName))
169 oss <<
"CNTV2MCSfile::InsertBitFile: mcsFile '" << inMCSFileName <<
"' not found";
170 SetLastError(oss.str());
175 if (!bitfile.
Open(inBitFileName))
177 oss <<
"CNTV2MCSfile::InsertBitFile: Bitfile '" << inBitFileName <<
"' not found";
178 SetLastError(oss.str());
183 NTV2Buffer bitfileBuffer(bitfileLength + 512);
186 oss <<
"CNTV2MCSfile::InsertBitFile: Unable to allocate " <<
DEC(bitfileLength+512) <<
"-byte bitfile buffer";
187 SetLastError(oss.str());
191 bitfileBuffer.Fill(0xFFFFFF);
194 if (readBytes != bitfileLength)
196 oss <<
"CNTV2MCSfile::InsertBitFile: Invalid bitfile length, read " << readBytes <<
" bytes, expected " << bitfileLength;
197 SetLastError(oss.str());
202 size_t bitfileBufferNdx(0);
203 uint64_t bytesLeftToWrite (bitfileLength);
204 while (bytesLeftToWrite)
206 recordSize = bytesLeftToWrite > 16 ? 16 : bytesLeftToWrite;
211 if (baseAddress == 0x0000)
214 string ELARString(
":02000004000000");
215 ::snprintf(&ELARString[9],
sizeof(ELARString)-9,
"%04X", ExtendedBaseAddress);
216 for (i = 1; i < 13; i++)
217 checksum +=
UByte(ELARString[i]) - 0x30;
218 checksum = (~checksum) + 1;
219 ::snprintf(&ELARString[13],
sizeof(ELARString)-13,
"%02X", checksum);
220 IRecordOutput(ELARString.c_str());
221 ExtendedBaseAddress++;
227 ::snprintf(&iRecord[1],
sizeof(iRecord)-1,
"%02X",
UByte(recordSize));
228 checksum +=
UByte(recordSize);
230 UWord addr = baseAddress;
231 UByte aa = ((addr >> 8) & 0xff);
232 ::snprintf(&iRecord[3],
sizeof(iRecord)-3,
"%02X", aa);
236 ::snprintf(&iRecord[5],
sizeof(iRecord)-5,
"%02X", aa);
239 ::snprintf(&iRecord[7],
sizeof(iRecord)-7,
"%02X", recordType);
243 while (i <
int(recordSize))
245 unsigned char dd = bitfileBuffer.U8(
int(bitfileBufferNdx++));
246 ::snprintf(&iRecord[index],
sizeof(iRecord)-index,
"%02X", dd);
253 baseAddress += 0x0010;
254 checksum = (~checksum) + 1;
255 ::snprintf(&iRecord[index],
sizeof(iRecord)-index,
"%02X", checksum);
257 IRecordOutput(iRecord);
261 if (!inUserMessage.empty())
262 mCommentString.append(inUserMessage);
263 uint32_t commentSize =
static_cast<uint32_t
>(mCommentString.length());
264 bytesLeftToWrite = commentSize;
266 ExtendedBaseAddress = 0x01f4;
267 baseAddress = 0x0000;
268 uint32_t commentIndex = 0;
269 while (bytesLeftToWrite > 0)
271 recordSize = bytesLeftToWrite > 16 ? 16 : bytesLeftToWrite;
276 if (ExtendedBaseAddress == 0x01f4)
279 string ELARString(
":02000004000000");
280 ::snprintf(&ELARString[9],
sizeof(ELARString)-9,
"%04X", ExtendedBaseAddress);
281 for (i = 1; i < 13; i++)
282 checksum += ELARString[i] - 0x30;
283 checksum = (~checksum) + 1;
284 ::snprintf(&ELARString[13],
sizeof(ELARString)-13,
"%02X", checksum);
285 IRecordOutput(ELARString.c_str());
286 ExtendedBaseAddress++;
292 ::snprintf(&iRecord[1],
sizeof(iRecord)-1,
"%02X",
UByte(recordSize));
293 checksum +=
UByte(recordSize);
295 UWord addr = baseAddress;
296 UByte aa = ((addr >> 8) & 0xff);
297 ::snprintf(&iRecord[3],
sizeof(iRecord)-3,
"%02X", aa);
301 ::snprintf(&iRecord[5],
sizeof(iRecord)-5,
"%02X", aa);
304 ::snprintf(&iRecord[7],
sizeof(iRecord)-7,
"%02X", recordType);
307 while (i <
int(recordSize))
309 unsigned char dd = mCommentString.at(commentIndex);
310 ::snprintf(&iRecord[index],
sizeof(iRecord)-index,
"%02X", dd);
318 baseAddress += 0x0010;
319 checksum = (~checksum) + 1;
320 ::snprintf(&iRecord[index],
sizeof(iRecord)-index,
"%02X", checksum);
321 IRecordOutput(iRecord);
326 if (!FindExtendedLinearAddressRecord(0x0200))
328 SetLastError(
"FindExtendedLinearAddressRecord failed");
331 mCurrentLocation = mBaseELARLocation;
332 while (mCurrentLocation != mFileLines.end())
334 IRecordOutput(mCurrentLocation->c_str());
344 ::printf(
"%s\n", pIRecord);
355 const uint32_t maxNumLines = 2000000;
358 if (!mMCSFileStream.is_open())
361 mMCSFileStream.seekg(0, std::ios::beg);
362 if (numberOfLines == 0)
364 mFileLines.resize(maxNumLines);
365 numberOfLines = maxNumLines;
368 mFileLines.resize(numberOfLines+1);
371 mMCSFileStream.sync_with_stdio(
false);
372 while (getline(mMCSFileStream, line) && index < numberOfLines)
374 mFileLines[index] = line;
377 if (numberOfLines < maxNumLines)
378 mFileLines[index] =
":00000001FF";
386 string ELARString(
":02000004000000");
387 ::snprintf(&ELARString[9],
sizeof(ELARString)-9,
"%04X", address);
388 uint8_t checksum = 0;
389 for (
int i = 1; i < 13; i++)
390 checksum += ELARString[i] - 0x30;
391 checksum = (~checksum) + 1;
392 ::snprintf(&ELARString[13],
sizeof(ELARString)-13,
"%02X", checksum);
395 string needle(ELARString, 0, 13);
397 mBaseELARLocation = mFileLines.end();
398 while (it != mFileLines.end())
400 string hay(*it, 0, 13);
403 mBaseELARLocation = it;
408 return mBaseELARLocation != mFileLines.end();
415 bool status = ParseCurrentRecord(currentRecordInfo);
430 if (mCurrentLocation->size() == 0)
436 if (!mCurrentLocation[0].compare(
":"))
443 uint16_t byteCount16 = 0;
444 ::sscanf(mCurrentLocation[0].c_str(),
":%02hX%04hX%02X", &byteCount16, &recordInfo.
linearAddress, &rType);
445 recordInfo.
byteCount = uint8_t(byteCount16);
455 ::sscanf(mCurrentLocation[0].c_str(),
":%02hX%04hX%02X%04hX", &byteCount16, &recordInfo.
linearAddress, &rType, &recordInfo.
linearAddress);
456 recordInfo.
byteCount = uint8_t(byteCount16);
472 if (!FindExtendedLinearAddressRecord(baseELARaddress))
474 mCurrentLocation = mBaseELARLocation;
478 ParseCurrentRecord(recordInfo);
480 mBaseELARLocation = mCurrentLocation;
483 uint16_t lastELARAddress = baseELARaddress;
485 ParseCurrentRecord(recordInfo);
490 string temp(mCurrentLocation[0].c_str());
491 for (
int i(0); i < recordInfo.
byteCount*2; i+=2)
494 ::sscanf(&mCurrentLocation[0].c_str()[9 + i],
"%02X", &c);
495 partitionBuffer.push_back(uint8_t(c & 0x000000FF));
498 ParseCurrentRecord(recordInfo);
509 ParseCurrentRecord(recordInfo);
512 return uint32_t(partitionBuffer.size());
514 return uint32_t(partitionBuffer.size());
516 return uint32_t(partitionBuffer.size());
virtual std::string ParseHeaderFromBuffer(const uint8_t *inBitfileBuffer, const size_t inBufferSize)
Parse a bitfile header that's stored in a buffer.
virtual size_t GetFileStreamLength(void) const
virtual std::string GetMCSPackageVersionString(void) const
IntelRecordType recordType
virtual bool FindExtendedLinearAddressRecord(uint16_t address=0x0000)
Declares the AJADebug class.
NTV2StringList::iterator NTV2StringListIter
virtual size_t GetFileByteStream(NTV2Buffer &outBuffer)
Retrieves the file bitstream.
virtual bool GetMCSHeaderInfo(const std::string &inMCSFileName)
virtual bool InsertBitFile(const std::string &inBitFileName, const std::string &inMCSFileName, const std::string &inUserMessage)
std::vector< uint8_t > UByteSequence
An ordered sequence of UByte (uint8_t) values.
virtual ~CNTV2MCSfile()
My destructor.
virtual void SetLastError(const std::string &inStr, const bool inAppend=false)
virtual std::string GetDesignName(void) const
virtual uint32_t GetFileByteStream(uint32_t numberOfLines=0)
Instances of me can parse an MCS file.
virtual bool Open(const std::string &inBitfilePath)
Opens the bitfile at the given path, then parses its header.
virtual const std::string & GetTime(void) const
virtual void IRecordOutput(const char *pIRecord)
virtual bool isReady(void) const
Declares the CNTV2MCSfile class.
virtual bool Open(const std::string &inMCSFilePath)
Opens the bitfile at the given path, then parses its header.
Describes a user-space buffer on the host computer. I have an address and a length, plus some optional attributes (allocated by SDK?, page-aligned? etc.).
#define AJA_sERROR(_index_, _expr_)
virtual void Close(void)
Closes mcs file (if open).
virtual std::string GetMCSPackageDateString(void) const
Declares numerous NTV2 utility functions.
virtual bool GetCurrentParsedRecord(IntelRecordInfo &recordInfo)
virtual const std::string & GetDate(void) const
Declares the CNTV2Bitfile class.
CNTV2MCSfile()
My constructor.
virtual const std::string & GetPartName(void) const
Instances of me can parse a bitfile.
virtual uint32_t GetPartition(UByteSequence &patitionBuffer, uint16_t baseELARaddress, uint16_t &partitionOffset, bool nextPartition=false)