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