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