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