2 * File: EncoreBootImage.h
4 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5 * See included license file for license details.
7 #if !defined(_EncoreBootImage_h_)
8 #define _EncoreBootImage_h_
16 #include "BootImage.h"
18 #include "smart_ptr.h"
20 #include "StExecutableImage.h"
25 //! An AES-128 cipher block is 16 bytes.
26 typedef uint8_t cipher_block_t[16];
28 //! A SHA-1 digest is 160 bits, or 20 bytes.
29 typedef uint8_t sha1_digest_t[20];
31 //! Unique identifier type for a section.
32 typedef uint32_t section_id_t;
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; }
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); }
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)); }
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; }
52 * \brief Class to manage Encore boot image files.
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.
58 * A boot image is composed of the following regions:
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.
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.
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.
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.
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
90 class EncoreBootImage : public BootImage
93 //! \brief Flag constants for the m_flags field of #elftosb::EncoreBootImage::boot_image_header_t.
96 ROM_DISPLAY_PROGRESS = (1 << 0), //!< Print progress reports.
97 ROM_VERBOSE_PROGRESS = (1 << 1) //!< Progress reports are verbose.
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.
108 //! Minimum alignment for a section is 16 bytes.
109 BOOT_IMAGE_MINIMUM_SECTION_ALIGNMENT = sizeof(cipher_block_t)
112 // All of these structures are packed to byte alignment in order to match
113 // the structure on disk.
116 //! \brief Header for the entire boot image.
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
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.
127 //! The DEK dictionary, section table, and each section data region must all start on
128 //! cipher block boundaries.
130 //! This header is not encrypted in the image file.
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
139 sha1_digest_t m_digest; //!< SHA-1 digest of image header. Also used as the crypto IV.
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.
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.
167 //! \brief Entry in #elftosb::EncoreBootImage::dek_dictionary_t.
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
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.
177 //! \brief The DEK dictionary always follows the image header, in the next cipher block.
178 struct dek_dictionary_t
180 dek_dictionary_entry_t m_entries[1];
183 //! \brief Section flags constants for the m_flags field of #elftosb::EncoreBootImage::section_header_t.
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.
190 //! \brief Information about each section, held in the section table.
191 //! \see section_table_t
192 struct section_header_t
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.
200 //! \brief An index of all sections within the boot image.
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.
206 //! Sections are ordered as they appear in this table, but are identified by the
207 //! #elftosb::EncoreBootImage::section_header_t::m_tag.
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.
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
220 section_header_t m_sections[1]; //!< The table entries.
223 //! \brief Structure for a Piano bootloader command.
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.
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
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.
244 //! \brief Bootloader command tag constants.
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.
256 //! \brief Flag field constants for #ROM_TAG_CMD.
259 ROM_LAST_TAG = (1 << 0) //!< This tag command is the last one in the image.
262 //! \brief Flag field constants for #ROM_LOAD_CMD.
265 ROM_LOAD_DCD = (1 << 0) //!< Execute the DCD after loading completes.
268 //! \brief Flag field constants for #ROM_FILL_CMD.
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.
276 //! brief Flag field constants for #ROM_JUMP_CMD and #ROM_CALL_CMD.
279 ROM_HAB_EXEC = (1 << 0) //!< Changes jump or call command to a HAB jump or call.
283 // Forward declaration.
287 * \brief Base class for objects that produce cipher blocks.
289 class CipherBlockGenerator
293 //! \name Cipher blocks
295 //! \brief Returns the total number of cipher blocks.
297 //! The default implementation returns 0, indicating that no blocks are
299 virtual unsigned getBlockCount() const { return 0; }
301 //! \brief Returns the contents of up to \a maxCount cipher blocks.
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.
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.
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; }
320 //! \brief Print out a string representation of the object.
321 virtual void debugPrint() const {}
325 * \brief Abstract base class for all bootloader commands.
327 class BootCommand : public CipherBlockGenerator
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);
334 //! \brief Default constructor.
335 BootCommand() : CipherBlockGenerator() {}
337 //! \brief Destructor.
338 virtual ~BootCommand() {}
340 //! \brief Read the command contents from raw data.
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.
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
352 virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed)=0;
356 //! \brief Pure virtual method to return the tag value for this command.
357 virtual uint8_t getTag() const = 0;
359 //! \brief Pure virtual method to construct the header for this boot command.
360 virtual void fillCommandHeader(boot_command_t & header) = 0;
362 //! \brief Calculates the checksum for the given command header.
363 virtual uint8_t calculateChecksum(const boot_command_t & header);
366 //! \name Cipher blocks
368 //! \brief Returns the total number of cipher blocks.
369 virtual unsigned getBlockCount() const;
371 //! \brief Returns the contents of up to \a maxCount cipher blocks.
372 virtual unsigned getBlocks(unsigned offset, unsigned maxCount, cipher_block_t * data);
375 //! \name Data blocks
377 //! \brief Returns the number of data cipher blocks that follow this command.
379 //! The default implementation returns 0, indicating that no data blocks are
381 virtual unsigned getDataBlockCount() const { return 0; }
383 //! \brief Returns the contents of up to \a maxCount data blocks.
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.
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.
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; }
403 //! The flag bit values for the \a whichFields parameter of validateHeader().
408 CMD_ADDRESS_FIELD = 4,
414 void validateHeader(const boot_command_t * modelHeader, const boot_command_t * testHeader, unsigned whichFields);
418 * \brief No operation bootloader command.
420 class NopCommand : public BootCommand
423 //! \brief Default constructor.
424 NopCommand() : BootCommand() {}
426 //! \brief Read the command contents from raw data.
427 virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
431 //! \brief Returns the tag value for this command.
432 virtual uint8_t getTag() const { return ROM_NOP_CMD; }
434 //! \brief Constructs the header for this boot command.
435 virtual void fillCommandHeader(boot_command_t & header);
438 //! \brief Print out a string representation of the object.
439 virtual void debugPrint() const;
443 * \brief Section tag bootloader command.
445 class TagCommand : public BootCommand
448 //! \brief Default constructor.
449 TagCommand() : BootCommand() {}
451 //! \brief Constructor taking a section object.
452 TagCommand(const Section & section);
454 //! \brief Read the command contents from raw data.
455 virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
459 //! \brief Returns the tag value for this command.
460 virtual uint8_t getTag() const { return ROM_TAG_CMD; }
462 //! \brief Constructs the header for this boot command.
463 virtual void fillCommandHeader(boot_command_t & header);
466 //! \name Field accessors
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; }
474 //! \brief Print out a string representation of the object.
475 virtual void debugPrint() const;
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?
485 * \brief Load data bootloader command.
487 class LoadCommand : public BootCommand
490 //! \brief Default constructor.
493 //! \brief Constructor.
494 LoadCommand(uint32_t address, const uint8_t * data, uint32_t length);
496 //! \brief Read the command contents from raw data.
497 virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
501 //! \brief Returns the tag value for this command.
502 virtual uint8_t getTag() const { return ROM_LOAD_CMD; }
504 //! \brief Constructs the header for this boot command.
505 virtual void fillCommandHeader(boot_command_t & header);
507 //! \brief Sets the load-dcd flag.
508 inline void setDCD(bool isDCD) { m_loadDCD = isDCD; }
513 inline void setLoadAddress(uint32_t address) { m_address = address; }
514 inline uint32_t getLoadAddress() const { return m_address; }
519 //! \brief Set the data for the command to load.
520 void setData(const uint8_t * data, uint32_t length);
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; }
527 //! \name Data blocks
529 //! \brief Returns the number of data cipher blocks that follow this command.
530 virtual unsigned getDataBlockCount() const;
532 //! \brief Returns the contents of up to \a maxCount data blocks.
533 virtual unsigned getDataBlocks(unsigned offset, unsigned maxCount, cipher_block_t * data);
536 //! \brief Print out a string representation of the object.
537 virtual void debugPrint() const;
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.
548 uint32_t calculateCRC() const;
552 * \brief Pattern fill bootloader command.
554 class FillCommand : public BootCommand
557 //! \brief Default constructor.
560 //! \brief Read the command contents from raw data.
561 virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
565 //! \brief Returns the tag value for this command.
566 virtual uint8_t getTag() const { return ROM_FILL_CMD; }
568 //! \brief Constructs the header for this boot command.
569 virtual void fillCommandHeader(boot_command_t & header);
572 //! \name Address range
574 inline void setAddress(uint32_t address) { m_address = address; };
575 inline uint32_t getAddress() const { return m_address; }
577 inline void setFillCount(uint32_t count) { m_count = count; }
578 inline uint32_t getFillCount() const { return m_count; }
583 void setPattern(uint8_t pattern);
584 void setPattern(uint16_t pattern);
585 void setPattern(uint32_t pattern);
587 inline uint32_t getPattern() const { return m_pattern; }
590 //! \brief Print out a string representation of the object.
591 virtual void debugPrint() const;
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.
600 * \brief Change boot mode bootloader command.
602 class ModeCommand : public BootCommand
605 //! \brief Default constructor.
606 ModeCommand() : BootCommand(), m_mode(0) {}
608 //! \brief Read the command contents from raw data.
609 virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
613 //! \brief Returns the tag value for this command.
614 virtual uint8_t getTag() const { return ROM_MODE_CMD; }
616 //! \brief Constructs the header for this boot command.
617 virtual void fillCommandHeader(boot_command_t & header);
622 inline void setBootMode(uint32_t mode) { m_mode = mode; }
623 inline uint32_t getBootMode() const { return m_mode; }
626 //! \brief Print out a string representation of the object.
627 virtual void debugPrint() const;
630 uint32_t m_mode; //!< New boot mode.
634 * \brief Jump to address bootloader command.
636 class JumpCommand : public BootCommand
639 //! \brief Default constructor.
640 JumpCommand() : BootCommand(), m_address(0), m_argument(0), m_isHAB(false), m_ivtSize(0) {}
642 //! \brief Read the command contents from raw data.
643 virtual void initFromData(const cipher_block_t * blocks, unsigned count, unsigned * consumed);
647 //! \brief Returns the tag value for this command.
648 virtual uint8_t getTag() const { return ROM_JUMP_CMD; }
650 //! \brief Constructs the header for this boot command.
651 virtual void fillCommandHeader(boot_command_t & header);
656 inline void setAddress(uint32_t address) { m_address = address; }
657 inline uint32_t getAddress() const { return m_address; }
659 inline void setArgument(uint32_t argument) { m_argument = argument; }
660 inline uint32_t getArgument() const { return m_argument; }
662 inline void setIsHAB(bool isHAB) { m_isHAB = isHAB; }
663 inline bool isHAB() const { return m_isHAB; }
665 inline void setIVTSize(uint32_t ivtSize) { m_ivtSize = ivtSize; }
666 inline uint32_t getIVTSize() const { return m_ivtSize; }
669 //! \brief Print out a string representation of the object.
670 virtual void debugPrint() const;
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.
680 * \brief Call function bootloader command.
682 class CallCommand : public JumpCommand
685 //! \brief Default constructor.
686 CallCommand() : JumpCommand() {}
688 //! \brief Returns the tag value for this command.
689 virtual uint8_t getTag() const { return ROM_CALL_CMD; }
691 //! \brief Print out a string representation of the object.
692 virtual void debugPrint() const;
696 * \brief Base class for a section of an Encore boot image.
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().
703 class Section : public CipherBlockGenerator
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) {}
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) {}
714 inline void setIdentifier(uint32_t identifier) { m_identifier = identifier; }
715 inline uint32_t getIdentifier() const { return m_identifier; }
720 //! \brief Sets explicit flags for this section.
721 virtual void setFlags(uint32_t flags) { m_flags = flags; }
723 //! \brief Returns the flags for this section.
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
728 virtual uint32_t getFlags() const { return m_flags | ( m_leaveUnencrypted ? ROM_SECTION_CLEARTEXT : 0); }
730 //! \brief Pure virtual method to construct the header for this section.
731 virtual void fillSectionHeader(section_header_t & header);
734 //! \name Owner image
736 //! \brief Called when the section is added to an image.
737 void setImage(EncoreBootImage * image) { m_image = image; }
739 //! \brief Returns a pointer to the image that this section belongs to.
740 EncoreBootImage * getImage() const { return m_image; }
745 //! \brief Sets the required alignment in the output file for this section.
746 void setAlignment(unsigned alignment);
748 //! \brief Returns the current alignment, the minimum of which will be 16.
749 unsigned getAlignment() const { return m_alignment; }
751 //! \brief Computes padding amount for alignment requirement.
752 unsigned getPadBlockCountForOffset(unsigned offset);
755 //! \name Leave unencrypted flag
757 //! \brief Sets whether the section will be left unencrypted.
758 void setLeaveUnencrypted(unsigned flag) { m_leaveUnencrypted = flag; }
760 //! \brief Returns true if the section will remain unencrypted.
761 bool getLeaveUnencrypted() const { return m_leaveUnencrypted; }
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.
773 * \brief A bootable section of an Encore boot image.
775 class BootSection : public Section
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;
783 //! \brief Default constructor.
784 BootSection() : Section() {}
786 //! \brief Constructor taking the unique identifier for this section.
787 BootSection(uint32_t identifier) : Section(identifier) {}
789 //! \brief Destructor.
790 virtual ~BootSection();
792 //! \brief Load the section from raw data.
793 virtual void fillFromData(const cipher_block_t * blocks, unsigned count);
797 //! \brief Returns the flags for this section.
798 virtual uint32_t getFlags() const { return Section::getFlags() | ROM_SECTION_BOOTABLE; }
803 //! \brief Append a new command to the section.
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); }
809 //! \brief Returns the number of commands in this section, excluding the tag command.
810 unsigned getCommandCount() const { return (unsigned)m_commands.size(); }
812 iterator_t begin() { return m_commands.begin(); }
813 iterator_t end() { return m_commands.end(); }
815 const_iterator_t begin() const { return m_commands.begin(); }
816 const_iterator_t end() const { return m_commands.end(); }
819 //! \name Cipher blocks
821 //! \brief Returns the total number of cipher blocks occupied by this section.
822 virtual unsigned getBlockCount() const;
824 //! \brief Returns the contents of up to \a maxCount cipher blocks.
825 virtual unsigned getBlocks(unsigned offset, unsigned maxCount, cipher_block_t * data);
828 //! \brief Print out a string representation of the object.
829 virtual void debugPrint() const;
832 command_list_t m_commands; //!< Commands held in this section.
835 //! \brief Remove all commands from the section.
836 void deleteCommands();
840 * \brief A non-bootable section of an Encore boot image.
842 class DataSection : public Section
845 //! \brief Default constructor.
846 DataSection() : Section(), m_data(), m_length(0) {}
848 //! \brief Constructor taking the unique identifier for this section.
849 DataSection(uint32_t identifier) : Section(identifier), m_data(), m_length(0) {}
851 //! \brief Set the data section's contents.
852 void setData(const uint8_t * data, unsigned length);
854 //! \brief Set the data section's contents without copying \a data.
855 void setDataNoCopy(const uint8_t * data, unsigned length);
857 //! \name Cipher blocks
859 //! \brief Returns the total number of cipher blocks occupied by this section.
860 virtual unsigned getBlockCount() const;
862 //! \brief Returns the contents of up to \a maxCount cipher blocks.
863 virtual unsigned getBlocks(unsigned offset, unsigned maxCount, cipher_block_t * data);
866 //! \brief Print out a string representation of the object.
867 virtual void debugPrint() const;
870 smart_array_ptr<uint8_t> m_data; //!< The section's contents.
871 unsigned m_length; //!< Number of bytes of data.
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.
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.
884 //! \brief Default constructor.
887 //! \brief Destructor.
888 virtual ~EncoreBootImage();
892 void addSection(Section * newSection);
893 inline unsigned sectionCount() const { return (unsigned)m_sections.size(); }
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(); }
900 section_iterator_t findSection(Section * section);
902 //! \brief Calculates the starting block number for the given section.
903 uint32_t getSectionOffset(Section * section);
906 //! \name Encryption keys
908 inline void addKey(const AES128Key & newKey) { m_keys.push_back(newKey); }
909 inline unsigned keyCount() const { return (unsigned)m_keys.size(); }
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(); }
916 //! \brief The image is encrypted if there is at least one key.
917 inline bool isEncrypted() const { return m_keys.size() != 0; }
922 virtual void setProductVersion(const version_t & version);
923 virtual void setComponentVersion(const version_t & version);
928 inline void setFlags(uint16_t flags) { m_headerFlags = flags; }
929 inline uint32_t getFlags() const { return m_headerFlags; }
932 //! \brief Specify the drive tag to be set in the output file header.
933 virtual void setDriveTag(uint16_t tag) { m_driveTag = tag; }
935 //! \brief Calculates the total number of cipher blocks the image consumes.
936 uint32_t getImageSize();
938 //! \brief Returns the preferred ".sb" extension for Encore boot images.
939 virtual std::string getFileExtension() const { return ".sb"; }
943 //! \brief Write the boot image to an output stream.
944 virtual void writeToStream(std::ostream & stream);
947 //! \brief Print out a string representation of the object.
948 virtual void debugPrint() const;
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.
959 void prepareImageHeader(boot_image_header_t & header);
960 uint64_t getTimestamp();
961 Section * findFirstBootableSection();
962 unsigned getPadBlockCountForSection(Section * section, unsigned offset);
965 }; // namespace elftosb
967 #endif // _EncoreBootImage_h_