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
12 using namespace elftosb;
13
DataSourceImager()14 DataSourceImager::DataSourceImager()
15 : Blob(),
16 m_fill(0),
17 m_baseAddress(0),
18 m_isBaseAddressSet(false)
19 {
20 }
21
setBaseAddress(uint32_t address)22 void DataSourceImager::setBaseAddress(uint32_t address)
23 {
24 m_baseAddress = address;
25 m_isBaseAddressSet = true;
26 }
27
setFillPattern(uint8_t pattern)28 void DataSourceImager::setFillPattern(uint8_t pattern)
29 {
30 m_fill = pattern;
31 }
32
reset()33 void 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 //!
addDataSource(DataSource * source)44 void 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.
addDataSegment(DataSource::Segment * segment)56 void 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