]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/elftosb/common/DataSourceImager.cpp
Unified codebase for TX28, TX48, TX51, TX53
[karo-tx-uboot.git] / tools / elftosb / common / DataSourceImager.cpp
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
14 DataSourceImager::DataSourceImager()
15 :       Blob(),
16         m_fill(0),
17         m_baseAddress(0),
18         m_isBaseAddressSet(false)
19 {
20 }
21
22 void DataSourceImager::setBaseAddress(uint32_t address)
23 {
24         m_baseAddress = address;
25         m_isBaseAddressSet = true;
26 }
27
28 void DataSourceImager::setFillPattern(uint8_t pattern)
29 {
30         m_fill = pattern;
31 }
32
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 //!
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.
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