diff options
author | Juergen Beisert <jbe@pengutronix.de> | 2011-06-06 16:57:16 +0200 |
---|---|---|
committer | Juergen Beisert <jbe@pengutronix.de> | 2011-06-06 16:57:16 +0200 |
commit | dd57c62797d2b8d05e224680c7bc6e3d4640dde0 (patch) | |
tree | 30046767e14e220ac2b66e2314530565b2117b40 /elftosb2/EncoreBootImageGenerator.cpp | |
parent | 3647e131f8f2779d203d737a3c59baf6c061d528 (diff) | |
download | mxs-utils-dd57c62797d2b8d05e224680c7bc6e3d4640dde0.tar.gz mxs-utils-dd57c62797d2b8d05e224680c7bc6e3d4640dde0.tar.xz |
Import FSL's release 10.11.01
Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
Diffstat (limited to 'elftosb2/EncoreBootImageGenerator.cpp')
-rw-r--r-- | elftosb2/EncoreBootImageGenerator.cpp | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/elftosb2/EncoreBootImageGenerator.cpp b/elftosb2/EncoreBootImageGenerator.cpp new file mode 100644 index 0000000..9bb65c2 --- /dev/null +++ b/elftosb2/EncoreBootImageGenerator.cpp @@ -0,0 +1,297 @@ +/* + * File: EncoreBootImageGenerator.cpp + * + * Copyright (c) Freescale Semiconductor, Inc. All rights reserved. + * See included license file for license details. + */ + +#include "EncoreBootImageGenerator.h" +#include "Logging.h" + +#define kFlagsOption "flags" +#define kSectionFlagsOption "sectionFlags" +#define kProductVersionOption "productVersion" +#define kComponentVersionOption "componentVersion" +#define kAlignmentOption "alignment" +#define kCleartextOption "cleartext" + +using namespace elftosb; + +BootImage * EncoreBootImageGenerator::generate() +{ + EncoreBootImage * image = new EncoreBootImage(); + + // process each output section + section_vector_t::iterator it = m_sections.begin(); + for (; it != m_sections.end(); ++it) + { + OutputSection * section = *it; + + OperationSequenceSection * opSection = dynamic_cast<OperationSequenceSection*>(section); + if (opSection) + { + processOperationSection(opSection, image); + continue; + } + + BinaryDataSection * dataSection = dynamic_cast<BinaryDataSection*>(section); + if (dataSection) + { + processDataSection(dataSection, image); + continue; + } + + Log::log(Logger::WARNING, "warning: unexpected output section type\n"); + } + + // handle global options that affect the image + processOptions(image); + + return image; +} + +void EncoreBootImageGenerator::processOptions(EncoreBootImage * image) +{ + // bail if no option context was set + if (!m_options) + { + return; + } + + if (m_options->hasOption(kFlagsOption)) + { + const IntegerValue * intValue = dynamic_cast<const IntegerValue *>(m_options->getOption(kFlagsOption)); + if (intValue) + { + image->setFlags(intValue->getValue()); + } + else + { + Log::log(Logger::WARNING, "warning: flags option is an unexpected type\n"); + } + } + + // handle common options + processVersionOptions(image); + processDriveTagOption(image); +} + +void EncoreBootImageGenerator::processSectionOptions(EncoreBootImage::Section * imageSection, OutputSection * modelSection) +{ + // Get options context for this output section. + const OptionContext * context = modelSection->getOptions(); + if (!context) + { + return; + } + + // Check for and handle "sectionFlags" option. + if (context->hasOption(kSectionFlagsOption)) + { + const Value * value = context->getOption(kSectionFlagsOption); + const IntegerValue * intValue = dynamic_cast<const IntegerValue *>(value); + if (intValue) + { + // set explicit flags for this section + imageSection->setFlags(intValue->getValue()); + } + else + { + Log::log(Logger::WARNING, "warning: sectionFlags option is an unexpected type\n"); + } + } + + // Check for and handle "alignment" option. + if (context->hasOption(kAlignmentOption)) + { + const Value * value = context->getOption(kAlignmentOption); + const IntegerValue * intValue = dynamic_cast<const IntegerValue *>(value); + if (intValue) + { + // verify alignment value + if (intValue->getValue() < EncoreBootImage::BOOT_IMAGE_MINIMUM_SECTION_ALIGNMENT) + { + Log::log(Logger::WARNING, "warning: alignment option value must be 16 or greater\n"); + } + + imageSection->setAlignment(intValue->getValue()); + } + else + { + Log::log(Logger::WARNING, "warning: alignment option is an unexpected type\n"); + } + } + + // Check for and handle "cleartext" option. + if (context->hasOption(kCleartextOption)) + { + const Value * value = context->getOption(kCleartextOption); + const IntegerValue * intValue = dynamic_cast<const IntegerValue *>(value); + if (intValue) + { + bool leaveUnencrypted = intValue->getValue() != 0; + imageSection->setLeaveUnencrypted(leaveUnencrypted); + } + else + { + Log::log(Logger::WARNING, "warning: cleartext option is an unexpected type\n"); + } + } +} + +void EncoreBootImageGenerator::processOperationSection(OperationSequenceSection * section, EncoreBootImage * image) +{ + EncoreBootImage::BootSection * newSection = new EncoreBootImage::BootSection(section->getIdentifier()); + + OperationSequence & sequence = section->getSequence(); + OperationSequence::iterator_t it = sequence.begin(); + for (; it != sequence.end(); ++it) + { + Operation * op = *it; + + LoadOperation * loadOp = dynamic_cast<LoadOperation*>(op); + if (loadOp) + { + processLoadOperation(loadOp, newSection); + continue; + } + + ExecuteOperation * execOp = dynamic_cast<ExecuteOperation*>(op); + if (execOp) + { + processExecuteOperation(execOp, newSection); + continue; + } + + BootModeOperation * modeOp = dynamic_cast<BootModeOperation*>(op); + if (modeOp) + { + processBootModeOperation(modeOp, newSection); + continue; + } + + Log::log(Logger::WARNING, "warning: unexpected operation type\n"); + } + + // Deal with options that apply to sections. + processSectionOptions(newSection, section); + + // add the boot section to the image + image->addSection(newSection); +} + +void EncoreBootImageGenerator::processLoadOperation(LoadOperation * op, EncoreBootImage::BootSection * section) +{ + DataSource * source = op->getSource(); + DataTarget * target = op->getTarget(); + + // other sources get handled the same way + unsigned segmentCount = source->getSegmentCount(); + unsigned index = 0; + for (; index < segmentCount; ++index) + { + DataSource::Segment * segment = source->getSegmentAt(index); + DataTarget::AddressRange range = target->getRangeForSegment(*source, *segment); + unsigned rangeLength = range.m_end - range.m_begin; + + // handle a pattern segment as a special case to create a fill command + DataSource::PatternSegment * patternSegment = dynamic_cast<DataSource::PatternSegment*>(segment); + if (patternSegment) + { + SizedIntegerValue & pattern = patternSegment->getPattern(); + + EncoreBootImage::FillCommand * command = new EncoreBootImage::FillCommand(); + command->setAddress(range.m_begin); + command->setFillCount(rangeLength); + setFillPatternFromValue(*command, pattern); + + section->addCommand(command); + continue; + } + + // get the data from the segment + uint8_t * data = new uint8_t[rangeLength]; + segment->getData(0, rangeLength, data); + + // create the boot command + EncoreBootImage::LoadCommand * command = new EncoreBootImage::LoadCommand(); + command->setData(data, rangeLength); // Makes a copy of the data buffer. + command->setLoadAddress(range.m_begin); + command->setDCD(op->isDCDLoad()); + + section->addCommand(command); + + // Free the segment buffer. + delete [] data; + } +} + +void EncoreBootImageGenerator::setFillPatternFromValue(EncoreBootImage::FillCommand & command, SizedIntegerValue & pattern) +{ + uint32_t u32PatternValue = pattern.getValue() & pattern.getWordSizeMask(); + switch (pattern.getWordSize()) + { + case kWordSize: + { + command.setPattern(u32PatternValue); + break; + } + + case kHalfWordSize: + { + uint16_t u16PatternValue = static_cast<uint16_t>(u32PatternValue); + command.setPattern(u16PatternValue); + break; + } + + case kByteSize: + { + uint8_t u8PatternValue = static_cast<uint8_t>(u32PatternValue); + command.setPattern(u8PatternValue); + } + } +} + +void EncoreBootImageGenerator::processExecuteOperation(ExecuteOperation * op, EncoreBootImage::BootSection * section) +{ + DataTarget * target = op->getTarget(); + uint32_t arg = static_cast<uint32_t>(op->getArgument()); + + EncoreBootImage::JumpCommand * command; + switch (op->getExecuteType()) + { + case ExecuteOperation::kJump: + command = new EncoreBootImage::JumpCommand(); + break; + + case ExecuteOperation::kCall: + command = new EncoreBootImage::CallCommand(); + break; + } + + command->setAddress(target->getBeginAddress()); + command->setArgument(arg); + command->setIsHAB(op->isHAB()); + + section->addCommand(command); +} + +void EncoreBootImageGenerator::processBootModeOperation(BootModeOperation * op, EncoreBootImage::BootSection * section) +{ + EncoreBootImage::ModeCommand * command = new EncoreBootImage::ModeCommand(); + command->setBootMode(op->getBootMode()); + + section->addCommand(command); +} + +void EncoreBootImageGenerator::processDataSection(BinaryDataSection * section, EncoreBootImage * image) +{ + EncoreBootImage::DataSection * dataSection = new EncoreBootImage::DataSection(section->getIdentifier()); + dataSection->setData(section->getData(), section->getLength()); + + // Handle alignment option. + processSectionOptions(dataSection, section); + + image->addSection(dataSection); +} + |