Home | History | Annotate | Line # | Download | only in elftosb2
      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 
    298