]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/elftosb/elftosb2/EncoreBootImageGenerator.cpp
Unified codebase for TX28, TX48, TX51, TX53
[karo-tx-uboot.git] / tools / elftosb / elftosb2 / EncoreBootImageGenerator.cpp
1 /*
2  * File:        EncoreBootImageGenerator.cpp
3  *
4  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5  * See included license file for license details.
6  */
7
8 #include "EncoreBootImageGenerator.h"
9 #include "Logging.h"
10
11 #define kFlagsOption "flags"
12 #define kSectionFlagsOption "sectionFlags"
13 #define kProductVersionOption "productVersion"
14 #define kComponentVersionOption "componentVersion"
15 #define kAlignmentOption "alignment"
16 #define kCleartextOption "cleartext"
17
18 using namespace elftosb;
19
20 BootImage * EncoreBootImageGenerator::generate()
21 {
22         EncoreBootImage * image = new EncoreBootImage();
23         
24         // process each output section
25         section_vector_t::iterator it = m_sections.begin();
26         for (; it != m_sections.end(); ++it)
27         {
28                 OutputSection * section = *it;
29                 
30                 OperationSequenceSection * opSection = dynamic_cast<OperationSequenceSection*>(section);
31                 if (opSection)
32                 {
33                         processOperationSection(opSection, image);
34                         continue;
35                 }
36                 
37                 BinaryDataSection * dataSection = dynamic_cast<BinaryDataSection*>(section);
38                 if (dataSection)
39                 {
40                         processDataSection(dataSection, image);
41                         continue;
42                 }
43                 
44                 Log::log(Logger::WARNING, "warning: unexpected output section type\n");
45         }
46         
47         // handle global options that affect the image
48         processOptions(image);
49         
50         return image;
51 }
52
53 void EncoreBootImageGenerator::processOptions(EncoreBootImage * image)
54 {
55         // bail if no option context was set
56         if (!m_options)
57         {
58                 return;
59         }
60         
61         if (m_options->hasOption(kFlagsOption))
62         {
63         const IntegerValue * intValue = dynamic_cast<const IntegerValue *>(m_options->getOption(kFlagsOption));
64                 if (intValue)
65                 {
66                         image->setFlags(intValue->getValue());
67                 }
68         else
69         {
70             Log::log(Logger::WARNING, "warning: flags option is an unexpected type\n");
71         }
72         }
73         
74     // handle common options
75         processVersionOptions(image);
76         processDriveTagOption(image);
77 }
78
79 void EncoreBootImageGenerator::processSectionOptions(EncoreBootImage::Section * imageSection, OutputSection * modelSection)
80 {
81         // Get options context for this output section.
82         const OptionContext * context = modelSection->getOptions();
83         if (!context)
84         {
85                 return;
86         }
87         
88         // Check for and handle "sectionFlags" option.
89         if (context->hasOption(kSectionFlagsOption))
90         {
91                 const Value * value = context->getOption(kSectionFlagsOption);
92         const IntegerValue * intValue = dynamic_cast<const IntegerValue *>(value);
93                 if (intValue)
94                 {
95                         // set explicit flags for this section
96                         imageSection->setFlags(intValue->getValue());
97                 }
98         else
99         {
100             Log::log(Logger::WARNING, "warning: sectionFlags option is an unexpected type\n");
101         }
102         }
103         
104         // Check for and handle "alignment" option.
105         if (context->hasOption(kAlignmentOption))
106         {
107                 const Value * value = context->getOption(kAlignmentOption);
108         const IntegerValue * intValue = dynamic_cast<const IntegerValue *>(value);
109                 if (intValue)
110                 {
111                         // verify alignment value
112                         if (intValue->getValue() < EncoreBootImage::BOOT_IMAGE_MINIMUM_SECTION_ALIGNMENT)
113                         {
114                                 Log::log(Logger::WARNING, "warning: alignment option value must be 16 or greater\n");
115                         }
116                         
117                         imageSection->setAlignment(intValue->getValue());
118                 }
119         else
120         {
121             Log::log(Logger::WARNING, "warning: alignment option is an unexpected type\n");
122         }
123         }
124         
125         // Check for and handle "cleartext" option.
126         if (context->hasOption(kCleartextOption))
127         {
128                 const Value * value = context->getOption(kCleartextOption);
129         const IntegerValue * intValue = dynamic_cast<const IntegerValue *>(value);
130                 if (intValue)
131                 {
132                         bool leaveUnencrypted = intValue->getValue() != 0;
133                         imageSection->setLeaveUnencrypted(leaveUnencrypted);
134                 }
135         else
136         {
137             Log::log(Logger::WARNING, "warning: cleartext option is an unexpected type\n");
138         }
139         }
140 }
141
142 void EncoreBootImageGenerator::processOperationSection(OperationSequenceSection * section, EncoreBootImage * image)
143 {
144         EncoreBootImage::BootSection * newSection = new EncoreBootImage::BootSection(section->getIdentifier());
145         
146         OperationSequence & sequence = section->getSequence();
147         OperationSequence::iterator_t it = sequence.begin();
148         for (; it != sequence.end(); ++it)
149         {
150                 Operation * op = *it;
151                 
152                 LoadOperation * loadOp = dynamic_cast<LoadOperation*>(op);
153                 if (loadOp)
154                 {
155                         processLoadOperation(loadOp, newSection);
156                         continue;
157                 }
158                 
159                 ExecuteOperation * execOp = dynamic_cast<ExecuteOperation*>(op);
160                 if (execOp)
161                 {
162                         processExecuteOperation(execOp, newSection);
163                         continue;
164                 }
165                 
166                 BootModeOperation * modeOp = dynamic_cast<BootModeOperation*>(op);
167                 if (modeOp)
168                 {
169                         processBootModeOperation(modeOp, newSection);
170                         continue;
171                 }
172                 
173                 Log::log(Logger::WARNING, "warning: unexpected operation type\n");
174         }
175         
176         // Deal with options that apply to sections.
177         processSectionOptions(newSection, section);
178         
179         // add the boot section to the image
180         image->addSection(newSection);
181 }
182
183 void EncoreBootImageGenerator::processLoadOperation(LoadOperation * op, EncoreBootImage::BootSection * section)
184 {
185         DataSource * source = op->getSource();
186         DataTarget * target = op->getTarget();
187         
188         // other sources get handled the same way
189         unsigned segmentCount = source->getSegmentCount();
190         unsigned index = 0;
191         for (; index < segmentCount; ++index)
192         {
193                 DataSource::Segment * segment = source->getSegmentAt(index);
194                 DataTarget::AddressRange range = target->getRangeForSegment(*source, *segment);
195                 unsigned rangeLength = range.m_end - range.m_begin;
196                 
197                 // handle a pattern segment as a special case to create a fill command
198                 DataSource::PatternSegment * patternSegment = dynamic_cast<DataSource::PatternSegment*>(segment);
199                 if (patternSegment)
200                 {
201                         SizedIntegerValue & pattern = patternSegment->getPattern();
202                         
203                         EncoreBootImage::FillCommand * command = new EncoreBootImage::FillCommand();
204                         command->setAddress(range.m_begin);
205                         command->setFillCount(rangeLength);
206                         setFillPatternFromValue(*command, pattern);
207                         
208                         section->addCommand(command);
209                         continue;
210                 }
211                 
212                 // get the data from the segment
213                 uint8_t * data = new uint8_t[rangeLength];
214                 segment->getData(0, rangeLength, data);
215                 
216                 // create the boot command
217                 EncoreBootImage::LoadCommand * command = new EncoreBootImage::LoadCommand();
218                 command->setData(data, rangeLength); // Makes a copy of the data buffer.
219                 command->setLoadAddress(range.m_begin);
220                 command->setDCD(op->isDCDLoad());
221                 
222                 section->addCommand(command);
223         
224         // Free the segment buffer.
225         delete [] data;
226         }
227 }
228
229 void EncoreBootImageGenerator::setFillPatternFromValue(EncoreBootImage::FillCommand & command, SizedIntegerValue & pattern)
230 {
231         uint32_t u32PatternValue = pattern.getValue() & pattern.getWordSizeMask();
232         switch (pattern.getWordSize())
233         {
234                 case kWordSize:
235                 {
236                         command.setPattern(u32PatternValue);
237                         break;
238                 }
239                 
240                 case kHalfWordSize:
241                 {
242                         uint16_t u16PatternValue = static_cast<uint16_t>(u32PatternValue);
243                         command.setPattern(u16PatternValue);
244                         break;
245                 }
246                 
247                 case kByteSize:
248                 {
249                         uint8_t u8PatternValue = static_cast<uint8_t>(u32PatternValue);
250                         command.setPattern(u8PatternValue);
251                 }
252         }
253 }
254
255 void EncoreBootImageGenerator::processExecuteOperation(ExecuteOperation * op, EncoreBootImage::BootSection * section)
256 {
257         DataTarget * target = op->getTarget();
258         uint32_t arg = static_cast<uint32_t>(op->getArgument());
259         
260         EncoreBootImage::JumpCommand * command;
261         switch (op->getExecuteType())
262         {
263                 case ExecuteOperation::kJump:
264                         command = new EncoreBootImage::JumpCommand();
265                         break;
266                 
267                 case ExecuteOperation::kCall:
268                         command = new EncoreBootImage::CallCommand();
269                         break;
270         }
271         
272         command->setAddress(target->getBeginAddress());
273         command->setArgument(arg);
274         command->setIsHAB(op->isHAB());
275         
276         section->addCommand(command);
277 }
278
279 void EncoreBootImageGenerator::processBootModeOperation(BootModeOperation * op, EncoreBootImage::BootSection * section)
280 {
281         EncoreBootImage::ModeCommand * command = new EncoreBootImage::ModeCommand();
282         command->setBootMode(op->getBootMode());
283         
284         section->addCommand(command);
285 }
286
287 void EncoreBootImageGenerator::processDataSection(BinaryDataSection * section, EncoreBootImage * image)
288 {
289         EncoreBootImage::DataSection * dataSection = new EncoreBootImage::DataSection(section->getIdentifier());
290         dataSection->setData(section->getData(), section->getLength());
291         
292         // Handle alignment option.
293         processSectionOptions(dataSection, section);
294         
295         image->addSection(dataSection);
296 }
297