Home | History | Annotate | Line # | Download | only in common
      1  1.1  jkunz /*
      2  1.1  jkunz  * File:	SRecordSourceFile.cpp
      3  1.1  jkunz  *
      4  1.1  jkunz  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
      5  1.1  jkunz  * See included license file for license details.
      6  1.1  jkunz  */
      7  1.1  jkunz 
      8  1.1  jkunz #include "SRecordSourceFile.h"
      9  1.1  jkunz #include "Logging.h"
     10  1.1  jkunz #include "smart_ptr.h"
     11  1.1  jkunz #include <assert.h>
     12  1.1  jkunz #include <string.h>
     13  1.1  jkunz enum
     14  1.1  jkunz {
     15  1.1  jkunz 	//! Size in bytes of the buffer used to collect S-record data records
     16  1.1  jkunz 	//! before adding them to the executable image. Currently 64KB.
     17  1.1  jkunz 	COLLECTION_BUFFER_SIZE = 64 * 1024
     18  1.1  jkunz };
     19  1.1  jkunz 
     20  1.1  jkunz using namespace elftosb;
     21  1.1  jkunz 
     22  1.1  jkunz SRecordSourceFile::SRecordSourceFile(const std::string & path)
     23  1.1  jkunz :	SourceFile(path), m_image(0), m_hasEntryRecord(false)
     24  1.1  jkunz {
     25  1.1  jkunz }
     26  1.1  jkunz 
     27  1.1  jkunz bool SRecordSourceFile::isSRecordFile(std::istream & stream)
     28  1.1  jkunz {
     29  1.1  jkunz 	StSRecordFile srec(stream);
     30  1.1  jkunz 	return srec.isSRecordFile();
     31  1.1  jkunz }
     32  1.1  jkunz 
     33  1.1  jkunz void SRecordSourceFile::open()
     34  1.1  jkunz {
     35  1.1  jkunz 	SourceFile::open();
     36  1.1  jkunz 
     37  1.1  jkunz 	// create file parser and examine file
     38  1.1  jkunz 	m_file = new StSRecordFile(*m_stream);
     39  1.1  jkunz 	m_file->parse();
     40  1.1  jkunz 
     41  1.1  jkunz 	// build an image of the file
     42  1.1  jkunz 	m_image = new StExecutableImage();
     43  1.1  jkunz 	buildMemoryImage();
     44  1.1  jkunz 
     45  1.1  jkunz 	// dispose of file parser object
     46  1.1  jkunz 	delete m_file;
     47  1.1  jkunz 	m_file = 0;
     48  1.1  jkunz }
     49  1.1  jkunz 
     50  1.1  jkunz void SRecordSourceFile::close()
     51  1.1  jkunz {
     52  1.1  jkunz 	assert(m_image);
     53  1.1  jkunz 
     54  1.1  jkunz 	SourceFile::close();
     55  1.1  jkunz 
     56  1.1  jkunz 	// dispose of memory image
     57  1.1  jkunz 	delete m_image;
     58  1.1  jkunz 	m_image = 0;
     59  1.1  jkunz }
     60  1.1  jkunz 
     61  1.1  jkunz //! \pre The file must be open before this method can be called.
     62  1.1  jkunz //!
     63  1.1  jkunz DataSource * SRecordSourceFile::createDataSource()
     64  1.1  jkunz {
     65  1.1  jkunz 	assert(m_image);
     66  1.1  jkunz 	return new MemoryImageDataSource(m_image);
     67  1.1  jkunz }
     68  1.1  jkunz 
     69  1.1  jkunz //! \retval true The file has an S7, S8, or S9 record.
     70  1.1  jkunz //! \retval false No entry point is available.
     71  1.1  jkunz bool SRecordSourceFile::hasEntryPoint()
     72  1.1  jkunz {
     73  1.1  jkunz 	return m_hasEntryRecord;
     74  1.1  jkunz }
     75  1.1  jkunz 
     76  1.1  jkunz //! If no entry point is available then 0 is returned instead. The method scans
     77  1.1  jkunz //! the records in the file looking for S7, S8, or S9 records. Thus, 16-bit,
     78  1.1  jkunz //! 24-bit, and 32-bit entry point records are supported.
     79  1.1  jkunz //!
     80  1.1  jkunz //! \return Entry point address.
     81  1.1  jkunz //! \retval 0 No entry point is available.
     82  1.1  jkunz uint32_t SRecordSourceFile::getEntryPointAddress()
     83  1.1  jkunz {
     84  1.1  jkunz 	if (m_hasEntryRecord)
     85  1.1  jkunz 	{
     86  1.1  jkunz 		// the address in the record is the entry point
     87  1.1  jkunz 		Log::log(Logger::DEBUG2, "entry point address is 0x%08x\n", m_entryRecord.m_address);
     88  1.1  jkunz 		return m_entryRecord.m_address;
     89  1.1  jkunz 	}
     90  1.1  jkunz 
     91  1.1  jkunz 	return 0;
     92  1.1  jkunz }
     93  1.1  jkunz 
     94  1.1  jkunz //! Scans the S-records of the file looking for data records. These are S3, S2, or
     95  1.1  jkunz //! S1 records. The contents of these records are added to an StExecutableImage
     96  1.1  jkunz //! object, which coalesces the individual records into contiguous regions of
     97  1.1  jkunz //! memory.
     98  1.1  jkunz //!
     99  1.1  jkunz //! Also looks for S7, S8, or S9 records that contain the entry point. The first
    100  1.1  jkunz //! match of one of these records is saved off into the #m_entryRecord member.
    101  1.1  jkunz //!
    102  1.1  jkunz //! \pre The #m_file member must be valid.
    103  1.1  jkunz //! \pre The #m_image member variable must have been instantiated.
    104  1.1  jkunz void SRecordSourceFile::buildMemoryImage()
    105  1.1  jkunz {
    106  1.1  jkunz 	assert(m_file);
    107  1.1  jkunz 	assert(m_image);
    108  1.1  jkunz 
    109  1.1  jkunz 	// Clear the entry point related members.
    110  1.1  jkunz 	m_hasEntryRecord = false;
    111  1.1  jkunz 	memset(&m_entryRecord, 0, sizeof(m_entryRecord));
    112  1.1  jkunz 
    113  1.1  jkunz 	// Allocate buffer to hold data before adding it to the executable image.
    114  1.1  jkunz 	// Contiguous records are added to this buffer. When overflowed or when a
    115  1.1  jkunz 	// non-contiguous record is encountered the buffer is added to the executable
    116  1.1  jkunz 	// image where it will be coalesced further. We don't add records individually
    117  1.1  jkunz 	// to the image because coalescing record by record is very slow.
    118  1.1  jkunz 	smart_array_ptr<uint8_t> buffer = new uint8_t[COLLECTION_BUFFER_SIZE];
    119  1.1  jkunz 	unsigned startAddress;
    120  1.1  jkunz 	unsigned nextAddress;
    121  1.1  jkunz 	unsigned dataLength = 0;
    122  1.1  jkunz 
    123  1.1  jkunz 	// process SRecords
    124  1.1  jkunz     StSRecordFile::const_iterator it = m_file->getBegin();
    125  1.1  jkunz 	for (; it != m_file->getEnd(); it++)
    126  1.1  jkunz 	{
    127  1.1  jkunz         const StSRecordFile::SRecord & theRecord = *it;
    128  1.1  jkunz 
    129  1.1  jkunz         // only handle S3,2,1 records
    130  1.1  jkunz         bool isDataRecord = theRecord.m_type == 3 || theRecord.m_type == 2 || theRecord.m_type == 1;
    131  1.1  jkunz         bool hasData = theRecord.m_data && theRecord.m_dataCount;
    132  1.1  jkunz 		if (isDataRecord && hasData)
    133  1.1  jkunz 		{
    134  1.1  jkunz 			// If this record's data would overflow the collection buffer, or if the
    135  1.1  jkunz 			// record is not contiguous with the rest of the data in the collection
    136  1.1  jkunz 			// buffer, then flush the buffer to the executable image and restart.
    137  1.1  jkunz 			if (dataLength && ((dataLength + theRecord.m_dataCount > COLLECTION_BUFFER_SIZE) || (theRecord.m_address != nextAddress)))
    138  1.1  jkunz 			{
    139  1.1  jkunz 				m_image->addTextRegion(startAddress, buffer, dataLength);
    140  1.1  jkunz 
    141  1.1  jkunz 				dataLength = 0;
    142  1.1  jkunz 			}
    143  1.1  jkunz 
    144  1.1  jkunz 			// Capture addresses when starting an empty buffer.
    145  1.1  jkunz 			if (dataLength == 0)
    146  1.1  jkunz 			{
    147  1.1  jkunz 				startAddress = theRecord.m_address;
    148  1.1  jkunz 				nextAddress = startAddress;
    149  1.1  jkunz 			}
    150  1.1  jkunz 
    151  1.1  jkunz 			// Copy record data into place in the collection buffer and update
    152  1.1  jkunz 			// size and address.
    153  1.1  jkunz 			memcpy(&buffer[dataLength], theRecord.m_data, theRecord.m_dataCount);
    154  1.1  jkunz 			dataLength += theRecord.m_dataCount;
    155  1.1  jkunz 			nextAddress += theRecord.m_dataCount;
    156  1.1  jkunz 		}
    157  1.1  jkunz 		else if (!m_hasEntryRecord)
    158  1.1  jkunz 		{
    159  1.1  jkunz 			// look for S7,8,9 records
    160  1.1  jkunz 			bool isEntryPointRecord = theRecord.m_type == 7 || theRecord.m_type == 8 || theRecord.m_type == 9;
    161  1.1  jkunz 			if (isEntryPointRecord)
    162  1.1  jkunz 			{
    163  1.1  jkunz 				// save off the entry point record so we don't have to scan again
    164  1.1  jkunz 				memcpy(&m_entryRecord, &theRecord, sizeof(m_entryRecord));
    165  1.1  jkunz 				m_hasEntryRecord = true;
    166  1.1  jkunz 			}
    167  1.1  jkunz 		}
    168  1.1  jkunz 	}
    169  1.1  jkunz 
    170  1.1  jkunz 	// Add any leftover data in the collection buffer to the executable image.
    171  1.1  jkunz 	if (dataLength)
    172  1.1  jkunz 	{
    173  1.1  jkunz 		m_image->addTextRegion(startAddress, buffer, dataLength);
    174  1.1  jkunz 	}
    175  1.1  jkunz }
    176  1.1  jkunz 
    177