2 * File: EncoreBootImageGenerator.cpp
4 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5 * See included license file for license details.
8 #include "EncoreBootImageGenerator.h"
11 #define kFlagsOption "flags"
12 #define kSectionFlagsOption "sectionFlags"
13 #define kProductVersionOption "productVersion"
14 #define kComponentVersionOption "componentVersion"
15 #define kAlignmentOption "alignment"
16 #define kCleartextOption "cleartext"
18 using namespace elftosb;
20 BootImage * EncoreBootImageGenerator::generate()
22 EncoreBootImage * image = new EncoreBootImage();
24 // process each output section
25 section_vector_t::iterator it = m_sections.begin();
26 for (; it != m_sections.end(); ++it)
28 OutputSection * section = *it;
30 OperationSequenceSection * opSection = dynamic_cast<OperationSequenceSection*>(section);
33 processOperationSection(opSection, image);
37 BinaryDataSection * dataSection = dynamic_cast<BinaryDataSection*>(section);
40 processDataSection(dataSection, image);
44 Log::log(Logger::WARNING, "warning: unexpected output section type\n");
47 // handle global options that affect the image
48 processOptions(image);
53 void EncoreBootImageGenerator::processOptions(EncoreBootImage * image)
55 // bail if no option context was set
61 if (m_options->hasOption(kFlagsOption))
63 const IntegerValue * intValue = dynamic_cast<const IntegerValue *>(m_options->getOption(kFlagsOption));
66 image->setFlags(intValue->getValue());
70 Log::log(Logger::WARNING, "warning: flags option is an unexpected type\n");
74 // handle common options
75 processVersionOptions(image);
76 processDriveTagOption(image);
79 void EncoreBootImageGenerator::processSectionOptions(EncoreBootImage::Section * imageSection, OutputSection * modelSection)
81 // Get options context for this output section.
82 const OptionContext * context = modelSection->getOptions();
88 // Check for and handle "sectionFlags" option.
89 if (context->hasOption(kSectionFlagsOption))
91 const Value * value = context->getOption(kSectionFlagsOption);
92 const IntegerValue * intValue = dynamic_cast<const IntegerValue *>(value);
95 // set explicit flags for this section
96 imageSection->setFlags(intValue->getValue());
100 Log::log(Logger::WARNING, "warning: sectionFlags option is an unexpected type\n");
104 // Check for and handle "alignment" option.
105 if (context->hasOption(kAlignmentOption))
107 const Value * value = context->getOption(kAlignmentOption);
108 const IntegerValue * intValue = dynamic_cast<const IntegerValue *>(value);
111 // verify alignment value
112 if (intValue->getValue() < EncoreBootImage::BOOT_IMAGE_MINIMUM_SECTION_ALIGNMENT)
114 Log::log(Logger::WARNING, "warning: alignment option value must be 16 or greater\n");
117 imageSection->setAlignment(intValue->getValue());
121 Log::log(Logger::WARNING, "warning: alignment option is an unexpected type\n");
125 // Check for and handle "cleartext" option.
126 if (context->hasOption(kCleartextOption))
128 const Value * value = context->getOption(kCleartextOption);
129 const IntegerValue * intValue = dynamic_cast<const IntegerValue *>(value);
132 bool leaveUnencrypted = intValue->getValue() != 0;
133 imageSection->setLeaveUnencrypted(leaveUnencrypted);
137 Log::log(Logger::WARNING, "warning: cleartext option is an unexpected type\n");
142 void EncoreBootImageGenerator::processOperationSection(OperationSequenceSection * section, EncoreBootImage * image)
144 EncoreBootImage::BootSection * newSection = new EncoreBootImage::BootSection(section->getIdentifier());
146 OperationSequence & sequence = section->getSequence();
147 OperationSequence::iterator_t it = sequence.begin();
148 for (; it != sequence.end(); ++it)
150 Operation * op = *it;
152 LoadOperation * loadOp = dynamic_cast<LoadOperation*>(op);
155 processLoadOperation(loadOp, newSection);
159 ExecuteOperation * execOp = dynamic_cast<ExecuteOperation*>(op);
162 processExecuteOperation(execOp, newSection);
166 BootModeOperation * modeOp = dynamic_cast<BootModeOperation*>(op);
169 processBootModeOperation(modeOp, newSection);
173 Log::log(Logger::WARNING, "warning: unexpected operation type\n");
176 // Deal with options that apply to sections.
177 processSectionOptions(newSection, section);
179 // add the boot section to the image
180 image->addSection(newSection);
183 void EncoreBootImageGenerator::processLoadOperation(LoadOperation * op, EncoreBootImage::BootSection * section)
185 DataSource * source = op->getSource();
186 DataTarget * target = op->getTarget();
188 // other sources get handled the same way
189 unsigned segmentCount = source->getSegmentCount();
191 for (; index < segmentCount; ++index)
193 DataSource::Segment * segment = source->getSegmentAt(index);
194 DataTarget::AddressRange range = target->getRangeForSegment(*source, *segment);
195 unsigned rangeLength = range.m_end - range.m_begin;
197 // handle a pattern segment as a special case to create a fill command
198 DataSource::PatternSegment * patternSegment = dynamic_cast<DataSource::PatternSegment*>(segment);
201 SizedIntegerValue & pattern = patternSegment->getPattern();
203 EncoreBootImage::FillCommand * command = new EncoreBootImage::FillCommand();
204 command->setAddress(range.m_begin);
205 command->setFillCount(rangeLength);
206 setFillPatternFromValue(*command, pattern);
208 section->addCommand(command);
212 // get the data from the segment
213 uint8_t * data = new uint8_t[rangeLength];
214 segment->getData(0, rangeLength, data);
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());
222 section->addCommand(command);
224 // Free the segment buffer.
229 void EncoreBootImageGenerator::setFillPatternFromValue(EncoreBootImage::FillCommand & command, SizedIntegerValue & pattern)
231 uint32_t u32PatternValue = pattern.getValue() & pattern.getWordSizeMask();
232 switch (pattern.getWordSize())
236 command.setPattern(u32PatternValue);
242 uint16_t u16PatternValue = static_cast<uint16_t>(u32PatternValue);
243 command.setPattern(u16PatternValue);
249 uint8_t u8PatternValue = static_cast<uint8_t>(u32PatternValue);
250 command.setPattern(u8PatternValue);
255 void EncoreBootImageGenerator::processExecuteOperation(ExecuteOperation * op, EncoreBootImage::BootSection * section)
257 DataTarget * target = op->getTarget();
258 uint32_t arg = static_cast<uint32_t>(op->getArgument());
260 EncoreBootImage::JumpCommand * command;
261 switch (op->getExecuteType())
263 case ExecuteOperation::kJump:
264 command = new EncoreBootImage::JumpCommand();
267 case ExecuteOperation::kCall:
268 command = new EncoreBootImage::CallCommand();
272 command->setAddress(target->getBeginAddress());
273 command->setArgument(arg);
274 command->setIsHAB(op->isHAB());
276 section->addCommand(command);
279 void EncoreBootImageGenerator::processBootModeOperation(BootModeOperation * op, EncoreBootImage::BootSection * section)
281 EncoreBootImage::ModeCommand * command = new EncoreBootImage::ModeCommand();
282 command->setBootMode(op->getBootMode());
284 section->addCommand(command);
287 void EncoreBootImageGenerator::processDataSection(BinaryDataSection * section, EncoreBootImage * image)
289 EncoreBootImage::DataSection * dataSection = new EncoreBootImage::DataSection(section->getIdentifier());
290 dataSection->setData(section->getData(), section->getLength());
292 // Handle alignment option.
293 processSectionOptions(dataSection, section);
295 image->addSection(dataSection);