Add KBOOT.
This commit is contained in:
236
apps/elftosb/common/StSRecordFile.cpp
Normal file
236
apps/elftosb/common/StSRecordFile.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* File: StSRecordFile.cpp
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "StSRecordFile.h"
|
||||
#include "string.h"
|
||||
|
||||
StSRecordFile::StSRecordFile(std::istream &inStream)
|
||||
: m_stream(inStream)
|
||||
{
|
||||
}
|
||||
|
||||
//! Frees any data allocated as part of an S-record.
|
||||
StSRecordFile::~StSRecordFile()
|
||||
{
|
||||
const_iterator it;
|
||||
for (it = m_records.begin(); it != m_records.end(); it++)
|
||||
{
|
||||
SRecord &theRecord = (SRecord &)*it;
|
||||
if (theRecord.m_data)
|
||||
{
|
||||
delete[] theRecord.m_data;
|
||||
theRecord.m_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Just looks for "S[0-9]" as the first two characters of the file.
|
||||
bool StSRecordFile::isSRecordFile()
|
||||
{
|
||||
int savePosition = static_cast<int>(m_stream.tellg());
|
||||
m_stream.seekg(0, std::ios_base::beg);
|
||||
|
||||
char buffer[2];
|
||||
m_stream.read(buffer, 2);
|
||||
bool isSRecord = (buffer[0] == 'S' && isdigit(buffer[1]));
|
||||
|
||||
m_stream.seekg(savePosition, std::ios_base::beg);
|
||||
|
||||
return isSRecord;
|
||||
}
|
||||
|
||||
//! Extract records one line at a time and hand them to the parseLine()
|
||||
//! method. Either CR, LF, or CRLF line endings are supported. The input
|
||||
//! stream is read until EOF.
|
||||
//! The parse() method must be called after the object has been constructed
|
||||
//! before any of the records will become accessible.
|
||||
//! \exception StSRecordParseException will be thrown if any error occurs while
|
||||
//! parsing the input.
|
||||
void StSRecordFile::parse()
|
||||
{
|
||||
// back to start of stream
|
||||
m_stream.seekg(0, std::ios_base::beg);
|
||||
|
||||
std::string thisLine;
|
||||
|
||||
do
|
||||
{
|
||||
char thisChar;
|
||||
m_stream.get(thisChar);
|
||||
|
||||
if (thisChar == '\r' || thisChar == '\n')
|
||||
{
|
||||
// skip the LF in a CRLF
|
||||
if (thisChar == '\r' && m_stream.peek() == '\n')
|
||||
m_stream.ignore();
|
||||
|
||||
// parse line if it's not empty
|
||||
if (!thisLine.empty())
|
||||
{
|
||||
parseLine(thisLine);
|
||||
|
||||
// reset line
|
||||
thisLine.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
thisLine += thisChar;
|
||||
}
|
||||
} while (!m_stream.eof());
|
||||
}
|
||||
|
||||
bool StSRecordFile::isHexDigit(char c)
|
||||
{
|
||||
return (isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
|
||||
}
|
||||
|
||||
int StSRecordFile::hexDigitToInt(char digit)
|
||||
{
|
||||
if (isdigit(digit))
|
||||
return digit - '0';
|
||||
else if (digit >= 'a' && digit <= 'f')
|
||||
return 10 + digit - 'a';
|
||||
else if (digit >= 'A' && digit <= 'F')
|
||||
return 10 + digit - 'A';
|
||||
|
||||
// unknow char
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! \exception StSRecordParseException is thrown if either of the nibble characters
|
||||
//! is not a valid hex digit.
|
||||
int StSRecordFile::readHexByte(std::string &inString, int inIndex)
|
||||
{
|
||||
char nibbleCharHi = inString[inIndex];
|
||||
char nibbleCharLo = inString[inIndex + 1];
|
||||
|
||||
// must be hex digits
|
||||
if (!(isHexDigit(nibbleCharHi) && isHexDigit(nibbleCharLo)))
|
||||
{
|
||||
throw StSRecordParseException("invalid hex digit");
|
||||
}
|
||||
|
||||
return (hexDigitToInt(nibbleCharHi) << 4) | hexDigitToInt(nibbleCharLo);
|
||||
}
|
||||
|
||||
//! \brief Parses individual S-records.
|
||||
//!
|
||||
//! Takes a single S-record line as input and appends a new SRecord struct
|
||||
//! to the m_records vector.
|
||||
//! \exception StSRecordParseException will be thrown if any error occurs while
|
||||
//! parsing \a inLine.
|
||||
void StSRecordFile::parseLine(std::string &inLine)
|
||||
{
|
||||
int checksum = 0;
|
||||
SRecord newRecord;
|
||||
memset(&newRecord, 0, sizeof(newRecord));
|
||||
|
||||
// must start with "S" and be at least a certain length
|
||||
if (inLine[0] != SRECORD_START_CHAR && inLine.length() >= SRECORD_MIN_LENGTH)
|
||||
{
|
||||
throw StSRecordParseException("invalid record length");
|
||||
}
|
||||
|
||||
// parse type field
|
||||
char typeChar = inLine[1];
|
||||
if (!isdigit(typeChar))
|
||||
{
|
||||
throw StSRecordParseException("invalid S-record type");
|
||||
}
|
||||
newRecord.m_type = typeChar - '0';
|
||||
|
||||
// parse count field
|
||||
newRecord.m_count = readHexByte(inLine, 2);
|
||||
checksum += newRecord.m_count;
|
||||
|
||||
// verify the record length now that we know the count
|
||||
if (inLine.length() != 4 + newRecord.m_count * 2)
|
||||
{
|
||||
throw StSRecordParseException("invalid record length");
|
||||
}
|
||||
|
||||
// get address length
|
||||
int addressLength = 0; // len in bytes
|
||||
bool hasData = false;
|
||||
switch (newRecord.m_type)
|
||||
{
|
||||
case 0: // contains header information
|
||||
addressLength = 2;
|
||||
hasData = true;
|
||||
break;
|
||||
case 1: // data record with 2-byte address
|
||||
addressLength = 2;
|
||||
hasData = true;
|
||||
break;
|
||||
case 2: // data record with 3-byte address
|
||||
addressLength = 3;
|
||||
hasData = true;
|
||||
break;
|
||||
case 3: // data record with 4-byte address
|
||||
addressLength = 4;
|
||||
hasData = true;
|
||||
break;
|
||||
case 5: // the 2-byte address field contains a count of all prior S1, S2, and S3 records
|
||||
addressLength = 2;
|
||||
break;
|
||||
case 7: // entry point record with 4-byte address
|
||||
addressLength = 4;
|
||||
break;
|
||||
case 8: // entry point record with 3-byte address
|
||||
addressLength = 3;
|
||||
break;
|
||||
case 9: // entry point record with 2-byte address
|
||||
addressLength = 2;
|
||||
break;
|
||||
default:
|
||||
// unrecognized type
|
||||
// throw StSRecordParseException("unknown S-record type");
|
||||
break;
|
||||
}
|
||||
|
||||
// read address
|
||||
int address = 0;
|
||||
int i;
|
||||
for (i = 0; i < addressLength; ++i)
|
||||
{
|
||||
int addressByte = readHexByte(inLine, SRECORD_ADDRESS_START_CHAR_INDEX + i * 2);
|
||||
address = (address << 8) | addressByte;
|
||||
checksum += addressByte;
|
||||
}
|
||||
newRecord.m_address = address;
|
||||
|
||||
// read data
|
||||
if (hasData)
|
||||
{
|
||||
int dataStartCharIndex = 4 + addressLength * 2;
|
||||
int dataLength = newRecord.m_count - addressLength - 1; // total rem - addr - cksum (in bytes)
|
||||
uint8_t *data = new uint8_t[dataLength];
|
||||
|
||||
for (i = 0; i < dataLength; ++i)
|
||||
{
|
||||
int dataByte = readHexByte(inLine, dataStartCharIndex + i * 2);
|
||||
data[i] = dataByte;
|
||||
checksum += dataByte;
|
||||
}
|
||||
|
||||
newRecord.m_data = data;
|
||||
newRecord.m_dataCount = dataLength;
|
||||
}
|
||||
|
||||
// read and compare checksum byte
|
||||
checksum = (~checksum) & 0xff; // low byte of one's complement of sum of other bytes
|
||||
newRecord.m_checksum = readHexByte(inLine, (int)inLine.length() - 2);
|
||||
if (checksum != newRecord.m_checksum)
|
||||
{
|
||||
throw StSRecordParseException("invalid checksum");
|
||||
}
|
||||
|
||||
// now save the new S-record
|
||||
m_records.push_back(newRecord);
|
||||
}
|
||||
Reference in New Issue
Block a user