1/* 2 * File: DataSourceImager.cpp 3 * 4 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved. 5 * See included license file for license details. 6 */ 7 8#include "DataSourceImager.h" 9#include <stdlib.h> 10#include <string.h> 11 12using namespace elftosb; 13 14DataSourceImager::DataSourceImager() 15: Blob(), 16 m_fill(0), 17 m_baseAddress(0), 18 m_isBaseAddressSet(false) 19{ 20} 21 22void DataSourceImager::setBaseAddress(uint32_t address) 23{ 24 m_baseAddress = address; 25 m_isBaseAddressSet = true; 26} 27 28void DataSourceImager::setFillPattern(uint8_t pattern) 29{ 30 m_fill = pattern; 31} 32 33void DataSourceImager::reset() 34{ 35 clear(); 36 37 m_fill = 0; 38 m_baseAddress = 0; 39 m_isBaseAddressSet = false; 40} 41 42//! \param dataSource Pointer to an instance of a concrete data source subclass. 43//! 44void DataSourceImager::addDataSource(DataSource * source) 45{ 46 unsigned segmentCount = source->getSegmentCount(); 47 unsigned index = 0; 48 for (; index < segmentCount; ++index) 49 { 50 addDataSegment(source->getSegmentAt(index)); 51 } 52} 53 54//! \param segment The segment to add. May be any type of data segment, including 55//! a pattern segment. 56void DataSourceImager::addDataSegment(DataSource::Segment * segment) 57{ 58 DataSource::PatternSegment * patternSegment = dynamic_cast<DataSource::PatternSegment*>(segment); 59 60 unsigned segmentLength = segment->getLength(); 61 bool segmentHasLocation = segment->hasNaturalLocation(); 62 uint32_t segmentAddress = segment->getBaseAddress(); 63 64 uint8_t * toPtr = NULL; 65 unsigned addressDelta; 66 unsigned newLength; 67 68 // If a pattern segment's length is 0 then make it as big as the fill pattern. 69 // This needs to be done before the buffer is adjusted. 70 if (patternSegment && segmentLength == 0) 71 { 72 SizedIntegerValue & pattern = patternSegment->getPattern(); 73 segmentLength = pattern.getSize(); 74 } 75 76 if (segmentLength) 77 { 78 if (segmentHasLocation) 79 { 80 // Make sure a base address is set. 81 if (!m_isBaseAddressSet) 82 { 83 m_baseAddress = segmentAddress; 84 m_isBaseAddressSet = true; 85 } 86 87 // The segment is located before our buffer's first address. 88 // toPtr is not set in this if, but in the else branch of the next if. 89 // Unless the segment completely overwrite the current data. 90 if (segmentAddress < m_baseAddress) 91 { 92 addressDelta = m_baseAddress - segmentAddress; 93 94 uint8_t * newData = (uint8_t *)malloc(m_length + addressDelta); 95 memcpy(&newData[addressDelta], m_data, m_length); 96 free(m_data); 97 98 m_data = newData; 99 m_length += addressDelta; 100 m_baseAddress = segmentAddress; 101 } 102 103 // This segment is located or extends outside of our buffer. 104 if (segmentAddress + segmentLength > m_baseAddress + m_length) 105 { 106 newLength = segmentAddress + segmentLength - m_baseAddress; 107 108 m_data = (uint8_t *)realloc(m_data, newLength); 109 110 // Clear any bytes between the old data and the new segment. 111 addressDelta = segmentAddress - (m_baseAddress + m_length); 112 if (addressDelta) 113 { 114 memset(m_data + m_length, 0, addressDelta); 115 } 116 117 toPtr = m_data + (segmentAddress - m_baseAddress); 118 m_length = newLength; 119 } 120 else 121 { 122 toPtr = m_data + (segmentAddress - m_baseAddress); 123 } 124 } 125 // Segment has no natural location, so just append it to the end of our buffer. 126 else 127 { 128 newLength = m_length + segmentLength; 129 m_data = (uint8_t *)realloc(m_data, newLength); 130 toPtr = m_data + m_length; 131 m_length = newLength; 132 } 133 } 134 135 // A loop is used because getData() may fill in less than the requested 136 // number of bytes per call. 137 unsigned offset = 0; 138 while (offset < segmentLength) 139 { 140 offset += segment->getData(offset, segmentLength - offset, toPtr + offset); 141 } 142} 143 144