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