/* * File: DataSourceImager.cpp * * Copyright (c) Freescale Semiconductor, Inc. All rights reserved. * See included license file for license details. */ #include "DataSourceImager.h" #include #include using namespace elftosb; DataSourceImager::DataSourceImager() : Blob(), m_fill(0), m_baseAddress(0), m_isBaseAddressSet(false) { } void DataSourceImager::setBaseAddress(uint32_t address) { m_baseAddress = address; m_isBaseAddressSet = true; } void DataSourceImager::setFillPattern(uint8_t pattern) { m_fill = pattern; } void DataSourceImager::reset() { clear(); m_fill = 0; m_baseAddress = 0; m_isBaseAddressSet = false; } //! \param dataSource Pointer to an instance of a concrete data source subclass. //! void DataSourceImager::addDataSource(DataSource * source) { unsigned segmentCount = source->getSegmentCount(); unsigned index = 0; for (; index < segmentCount; ++index) { addDataSegment(source->getSegmentAt(index)); } } //! \param segment The segment to add. May be any type of data segment, including //! a pattern segment. void DataSourceImager::addDataSegment(DataSource::Segment * segment) { DataSource::PatternSegment * patternSegment = dynamic_cast(segment); unsigned segmentLength = segment->getLength(); bool segmentHasLocation = segment->hasNaturalLocation(); uint32_t segmentAddress = segment->getBaseAddress(); uint8_t * toPtr = NULL; unsigned addressDelta; unsigned newLength; // If a pattern segment's length is 0 then make it as big as the fill pattern. // This needs to be done before the buffer is adjusted. if (patternSegment && segmentLength == 0) { SizedIntegerValue & pattern = patternSegment->getPattern(); segmentLength = pattern.getSize(); } if (segmentLength) { if (segmentHasLocation) { // Make sure a base address is set. if (!m_isBaseAddressSet) { m_baseAddress = segmentAddress; m_isBaseAddressSet = true; } // The segment is located before our buffer's first address. // toPtr is not set in this if, but in the else branch of the next if. // Unless the segment completely overwrite the current data. if (segmentAddress < m_baseAddress) { addressDelta = m_baseAddress - segmentAddress; uint8_t * newData = (uint8_t *)malloc(m_length + addressDelta); memcpy(&newData[addressDelta], m_data, m_length); free(m_data); m_data = newData; m_length += addressDelta; m_baseAddress = segmentAddress; } // This segment is located or extends outside of our buffer. if (segmentAddress + segmentLength > m_baseAddress + m_length) { newLength = segmentAddress + segmentLength - m_baseAddress; m_data = (uint8_t *)realloc(m_data, newLength); // Clear any bytes between the old data and the new segment. addressDelta = segmentAddress - (m_baseAddress + m_length); if (addressDelta) { memset(m_data + m_length, 0, addressDelta); } toPtr = m_data + (segmentAddress - m_baseAddress); m_length = newLength; } else { toPtr = m_data + (segmentAddress - m_baseAddress); } } // Segment has no natural location, so just append it to the end of our buffer. else { newLength = m_length + segmentLength; m_data = (uint8_t *)realloc(m_data, newLength); toPtr = m_data + m_length; m_length = newLength; } } // A loop is used because getData() may fill in less than the requested // number of bytes per call. unsigned offset = 0; while (offset < segmentLength) { offset += segment->getData(offset, segmentLength - offset, toPtr + offset); } }