xref: /netbsd-src/external/bsd/elftosb/dist/common/EncoreBootImage.h (revision 8fb7bb9693a3df9b77e6e5bea8efd0a3ab732cd1)
1 /*
2  * File:	EncoreBootImage.h
3  *
4  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5  * See included license file for license details.
6  */
7 #if !defined(_EncoreBootImage_h_)
8 #define _EncoreBootImage_h_
9 
10 #include <list>
11 #include <vector>
12 #include <string>
13 #include <iostream>
14 #include <fstream>
15 #include <string.h>
16 #include "BootImage.h"
17 #include "rijndael.h"
18 #include "smart_ptr.h"
19 #include "AESKey.h"
20 #include "StExecutableImage.h"
21 
22 namespace elftosb
23 {
24 
25 //! An AES-128 cipher block is 16 bytes.
26 typedef uint8_t cipher_block_t[16];
27 
28 //! A SHA-1 digest is 160 bits, or 20 bytes.
29 typedef uint8_t sha1_digest_t[20];
30 
31 //! Unique identifier type for a section.
32 typedef uint32_t section_id_t;
33 
34 //! Utility to return the byte length of a number of cipher blocks.
sizeOfCipherBlocks(unsigned count)35 inline size_t sizeOfCipherBlocks(unsigned count) { return sizeof(cipher_block_t) * count; }
36 
37 //! Utility to return the number of cipher blocks required to hold an object
38 //! that is \a s bytes long.
numberOfCipherBlocks(size_t s)39 inline size_t numberOfCipherBlocks(size_t s) { return (s + sizeof(cipher_block_t) - 1) / sizeof(cipher_block_t); }
40 
41 //! Utility to calculate the byte length for the cipher blocks required to hold
42 //! and object that is \a bytes long.
sizeInCipherBlocks(size_t s)43 inline size_t sizeInCipherBlocks(size_t s) { return (unsigned)sizeOfCipherBlocks(numberOfCipherBlocks(s)); }
44 
45 //! Utility to return the number of bytes of padding required to fill out
46 //! the last cipher block in a set of cipher blocks large enough to hold
47 //! an object that is \a s bytes large. The result may be 0 if \a s is
48 //! an even multiple of the cipher block size.
sizeOfPaddingForCipherBlocks(size_t s)49 inline size_t sizeOfPaddingForCipherBlocks(size_t s) { return sizeInCipherBlocks(s) - s; }
50 
51 /*!
52  * \brief Class to manage Encore boot image files.
53  *
54  * Initially this class will only support generation of boot images, but
55  * its design will facilitate the addition of the ability to read an
56  * image and examine its contents.
57  *
58  * A boot image is composed of the following regions:
59  * - Header
60  * - Section table
61  * - Key dictionary
62  * - Section data
63  * - Authentication
64  *
65  * Multiple sections are within a boot image are fully supported. Two general types
66  * of sections are supported with this class. Bootable sections, represented by the
67  * EncoreBootImage::BootSection class, contain a sequence of commands to be
68  * interpreted by the boot ROM. Data sections are represented by the
69  * EncoreBootImage::DataSection class and can contain any arbitrary data.
70  *
71  * An image can either be encrypted or unencrypted. The image uses a session key,
72  * or DEK (data encryption key), and the key dictionary to support any number of keys
73  * using a single image. The header and section table are always unencrypted even
74  * in encrypted images. This allows host utilities to access the individual
75  * sections without needing to have access to an encryption key.
76  *
77  * To construct a boot image, first create an instance of EncoreBootImage. Then
78  * create instances of the EncoreBootImage::BootSection or EncoreBootImage::DataSection
79  * for each of the sections in the image. For bootable sections, create and add
80  * the desired boot command objects. These are all subclasses of
81  * EncoreBootImage::BootCommand.
82  *
83  * If the boot image is to be encrypted, you need to add keys, which are instances
84  * of the AES128Key class. If no keys are added, the entire boot image will be unencrypted.
85  *
86  * When the image is fully constructed, it can be written to any std::ostream with
87  * a call to writeToStream(). The same image can be written to streams any
88  * number of times.
89  */
90 class EncoreBootImage : public BootImage
91 {
92 public:
93 	//! \brief Flag constants for the m_flags field of #elftosb::EncoreBootImage::boot_image_header_t.
94 	enum
95 	{
96 		ROM_DISPLAY_PROGRESS = (1 << 0),		//!< Print progress reports.
97 		ROM_VERBOSE_PROGRESS = (1 << 1)			//!< Progress reports are verbose.
98 	};
99 
100 #define ROM_IMAGE_HEADER_SIGNATURE "STMP"	//!< Signature in #elftosb::EncoreBootImage::boot_image_header_t::m_signature.
101 #define ROM_IMAGE_HEADER_SIGNATURE2 "sgtl"	//!< Value for #elftosb::EncoreBootImage::boot_image_header_t::m_signature2;
102 #define	ROM_BOOT_IMAGE_MAJOR_VERSION 1		//!< Current boot image major version.
103 #define	ROM_BOOT_IMAGE_MINOR_VERSION 1		//!< Current boot image minor version.
104 
105 	enum {
106 		//! Minimum alignment for a section is 16 bytes.
107 		BOOT_IMAGE_MINIMUM_SECTION_ALIGNMENT = sizeof(cipher_block_t)
108 	};
109 
110 // All of these structures are packed to byte alignment in order to match
111 // the structure on disk.
112 #pragma pack(1)
113 
114 	//! \brief Header for the entire boot image.
115 	//!
116 	//! Fields of this header are arranged so that those used by the bootloader ROM all come
117 	//! first. They are also set up so that all fields are not split across cipher block
118 	//! boundaries. The fields not used by the bootloader are not subject to this
119 	//! restraint.
120 	//!
121 	//! Image header size is always a round number of cipher blocks. The same also applies to
122 	//! the boot image itself. The padding, held in #elftosb::EncoreBootImage::boot_image_header_t::m_padding0
123 	//! and #elftosb::EncoreBootImage::boot_image_header_t::m_padding1 is filled with random bytes.
124 	//!
125 	//! The DEK dictionary, section table, and each section data region must all start on
126 	//! cipher block boundaries.
127 	//!
128 	//! This header is not encrypted in the image file.
129 	//!
130 	//! The m_digest field contains a SHA-1 digest of the fields of the header that follow it.
131 	//! It is the first field in the header so it doesn't change position or split the header
132 	//! in two if fields are added to the header.
133 	struct boot_image_header_t
134 	{
135 		union
136 		{
137 			sha1_digest_t m_digest;		//!< SHA-1 digest of image header. Also used as the crypto IV.
138 			struct
139 			{
140 				cipher_block_t m_iv;	//!< The first 16 bytes of the digest form the initialization vector.
141 				uint8_t m_extra[4];		//!< The leftover top four bytes of the SHA-1 digest.
142 			};
143 		};
144 		uint8_t m_signature[4];			//!< 'STMP', see #ROM_IMAGE_HEADER_SIGNATURE.
145 		uint8_t m_majorVersion;			//!< Major version for the image format, see #ROM_BOOT_IMAGE_MAJOR_VERSION.
146 		uint8_t m_minorVersion;		//!< Minor version of the boot image format, see #ROM_BOOT_IMAGE_MINOR_VERSION.
147 		uint16_t m_flags;				//!< Flags or options associated with the entire image.
148 		uint32_t m_imageBlocks;			//!< Size of entire image in blocks.
149 		uint32_t m_firstBootTagBlock;	//!< Offset from start of file to the first boot tag, in blocks.
150 		section_id_t m_firstBootableSectionID;	//!< ID of section to start booting from.
151 		uint16_t m_keyCount;			//!< Number of entries in DEK dictionary.
152 		uint16_t m_keyDictionaryBlock;	//!< Starting block number for the key dictionary.
153 		uint16_t m_headerBlocks;		//!< Size of this header, including this size word, in blocks.
154 		uint16_t m_sectionCount;		//!< Number of section headers in this table.
155 		uint16_t m_sectionHeaderSize;	//!< Size in blocks of a section header.
156 		uint8_t m_padding0[2];			//!< Padding to align #m_timestamp to long word.
157 		uint8_t m_signature2[4];		//!< Second signature to distinguish this .sb format from the 36xx format, see #ROM_IMAGE_HEADER_SIGNATURE2.
158 		uint64_t m_timestamp;			//!< Timestamp when image was generated in microseconds since 1-1-2000.
159 		version_t m_productVersion;		//!< Product version.
160 		version_t m_componentVersion;	//!< Component version.
161 		uint16_t m_driveTag;			//!< Drive tag for the system drive which this boot image belongs to.
162 		uint8_t m_padding1[6];          //!< Padding to round up to next cipher block.
163 	};
164 
165 	//! \brief Entry in #elftosb::EncoreBootImage::dek_dictionary_t.
166 	//!
167 	//! The m_dek field in each entry is encrypted using the KEK with the m_iv field from
168 	//! the image header as the IV.
169 	struct dek_dictionary_entry_t
170 	{
171 		cipher_block_t m_mac;			//!< CBC-MAC of the header.
172 		aes128_key_t m_dek;				//!< AES-128 key with which the image payload is encrypted.
173 	};
174 
175 	//! \brief The DEK dictionary always follows the image header, in the next cipher block.
176 	struct dek_dictionary_t
177 	{
178 		dek_dictionary_entry_t m_entries[1];
179 	};
180 
181 	//! \brief Section flags constants for the m_flags field of #elftosb::EncoreBootImage::section_header_t.
182 	enum
183 	{
184 		ROM_SECTION_BOOTABLE = (1 << 0),	//!< The section contains bootloader commands.
185 		ROM_SECTION_CLEARTEXT = (1 << 1)	//!< The section is unencrypted. Applies only if the rest of the boot image is encrypted.
186 	};
187 
188 	//! \brief Information about each section, held in the section table.
189 	//! \see section_table_t
190 	struct section_header_t
191 	{
192 		uint32_t m_tag;					//!< Unique identifier for this section. High bit must be zero.
193 		uint32_t m_offset;				//!< Offset to section data from start of image in blocks.
194 		uint32_t m_length;				//!< Size of section data in blocks.
195 		uint32_t m_flags;				//!< Section flags.
196 	};
197 
198 	//! \brief An index of all sections within the boot image.
199 	//!
200 	//! The section table will be padded so that its length is divisible by 16 (if necessary).
201 	//! Actually, each entry is padded to be a round number of cipher blocks, which
202 	//! automatically makes this true for the entire table.
203 	//!
204 	//! Sections are ordered as they appear in this table, but are identified by the
205 	//! #elftosb::EncoreBootImage::section_header_t::m_tag.
206 	//!
207 	//! The data for each section in encrypted separately with the DEK in CBC mode using
208 	//! m_iv for the IV. This allows the ROM to jump to any given section without needing
209 	//! to read the previous cipher block. In addition, the data for each section is
210 	//! prefixed with a "boot tag", which describes the section which follows it. Boot
211 	//! tags are the same format as a boot command, and are described by the
212 	//! EncoreBootImage::TagCommand class.
213 	//!
214 	//! The section table starts immediately after the image header, coming before the
215 	//! key dictionary (if present). The section table is not encrypted.
216 	struct section_table_t
217 	{
218 		section_header_t m_sections[1];	//!< The table entries.
219 	};
220 
221 	//! \brief Structure for a Piano bootloader command.
222 	//!
223 	//! Each command is composed of a fixed length header of 16 bytes. This happens to be
224 	//! the size of a cipher block. Most commands will only require the header.
225 	//!
226 	//! But some commands, i.e. the "load data" command, may require additional arbitrary
227 	//! amounts of data. This data is packed into the N cipher blocks that immediately
228 	//! follow the command header. If the length of the data is not divisible by 16, then
229 	//! random (not zero!) pad bytes will be added.
230 	struct boot_command_t
231 	{
232 		uint8_t m_checksum;				//!< Simple checksum over other command fields.
233 		uint8_t m_tag;					//!< Tag telling which command this is.
234 		uint16_t m_flags;				//!< Flags for this command.
235 		uint32_t m_address;				//!< Target address.
236 		uint32_t m_count;				//!< Number of bytes on which to operate.
237 		uint32_t m_data;				//!< Additional data used by certain commands.
238 	};
239 
240 #pragma pack()
241 
242 	//! \brief Bootloader command tag constants.
243 	enum
244 	{
245 		ROM_NOP_CMD = 0x00,		//!< A no-op command.
246 		ROM_TAG_CMD = 0x01,		//!< Section tag command.
247 		ROM_LOAD_CMD = 0x02,	//!< Load data command.
248 		ROM_FILL_CMD = 0x03,	//!< Pattern fill command.
249 		ROM_JUMP_CMD = 0x04,	//!< Jump to address command.
250 		ROM_CALL_CMD = 0x05,	//!< Call function command.
251 		ROM_MODE_CMD = 0x06		//!< Change boot mode command.
252 	};
253 
254 	//! \brief Flag field constants for #ROM_TAG_CMD.
255 	enum
256 	{
257 		ROM_LAST_TAG = (1 << 0)	//!< This tag command is the last one in the image.
258 	};
259 
260 	//! \brief Flag field constants for #ROM_LOAD_CMD.
261 	enum
262 	{
263 		ROM_LOAD_DCD = (1 << 0)	//!< Execute the DCD after loading completes.
264 	};
265 
266 	//! \brief Flag field constants for #ROM_FILL_CMD.
267 	enum
268 	{
269 		ROM_FILL_BYTE = 0,		//!< Fill with byte sized pattern.
270 		ROM_FILL_HALF_WORD = 1,	//!< Fill with half-word sized pattern.
271 		ROM_FILL_WORD = 2		//!< Fill with word sized pattern.
272 	};
273 
274 	//! brief Flag field constants for #ROM_JUMP_CMD and #ROM_CALL_CMD.
275 	enum
276 	{
277 		ROM_HAB_EXEC = (1 << 0)	//!< Changes jump or call command to a HAB jump or call.
278 	};
279 
280 public:
281 	// Forward declaration.
282 	class Section;
283 
284 	/*!
285 	 * \brief Base class for objects that produce cipher blocks.
286 	 */
287 	class CipherBlockGenerator
288 	{
289 	public:
290 
291 		//! \name Cipher blocks
292 		//@{
293 		//! \brief Returns the total number of cipher blocks.
294 		//!
295 		//! The default implementation returns 0, indicating that no blocks are
296 		//! available.
getBlockCount()297 		virtual unsigned getBlockCount() const { return 0; }
298 
299 		//! \brief Returns the contents of up to \a maxCount cipher blocks.
300 		//!
301 		//! Up to \a maxCount cipher blocks are copied into the buffer pointed to by
302 		//! the \a data argument. This is only a request for \a maxCount blocks,
303 		//! the subclass implementation of this method is free to return any number
304 		//! of blocks from 0 up to \a maxCount. A return value of 0 indicates that
305 		//! no more blocks are available. The index of the first block to copy is
306 		//! held in the \a offset argument.
307 		//!
308 		//! \param offset Starting block number to copy. Zero means the first available block.
309 		//! \param maxCount Up to this number of blocks may be copied into \a data. Must be 1 or greater.
310 		//! \param data Buffer for outgoing cipher blocks. Must have enough room to hold
311 		//!		\a maxCount blocks.
312 		//!
313 		//! \return The number of cipher blocks copied into \a data.
314 		//! \retval 0 No more blocks are available and nothing was written to \a data.
getBlocks(unsigned offset,unsigned maxCount,cipher_block_t * data)315 		virtual unsigned getBlocks(unsigned offset, unsigned maxCount, cipher_block_t * data) { return 0; }
316 		//@}
317 
318 		//! \brief Print out a string representation of the object.
debugPrint()319 		virtual void debugPrint() const {}
320 	};
321 
322 	/*!
323 	 * \brief Abstract base class for all bootloader commands.
324 	 */
325 	class BootCommand : public CipherBlockGenerator
326 	{
327 	public:
328 		//! \brief Creates the correct subclass of BootCommand for the given raw data.
329 		static BootCommand * createFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
330 
331 	public:
332 		//! \brief Default constructor.
BootCommand()333 		BootCommand() : CipherBlockGenerator() {}
334 
335 		//! \brief Destructor.
~BootCommand()336 		virtual ~BootCommand() {}
337 
338 		//! \brief Read the command contents from raw data.
339 		//!
340 		//! The subclass implementations should validate the contents of the command, including
341 		//! the fields of the command header in the first block. It should be assumed that
342 		//! only the tag field was examined to determine which subclass of BootCommand
343 		//! should be created.
344 		//!
345 		//! \param blocks Pointer to the raw data blocks.
346 		//! \param count Number of blocks pointed to by \a blocks.
347 		//! \param[out] consumed On exit, this points to the number of cipher blocks that were occupied
348 		//!		by the command. Should be at least 1 for every command. This must not be NULL
349 		//!		on entry!
350 		virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed)=0;
351 
352 		//! \name Header
353 		//@{
354 		//! \brief Pure virtual method to return the tag value for this command.
355 		virtual uint8_t getTag() const = 0;
356 
357 		//! \brief Pure virtual method to construct the header for this boot command.
358 		virtual void fillCommandHeader(boot_command_t & header) = 0;
359 
360 		//! \brief Calculates the checksum for the given command header.
361 		virtual uint8_t calculateChecksum(const boot_command_t & header);
362 		//@}
363 
364 		//! \name Cipher blocks
365 		//@{
366 		//! \brief Returns the total number of cipher blocks.
367 		virtual unsigned getBlockCount() const;
368 
369 		//! \brief Returns the contents of up to \a maxCount cipher blocks.
370 		virtual unsigned getBlocks(unsigned offset, unsigned maxCount, cipher_block_t * data);
371 		//@}
372 
373 		//! \name Data blocks
374 		//@{
375 		//! \brief Returns the number of data cipher blocks that follow this command.
376 		//!
377 		//! The default implementation returns 0, indicating that no data blocks are
378 		//! available.
getDataBlockCount()379 		virtual unsigned getDataBlockCount() const { return 0; }
380 
381 		//! \brief Returns the contents of up to \a maxCount data blocks.
382 		//!
383 		//! Up to \a maxCount data blocks are copied into the buffer pointed to by
384 		//! the \a data argument. This is only a request for \a maxCount blocks,
385 		//! the subclass implementation of this method is free to return any number
386 		//! of blocks from 0 up to \a maxCount. A return value of 0 indicates that
387 		//! no more blocks are available. The index of the first block to copy is
388 		//! held in the \a offset argument.
389 		//!
390 		//! \param offset Starting block number to copy. Zero means the first available block.
391 		//! \param maxCount Up to this number of blocks may be copied into \a data. Must be 1 or greater.
392 		//! \param data Buffer for outgoing data blocks. Must have enough room to hold
393 		//!		\a maxCount blocks.
394 		//!
395 		//! \return The number of data blocks copied into \a data.
396 		//! \retval 0 No more blocks are available and nothing was written to \a data.
getDataBlocks(unsigned offset,unsigned maxCount,cipher_block_t * data)397 		virtual unsigned getDataBlocks(unsigned offset, unsigned maxCount, cipher_block_t * data) { return 0; }
398 		//@}
399 
400 	protected:
401 		//! The flag bit values for the \a whichFields parameter of validateHeader().
402 		enum
403 		{
404 			CMD_TAG_FIELD = 1,
405 			CMD_FLAGS_FIELD = 2,
406 			CMD_ADDRESS_FIELD = 4,
407 			CMD_COUNT_FIELD = 8,
408 			CMD_DATA_FIELD = 16
409 		};
410 
411 		//! \brief
412 		void validateHeader(const boot_command_t * modelHeader, const boot_command_t * testHeader, unsigned whichFields);
413 	};
414 
415 	/*!
416 	 * \brief No operation bootloader command.
417 	 */
418 	class NopCommand : public BootCommand
419 	{
420 	public:
421 		//! \brief Default constructor.
NopCommand()422 		NopCommand() : BootCommand() {}
423 
424 		//! \brief Read the command contents from raw data.
425 		virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
426 
427 		//! \name Header
428 		//@{
429 		//! \brief Returns the tag value for this command.
getTag()430 		virtual uint8_t getTag() const { return ROM_NOP_CMD; }
431 
432 		//! \brief Constructs the header for this boot command.
433 		virtual void fillCommandHeader(boot_command_t & header);
434 		//@}
435 
436 		//! \brief Print out a string representation of the object.
437 		virtual void debugPrint() const;
438 	};
439 
440 	/*!
441 	 * \brief Section tag bootloader command.
442 	 */
443 	class TagCommand : public BootCommand
444 	{
445 	public:
446 		//! \brief Default constructor.
TagCommand()447 		TagCommand() : BootCommand() {}
448 
449 		//! \brief Constructor taking a section object.
450 		TagCommand(const Section & section);
451 
452 		//! \brief Read the command contents from raw data.
453 		virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
454 
455 		//! \name Header
456 		//@{
457 		//! \brief Returns the tag value for this command.
getTag()458 		virtual uint8_t getTag() const { return ROM_TAG_CMD; }
459 
460 		//! \brief Constructs the header for this boot command.
461 		virtual void fillCommandHeader(boot_command_t & header);
462 		//@}
463 
464 		//! \name Field accessors
465 		//@{
setSectionIdentifier(uint32_t identifier)466 		inline void setSectionIdentifier(uint32_t identifier) { m_sectionIdentifier = identifier; }
setSectionLength(uint32_t length)467 		inline void setSectionLength(uint32_t length) { m_sectionLength = length; }
setSectionFlags(uint32_t flags)468 		inline void setSectionFlags(uint32_t flags) { m_sectionFlags = flags; }
setLast(bool isLast)469 		inline void setLast(bool isLast) { m_isLast = isLast; }
470 		//@}
471 
472 		//! \brief Print out a string representation of the object.
473 		virtual void debugPrint() const;
474 
475 	protected:
476 		uint32_t m_sectionIdentifier;	//!< Unique identifier for the section containing this command.
477 		uint32_t m_sectionLength;	//!< Number of cipher blocks this section occupies.
478 		uint32_t m_sectionFlags;	//!< Flags pertaining to this section.
479 		bool m_isLast;	//!< Is this the last tag command?
480 	};
481 
482 	/*!
483 	 * \brief Load data bootloader command.
484 	 */
485 	class LoadCommand : public BootCommand
486 	{
487 	public:
488 		//! \brief Default constructor.
489 		LoadCommand();
490 
491 		//! \brief Constructor.
492 		LoadCommand(uint32_t address, const uint8_t * data, uint32_t length);
493 
494 		//! \brief Read the command contents from raw data.
495 		virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
496 
497 		//! \name Header
498 		//@{
499 		//! \brief Returns the tag value for this command.
getTag()500 		virtual uint8_t getTag() const { return ROM_LOAD_CMD; }
501 
502 		//! \brief Constructs the header for this boot command.
503 		virtual void fillCommandHeader(boot_command_t & header);
504 
505 		//! \brief Sets the load-dcd flag.
setDCD(bool isDCD)506 		inline void setDCD(bool isDCD) { m_loadDCD = isDCD; }
507 		//@}
508 
509 		//! \name Address
510 		//@{
setLoadAddress(uint32_t address)511 		inline void setLoadAddress(uint32_t address) { m_address = address; }
getLoadAddress()512 		inline uint32_t getLoadAddress() const { return m_address; }
513 		//@}
514 
515 		//! \name Load data
516 		//@{
517 		//! \brief Set the data for the command to load.
518 		void setData(const uint8_t * data, uint32_t length);
519 
getData()520 		inline uint8_t * getData() { return m_data; }
getData()521 		inline const uint8_t * getData() const { return m_data; }
getLength()522 		inline uint32_t getLength() const { return m_length; }
523 		//@}
524 
525 		//! \name Data blocks
526 		//@{
527 		//! \brief Returns the number of data cipher blocks that follow this command.
528 		virtual unsigned getDataBlockCount() const;
529 
530 		//! \brief Returns the contents of up to \a maxCount data blocks.
531 		virtual unsigned getDataBlocks(unsigned offset, unsigned maxCount, cipher_block_t * data);
532 		//@}
533 
534 		//! \brief Print out a string representation of the object.
535 		virtual void debugPrint() const;
536 
537 	protected:
538 		smart_array_ptr<uint8_t> m_data;	//!< Pointer to data to load.
539 		uint8_t m_padding[15];	//!< Up to 15 pad bytes may be required.
540 		unsigned m_padCount;	//!< Number of pad bytes.
541 		uint32_t m_length;	//!< Number of bytes to load.
542 		uint32_t m_address;	//!< Address to which data will be loaded.
543 		bool m_loadDCD;	//!< Whether to execute the DCD after loading.
544 
545 		void fillPadding();
546 		uint32_t calculateCRC() const;
547 	};
548 
549 	/*!
550 	 * \brief Pattern fill bootloader command.
551 	 */
552 	class FillCommand : public BootCommand
553 	{
554 	public:
555 		//! \brief Default constructor.
556 		FillCommand();
557 
558 		//! \brief Read the command contents from raw data.
559 		virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
560 
561 		//! \name Header
562 		//@{
563 		//! \brief Returns the tag value for this command.
getTag()564 		virtual uint8_t getTag() const { return ROM_FILL_CMD; }
565 
566 		//! \brief Constructs the header for this boot command.
567 		virtual void fillCommandHeader(boot_command_t & header);
568 		//@}
569 
570 		//! \name Address range
571 		//@{
setAddress(uint32_t address)572 		inline void setAddress(uint32_t address) { m_address = address; };
getAddress()573 		inline uint32_t getAddress() const { return m_address; }
574 
setFillCount(uint32_t count)575 		inline void setFillCount(uint32_t count) { m_count = count; }
getFillCount()576 		inline uint32_t getFillCount() const { return m_count; }
577 		//@}
578 
579 		//! \name Pattern
580 		//@{
581 		void setPattern(uint8_t pattern);
582 		void setPattern(uint16_t pattern);
583 		void setPattern(uint32_t pattern);
584 
getPattern()585 		inline uint32_t getPattern() const { return m_pattern; }
586 		//@}
587 
588 		//! \brief Print out a string representation of the object.
589 		virtual void debugPrint() const;
590 
591 	protected:
592 		uint32_t m_address;	//!< Fill start address.
593 		uint32_t m_count;	//!< Number of bytes to fill.
594 		uint32_t m_pattern;	//!< Fill pattern.
595 	};
596 
597 	/*!
598 	 * \brief Change boot mode bootloader command.
599 	 */
600 	class ModeCommand : public BootCommand
601 	{
602 	public:
603 		//! \brief Default constructor.
ModeCommand()604 		ModeCommand() : BootCommand(), m_mode(0) {}
605 
606 		//! \brief Read the command contents from raw data.
607 		virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
608 
609 		//! \name Header
610 		//@{
611 		//! \brief Returns the tag value for this command.
getTag()612 		virtual uint8_t getTag() const { return ROM_MODE_CMD; }
613 
614 		//! \brief Constructs the header for this boot command.
615 		virtual void fillCommandHeader(boot_command_t & header);
616 		//@}
617 
618 		//! \name Boot mode
619 		//@{
setBootMode(uint32_t mode)620 		inline void setBootMode(uint32_t mode) { m_mode = mode; }
getBootMode()621 		inline uint32_t getBootMode() const { return m_mode; }
622 		//@}
623 
624 		//! \brief Print out a string representation of the object.
625 		virtual void debugPrint() const;
626 
627 	protected:
628 		uint32_t m_mode;	//!< New boot mode.
629 	};
630 
631 	/*!
632 	 * \brief Jump to address bootloader command.
633 	 */
634 	class JumpCommand : public BootCommand
635 	{
636 	public:
637 		//! \brief Default constructor.
JumpCommand()638 		JumpCommand() : BootCommand(), m_address(0), m_argument(0), m_isHAB(false), m_ivtSize(0) {}
639 
640 		//! \brief Read the command contents from raw data.
641 		virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
642 
643 		//! \name Header
644 		//@{
645 		//! \brief Returns the tag value for this command.
getTag()646 		virtual uint8_t getTag() const { return ROM_JUMP_CMD; }
647 
648 		//! \brief Constructs the header for this boot command.
649 		virtual void fillCommandHeader(boot_command_t & header);
650 		//@}
651 
652 		//! \name Accessors
653 		//@{
setAddress(uint32_t address)654 		inline void setAddress(uint32_t address) { m_address = address; }
getAddress()655 		inline uint32_t getAddress() const { return m_address; }
656 
setArgument(uint32_t argument)657 		inline void setArgument(uint32_t argument) { m_argument = argument; }
getArgument()658 		inline uint32_t getArgument() const { return m_argument; }
659 
setIsHAB(bool isHAB)660 		inline void setIsHAB(bool isHAB) { m_isHAB = isHAB; }
isHAB()661 		inline bool isHAB() const { return m_isHAB; }
662 
setIVTSize(uint32_t ivtSize)663 		inline void setIVTSize(uint32_t ivtSize) { m_ivtSize = ivtSize; }
getIVTSize()664 		inline uint32_t getIVTSize() const { return m_ivtSize; }
665 		//@}
666 
667 		//! \brief Print out a string representation of the object.
668 		virtual void debugPrint() const;
669 
670 	protected:
671 		uint32_t m_address;	//!< Address of the code to execute.
672 		uint32_t m_argument;	//!< Sole argument to pass to code.
673 		bool m_isHAB;		//!< Whether this jump/call is a special HAB jump/call. When this flag is set, m_address becomes the IVT address and m_ivtSize is the IVT size.
674 		uint32_t m_ivtSize;	//!< Size of the IVT for a HAB jump/call.
675 	};
676 
677 	/*!
678 	 * \brief Call function bootloader command.
679 	 */
680 	class CallCommand : public JumpCommand
681 	{
682 	public:
683 		//! \brief Default constructor.
CallCommand()684 		CallCommand() : JumpCommand() {}
685 
686 		//! \brief Returns the tag value for this command.
getTag()687 		virtual uint8_t getTag() const { return ROM_CALL_CMD; }
688 
689 		//! \brief Print out a string representation of the object.
690 		virtual void debugPrint() const;
691 	};
692 
693 	/*!
694 	 * \brief Base class for a section of an Encore boot image.
695 	 *
696 	 * Provides methods to manage the unique identifier that all sections have, and
697 	 * to set the boot image object which owns the section. There are also virtual
698 	 * methods to get header flags and fill in the header used in the section
699 	 * table. Subclasses must implement at least fillSectionHeader().
700 	 */
701 	class Section : public CipherBlockGenerator
702 	{
703 	public:
704 		//! \brief Default constructor.
Section()705 		Section() : CipherBlockGenerator(), m_identifier(0), m_image(0), m_alignment(BOOT_IMAGE_MINIMUM_SECTION_ALIGNMENT), m_flags(0), m_leaveUnencrypted(false) {}
706 
707 		//! \brief Constructor taking the unique identifier for this section.
Section(uint32_t identifier)708 		Section(uint32_t identifier) : CipherBlockGenerator(), m_identifier(identifier), m_image(0), m_alignment(BOOT_IMAGE_MINIMUM_SECTION_ALIGNMENT), m_flags(0), m_leaveUnencrypted(false) {}
709 
710 		//! \name Identifier
711 		//@{
setIdentifier(uint32_t identifier)712 		inline void setIdentifier(uint32_t identifier) { m_identifier = identifier; }
getIdentifier()713 		inline uint32_t getIdentifier() const { return m_identifier; }
714 		//@}
715 
716 		//! \name Header
717 		//@{
718 		//! \brief Sets explicit flags for this section.
setFlags(uint32_t flags)719 		virtual void setFlags(uint32_t flags) { m_flags = flags; }
720 
721 		//! \brief Returns the flags for this section.
722 		//!
723 		//! The return value consists of the flags set with setFlags() possibly or-ed
724 		//! with #ROM_SECTION_CLEARTEXT if the section has been set to be left
725 		//! unencrypted.
getFlags()726 		virtual uint32_t getFlags() const { return m_flags | ( m_leaveUnencrypted ? ROM_SECTION_CLEARTEXT : 0); }
727 
728 		//! \brief Pure virtual method to construct the header for this section.
729 		virtual void fillSectionHeader(section_header_t & header);
730 		//@}
731 
732 		//! \name Owner image
733 		//@{
734 		//! \brief Called when the section is added to an image.
setImage(EncoreBootImage * image)735 		void setImage(EncoreBootImage * image) { m_image = image; }
736 
737 		//! \brief Returns a pointer to the image that this section belongs to.
getImage()738 		EncoreBootImage * getImage() const { return m_image; }
739 		//@}
740 
741 		//! \name Alignment
742 		//@{
743 		//! \brief Sets the required alignment in the output file for this section.
744 		void setAlignment(unsigned alignment);
745 
746 		//! \brief Returns the current alignment, the minimum of which will be 16.
getAlignment()747 		unsigned getAlignment() const { return m_alignment; }
748 
749 		//! \brief Computes padding amount for alignment requirement.
750 		unsigned getPadBlockCountForOffset(unsigned offset);
751 		//@}
752 
753 		//! \name Leave unencrypted flag
754 		//@{
755 		//! \brief Sets whether the section will be left unencrypted.
setLeaveUnencrypted(unsigned flag)756 		void setLeaveUnencrypted(unsigned flag) { m_leaveUnencrypted = flag; }
757 
758 		//! \brief Returns true if the section will remain unencrypted.
getLeaveUnencrypted()759 		bool getLeaveUnencrypted() const { return m_leaveUnencrypted; }
760 		//@}
761 
762 	protected:
763 		uint32_t m_identifier;	//!< Unique identifier for this section.
764 		EncoreBootImage * m_image;	//!< The image to which this section belongs.
765 		unsigned m_alignment;	//!< Alignment requirement for the start of this section.
766 		uint32_t m_flags;	//!< Section flags set by the user.
767 		bool m_leaveUnencrypted;	//!< Set to true to prevent this section from being encrypted.
768 	};
769 
770 	/*!
771 	 * \brief A bootable section of an Encore boot image.
772 	 */
773 	class BootSection : public Section
774 	{
775 	public:
776 		typedef std::list<BootCommand*> command_list_t;
777 		typedef command_list_t::iterator iterator_t;
778 		typedef command_list_t::const_iterator const_iterator_t;
779 
780 	public:
781 		//! \brief Default constructor.
BootSection()782 		BootSection() : Section() {}
783 
784 		//! \brief Constructor taking the unique identifier for this section.
BootSection(uint32_t identifier)785 		BootSection(uint32_t identifier) : Section(identifier) {}
786 
787 		//! \brief Destructor.
788 		virtual ~BootSection();
789 
790 		//! \brief Load the section from raw data.
791 		virtual void fillFromData(const cipher_block_t * blocks, unsigned count);
792 
793 		//! \name Header
794 		//@{
795 		//! \brief Returns the flags for this section.
getFlags()796 		virtual uint32_t getFlags() const { return Section::getFlags() | ROM_SECTION_BOOTABLE; }
797 		//@}
798 
799 		//! \name Commands
800 		//@{
801 		//! \brief Append a new command to the section.
802 		//!
803 		//! The section takes ownership of the command and will delete it when
804 		//! the section is destroyed.
addCommand(BootCommand * command)805 		void addCommand(BootCommand * command) { m_commands.push_back(command); }
806 
807 		//! \brief Returns the number of commands in this section, excluding the tag command.
getCommandCount()808 		unsigned getCommandCount() const { return (unsigned)m_commands.size(); }
809 
begin()810 		iterator_t begin() { return m_commands.begin(); }
end()811 		iterator_t end() { return m_commands.end(); }
812 
begin()813 		const_iterator_t begin() const { return m_commands.begin(); }
end()814 		const_iterator_t end() const { return m_commands.end(); }
815 		//@}
816 
817 		//! \name Cipher blocks
818 		//@{
819 		//! \brief Returns the total number of cipher blocks occupied by this section.
820 		virtual unsigned getBlockCount() const;
821 
822 		//! \brief Returns the contents of up to \a maxCount cipher blocks.
823 		virtual unsigned getBlocks(unsigned offset, unsigned maxCount, cipher_block_t * data);
824 		//@}
825 
826 		//! \brief Print out a string representation of the object.
827 		virtual void debugPrint() const;
828 
829 	protected:
830 		command_list_t m_commands;	//!< Commands held in this section.
831 
832 	protected:
833 		//! \brief Remove all commands from the section.
834 		void deleteCommands();
835 	};
836 
837 	/*!
838 	 * \brief A non-bootable section of an Encore boot image.
839 	 */
840 	class DataSection : public Section
841 	{
842 	public:
843 		//! \brief Default constructor.
DataSection()844 		DataSection() : Section(), m_data(), m_length(0) {}
845 
846 		//! \brief Constructor taking the unique identifier for this section.
DataSection(uint32_t identifier)847 		DataSection(uint32_t identifier) : Section(identifier), m_data(), m_length(0) {}
848 
849 		//! \brief Set the data section's contents.
850 		void setData(const uint8_t * data, unsigned length);
851 
852 		//! \brief Set the data section's contents without copying \a data.
853 		void setDataNoCopy(const uint8_t * data, unsigned length);
854 
855 		//! \name Cipher blocks
856 		//@{
857 		//! \brief Returns the total number of cipher blocks occupied by this section.
858 		virtual unsigned getBlockCount() const;
859 
860 		//! \brief Returns the contents of up to \a maxCount cipher blocks.
861 		virtual unsigned getBlocks(unsigned offset, unsigned maxCount, cipher_block_t * data);
862 		//@}
863 
864 		//! \brief Print out a string representation of the object.
865 		virtual void debugPrint() const;
866 
867 	protected:
868 		smart_array_ptr<uint8_t> m_data;	//!< The section's contents.
869 		unsigned m_length;	//!< Number of bytes of data.
870 	};
871 
872 public:
873 	typedef std::list<Section*> section_list_t;				//!< List of image sections.
874 	typedef section_list_t::iterator section_iterator_t;	//!< Iterator over sections.
875 	typedef section_list_t::const_iterator const_section_iterator_t;	//!< Const iterator over sections.
876 
877 	typedef std::vector<AES128Key> key_list_t;				//!< List of KEKs.
878 	typedef key_list_t::iterator key_iterator_t;			//!< Iterator over KEKs.
879 	typedef key_list_t::const_iterator const_key_iterator_t;			//!< Const iterator over KEKs.
880 
881 public:
882 	//! \brief Default constructor.
883 	EncoreBootImage();
884 
885 	//! \brief Destructor.
886 	virtual ~EncoreBootImage();
887 
888 	//! \name Sections
889 	//@{
890 	void addSection(Section * newSection);
sectionCount()891 	inline unsigned sectionCount() const { return (unsigned)m_sections.size(); }
892 
beginSection()893 	inline section_iterator_t beginSection() { return m_sections.begin(); }
endSection()894 	inline section_iterator_t endSection() { return m_sections.end(); }
beginSection()895 	inline const_section_iterator_t beginSection() const { return m_sections.begin(); }
endSection()896 	inline const_section_iterator_t endSection() const { return m_sections.end(); }
897 
898 	section_iterator_t findSection(Section * section);
899 
900 	//! \brief Calculates the starting block number for the given section.
901 	uint32_t getSectionOffset(Section * section);
902 	//@}
903 
904 	//! \name Encryption keys
905 	//@{
addKey(const AES128Key & newKey)906 	inline void addKey(const AES128Key & newKey) { m_keys.push_back(newKey); }
keyCount()907 	inline unsigned keyCount() const { return (unsigned)m_keys.size(); }
908 
beginKeys()909 	inline key_iterator_t beginKeys() { return m_keys.begin(); }
endKeys()910 	inline key_iterator_t endKeys() { return m_keys.end(); }
beginKeys()911 	inline const_key_iterator_t beginKeys() const { return m_keys.begin(); }
endKeys()912 	inline const_key_iterator_t endKeys() const { return m_keys.end(); }
913 
914 	//! \brief The image is encrypted if there is at least one key.
isEncrypted()915 	inline bool isEncrypted() const { return m_keys.size() != 0; }
916 	//@}
917 
918 	//! \name Versions
919 	//@{
920 	virtual void setProductVersion(const version_t & version);
921 	virtual void setComponentVersion(const version_t & version);
922 	//@}
923 
924 	//! \name Flags
925 	//@{
setFlags(uint16_t flags)926 	inline void setFlags(uint16_t flags) { m_headerFlags = flags; }
getFlags()927 	inline uint32_t getFlags() const { return m_headerFlags; }
928 	//@}
929 
930 	//! \brief Specify the drive tag to be set in the output file header.
setDriveTag(uint16_t tag)931 	virtual void setDriveTag(uint16_t tag) { m_driveTag = tag; }
932 
933 	//! \brief Calculates the total number of cipher blocks the image consumes.
934 	uint32_t getImageSize();
935 
936 	//! \brief Returns the preferred ".sb" extension for Encore boot images.
getFileExtension()937 	virtual std::string getFileExtension() const { return ".sb"; }
938 
939 	//! \name Output
940 	//@{
941 	//! \brief Write the boot image to an output stream.
942 	virtual void writeToStream(std::ostream & stream);
943 	//@}
944 
945 	//! \brief Print out a string representation of the object.
946 	virtual void debugPrint() const;
947 
948 protected:
949 	uint16_t m_headerFlags;	//!< Flags field in the boot image header.
950 	version_t m_productVersion;		//!< Product version.
951 	version_t m_componentVersion;	//!< Component version.
952 	uint16_t m_driveTag;	//!< System drive tag for this boot image.
953 	section_list_t m_sections;	//!< Sections contained in this image.
954 	key_list_t m_keys;	//!< List of key encryption keys. If empty, the image is unencrypted.
955 	AES128Key m_sessionKey;	//!< Session key we're using.
956 
957 	void prepareImageHeader(boot_image_header_t & header);
958 	uint64_t getTimestamp();
959 	Section * findFirstBootableSection();
960 	unsigned getPadBlockCountForSection(Section * section, unsigned offset);
961 };
962 
963 }; // namespace elftosb
964 
965 #endif // _EncoreBootImage_h_
966