Commit bce8837071617a13f8e28f60400ee826b3f8a308

Authored by Marek Vasut
Committed by Stefano Babic
1 parent b83c709e8d

ARM: mxs: tools: Add mkimage support for MXS bootstream

Add mkimage support for generating and verifying MXS bootstream.
The implementation here is mostly a glue code between MXSSB v0.4
and mkimage, but the long-term goal is to rectify this and merge
MXSSB with mkimage more tightly. Once this code is properly in
U-Boot, MXSSB shall be deprecated in favor of mkimage-mxsimage
support.

Note that the mxsimage generator needs libcrypto from OpenSSL, I
therefore enabled the libcrypto/libssl unconditionally.

MXSSB: http://git.denx.de/?p=mxssb.git;a=summary

The code is based on research presented at:
http://www.rockbox.org/wiki/SbFileFormat

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Tom Rini <trini@ti.com>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Otavio Salvador <otavio@ossystems.com.br>

Showing 11 changed files with 2772 additions and 0 deletions Side-by-side Diff

arch/arm/cpu/arm926ejs/mxs/mxsimage.mx23.cfg
  1 +SECTION 0x0 BOOTABLE
  2 + TAG LAST
  3 + LOAD 0x0 spl/u-boot-spl.bin
  4 + CALL 0x14 0x0
  5 + LOAD 0x40000100 u-boot.bin
  6 + CALL 0x40000100 0x0
arch/arm/cpu/arm926ejs/mxs/mxsimage.mx28.cfg
  1 +SECTION 0x0 BOOTABLE
  2 + TAG LAST
  3 + LOAD 0x0 spl/u-boot-spl.bin
  4 + LOAD IVT 0x8000 0x14
  5 + CALL HAB 0x8000 0x0
  6 + LOAD 0x40000100 u-boot.bin
  7 + LOAD IVT 0x8000 0x40000100
  8 + CALL HAB 0x8000 0x0
... ... @@ -135,6 +135,7 @@
135 135 { IH_TYPE_SCRIPT, "script", "Script", },
136 136 { IH_TYPE_STANDALONE, "standalone", "Standalone Program", },
137 137 { IH_TYPE_UBLIMAGE, "ublimage", "Davinci UBL image",},
  138 + { IH_TYPE_MXSIMAGE, "mxsimage", "Freescale MXS Boot Image",},
138 139 { -1, "", "", },
139 140 };
140 141  
... ... @@ -194,6 +194,15 @@
194 194 endif
195 195  
196 196 # TODO(sjg@chromium.org): Is this correct on Mac OS?
  197 +
  198 +# MXSImage needs LibSSL
  199 +ifneq ($(CONFIG_MX23)$(CONFIG_MX28),)
  200 +HOSTLIBS += -lssl -lcrypto
  201 +# Add CONFIG_MXS into host CFLAGS, so we can check whether or not register
  202 +# the mxsimage support within tools/mxsimage.c .
  203 +HOSTCFLAGS += -DCONFIG_MXS
  204 +endif
  205 +
197 206 ifdef CONFIG_FIT_SIGNATURE
198 207 HOSTLIBS += -lssl -lcrypto
199 208  
  1 +Freescale i.MX233/i.MX28 SB image generator via mkimage
  2 +=======================================================
  3 +
  4 +This tool allows user to produce SB BootStream encrypted with a zero key.
  5 +Such a BootStream is then bootable on i.MX23/i.MX28.
  6 +
  7 +Usage -- producing image:
  8 +=========================
  9 +The mxsimage tool is targeted to be a simple replacement for the elftosb2 .
  10 +To generate an image, write an image configuration file and run:
  11 +
  12 + mkimage -A arm -O u-boot -T mxsimage -n <path to configuration file> \
  13 + <output bootstream file>
  14 +
  15 +The output bootstream file is usually using the .sb file extension. Note
  16 +that the example configuration files for producing bootable BootStream with
  17 +the U-Boot bootloader can be found under arch/arm/boot/cpu/arm926ejs/mxs/
  18 +directory. See the following files:
  19 +
  20 + mxsimage.mx23.cfg -- This is an example configuration for i.MX23
  21 + mxsimage.mx28.cfg -- This is an example configuration for i.MX28
  22 +
  23 +Each configuration file uses very simple instruction semantics and a few
  24 +additional rules have to be followed so that a useful image can be produced.
  25 +These semantics and rules will be outlined now.
  26 +
  27 +- Each line of the configuration file contains exactly one instruction.
  28 +- Every numeric value must be encoded in hexadecimal and in format 0xabcdef12 .
  29 +- The configuration file is a concatenation of blocks called "sections" and
  30 + optionally "DCD blocks" (see below).
  31 + - Each "section" is started by the "SECTION" instruction.
  32 + - The "SECTION" instruction has the following semantics:
  33 +
  34 + SECTION u32_section_number [BOOTABLE]
  35 + - u32_section_number :: User-selected ID of the section
  36 + - BOOTABLE :: Sets the section as bootable
  37 +
  38 + - A bootable section is one from which the BootROM starts executing
  39 + subsequent instructions or code. Exactly one section must be selected
  40 + as bootable, usually the one containing the instructions and data to
  41 + load the bootloader.
  42 +
  43 + - A "SECTION" must be immediatelly followed by a "TAG" instruction.
  44 + - The "TAG" instruction has the following semantics:
  45 +
  46 + TAG [LAST]
  47 + - LAST :: Flag denoting the last section in the file
  48 +
  49 + - After a "TAG" unstruction, any of the following instructions may follow
  50 + in any order and any quantity:
  51 +
  52 + NOOP
  53 + - This instruction does nothing
  54 +
  55 + LOAD u32_address string_filename
  56 + - Instructs the BootROM to load file pointed by "string_filename" onto
  57 + address "u32_address".
  58 +
  59 + LOAD IVT u32_address u32_IVT_entry_point
  60 + - Crafts and loads IVT onto address "u32_address" with the entry point
  61 + of u32_IVT_entry_point.
  62 + - i.MX28-specific instruction!
  63 +
  64 + LOAD DCD u32_address u32_DCD_block_ID
  65 + - Loads the DCD block with ID "u32_DCD_block_ID" onto address
  66 + "u32_address" and executes the contents of this DCD block
  67 + - i.MX28-specific instruction!
  68 +
  69 + FILL u32_address u32_pattern u32_length
  70 + - Starts to write memory from addres "u32_address" with a pattern
  71 + specified by "u32_pattern". Writes exactly "u32_length" bytes of the
  72 + pattern.
  73 +
  74 + JUMP [HAB] u32_address [u32_r0_arg]
  75 + - Jumps onto memory address specified by "u32_address" by setting this
  76 + address in PT. The BootROM will pass the "u32_r0_arg" value in ARM
  77 + register "r0" to the executed code if this option is specified.
  78 + Otherwise, ARM register "r0" will default to value 0x00000000. The
  79 + optional "HAB" flag is i.MX28-specific flag turning on the HAB boot.
  80 +
  81 + CALL [HAB] u32_address [u32_r0_arg]
  82 + - See JUMP instruction above, as the operation is exactly the same with
  83 + one difference. The CALL instruction does allow returning into the
  84 + BootROM from the executed code. U-Boot makes use of this in it's SPL
  85 + code.
  86 +
  87 + MODE string_mode
  88 + - Restart the CPU and start booting from device specified by the
  89 + "string_mode" argument. The "string_mode" differs for each CPU
  90 + and can be:
  91 + i.MX23, string_mode = USB/I2C/SPI1_FLASH/SPI2_FLASH/NAND_BCH
  92 + JTAG/SPI3_EEPROM/SD_SSP0/SD_SSP1
  93 + i.MX28, string_mode = USB/I2C/SPI2_FLASH/SPI3_FLASH/NAND_BCH
  94 + JTAG/SPI2_EEPROM/SD_SSP0/SD_SSP1
  95 +
  96 + - An optional "DCD" blocks can be added at the begining of the configuration
  97 + file. Note that the DCD is only supported on i.MX28.
  98 + - The DCD blocks must be inserted before the first "section" in the
  99 + configuration file.
  100 + - The DCD block has the following semantics:
  101 +
  102 + DCD u32_DCD_block_ID
  103 + - u32_DCD_block_ID :: The ID number of the DCD block, must match
  104 + the ID number used by "LOAD DCD" instruction.
  105 +
  106 + - The DCD block must be followed by one of the following instructions. All
  107 + of the instructions operate either on 1, 2 or 4 bytes. This is selected by
  108 + the 'n' suffix of the instruction:
  109 +
  110 + WRITE.n u32_address u32_value
  111 + - Write the "u32_value" to the "u32_address" address.
  112 +
  113 + ORR.n u32_address u32_value
  114 + - Read the "u32_address", perform a bitwise-OR with the "u32_value" and
  115 + write the result back to "u32_address".
  116 +
  117 + ANDC.n u32_address u32_value
  118 + - Read the "u32_address", perform a bitwise-AND with the complement of
  119 + "u32_value" and write the result back to "u32_address".
  120 +
  121 + EQZ.n u32_address u32_count
  122 + - Read the "u32_address" at most "u32_count" times and test if the value
  123 + read is zero. If it is, break the loop earlier.
  124 +
  125 + NEZ.n u32_address u32_count
  126 + - Read the "u32_address" at most "u32_count" times and test if the value
  127 + read is non-zero. If it is, break the loop earlier.
  128 +
  129 + EQ.n u32_address u32_mask
  130 + - Read the "u32_address" in a loop and test if the result masked with
  131 + "u32_mask" equals the "u32_mask". If the values are equal, break the
  132 + reading loop.
  133 +
  134 + NEQ.n u32_address u32_mask
  135 + - Read the "u32_address" in a loop and test if the result masked with
  136 + "u32_mask" does not equal the "u32_mask". If the values are not equal,
  137 + break the reading loop.
  138 +
  139 + NOOP
  140 + - This instruction does nothing.
  141 +
  142 +- If the verbose output from the BootROM is enabled, the BootROM will produce a
  143 + letter on the Debug UART for each instruction it started processing. Here is a
  144 + mapping between the above instructions and the BootROM verbose output:
  145 +
  146 + H -- SB Image header loaded
  147 + T -- TAG instruction
  148 + N -- NOOP instruction
  149 + L -- LOAD instruction
  150 + F -- FILL instruction
  151 + J -- JUMP instruction
  152 + C -- CALL instruction
  153 + M -- MODE instruction
  154 +
  155 +Usage -- verifying image:
  156 +=========================
  157 +
  158 +The mxsimage can also verify and dump contents of an image. Use the following
  159 +syntax to verify and dump contents of an image:
  160 +
  161 + mkimage -l <input bootstream file>
  162 +
  163 +This will output all the information from the SB image header and all the
  164 +instructions contained in the SB image. It will also check if the various
  165 +checksums in the SB image are correct.
... ... @@ -212,6 +212,7 @@
212 212 #define IH_TYPE_AISIMAGE 13 /* TI Davinci AIS Image */
213 213 #define IH_TYPE_KERNEL_NOLOAD 14 /* OS Kernel Image, can run from any load address */
214 214 #define IH_TYPE_PBLIMAGE 15 /* Freescale PBL Boot Image */
  215 +#define IH_TYPE_MXSIMAGE 16 /* Freescale MXSBoot Image */
215 216  
216 217 /*
217 218 * Compression Types
... ... @@ -83,6 +83,7 @@
83 83 NOPED_OBJ_FILES-y += kwbimage.o
84 84 NOPED_OBJ_FILES-y += pblimage.o
85 85 NOPED_OBJ_FILES-y += imximage.o
  86 +NOPED_OBJ_FILES-y += mxsimage.o
86 87 NOPED_OBJ_FILES-y += image-host.o
87 88 NOPED_OBJ_FILES-y += omapimage.o
88 89 NOPED_OBJ_FILES-y += mkenvimage.o
... ... @@ -209,6 +210,7 @@
209 210 $(obj)image-host.o \
210 211 $(FIT_SIG_OBJS) \
211 212 $(obj)imximage.o \
  213 + $(obj)mxsimage.o \
212 214 $(obj)kwbimage.o \
213 215 $(obj)pblimage.o \
214 216 $(obj)md5.o \
... ... @@ -145,6 +145,8 @@
145 145 init_kwb_image_type ();
146 146 /* Init Freescale imx Boot image generation/list support */
147 147 init_imx_image_type ();
  148 + /* Init Freescale mxs Boot image generation/list support */
  149 + init_mxs_image_type();
148 150 /* Init FIT image generation/list support */
149 151 init_fit_image_type ();
150 152 /* Init TI OMAP Boot image generation/list support */
... ... @@ -161,6 +161,7 @@
161 161 void init_ais_image_type(void);
162 162 void init_kwb_image_type (void);
163 163 void init_imx_image_type (void);
  164 +void init_mxs_image_type(void);
164 165 void init_default_image_type (void);
165 166 void init_fit_image_type (void);
166 167 void init_ubl_image_type(void);
Changes suppressed. Click to show
  1 +/*
  2 + * Freescale i.MX23/i.MX28 SB image generator
  3 + *
  4 + * Copyright (C) 2012-2013 Marek Vasut <marex@denx.de>
  5 + *
  6 + * SPDX-License-Identifier: GPL-2.0+
  7 + */
  8 +
  9 +#ifdef CONFIG_MXS
  10 +
  11 +#include <errno.h>
  12 +#include <fcntl.h>
  13 +#include <stdio.h>
  14 +#include <string.h>
  15 +#include <unistd.h>
  16 +#include <limits.h>
  17 +
  18 +#include <openssl/evp.h>
  19 +
  20 +#include "mkimage.h"
  21 +#include "mxsimage.h"
  22 +#include <image.h>
  23 +
  24 +
  25 +/*
  26 + * DCD block
  27 + * |-Write to address command block
  28 + * | 0xf00 == 0xf33d
  29 + * | 0xba2 == 0xb33f
  30 + * |-ORR address with mask command block
  31 + * | 0xf00 |= 0x1337
  32 + * |-Write to address command block
  33 + * | 0xba2 == 0xd00d
  34 + * :
  35 + */
  36 +#define SB_HAB_DCD_WRITE 0xccUL
  37 +#define SB_HAB_DCD_CHECK 0xcfUL
  38 +#define SB_HAB_DCD_NOOP 0xc0UL
  39 +#define SB_HAB_DCD_MASK_BIT (1 << 3)
  40 +#define SB_HAB_DCD_SET_BIT (1 << 4)
  41 +
  42 +/* Addr.n = Value.n */
  43 +#define SB_DCD_WRITE \
  44 + (SB_HAB_DCD_WRITE << 24)
  45 +/* Addr.n &= ~Value.n */
  46 +#define SB_DCD_ANDC \
  47 + ((SB_HAB_DCD_WRITE << 24) | SB_HAB_DCD_SET_BIT)
  48 +/* Addr.n |= Value.n */
  49 +#define SB_DCD_ORR \
  50 + ((SB_HAB_DCD_WRITE << 24) | SB_HAB_DCD_SET_BIT | SB_HAB_DCD_MASK_BIT)
  51 +/* (Addr.n & Value.n) == 0 */
  52 +#define SB_DCD_CHK_EQZ \
  53 + (SB_HAB_DCD_CHECK << 24)
  54 +/* (Addr.n & Value.n) == Value.n */
  55 +#define SB_DCD_CHK_EQ \
  56 + ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_SET_BIT)
  57 +/* (Addr.n & Value.n) != Value.n */
  58 +#define SB_DCD_CHK_NEQ \
  59 + ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_MASK_BIT)
  60 +/* (Addr.n & Value.n) != 0 */
  61 +#define SB_DCD_CHK_NEZ \
  62 + ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_SET_BIT | SB_HAB_DCD_MASK_BIT)
  63 +/* NOP */
  64 +#define SB_DCD_NOOP \
  65 + (SB_HAB_DCD_NOOP << 24)
  66 +
  67 +struct sb_dcd_ctx {
  68 + struct sb_dcd_ctx *dcd;
  69 +
  70 + uint32_t id;
  71 +
  72 + /* The DCD block. */
  73 + uint32_t *payload;
  74 + /* Size of the whole DCD block. */
  75 + uint32_t size;
  76 +
  77 + /* Pointer to previous DCD command block. */
  78 + uint32_t *prev_dcd_head;
  79 +};
  80 +
  81 +/*
  82 + * IMAGE
  83 + * |-SECTION
  84 + * | |-CMD
  85 + * | |-CMD
  86 + * | `-CMD
  87 + * |-SECTION
  88 + * | |-CMD
  89 + * : :
  90 + */
  91 +struct sb_cmd_list {
  92 + char *cmd;
  93 + size_t len;
  94 + unsigned int lineno;
  95 +};
  96 +
  97 +struct sb_cmd_ctx {
  98 + uint32_t size;
  99 +
  100 + struct sb_cmd_ctx *cmd;
  101 +
  102 + uint8_t *data;
  103 + uint32_t length;
  104 +
  105 + struct sb_command payload;
  106 + struct sb_command c_payload;
  107 +};
  108 +
  109 +struct sb_section_ctx {
  110 + uint32_t size;
  111 +
  112 + /* Section flags */
  113 + unsigned int boot:1;
  114 +
  115 + struct sb_section_ctx *sect;
  116 +
  117 + struct sb_cmd_ctx *cmd_head;
  118 + struct sb_cmd_ctx *cmd_tail;
  119 +
  120 + struct sb_sections_header payload;
  121 +};
  122 +
  123 +struct sb_image_ctx {
  124 + unsigned int in_section:1;
  125 + unsigned int in_dcd:1;
  126 + /* Image configuration */
  127 + unsigned int verbose_boot:1;
  128 + unsigned int silent_dump:1;
  129 + char *input_filename;
  130 + char *output_filename;
  131 + char *cfg_filename;
  132 + uint8_t image_key[16];
  133 +
  134 + /* Number of section in the image */
  135 + unsigned int sect_count;
  136 + /* Bootable section */
  137 + unsigned int sect_boot;
  138 + unsigned int sect_boot_found:1;
  139 +
  140 + struct sb_section_ctx *sect_head;
  141 + struct sb_section_ctx *sect_tail;
  142 +
  143 + struct sb_dcd_ctx *dcd_head;
  144 + struct sb_dcd_ctx *dcd_tail;
  145 +
  146 + EVP_CIPHER_CTX cipher_ctx;
  147 + EVP_MD_CTX md_ctx;
  148 + uint8_t digest[32];
  149 + struct sb_key_dictionary_key sb_dict_key;
  150 +
  151 + struct sb_boot_image_header payload;
  152 +};
  153 +
  154 +/*
  155 + * Instruction semantics:
  156 + * NOOP
  157 + * TAG [LAST]
  158 + * LOAD address file
  159 + * LOAD IVT address IVT_entry_point
  160 + * FILL address pattern length
  161 + * JUMP [HAB] address [r0_arg]
  162 + * CALL [HAB] address [r0_arg]
  163 + * MODE mode
  164 + * For i.MX23, mode = USB/I2C/SPI1_FLASH/SPI2_FLASH/NAND_BCH
  165 + * JTAG/SPI3_EEPROM/SD_SSP0/SD_SSP1
  166 + * For i.MX28, mode = USB/I2C/SPI2_FLASH/SPI3_FLASH/NAND_BCH
  167 + * JTAG/SPI2_EEPROM/SD_SSP0/SD_SSP1
  168 + */
  169 +
  170 +/*
  171 + * AES libcrypto
  172 + */
  173 +static int sb_aes_init(struct sb_image_ctx *ictx, uint8_t *iv, int enc)
  174 +{
  175 + EVP_CIPHER_CTX *ctx = &ictx->cipher_ctx;
  176 + int ret;
  177 +
  178 + /* If there is no init vector, init vector is all zeroes. */
  179 + if (!iv)
  180 + iv = ictx->image_key;
  181 +
  182 + EVP_CIPHER_CTX_init(ctx);
  183 + ret = EVP_CipherInit(ctx, EVP_aes_128_cbc(), ictx->image_key, iv, enc);
  184 + if (ret == 1)
  185 + EVP_CIPHER_CTX_set_padding(ctx, 0);
  186 + return ret;
  187 +}
  188 +
  189 +static int sb_aes_crypt(struct sb_image_ctx *ictx, uint8_t *in_data,
  190 + uint8_t *out_data, int in_len)
  191 +{
  192 + EVP_CIPHER_CTX *ctx = &ictx->cipher_ctx;
  193 + int ret, outlen;
  194 + uint8_t *outbuf;
  195 +
  196 + outbuf = malloc(in_len);
  197 + if (!outbuf)
  198 + return -ENOMEM;
  199 + memset(outbuf, 0, sizeof(in_len));
  200 +
  201 + ret = EVP_CipherUpdate(ctx, outbuf, &outlen, in_data, in_len);
  202 + if (!ret) {
  203 + ret = -EINVAL;
  204 + goto err;
  205 + }
  206 +
  207 + if (out_data)
  208 + memcpy(out_data, outbuf, outlen);
  209 +
  210 +err:
  211 + free(outbuf);
  212 + return ret;
  213 +}
  214 +
  215 +static int sb_aes_deinit(EVP_CIPHER_CTX *ctx)
  216 +{
  217 + return EVP_CIPHER_CTX_cleanup(ctx);
  218 +}
  219 +
  220 +static int sb_aes_reinit(struct sb_image_ctx *ictx, int enc)
  221 +{
  222 + int ret;
  223 + EVP_CIPHER_CTX *ctx = &ictx->cipher_ctx;
  224 + struct sb_boot_image_header *sb_header = &ictx->payload;
  225 + uint8_t *iv = sb_header->iv;
  226 +
  227 + ret = sb_aes_deinit(ctx);
  228 + if (!ret)
  229 + return ret;
  230 + return sb_aes_init(ictx, iv, enc);
  231 +}
  232 +
  233 +/*
  234 + * CRC32
  235 + */
  236 +static uint32_t crc32(uint8_t *data, uint32_t len)
  237 +{
  238 + const uint32_t poly = 0x04c11db7;
  239 + uint32_t crc32 = 0xffffffff;
  240 + unsigned int byte, bit;
  241 +
  242 + for (byte = 0; byte < len; byte++) {
  243 + crc32 ^= data[byte] << 24;
  244 +
  245 + for (bit = 8; bit > 0; bit--) {
  246 + if (crc32 & (1UL << 31))
  247 + crc32 = (crc32 << 1) ^ poly;
  248 + else
  249 + crc32 = (crc32 << 1);
  250 + }
  251 + }
  252 +
  253 + return crc32;
  254 +}
  255 +
  256 +/*
  257 + * Debug
  258 + */
  259 +static void soprintf(struct sb_image_ctx *ictx, const char *fmt, ...)
  260 +{
  261 + va_list ap;
  262 +
  263 + if (ictx->silent_dump)
  264 + return;
  265 +
  266 + va_start(ap, fmt);
  267 + vfprintf(stdout, fmt, ap);
  268 + va_end(ap);
  269 +}
  270 +
  271 +/*
  272 + * Code
  273 + */
  274 +static time_t sb_get_timestamp(void)
  275 +{
  276 + struct tm time_2000 = {
  277 + .tm_yday = 1, /* Jan. 1st */
  278 + .tm_year = 100, /* 2000 */
  279 + };
  280 + time_t seconds_to_2000 = mktime(&time_2000);
  281 + time_t seconds_to_now = time(NULL);
  282 +
  283 + return seconds_to_now - seconds_to_2000;
  284 +}
  285 +
  286 +static int sb_get_time(time_t time, struct tm *tm)
  287 +{
  288 + struct tm time_2000 = {
  289 + .tm_yday = 1, /* Jan. 1st */
  290 + .tm_year = 0, /* 1900 */
  291 + };
  292 + const time_t seconds_to_2000 = mktime(&time_2000);
  293 + const time_t seconds_to_now = seconds_to_2000 + time;
  294 + struct tm *ret;
  295 + ret = gmtime_r(&seconds_to_now, tm);
  296 + return ret ? 0 : -EINVAL;
  297 +}
  298 +
  299 +static void sb_encrypt_sb_header(struct sb_image_ctx *ictx)
  300 +{
  301 + EVP_MD_CTX *md_ctx = &ictx->md_ctx;
  302 + struct sb_boot_image_header *sb_header = &ictx->payload;
  303 + uint8_t *sb_header_ptr = (uint8_t *)sb_header;
  304 +
  305 + /* Encrypt the header, compute the digest. */
  306 + sb_aes_crypt(ictx, sb_header_ptr, NULL, sizeof(*sb_header));
  307 + EVP_DigestUpdate(md_ctx, sb_header_ptr, sizeof(*sb_header));
  308 +}
  309 +
  310 +static void sb_encrypt_sb_sections_header(struct sb_image_ctx *ictx)
  311 +{
  312 + EVP_MD_CTX *md_ctx = &ictx->md_ctx;
  313 + struct sb_section_ctx *sctx = ictx->sect_head;
  314 + struct sb_sections_header *shdr;
  315 + uint8_t *sb_sections_header_ptr;
  316 + const int size = sizeof(*shdr);
  317 +
  318 + while (sctx) {
  319 + shdr = &sctx->payload;
  320 + sb_sections_header_ptr = (uint8_t *)shdr;
  321 +
  322 + sb_aes_crypt(ictx, sb_sections_header_ptr,
  323 + ictx->sb_dict_key.cbc_mac, size);
  324 + EVP_DigestUpdate(md_ctx, sb_sections_header_ptr, size);
  325 +
  326 + sctx = sctx->sect;
  327 + };
  328 +}
  329 +
  330 +static void sb_encrypt_key_dictionary_key(struct sb_image_ctx *ictx)
  331 +{
  332 + EVP_MD_CTX *md_ctx = &ictx->md_ctx;
  333 +
  334 + sb_aes_crypt(ictx, ictx->image_key, ictx->sb_dict_key.key,
  335 + sizeof(ictx->sb_dict_key.key));
  336 + EVP_DigestUpdate(md_ctx, &ictx->sb_dict_key, sizeof(ictx->sb_dict_key));
  337 +}
  338 +
  339 +static void sb_decrypt_key_dictionary_key(struct sb_image_ctx *ictx)
  340 +{
  341 + EVP_MD_CTX *md_ctx = &ictx->md_ctx;
  342 +
  343 + EVP_DigestUpdate(md_ctx, &ictx->sb_dict_key, sizeof(ictx->sb_dict_key));
  344 + sb_aes_crypt(ictx, ictx->sb_dict_key.key, ictx->image_key,
  345 + sizeof(ictx->sb_dict_key.key));
  346 +}
  347 +
  348 +static void sb_encrypt_tag(struct sb_image_ctx *ictx,
  349 + struct sb_cmd_ctx *cctx)
  350 +{
  351 + EVP_MD_CTX *md_ctx = &ictx->md_ctx;
  352 + struct sb_command *cmd = &cctx->payload;
  353 +
  354 + sb_aes_crypt(ictx, (uint8_t *)cmd,
  355 + (uint8_t *)&cctx->c_payload, sizeof(*cmd));
  356 + EVP_DigestUpdate(md_ctx, &cctx->c_payload, sizeof(*cmd));
  357 +}
  358 +
  359 +static int sb_encrypt_image(struct sb_image_ctx *ictx)
  360 +{
  361 + /* Start image-wide crypto. */
  362 + EVP_MD_CTX_init(&ictx->md_ctx);
  363 + EVP_DigestInit(&ictx->md_ctx, EVP_sha1());
  364 +
  365 + /*
  366 + * SB image header.
  367 + */
  368 + sb_aes_init(ictx, NULL, 1);
  369 + sb_encrypt_sb_header(ictx);
  370 +
  371 + /*
  372 + * SB sections header.
  373 + */
  374 + sb_encrypt_sb_sections_header(ictx);
  375 +
  376 + /*
  377 + * Key dictionary.
  378 + */
  379 + sb_aes_reinit(ictx, 1);
  380 + sb_encrypt_key_dictionary_key(ictx);
  381 +
  382 + /*
  383 + * Section tags.
  384 + */
  385 + struct sb_cmd_ctx *cctx;
  386 + struct sb_command *ccmd;
  387 + struct sb_section_ctx *sctx = ictx->sect_head;
  388 +
  389 + while (sctx) {
  390 + cctx = sctx->cmd_head;
  391 +
  392 + sb_aes_reinit(ictx, 1);
  393 +
  394 + while (cctx) {
  395 + ccmd = &cctx->payload;
  396 +
  397 + sb_encrypt_tag(ictx, cctx);
  398 +
  399 + if (ccmd->header.tag == ROM_TAG_CMD) {
  400 + sb_aes_reinit(ictx, 1);
  401 + } else if (ccmd->header.tag == ROM_LOAD_CMD) {
  402 + sb_aes_crypt(ictx, cctx->data, cctx->data,
  403 + cctx->length);
  404 + EVP_DigestUpdate(&ictx->md_ctx, cctx->data,
  405 + cctx->length);
  406 + }
  407 +
  408 + cctx = cctx->cmd;
  409 + }
  410 +
  411 + sctx = sctx->sect;
  412 + };
  413 +
  414 + /*
  415 + * Dump the SHA1 of the whole image.
  416 + */
  417 + sb_aes_reinit(ictx, 1);
  418 +
  419 + EVP_DigestFinal(&ictx->md_ctx, ictx->digest, NULL);
  420 + sb_aes_crypt(ictx, ictx->digest, ictx->digest, sizeof(ictx->digest));
  421 +
  422 + /* Stop the encryption session. */
  423 + sb_aes_deinit(&ictx->cipher_ctx);
  424 +
  425 + return 0;
  426 +}
  427 +
  428 +static int sb_load_file(struct sb_cmd_ctx *cctx, char *filename)
  429 +{
  430 + long real_size, roundup_size;
  431 + uint8_t *data;
  432 + long ret;
  433 + unsigned long size;
  434 + FILE *fp;
  435 +
  436 + if (!filename) {
  437 + fprintf(stderr, "ERR: Missing filename!\n");
  438 + return -EINVAL;
  439 + }
  440 +
  441 + fp = fopen(filename, "r");
  442 + if (!fp)
  443 + goto err_open;
  444 +
  445 + ret = fseek(fp, 0, SEEK_END);
  446 + if (ret < 0)
  447 + goto err_file;
  448 +
  449 + real_size = ftell(fp);
  450 + if (real_size < 0)
  451 + goto err_file;
  452 +
  453 + ret = fseek(fp, 0, SEEK_SET);
  454 + if (ret < 0)
  455 + goto err_file;
  456 +
  457 + roundup_size = roundup(real_size, SB_BLOCK_SIZE);
  458 + data = calloc(1, roundup_size);
  459 + if (!data)
  460 + goto err_file;
  461 +
  462 + size = fread(data, 1, real_size, fp);
  463 + if (size != (unsigned long)real_size)
  464 + goto err_alloc;
  465 +
  466 + cctx->data = data;
  467 + cctx->length = roundup_size;
  468 +
  469 + fclose(fp);
  470 + return 0;
  471 +
  472 +err_alloc:
  473 + free(data);
  474 +err_file:
  475 + fclose(fp);
  476 +err_open:
  477 + fprintf(stderr, "ERR: Failed to load file \"%s\"\n", filename);
  478 + return -EINVAL;
  479 +}
  480 +
  481 +static uint8_t sb_command_checksum(struct sb_command *inst)
  482 +{
  483 + uint8_t *inst_ptr = (uint8_t *)inst;
  484 + uint8_t csum = 0;
  485 + unsigned int i;
  486 +
  487 + for (i = 0; i < sizeof(struct sb_command); i++)
  488 + csum += inst_ptr[i];
  489 +
  490 + return csum;
  491 +}
  492 +
  493 +static int sb_token_to_long(char *tok, uint32_t *rid)
  494 +{
  495 + char *endptr;
  496 + unsigned long id;
  497 +
  498 + if (tok[0] != '0' || tok[1] != 'x') {
  499 + fprintf(stderr, "ERR: Invalid hexadecimal number!\n");
  500 + return -EINVAL;
  501 + }
  502 +
  503 + tok += 2;
  504 +
  505 + id = strtoul(tok, &endptr, 16);
  506 + if ((errno == ERANGE && id == ULONG_MAX) || (errno != 0 && id == 0)) {
  507 + fprintf(stderr, "ERR: Value can't be decoded!\n");
  508 + return -EINVAL;
  509 + }
  510 +
  511 + /* Check for 32-bit overflow. */
  512 + if (id > 0xffffffff) {
  513 + fprintf(stderr, "ERR: Value too big!\n");
  514 + return -EINVAL;
  515 + }
  516 +
  517 + if (endptr == tok) {
  518 + fprintf(stderr, "ERR: Deformed value!\n");
  519 + return -EINVAL;
  520 + }
  521 +
  522 + *rid = (uint32_t)id;
  523 + return 0;
  524 +}
  525 +
  526 +static int sb_grow_dcd(struct sb_dcd_ctx *dctx, unsigned int inc_size)
  527 +{
  528 + uint32_t *tmp;
  529 +
  530 + if (!inc_size)
  531 + return 0;
  532 +
  533 + dctx->size += inc_size;
  534 + tmp = realloc(dctx->payload, dctx->size);
  535 + if (!tmp)
  536 + return -ENOMEM;
  537 +
  538 + dctx->payload = tmp;
  539 +
  540 + /* Assemble and update the HAB DCD header. */
  541 + dctx->payload[0] = htonl((SB_HAB_DCD_TAG << 24) |
  542 + (dctx->size << 8) |
  543 + SB_HAB_VERSION);
  544 +
  545 + return 0;
  546 +}
  547 +
  548 +static int sb_build_dcd(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd)
  549 +{
  550 + struct sb_dcd_ctx *dctx;
  551 +
  552 + char *tok;
  553 + uint32_t id;
  554 + int ret;
  555 +
  556 + dctx = calloc(1, sizeof(*dctx));
  557 + if (!dctx)
  558 + return -ENOMEM;
  559 +
  560 + ret = sb_grow_dcd(dctx, 4);
  561 + if (ret)
  562 + goto err_dcd;
  563 +
  564 + /* Read DCD block number. */
  565 + tok = strtok(cmd->cmd, " ");
  566 + if (!tok) {
  567 + fprintf(stderr, "#%i ERR: DCD block without number!\n",
  568 + cmd->lineno);
  569 + ret = -EINVAL;
  570 + goto err_dcd;
  571 + }
  572 +
  573 + /* Parse the DCD block number. */
  574 + ret = sb_token_to_long(tok, &id);
  575 + if (ret) {
  576 + fprintf(stderr, "#%i ERR: Malformed DCD block number!\n",
  577 + cmd->lineno);
  578 + goto err_dcd;
  579 + }
  580 +
  581 + dctx->id = id;
  582 +
  583 + /*
  584 + * The DCD block is now constructed. Append it to the list.
  585 + * WARNING: The DCD size is still not computed and will be
  586 + * updated while parsing it's commands.
  587 + */
  588 + if (!ictx->dcd_head) {
  589 + ictx->dcd_head = dctx;
  590 + ictx->dcd_tail = dctx;
  591 + } else {
  592 + ictx->dcd_tail->dcd = dctx;
  593 + ictx->dcd_tail = dctx;
  594 + }
  595 +
  596 + return 0;
  597 +
  598 +err_dcd:
  599 + free(dctx->payload);
  600 + free(dctx);
  601 + return ret;
  602 +}
  603 +
  604 +static int sb_build_dcd_block(struct sb_image_ctx *ictx,
  605 + struct sb_cmd_list *cmd,
  606 + uint32_t type)
  607 +{
  608 + char *tok;
  609 + uint32_t address, value, length;
  610 + int ret;
  611 +
  612 + struct sb_dcd_ctx *dctx = ictx->dcd_tail;
  613 + uint32_t *dcd;
  614 +
  615 + if (dctx->prev_dcd_head && (type != SB_DCD_NOOP) &&
  616 + ((dctx->prev_dcd_head[0] & 0xff0000ff) == type)) {
  617 + /* Same instruction as before, just append it. */
  618 + ret = sb_grow_dcd(dctx, 8);
  619 + if (ret)
  620 + return ret;
  621 + } else if (type == SB_DCD_NOOP) {
  622 + ret = sb_grow_dcd(dctx, 4);
  623 + if (ret)
  624 + return ret;
  625 +
  626 + /* Update DCD command block pointer. */
  627 + dctx->prev_dcd_head = dctx->payload +
  628 + dctx->size / sizeof(*dctx->payload) - 1;
  629 +
  630 + /* NOOP has only 4 bytes and no payload. */
  631 + goto noop;
  632 + } else {
  633 + /*
  634 + * Either a different instruction block started now
  635 + * or this is the first instruction block.
  636 + */
  637 + ret = sb_grow_dcd(dctx, 12);
  638 + if (ret)
  639 + return ret;
  640 +
  641 + /* Update DCD command block pointer. */
  642 + dctx->prev_dcd_head = dctx->payload +
  643 + dctx->size / sizeof(*dctx->payload) - 3;
  644 + }
  645 +
  646 + dcd = dctx->payload + dctx->size / sizeof(*dctx->payload) - 2;
  647 +
  648 + /*
  649 + * Prepare the command.
  650 + */
  651 + tok = strtok(cmd->cmd, " ");
  652 + if (!tok) {
  653 + fprintf(stderr, "#%i ERR: Missing DCD address!\n",
  654 + cmd->lineno);
  655 + ret = -EINVAL;
  656 + goto err;
  657 + }
  658 +
  659 + /* Read DCD destination address. */
  660 + ret = sb_token_to_long(tok, &address);
  661 + if (ret) {
  662 + fprintf(stderr, "#%i ERR: Incorrect DCD address!\n",
  663 + cmd->lineno);
  664 + goto err;
  665 + }
  666 +
  667 + tok = strtok(NULL, " ");
  668 + if (!tok) {
  669 + fprintf(stderr, "#%i ERR: Missing DCD value!\n",
  670 + cmd->lineno);
  671 + ret = -EINVAL;
  672 + goto err;
  673 + }
  674 +
  675 + /* Read DCD operation value. */
  676 + ret = sb_token_to_long(tok, &value);
  677 + if (ret) {
  678 + fprintf(stderr, "#%i ERR: Incorrect DCD value!\n",
  679 + cmd->lineno);
  680 + goto err;
  681 + }
  682 +
  683 + /* Fill in the new DCD entry. */
  684 + dcd[0] = htonl(address);
  685 + dcd[1] = htonl(value);
  686 +
  687 +noop:
  688 + /* Update the DCD command block. */
  689 + length = dctx->size -
  690 + ((dctx->prev_dcd_head - dctx->payload) *
  691 + sizeof(*dctx->payload));
  692 + dctx->prev_dcd_head[0] = htonl(type | (length << 8));
  693 +
  694 +err:
  695 + return ret;
  696 +}
  697 +
  698 +static int sb_build_section(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd)
  699 +{
  700 + struct sb_section_ctx *sctx;
  701 + struct sb_sections_header *shdr;
  702 + char *tok;
  703 + uint32_t bootable = 0;
  704 + uint32_t id;
  705 + int ret;
  706 +
  707 + sctx = calloc(1, sizeof(*sctx));
  708 + if (!sctx)
  709 + return -ENOMEM;
  710 +
  711 + /* Read section number. */
  712 + tok = strtok(cmd->cmd, " ");
  713 + if (!tok) {
  714 + fprintf(stderr, "#%i ERR: Section without number!\n",
  715 + cmd->lineno);
  716 + ret = -EINVAL;
  717 + goto err_sect;
  718 + }
  719 +
  720 + /* Parse the section number. */
  721 + ret = sb_token_to_long(tok, &id);
  722 + if (ret) {
  723 + fprintf(stderr, "#%i ERR: Malformed section number!\n",
  724 + cmd->lineno);
  725 + goto err_sect;
  726 + }
  727 +
  728 + /* Read section's BOOTABLE flag. */
  729 + tok = strtok(NULL, " ");
  730 + if (tok && (strlen(tok) == 8) && !strncmp(tok, "BOOTABLE", 8))
  731 + bootable = SB_SECTION_FLAG_BOOTABLE;
  732 +
  733 + sctx->boot = bootable;
  734 +
  735 + shdr = &sctx->payload;
  736 + shdr->section_number = id;
  737 + shdr->section_flags = bootable;
  738 +
  739 + /*
  740 + * The section is now constructed. Append it to the list.
  741 + * WARNING: The section size is still not computed and will
  742 + * be updated while parsing it's commands.
  743 + */
  744 + ictx->sect_count++;
  745 +
  746 + /* Mark that this section is bootable one. */
  747 + if (bootable) {
  748 + if (ictx->sect_boot_found) {
  749 + fprintf(stderr,
  750 + "#%i WARN: Multiple bootable section!\n",
  751 + cmd->lineno);
  752 + } else {
  753 + ictx->sect_boot = id;
  754 + ictx->sect_boot_found = 1;
  755 + }
  756 + }
  757 +
  758 + if (!ictx->sect_head) {
  759 + ictx->sect_head = sctx;
  760 + ictx->sect_tail = sctx;
  761 + } else {
  762 + ictx->sect_tail->sect = sctx;
  763 + ictx->sect_tail = sctx;
  764 + }
  765 +
  766 + return 0;
  767 +
  768 +err_sect:
  769 + free(sctx);
  770 + return ret;
  771 +}
  772 +
  773 +static int sb_build_command_nop(struct sb_image_ctx *ictx)
  774 +{
  775 + struct sb_section_ctx *sctx = ictx->sect_tail;
  776 + struct sb_cmd_ctx *cctx;
  777 + struct sb_command *ccmd;
  778 +
  779 + cctx = calloc(1, sizeof(*cctx));
  780 + if (!cctx)
  781 + return -ENOMEM;
  782 +
  783 + ccmd = &cctx->payload;
  784 +
  785 + /*
  786 + * Construct the command.
  787 + */
  788 + ccmd->header.checksum = 0x5a;
  789 + ccmd->header.tag = ROM_NOP_CMD;
  790 +
  791 + cctx->size = sizeof(*ccmd);
  792 +
  793 + /*
  794 + * Append the command to the last section.
  795 + */
  796 + if (!sctx->cmd_head) {
  797 + sctx->cmd_head = cctx;
  798 + sctx->cmd_tail = cctx;
  799 + } else {
  800 + sctx->cmd_tail->cmd = cctx;
  801 + sctx->cmd_tail = cctx;
  802 + }
  803 +
  804 + return 0;
  805 +}
  806 +
  807 +static int sb_build_command_tag(struct sb_image_ctx *ictx,
  808 + struct sb_cmd_list *cmd)
  809 +{
  810 + struct sb_section_ctx *sctx = ictx->sect_tail;
  811 + struct sb_cmd_ctx *cctx;
  812 + struct sb_command *ccmd;
  813 + char *tok;
  814 +
  815 + cctx = calloc(1, sizeof(*cctx));
  816 + if (!cctx)
  817 + return -ENOMEM;
  818 +
  819 + ccmd = &cctx->payload;
  820 +
  821 + /*
  822 + * Prepare the command.
  823 + */
  824 + /* Check for the LAST keyword. */
  825 + tok = strtok(cmd->cmd, " ");
  826 + if (tok && !strcmp(tok, "LAST"))
  827 + ccmd->header.flags = ROM_TAG_CMD_FLAG_ROM_LAST_TAG;
  828 +
  829 + /*
  830 + * Construct the command.
  831 + */
  832 + ccmd->header.checksum = 0x5a;
  833 + ccmd->header.tag = ROM_TAG_CMD;
  834 +
  835 + cctx->size = sizeof(*ccmd);
  836 +
  837 + /*
  838 + * Append the command to the last section.
  839 + */
  840 + if (!sctx->cmd_head) {
  841 + sctx->cmd_head = cctx;
  842 + sctx->cmd_tail = cctx;
  843 + } else {
  844 + sctx->cmd_tail->cmd = cctx;
  845 + sctx->cmd_tail = cctx;
  846 + }
  847 +
  848 + return 0;
  849 +}
  850 +
  851 +static int sb_build_command_load(struct sb_image_ctx *ictx,
  852 + struct sb_cmd_list *cmd)
  853 +{
  854 + struct sb_section_ctx *sctx = ictx->sect_tail;
  855 + struct sb_cmd_ctx *cctx;
  856 + struct sb_command *ccmd;
  857 + char *tok;
  858 + int ret, is_ivt = 0, is_dcd = 0;
  859 + uint32_t dest, dcd = 0;
  860 +
  861 + cctx = calloc(1, sizeof(*cctx));
  862 + if (!cctx)
  863 + return -ENOMEM;
  864 +
  865 + ccmd = &cctx->payload;
  866 +
  867 + /*
  868 + * Prepare the command.
  869 + */
  870 + tok = strtok(cmd->cmd, " ");
  871 + if (!tok) {
  872 + fprintf(stderr, "#%i ERR: Missing LOAD address or 'IVT'!\n",
  873 + cmd->lineno);
  874 + ret = -EINVAL;
  875 + goto err;
  876 + }
  877 +
  878 + /* Check for "IVT" flag. */
  879 + if (!strcmp(tok, "IVT"))
  880 + is_ivt = 1;
  881 + if (!strcmp(tok, "DCD"))
  882 + is_dcd = 1;
  883 + if (is_ivt || is_dcd) {
  884 + tok = strtok(NULL, " ");
  885 + if (!tok) {
  886 + fprintf(stderr, "#%i ERR: Missing LOAD address!\n",
  887 + cmd->lineno);
  888 + ret = -EINVAL;
  889 + goto err;
  890 + }
  891 + }
  892 +
  893 + /* Read load destination address. */
  894 + ret = sb_token_to_long(tok, &dest);
  895 + if (ret) {
  896 + fprintf(stderr, "#%i ERR: Incorrect LOAD address!\n",
  897 + cmd->lineno);
  898 + goto err;
  899 + }
  900 +
  901 + /* Read filename or IVT entrypoint or DCD block ID. */
  902 + tok = strtok(NULL, " ");
  903 + if (!tok) {
  904 + fprintf(stderr,
  905 + "#%i ERR: Missing LOAD filename or IVT ep or DCD block ID!\n",
  906 + cmd->lineno);
  907 + ret = -EINVAL;
  908 + goto err;
  909 + }
  910 +
  911 + if (is_ivt) {
  912 + /* Handle IVT. */
  913 + struct sb_ivt_header *ivt;
  914 + uint32_t ivtep;
  915 + ret = sb_token_to_long(tok, &ivtep);
  916 +
  917 + if (ret) {
  918 + fprintf(stderr,
  919 + "#%i ERR: Incorrect IVT entry point!\n",
  920 + cmd->lineno);
  921 + goto err;
  922 + }
  923 +
  924 + ivt = calloc(1, sizeof(*ivt));
  925 + if (!ivt) {
  926 + ret = -ENOMEM;
  927 + goto err;
  928 + }
  929 +
  930 + ivt->header = sb_hab_ivt_header();
  931 + ivt->entry = ivtep;
  932 + ivt->self = dest;
  933 +
  934 + cctx->data = (uint8_t *)ivt;
  935 + cctx->length = sizeof(*ivt);
  936 + } else if (is_dcd) {
  937 + struct sb_dcd_ctx *dctx = ictx->dcd_head;
  938 + uint32_t dcdid;
  939 + uint8_t *payload;
  940 + uint32_t asize;
  941 + ret = sb_token_to_long(tok, &dcdid);
  942 +
  943 + if (ret) {
  944 + fprintf(stderr,
  945 + "#%i ERR: Incorrect DCD block ID!\n",
  946 + cmd->lineno);
  947 + goto err;
  948 + }
  949 +
  950 + while (dctx) {
  951 + if (dctx->id == dcdid)
  952 + break;
  953 + dctx = dctx->dcd;
  954 + }
  955 +
  956 + if (!dctx) {
  957 + fprintf(stderr, "#%i ERR: DCD block %08x not found!\n",
  958 + cmd->lineno, dcdid);
  959 + goto err;
  960 + }
  961 +
  962 + asize = roundup(dctx->size, SB_BLOCK_SIZE);
  963 + payload = calloc(1, asize);
  964 + if (!payload) {
  965 + ret = -ENOMEM;
  966 + goto err;
  967 + }
  968 +
  969 + memcpy(payload, dctx->payload, dctx->size);
  970 +
  971 + cctx->data = payload;
  972 + cctx->length = asize;
  973 +
  974 + /* Set the Load DCD flag. */
  975 + dcd = ROM_LOAD_CMD_FLAG_DCD_LOAD;
  976 + } else {
  977 + /* Regular LOAD of a file. */
  978 + ret = sb_load_file(cctx, tok);
  979 + if (ret) {
  980 + fprintf(stderr, "#%i ERR: Cannot load '%s'!\n",
  981 + cmd->lineno, tok);
  982 + goto err;
  983 + }
  984 + }
  985 +
  986 + if (cctx->length & (SB_BLOCK_SIZE - 1)) {
  987 + fprintf(stderr, "#%i ERR: Unaligned payload!\n",
  988 + cmd->lineno);
  989 + }
  990 +
  991 + /*
  992 + * Construct the command.
  993 + */
  994 + ccmd->header.checksum = 0x5a;
  995 + ccmd->header.tag = ROM_LOAD_CMD;
  996 + ccmd->header.flags = dcd;
  997 +
  998 + ccmd->load.address = dest;
  999 + ccmd->load.count = cctx->length;
  1000 + ccmd->load.crc32 = crc32(cctx->data, cctx->length);
  1001 +
  1002 + cctx->size = sizeof(*ccmd) + cctx->length;
  1003 +
  1004 + /*
  1005 + * Append the command to the last section.
  1006 + */
  1007 + if (!sctx->cmd_head) {
  1008 + sctx->cmd_head = cctx;
  1009 + sctx->cmd_tail = cctx;
  1010 + } else {
  1011 + sctx->cmd_tail->cmd = cctx;
  1012 + sctx->cmd_tail = cctx;
  1013 + }
  1014 +
  1015 + return 0;
  1016 +
  1017 +err:
  1018 + free(cctx);
  1019 + return ret;
  1020 +}
  1021 +
  1022 +static int sb_build_command_fill(struct sb_image_ctx *ictx,
  1023 + struct sb_cmd_list *cmd)
  1024 +{
  1025 + struct sb_section_ctx *sctx = ictx->sect_tail;
  1026 + struct sb_cmd_ctx *cctx;
  1027 + struct sb_command *ccmd;
  1028 + char *tok;
  1029 + uint32_t address, pattern, length;
  1030 + int ret;
  1031 +
  1032 + cctx = calloc(1, sizeof(*cctx));
  1033 + if (!cctx)
  1034 + return -ENOMEM;
  1035 +
  1036 + ccmd = &cctx->payload;
  1037 +
  1038 + /*
  1039 + * Prepare the command.
  1040 + */
  1041 + tok = strtok(cmd->cmd, " ");
  1042 + if (!tok) {
  1043 + fprintf(stderr, "#%i ERR: Missing FILL address!\n",
  1044 + cmd->lineno);
  1045 + ret = -EINVAL;
  1046 + goto err;
  1047 + }
  1048 +
  1049 + /* Read fill destination address. */
  1050 + ret = sb_token_to_long(tok, &address);
  1051 + if (ret) {
  1052 + fprintf(stderr, "#%i ERR: Incorrect FILL address!\n",
  1053 + cmd->lineno);
  1054 + goto err;
  1055 + }
  1056 +
  1057 + tok = strtok(NULL, " ");
  1058 + if (!tok) {
  1059 + fprintf(stderr, "#%i ERR: Missing FILL pattern!\n",
  1060 + cmd->lineno);
  1061 + ret = -EINVAL;
  1062 + goto err;
  1063 + }
  1064 +
  1065 + /* Read fill pattern address. */
  1066 + ret = sb_token_to_long(tok, &pattern);
  1067 + if (ret) {
  1068 + fprintf(stderr, "#%i ERR: Incorrect FILL pattern!\n",
  1069 + cmd->lineno);
  1070 + goto err;
  1071 + }
  1072 +
  1073 + tok = strtok(NULL, " ");
  1074 + if (!tok) {
  1075 + fprintf(stderr, "#%i ERR: Missing FILL length!\n",
  1076 + cmd->lineno);
  1077 + ret = -EINVAL;
  1078 + goto err;
  1079 + }
  1080 +
  1081 + /* Read fill pattern address. */
  1082 + ret = sb_token_to_long(tok, &length);
  1083 + if (ret) {
  1084 + fprintf(stderr, "#%i ERR: Incorrect FILL length!\n",
  1085 + cmd->lineno);
  1086 + goto err;
  1087 + }
  1088 +
  1089 + /*
  1090 + * Construct the command.
  1091 + */
  1092 + ccmd->header.checksum = 0x5a;
  1093 + ccmd->header.tag = ROM_FILL_CMD;
  1094 +
  1095 + ccmd->fill.address = address;
  1096 + ccmd->fill.count = length;
  1097 + ccmd->fill.pattern = pattern;
  1098 +
  1099 + cctx->size = sizeof(*ccmd);
  1100 +
  1101 + /*
  1102 + * Append the command to the last section.
  1103 + */
  1104 + if (!sctx->cmd_head) {
  1105 + sctx->cmd_head = cctx;
  1106 + sctx->cmd_tail = cctx;
  1107 + } else {
  1108 + sctx->cmd_tail->cmd = cctx;
  1109 + sctx->cmd_tail = cctx;
  1110 + }
  1111 +
  1112 + return 0;
  1113 +
  1114 +err:
  1115 + free(cctx);
  1116 + return ret;
  1117 +}
  1118 +
  1119 +static int sb_build_command_jump_call(struct sb_image_ctx *ictx,
  1120 + struct sb_cmd_list *cmd,
  1121 + unsigned int is_call)
  1122 +{
  1123 + struct sb_section_ctx *sctx = ictx->sect_tail;
  1124 + struct sb_cmd_ctx *cctx;
  1125 + struct sb_command *ccmd;
  1126 + char *tok;
  1127 + uint32_t dest, arg = 0x0;
  1128 + uint32_t hab = 0;
  1129 + int ret;
  1130 + const char *cmdname = is_call ? "CALL" : "JUMP";
  1131 +
  1132 + cctx = calloc(1, sizeof(*cctx));
  1133 + if (!cctx)
  1134 + return -ENOMEM;
  1135 +
  1136 + ccmd = &cctx->payload;
  1137 +
  1138 + /*
  1139 + * Prepare the command.
  1140 + */
  1141 + tok = strtok(cmd->cmd, " ");
  1142 + if (!tok) {
  1143 + fprintf(stderr,
  1144 + "#%i ERR: Missing %s address or 'HAB'!\n",
  1145 + cmd->lineno, cmdname);
  1146 + ret = -EINVAL;
  1147 + goto err;
  1148 + }
  1149 +
  1150 + /* Check for "HAB" flag. */
  1151 + if (!strcmp(tok, "HAB")) {
  1152 + hab = is_call ? ROM_CALL_CMD_FLAG_HAB : ROM_JUMP_CMD_FLAG_HAB;
  1153 + tok = strtok(NULL, " ");
  1154 + if (!tok) {
  1155 + fprintf(stderr, "#%i ERR: Missing %s address!\n",
  1156 + cmd->lineno, cmdname);
  1157 + ret = -EINVAL;
  1158 + goto err;
  1159 + }
  1160 + }
  1161 + /* Read load destination address. */
  1162 + ret = sb_token_to_long(tok, &dest);
  1163 + if (ret) {
  1164 + fprintf(stderr, "#%i ERR: Incorrect %s address!\n",
  1165 + cmd->lineno, cmdname);
  1166 + goto err;
  1167 + }
  1168 +
  1169 + tok = strtok(NULL, " ");
  1170 + if (tok) {
  1171 + ret = sb_token_to_long(tok, &arg);
  1172 + if (ret) {
  1173 + fprintf(stderr,
  1174 + "#%i ERR: Incorrect %s argument!\n",
  1175 + cmd->lineno, cmdname);
  1176 + goto err;
  1177 + }
  1178 + }
  1179 +
  1180 + /*
  1181 + * Construct the command.
  1182 + */
  1183 + ccmd->header.checksum = 0x5a;
  1184 + ccmd->header.tag = is_call ? ROM_CALL_CMD : ROM_JUMP_CMD;
  1185 + ccmd->header.flags = hab;
  1186 +
  1187 + ccmd->call.address = dest;
  1188 + ccmd->call.argument = arg;
  1189 +
  1190 + cctx->size = sizeof(*ccmd);
  1191 +
  1192 + /*
  1193 + * Append the command to the last section.
  1194 + */
  1195 + if (!sctx->cmd_head) {
  1196 + sctx->cmd_head = cctx;
  1197 + sctx->cmd_tail = cctx;
  1198 + } else {
  1199 + sctx->cmd_tail->cmd = cctx;
  1200 + sctx->cmd_tail = cctx;
  1201 + }
  1202 +
  1203 + return 0;
  1204 +
  1205 +err:
  1206 + free(cctx);
  1207 + return ret;
  1208 +}
  1209 +
  1210 +static int sb_build_command_jump(struct sb_image_ctx *ictx,
  1211 + struct sb_cmd_list *cmd)
  1212 +{
  1213 + return sb_build_command_jump_call(ictx, cmd, 0);
  1214 +}
  1215 +
  1216 +static int sb_build_command_call(struct sb_image_ctx *ictx,
  1217 + struct sb_cmd_list *cmd)
  1218 +{
  1219 + return sb_build_command_jump_call(ictx, cmd, 1);
  1220 +}
  1221 +
  1222 +static int sb_build_command_mode(struct sb_image_ctx *ictx,
  1223 + struct sb_cmd_list *cmd)
  1224 +{
  1225 + struct sb_section_ctx *sctx = ictx->sect_tail;
  1226 + struct sb_cmd_ctx *cctx;
  1227 + struct sb_command *ccmd;
  1228 + char *tok;
  1229 + int ret;
  1230 + unsigned int i;
  1231 + uint32_t mode = 0xffffffff;
  1232 +
  1233 + cctx = calloc(1, sizeof(*cctx));
  1234 + if (!cctx)
  1235 + return -ENOMEM;
  1236 +
  1237 + ccmd = &cctx->payload;
  1238 +
  1239 + /*
  1240 + * Prepare the command.
  1241 + */
  1242 + tok = strtok(cmd->cmd, " ");
  1243 + if (!tok) {
  1244 + fprintf(stderr, "#%i ERR: Missing MODE boot mode argument!\n",
  1245 + cmd->lineno);
  1246 + ret = -EINVAL;
  1247 + goto err;
  1248 + }
  1249 +
  1250 + for (i = 0; i < ARRAY_SIZE(modetable); i++) {
  1251 + if (!strcmp(tok, modetable[i].name)) {
  1252 + mode = modetable[i].mode;
  1253 + break;
  1254 + }
  1255 +
  1256 + if (!modetable[i].altname)
  1257 + continue;
  1258 +
  1259 + if (!strcmp(tok, modetable[i].altname)) {
  1260 + mode = modetable[i].mode;
  1261 + break;
  1262 + }
  1263 + }
  1264 +
  1265 + if (mode == 0xffffffff) {
  1266 + fprintf(stderr, "#%i ERR: Invalid MODE boot mode argument!\n",
  1267 + cmd->lineno);
  1268 + ret = -EINVAL;
  1269 + goto err;
  1270 + }
  1271 +
  1272 + /*
  1273 + * Construct the command.
  1274 + */
  1275 + ccmd->header.checksum = 0x5a;
  1276 + ccmd->header.tag = ROM_MODE_CMD;
  1277 +
  1278 + ccmd->mode.mode = mode;
  1279 +
  1280 + cctx->size = sizeof(*ccmd);
  1281 +
  1282 + /*
  1283 + * Append the command to the last section.
  1284 + */
  1285 + if (!sctx->cmd_head) {
  1286 + sctx->cmd_head = cctx;
  1287 + sctx->cmd_tail = cctx;
  1288 + } else {
  1289 + sctx->cmd_tail->cmd = cctx;
  1290 + sctx->cmd_tail = cctx;
  1291 + }
  1292 +
  1293 + return 0;
  1294 +
  1295 +err:
  1296 + free(cctx);
  1297 + return ret;
  1298 +}
  1299 +
  1300 +static int sb_prefill_image_header(struct sb_image_ctx *ictx)
  1301 +{
  1302 + struct sb_boot_image_header *hdr = &ictx->payload;
  1303 +
  1304 + /* Fill signatures */
  1305 + memcpy(hdr->signature1, "STMP", 4);
  1306 + memcpy(hdr->signature2, "sgtl", 4);
  1307 +
  1308 + /* SB Image version 1.1 */
  1309 + hdr->major_version = SB_VERSION_MAJOR;
  1310 + hdr->minor_version = SB_VERSION_MINOR;
  1311 +
  1312 + /* Boot image major version */
  1313 + hdr->product_version.major = htons(0x999);
  1314 + hdr->product_version.minor = htons(0x999);
  1315 + hdr->product_version.revision = htons(0x999);
  1316 + /* Boot image major version */
  1317 + hdr->component_version.major = htons(0x999);
  1318 + hdr->component_version.minor = htons(0x999);
  1319 + hdr->component_version.revision = htons(0x999);
  1320 +
  1321 + /* Drive tag must be 0x0 for i.MX23 */
  1322 + hdr->drive_tag = 0;
  1323 +
  1324 + hdr->header_blocks =
  1325 + sizeof(struct sb_boot_image_header) / SB_BLOCK_SIZE;
  1326 + hdr->section_header_size =
  1327 + sizeof(struct sb_sections_header) / SB_BLOCK_SIZE;
  1328 + hdr->timestamp_us = sb_get_timestamp() * 1000000;
  1329 +
  1330 + /* FIXME -- add proper config option */
  1331 + hdr->flags = ictx->verbose_boot ? SB_IMAGE_FLAG_VERBOSE : 0,
  1332 +
  1333 + /* FIXME -- We support only default key */
  1334 + hdr->key_count = 1;
  1335 +
  1336 + return 0;
  1337 +}
  1338 +
  1339 +static int sb_postfill_image_header(struct sb_image_ctx *ictx)
  1340 +{
  1341 + struct sb_boot_image_header *hdr = &ictx->payload;
  1342 + struct sb_section_ctx *sctx = ictx->sect_head;
  1343 + uint32_t kd_size, sections_blocks;
  1344 + EVP_MD_CTX md_ctx;
  1345 +
  1346 + /* The main SB header size in blocks. */
  1347 + hdr->image_blocks = hdr->header_blocks;
  1348 +
  1349 + /* Size of the key dictionary, which has single zero entry. */
  1350 + kd_size = hdr->key_count * sizeof(struct sb_key_dictionary_key);
  1351 + hdr->image_blocks += kd_size / SB_BLOCK_SIZE;
  1352 +
  1353 + /* Now count the payloads. */
  1354 + hdr->section_count = ictx->sect_count;
  1355 + while (sctx) {
  1356 + hdr->image_blocks += sctx->size / SB_BLOCK_SIZE;
  1357 + sctx = sctx->sect;
  1358 + }
  1359 +
  1360 + if (!ictx->sect_boot_found) {
  1361 + fprintf(stderr, "ERR: No bootable section selected!\n");
  1362 + return -EINVAL;
  1363 + }
  1364 + hdr->first_boot_section_id = ictx->sect_boot;
  1365 +
  1366 + /* The n * SB section size in blocks. */
  1367 + sections_blocks = hdr->section_count * hdr->section_header_size;
  1368 + hdr->image_blocks += sections_blocks;
  1369 +
  1370 + /* Key dictionary offset. */
  1371 + hdr->key_dictionary_block = hdr->header_blocks + sections_blocks;
  1372 +
  1373 + /* Digest of the whole image. */
  1374 + hdr->image_blocks += 2;
  1375 +
  1376 + /* Pointer past the dictionary. */
  1377 + hdr->first_boot_tag_block =
  1378 + hdr->key_dictionary_block + kd_size / SB_BLOCK_SIZE;
  1379 +
  1380 + /* Compute header digest. */
  1381 + EVP_MD_CTX_init(&md_ctx);
  1382 +
  1383 + EVP_DigestInit(&md_ctx, EVP_sha1());
  1384 + EVP_DigestUpdate(&md_ctx, hdr->signature1,
  1385 + sizeof(struct sb_boot_image_header) -
  1386 + sizeof(hdr->digest));
  1387 + EVP_DigestFinal(&md_ctx, hdr->digest, NULL);
  1388 +
  1389 + return 0;
  1390 +}
  1391 +
  1392 +static int sb_fixup_sections_and_tags(struct sb_image_ctx *ictx)
  1393 +{
  1394 + /* Fixup the placement of sections. */
  1395 + struct sb_boot_image_header *ihdr = &ictx->payload;
  1396 + struct sb_section_ctx *sctx = ictx->sect_head;
  1397 + struct sb_sections_header *shdr;
  1398 + struct sb_cmd_ctx *cctx;
  1399 + struct sb_command *ccmd;
  1400 + uint32_t offset = ihdr->first_boot_tag_block;
  1401 +
  1402 + while (sctx) {
  1403 + shdr = &sctx->payload;
  1404 +
  1405 + /* Fill in the section TAG offset. */
  1406 + shdr->section_offset = offset + 1;
  1407 + offset += shdr->section_size;
  1408 +
  1409 + /* Section length is measured from the TAG block. */
  1410 + shdr->section_size--;
  1411 +
  1412 + /* Fixup the TAG command. */
  1413 + cctx = sctx->cmd_head;
  1414 + while (cctx) {
  1415 + ccmd = &cctx->payload;
  1416 + if (ccmd->header.tag == ROM_TAG_CMD) {
  1417 + ccmd->tag.section_number = shdr->section_number;
  1418 + ccmd->tag.section_length = shdr->section_size;
  1419 + ccmd->tag.section_flags = shdr->section_flags;
  1420 + }
  1421 +
  1422 + /* Update the command checksum. */
  1423 + ccmd->header.checksum = sb_command_checksum(ccmd);
  1424 +
  1425 + cctx = cctx->cmd;
  1426 + }
  1427 +
  1428 + sctx = sctx->sect;
  1429 + }
  1430 +
  1431 + return 0;
  1432 +}
  1433 +
  1434 +static int sb_parse_line(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd)
  1435 +{
  1436 + char *tok;
  1437 + char *line = cmd->cmd;
  1438 + char *rptr;
  1439 + int ret;
  1440 +
  1441 + /* Analyze the identifier on this line first. */
  1442 + tok = strtok_r(line, " ", &rptr);
  1443 + if (!tok || (strlen(tok) == 0)) {
  1444 + fprintf(stderr, "#%i ERR: Invalid line!\n", cmd->lineno);
  1445 + return -EINVAL;
  1446 + }
  1447 +
  1448 + cmd->cmd = rptr;
  1449 +
  1450 + /* DCD */
  1451 + if (!strcmp(tok, "DCD")) {
  1452 + ictx->in_section = 0;
  1453 + ictx->in_dcd = 1;
  1454 + sb_build_dcd(ictx, cmd);
  1455 + return 0;
  1456 + }
  1457 +
  1458 + /* Section */
  1459 + if (!strcmp(tok, "SECTION")) {
  1460 + ictx->in_section = 1;
  1461 + ictx->in_dcd = 0;
  1462 + sb_build_section(ictx, cmd);
  1463 + return 0;
  1464 + }
  1465 +
  1466 + if (!ictx->in_section && !ictx->in_dcd) {
  1467 + fprintf(stderr, "#%i ERR: Data outside of a section!\n",
  1468 + cmd->lineno);
  1469 + return -EINVAL;
  1470 + }
  1471 +
  1472 + if (ictx->in_section) {
  1473 + /* Section commands */
  1474 + if (!strcmp(tok, "NOP")) {
  1475 + ret = sb_build_command_nop(ictx);
  1476 + } else if (!strcmp(tok, "TAG")) {
  1477 + ret = sb_build_command_tag(ictx, cmd);
  1478 + } else if (!strcmp(tok, "LOAD")) {
  1479 + ret = sb_build_command_load(ictx, cmd);
  1480 + } else if (!strcmp(tok, "FILL")) {
  1481 + ret = sb_build_command_fill(ictx, cmd);
  1482 + } else if (!strcmp(tok, "JUMP")) {
  1483 + ret = sb_build_command_jump(ictx, cmd);
  1484 + } else if (!strcmp(tok, "CALL")) {
  1485 + ret = sb_build_command_call(ictx, cmd);
  1486 + } else if (!strcmp(tok, "MODE")) {
  1487 + ret = sb_build_command_mode(ictx, cmd);
  1488 + } else {
  1489 + fprintf(stderr,
  1490 + "#%i ERR: Unsupported instruction '%s'!\n",
  1491 + cmd->lineno, tok);
  1492 + return -ENOTSUP;
  1493 + }
  1494 + } else if (ictx->in_dcd) {
  1495 + char *lptr;
  1496 + uint32_t ilen = '1';
  1497 +
  1498 + tok = strtok_r(tok, ".", &lptr);
  1499 + if (!tok || (strlen(tok) == 0) || (lptr && strlen(lptr) != 1)) {
  1500 + fprintf(stderr, "#%i ERR: Invalid line!\n",
  1501 + cmd->lineno);
  1502 + return -EINVAL;
  1503 + }
  1504 +
  1505 + if (lptr &&
  1506 + (lptr[0] != '1' && lptr[0] != '2' && lptr[0] != '4')) {
  1507 + fprintf(stderr, "#%i ERR: Invalid instruction width!\n",
  1508 + cmd->lineno);
  1509 + return -EINVAL;
  1510 + }
  1511 +
  1512 + if (lptr)
  1513 + ilen = lptr[0] - '1';
  1514 +
  1515 + /* DCD commands */
  1516 + if (!strcmp(tok, "WRITE")) {
  1517 + ret = sb_build_dcd_block(ictx, cmd,
  1518 + SB_DCD_WRITE | ilen);
  1519 + } else if (!strcmp(tok, "ANDC")) {
  1520 + ret = sb_build_dcd_block(ictx, cmd,
  1521 + SB_DCD_ANDC | ilen);
  1522 + } else if (!strcmp(tok, "ORR")) {
  1523 + ret = sb_build_dcd_block(ictx, cmd,
  1524 + SB_DCD_ORR | ilen);
  1525 + } else if (!strcmp(tok, "EQZ")) {
  1526 + ret = sb_build_dcd_block(ictx, cmd,
  1527 + SB_DCD_CHK_EQZ | ilen);
  1528 + } else if (!strcmp(tok, "EQ")) {
  1529 + ret = sb_build_dcd_block(ictx, cmd,
  1530 + SB_DCD_CHK_EQ | ilen);
  1531 + } else if (!strcmp(tok, "NEQ")) {
  1532 + ret = sb_build_dcd_block(ictx, cmd,
  1533 + SB_DCD_CHK_NEQ | ilen);
  1534 + } else if (!strcmp(tok, "NEZ")) {
  1535 + ret = sb_build_dcd_block(ictx, cmd,
  1536 + SB_DCD_CHK_NEZ | ilen);
  1537 + } else if (!strcmp(tok, "NOOP")) {
  1538 + ret = sb_build_dcd_block(ictx, cmd, SB_DCD_NOOP);
  1539 + } else {
  1540 + fprintf(stderr,
  1541 + "#%i ERR: Unsupported instruction '%s'!\n",
  1542 + cmd->lineno, tok);
  1543 + return -ENOTSUP;
  1544 + }
  1545 + } else {
  1546 + fprintf(stderr, "#%i ERR: Unsupported instruction '%s'!\n",
  1547 + cmd->lineno, tok);
  1548 + return -ENOTSUP;
  1549 + }
  1550 +
  1551 + /*
  1552 + * Here we have at least one section with one command, otherwise we
  1553 + * would have failed already higher above.
  1554 + *
  1555 + * FIXME -- should the updating happen here ?
  1556 + */
  1557 + if (ictx->in_section && !ret) {
  1558 + ictx->sect_tail->size += ictx->sect_tail->cmd_tail->size;
  1559 + ictx->sect_tail->payload.section_size =
  1560 + ictx->sect_tail->size / SB_BLOCK_SIZE;
  1561 + }
  1562 +
  1563 + return ret;
  1564 +}
  1565 +
  1566 +static int sb_load_cmdfile(struct sb_image_ctx *ictx)
  1567 +{
  1568 + struct sb_cmd_list cmd;
  1569 + int lineno = 1;
  1570 + FILE *fp;
  1571 + char *line = NULL;
  1572 + ssize_t rlen;
  1573 + size_t len;
  1574 +
  1575 + fp = fopen(ictx->cfg_filename, "r");
  1576 + if (!fp)
  1577 + goto err_file;
  1578 +
  1579 + while ((rlen = getline(&line, &len, fp)) > 0) {
  1580 + memset(&cmd, 0, sizeof(cmd));
  1581 +
  1582 + /* Strip the trailing newline. */
  1583 + line[rlen - 1] = '\0';
  1584 +
  1585 + cmd.cmd = line;
  1586 + cmd.len = rlen;
  1587 + cmd.lineno = lineno++;
  1588 +
  1589 + sb_parse_line(ictx, &cmd);
  1590 + }
  1591 +
  1592 + free(line);
  1593 +
  1594 + fclose(fp);
  1595 +
  1596 + return 0;
  1597 +
  1598 +err_file:
  1599 + fclose(fp);
  1600 + fprintf(stderr, "ERR: Failed to load file \"%s\"\n",
  1601 + ictx->cfg_filename);
  1602 + return -EINVAL;
  1603 +}
  1604 +
  1605 +static int sb_build_tree_from_cfg(struct sb_image_ctx *ictx)
  1606 +{
  1607 + int ret;
  1608 +
  1609 + ret = sb_load_cmdfile(ictx);
  1610 + if (ret)
  1611 + return ret;
  1612 +
  1613 + ret = sb_prefill_image_header(ictx);
  1614 + if (ret)
  1615 + return ret;
  1616 +
  1617 + ret = sb_postfill_image_header(ictx);
  1618 + if (ret)
  1619 + return ret;
  1620 +
  1621 + ret = sb_fixup_sections_and_tags(ictx);
  1622 + if (ret)
  1623 + return ret;
  1624 +
  1625 + return 0;
  1626 +}
  1627 +
  1628 +static int sb_verify_image_header(struct sb_image_ctx *ictx,
  1629 + FILE *fp, long fsize)
  1630 +{
  1631 + /* Verify static fields in the image header. */
  1632 + struct sb_boot_image_header *hdr = &ictx->payload;
  1633 + const char *stat[2] = { "[PASS]", "[FAIL]" };
  1634 + struct tm tm;
  1635 + int sz, ret = 0;
  1636 + unsigned char digest[20];
  1637 + EVP_MD_CTX md_ctx;
  1638 + unsigned long size;
  1639 +
  1640 + /* Start image-wide crypto. */
  1641 + EVP_MD_CTX_init(&ictx->md_ctx);
  1642 + EVP_DigestInit(&ictx->md_ctx, EVP_sha1());
  1643 +
  1644 + soprintf(ictx, "---------- Verifying SB Image Header ----------\n");
  1645 +
  1646 + size = fread(&ictx->payload, 1, sizeof(ictx->payload), fp);
  1647 + if (size != sizeof(ictx->payload)) {
  1648 + fprintf(stderr, "ERR: SB image header too short!\n");
  1649 + return -EINVAL;
  1650 + }
  1651 +
  1652 + /* Compute header digest. */
  1653 + EVP_MD_CTX_init(&md_ctx);
  1654 + EVP_DigestInit(&md_ctx, EVP_sha1());
  1655 + EVP_DigestUpdate(&md_ctx, hdr->signature1,
  1656 + sizeof(struct sb_boot_image_header) -
  1657 + sizeof(hdr->digest));
  1658 + EVP_DigestFinal(&md_ctx, digest, NULL);
  1659 +
  1660 + sb_aes_init(ictx, NULL, 1);
  1661 + sb_encrypt_sb_header(ictx);
  1662 +
  1663 + if (memcmp(digest, hdr->digest, 20))
  1664 + ret = -EINVAL;
  1665 + soprintf(ictx, "%s Image header checksum: %s\n", stat[!!ret],
  1666 + ret ? "BAD" : "OK");
  1667 + if (ret)
  1668 + return ret;
  1669 +
  1670 + if (memcmp(hdr->signature1, "STMP", 4) ||
  1671 + memcmp(hdr->signature2, "sgtl", 4))
  1672 + ret = -EINVAL;
  1673 + soprintf(ictx, "%s Signatures: '%.4s' '%.4s'\n",
  1674 + stat[!!ret], hdr->signature1, hdr->signature2);
  1675 + if (ret)
  1676 + return ret;
  1677 +
  1678 + if ((hdr->major_version != SB_VERSION_MAJOR) ||
  1679 + ((hdr->minor_version != 1) && (hdr->minor_version != 2)))
  1680 + ret = -EINVAL;
  1681 + soprintf(ictx, "%s Image version: v%i.%i\n", stat[!!ret],
  1682 + hdr->major_version, hdr->minor_version);
  1683 + if (ret)
  1684 + return ret;
  1685 +
  1686 + ret = sb_get_time(hdr->timestamp_us / 1000000, &tm);
  1687 + soprintf(ictx,
  1688 + "%s Creation time: %02i:%02i:%02i %02i/%02i/%04i\n",
  1689 + stat[!!ret], tm.tm_hour, tm.tm_min, tm.tm_sec,
  1690 + tm.tm_mday, tm.tm_mon, tm.tm_year + 2000);
  1691 + if (ret)
  1692 + return ret;
  1693 +
  1694 + soprintf(ictx, "%s Product version: %x.%x.%x\n", stat[0],
  1695 + ntohs(hdr->product_version.major),
  1696 + ntohs(hdr->product_version.minor),
  1697 + ntohs(hdr->product_version.revision));
  1698 + soprintf(ictx, "%s Component version: %x.%x.%x\n", stat[0],
  1699 + ntohs(hdr->component_version.major),
  1700 + ntohs(hdr->component_version.minor),
  1701 + ntohs(hdr->component_version.revision));
  1702 +
  1703 + if (hdr->flags & ~SB_IMAGE_FLAG_VERBOSE)
  1704 + ret = -EINVAL;
  1705 + soprintf(ictx, "%s Image flags: %s\n", stat[!!ret],
  1706 + hdr->flags & SB_IMAGE_FLAG_VERBOSE ? "Verbose_boot" : "");
  1707 + if (ret)
  1708 + return ret;
  1709 +
  1710 + if (hdr->drive_tag != 0)
  1711 + ret = -EINVAL;
  1712 + soprintf(ictx, "%s Drive tag: %i\n", stat[!!ret],
  1713 + hdr->drive_tag);
  1714 + if (ret)
  1715 + return ret;
  1716 +
  1717 + sz = sizeof(struct sb_boot_image_header) / SB_BLOCK_SIZE;
  1718 + if (hdr->header_blocks != sz)
  1719 + ret = -EINVAL;
  1720 + soprintf(ictx, "%s Image header size (blocks): %i\n", stat[!!ret],
  1721 + hdr->header_blocks);
  1722 + if (ret)
  1723 + return ret;
  1724 +
  1725 + sz = sizeof(struct sb_sections_header) / SB_BLOCK_SIZE;
  1726 + if (hdr->section_header_size != sz)
  1727 + ret = -EINVAL;
  1728 + soprintf(ictx, "%s Section header size (blocks): %i\n", stat[!!ret],
  1729 + hdr->section_header_size);
  1730 + if (ret)
  1731 + return ret;
  1732 +
  1733 + soprintf(ictx, "%s Sections count: %i\n", stat[!!ret],
  1734 + hdr->section_count);
  1735 + soprintf(ictx, "%s First bootable section %i\n", stat[!!ret],
  1736 + hdr->first_boot_section_id);
  1737 +
  1738 + if (hdr->image_blocks != fsize / SB_BLOCK_SIZE)
  1739 + ret = -EINVAL;
  1740 + soprintf(ictx, "%s Image size (blocks): %i\n", stat[!!ret],
  1741 + hdr->image_blocks);
  1742 + if (ret)
  1743 + return ret;
  1744 +
  1745 + sz = hdr->header_blocks + hdr->section_header_size * hdr->section_count;
  1746 + if (hdr->key_dictionary_block != sz)
  1747 + ret = -EINVAL;
  1748 + soprintf(ictx, "%s Key dict offset (blocks): %i\n", stat[!!ret],
  1749 + hdr->key_dictionary_block);
  1750 + if (ret)
  1751 + return ret;
  1752 +
  1753 + if (hdr->key_count != 1)
  1754 + ret = -EINVAL;
  1755 + soprintf(ictx, "%s Number of encryption keys: %i\n", stat[!!ret],
  1756 + hdr->key_count);
  1757 + if (ret)
  1758 + return ret;
  1759 +
  1760 + sz = hdr->header_blocks + hdr->section_header_size * hdr->section_count;
  1761 + sz += hdr->key_count *
  1762 + sizeof(struct sb_key_dictionary_key) / SB_BLOCK_SIZE;
  1763 + if (hdr->first_boot_tag_block != (unsigned)sz)
  1764 + ret = -EINVAL;
  1765 + soprintf(ictx, "%s First TAG block (blocks): %i\n", stat[!!ret],
  1766 + hdr->first_boot_tag_block);
  1767 + if (ret)
  1768 + return ret;
  1769 +
  1770 + return 0;
  1771 +}
  1772 +
  1773 +static void sb_decrypt_tag(struct sb_image_ctx *ictx,
  1774 + struct sb_cmd_ctx *cctx)
  1775 +{
  1776 + EVP_MD_CTX *md_ctx = &ictx->md_ctx;
  1777 + struct sb_command *cmd = &cctx->payload;
  1778 +
  1779 + sb_aes_crypt(ictx, (uint8_t *)&cctx->c_payload,
  1780 + (uint8_t *)&cctx->payload, sizeof(*cmd));
  1781 + EVP_DigestUpdate(md_ctx, &cctx->c_payload, sizeof(*cmd));
  1782 +}
  1783 +
  1784 +static int sb_verify_command(struct sb_image_ctx *ictx,
  1785 + struct sb_cmd_ctx *cctx, FILE *fp,
  1786 + unsigned long *tsize)
  1787 +{
  1788 + struct sb_command *ccmd = &cctx->payload;
  1789 + unsigned long size, asize;
  1790 + char *csum, *flag = "";
  1791 + int ret;
  1792 + unsigned int i;
  1793 + uint8_t csn, csc = ccmd->header.checksum;
  1794 + ccmd->header.checksum = 0x5a;
  1795 + csn = sb_command_checksum(ccmd);
  1796 + ccmd->header.checksum = csc;
  1797 +
  1798 + if (csc == csn)
  1799 + ret = 0;
  1800 + else
  1801 + ret = -EINVAL;
  1802 + csum = ret ? "checksum BAD" : "checksum OK";
  1803 +
  1804 + switch (ccmd->header.tag) {
  1805 + case ROM_NOP_CMD:
  1806 + soprintf(ictx, " NOOP # %s\n", csum);
  1807 + return ret;
  1808 + case ROM_TAG_CMD:
  1809 + if (ccmd->header.flags & ROM_TAG_CMD_FLAG_ROM_LAST_TAG)
  1810 + flag = "LAST";
  1811 + soprintf(ictx, " TAG %s # %s\n", flag, csum);
  1812 + sb_aes_reinit(ictx, 0);
  1813 + return ret;
  1814 + case ROM_LOAD_CMD:
  1815 + soprintf(ictx, " LOAD addr=0x%08x length=0x%08x # %s\n",
  1816 + ccmd->load.address, ccmd->load.count, csum);
  1817 +
  1818 + cctx->length = ccmd->load.count;
  1819 + asize = roundup(cctx->length, SB_BLOCK_SIZE);
  1820 + cctx->data = malloc(asize);
  1821 + if (!cctx->data)
  1822 + return -ENOMEM;
  1823 +
  1824 + size = fread(cctx->data, 1, asize, fp);
  1825 + if (size != asize) {
  1826 + fprintf(stderr,
  1827 + "ERR: SB LOAD command payload too short!\n");
  1828 + return -EINVAL;
  1829 + }
  1830 +
  1831 + *tsize += size;
  1832 +
  1833 + EVP_DigestUpdate(&ictx->md_ctx, cctx->data, asize);
  1834 + sb_aes_crypt(ictx, cctx->data, cctx->data, asize);
  1835 +
  1836 + if (ccmd->load.crc32 != crc32(cctx->data, asize)) {
  1837 + fprintf(stderr,
  1838 + "ERR: SB LOAD command payload CRC32 invalid!\n");
  1839 + return -EINVAL;
  1840 + }
  1841 + return 0;
  1842 + case ROM_FILL_CMD:
  1843 + soprintf(ictx,
  1844 + " FILL addr=0x%08x length=0x%08x pattern=0x%08x # %s\n",
  1845 + ccmd->fill.address, ccmd->fill.count,
  1846 + ccmd->fill.pattern, csum);
  1847 + return 0;
  1848 + case ROM_JUMP_CMD:
  1849 + if (ccmd->header.flags & ROM_JUMP_CMD_FLAG_HAB)
  1850 + flag = " HAB";
  1851 + soprintf(ictx,
  1852 + " JUMP%s addr=0x%08x r0_arg=0x%08x # %s\n",
  1853 + flag, ccmd->fill.address, ccmd->jump.argument, csum);
  1854 + return 0;
  1855 + case ROM_CALL_CMD:
  1856 + if (ccmd->header.flags & ROM_CALL_CMD_FLAG_HAB)
  1857 + flag = " HAB";
  1858 + soprintf(ictx,
  1859 + " CALL%s addr=0x%08x r0_arg=0x%08x # %s\n",
  1860 + flag, ccmd->fill.address, ccmd->jump.argument, csum);
  1861 + return 0;
  1862 + case ROM_MODE_CMD:
  1863 + for (i = 0; i < ARRAY_SIZE(modetable); i++) {
  1864 + if (ccmd->mode.mode == modetable[i].mode) {
  1865 + soprintf(ictx, " MODE %s # %s\n",
  1866 + modetable[i].name, csum);
  1867 + break;
  1868 + }
  1869 + }
  1870 + fprintf(stderr, " MODE !INVALID! # %s\n", csum);
  1871 + return 0;
  1872 + }
  1873 +
  1874 + return ret;
  1875 +}
  1876 +
  1877 +static int sb_verify_commands(struct sb_image_ctx *ictx,
  1878 + struct sb_section_ctx *sctx, FILE *fp)
  1879 +{
  1880 + unsigned long size, tsize = 0;
  1881 + struct sb_cmd_ctx *cctx;
  1882 + int ret;
  1883 +
  1884 + sb_aes_reinit(ictx, 0);
  1885 +
  1886 + while (tsize < sctx->size) {
  1887 + cctx = calloc(1, sizeof(*cctx));
  1888 + if (!cctx)
  1889 + return -ENOMEM;
  1890 + if (!sctx->cmd_head) {
  1891 + sctx->cmd_head = cctx;
  1892 + sctx->cmd_tail = cctx;
  1893 + } else {
  1894 + sctx->cmd_tail->cmd = cctx;
  1895 + sctx->cmd_tail = cctx;
  1896 + }
  1897 +
  1898 + size = fread(&cctx->c_payload, 1, sizeof(cctx->c_payload), fp);
  1899 + if (size != sizeof(cctx->c_payload)) {
  1900 + fprintf(stderr, "ERR: SB command header too short!\n");
  1901 + return -EINVAL;
  1902 + }
  1903 +
  1904 + tsize += size;
  1905 +
  1906 + sb_decrypt_tag(ictx, cctx);
  1907 +
  1908 + ret = sb_verify_command(ictx, cctx, fp, &tsize);
  1909 + if (ret)
  1910 + return -EINVAL;
  1911 + }
  1912 +
  1913 + return 0;
  1914 +}
  1915 +
  1916 +static int sb_verify_sections_cmds(struct sb_image_ctx *ictx, FILE *fp)
  1917 +{
  1918 + struct sb_boot_image_header *hdr = &ictx->payload;
  1919 + struct sb_sections_header *shdr;
  1920 + unsigned int i;
  1921 + int ret;
  1922 + struct sb_section_ctx *sctx;
  1923 + unsigned long size;
  1924 + char *bootable = "";
  1925 +
  1926 + soprintf(ictx, "----- Verifying SB Sections and Commands -----\n");
  1927 +
  1928 + for (i = 0; i < hdr->section_count; i++) {
  1929 + sctx = calloc(1, sizeof(*sctx));
  1930 + if (!sctx)
  1931 + return -ENOMEM;
  1932 + if (!ictx->sect_head) {
  1933 + ictx->sect_head = sctx;
  1934 + ictx->sect_tail = sctx;
  1935 + } else {
  1936 + ictx->sect_tail->sect = sctx;
  1937 + ictx->sect_tail = sctx;
  1938 + }
  1939 +
  1940 + size = fread(&sctx->payload, 1, sizeof(sctx->payload), fp);
  1941 + if (size != sizeof(sctx->payload)) {
  1942 + fprintf(stderr, "ERR: SB section header too short!\n");
  1943 + return -EINVAL;
  1944 + }
  1945 + }
  1946 +
  1947 + size = fread(&ictx->sb_dict_key, 1, sizeof(ictx->sb_dict_key), fp);
  1948 + if (size != sizeof(ictx->sb_dict_key)) {
  1949 + fprintf(stderr, "ERR: SB key dictionary too short!\n");
  1950 + return -EINVAL;
  1951 + }
  1952 +
  1953 + sb_encrypt_sb_sections_header(ictx);
  1954 + sb_aes_reinit(ictx, 0);
  1955 + sb_decrypt_key_dictionary_key(ictx);
  1956 +
  1957 + sb_aes_reinit(ictx, 0);
  1958 +
  1959 + sctx = ictx->sect_head;
  1960 + while (sctx) {
  1961 + shdr = &sctx->payload;
  1962 +
  1963 + if (shdr->section_flags & SB_SECTION_FLAG_BOOTABLE) {
  1964 + sctx->boot = 1;
  1965 + bootable = " BOOTABLE";
  1966 + }
  1967 +
  1968 + sctx->size = (shdr->section_size * SB_BLOCK_SIZE) +
  1969 + sizeof(struct sb_command);
  1970 + soprintf(ictx, "SECTION 0x%x%s # size = %i bytes\n",
  1971 + shdr->section_number, bootable, sctx->size);
  1972 +
  1973 + if (shdr->section_flags & ~SB_SECTION_FLAG_BOOTABLE)
  1974 + fprintf(stderr, " WARN: Unknown section flag(s) %08x\n",
  1975 + shdr->section_flags);
  1976 +
  1977 + if ((shdr->section_flags & SB_SECTION_FLAG_BOOTABLE) &&
  1978 + (hdr->first_boot_section_id != shdr->section_number)) {
  1979 + fprintf(stderr,
  1980 + " WARN: Bootable section does ID not match image header ID!\n");
  1981 + }
  1982 +
  1983 + ret = sb_verify_commands(ictx, sctx, fp);
  1984 + if (ret)
  1985 + return ret;
  1986 +
  1987 + sctx = sctx->sect;
  1988 + }
  1989 +
  1990 + /*
  1991 + * FIXME IDEA:
  1992 + * check if the first TAG command is at sctx->section_offset
  1993 + */
  1994 + return 0;
  1995 +}
  1996 +
  1997 +static int sb_verify_image_end(struct sb_image_ctx *ictx,
  1998 + FILE *fp, off_t filesz)
  1999 +{
  2000 + uint8_t digest[32];
  2001 + unsigned long size;
  2002 + off_t pos;
  2003 + int ret;
  2004 +
  2005 + soprintf(ictx, "------------- Verifying image end -------------\n");
  2006 +
  2007 + size = fread(digest, 1, sizeof(digest), fp);
  2008 + if (size != sizeof(digest)) {
  2009 + fprintf(stderr, "ERR: SB key dictionary too short!\n");
  2010 + return -EINVAL;
  2011 + }
  2012 +
  2013 + pos = ftell(fp);
  2014 + if (pos != filesz) {
  2015 + fprintf(stderr, "ERR: Trailing data past the image!\n");
  2016 + return -EINVAL;
  2017 + }
  2018 +
  2019 + /* Check the image digest. */
  2020 + EVP_DigestFinal(&ictx->md_ctx, ictx->digest, NULL);
  2021 +
  2022 + /* Decrypt the image digest from the input image. */
  2023 + sb_aes_reinit(ictx, 0);
  2024 + sb_aes_crypt(ictx, digest, digest, sizeof(digest));
  2025 +
  2026 + /* Check all of 20 bytes of the SHA1 hash. */
  2027 + ret = memcmp(digest, ictx->digest, 20) ? -EINVAL : 0;
  2028 +
  2029 + if (ret)
  2030 + soprintf(ictx, "[FAIL] Full-image checksum: BAD\n");
  2031 + else
  2032 + soprintf(ictx, "[PASS] Full-image checksum: OK\n");
  2033 +
  2034 + return ret;
  2035 +}
  2036 +
  2037 +
  2038 +static int sb_build_tree_from_img(struct sb_image_ctx *ictx)
  2039 +{
  2040 + long filesize;
  2041 + int ret;
  2042 + FILE *fp;
  2043 +
  2044 + if (!ictx->input_filename) {
  2045 + fprintf(stderr, "ERR: Missing filename!\n");
  2046 + return -EINVAL;
  2047 + }
  2048 +
  2049 + fp = fopen(ictx->input_filename, "r");
  2050 + if (!fp)
  2051 + goto err_open;
  2052 +
  2053 + ret = fseek(fp, 0, SEEK_END);
  2054 + if (ret < 0)
  2055 + goto err_file;
  2056 +
  2057 + filesize = ftell(fp);
  2058 + if (filesize < 0)
  2059 + goto err_file;
  2060 +
  2061 + ret = fseek(fp, 0, SEEK_SET);
  2062 + if (ret < 0)
  2063 + goto err_file;
  2064 +
  2065 + if (filesize < (signed)sizeof(ictx->payload)) {
  2066 + fprintf(stderr, "ERR: File too short!\n");
  2067 + goto err_file;
  2068 + }
  2069 +
  2070 + if (filesize & (SB_BLOCK_SIZE - 1)) {
  2071 + fprintf(stderr, "ERR: The file is not aligned!\n");
  2072 + goto err_file;
  2073 + }
  2074 +
  2075 + /* Load and verify image header */
  2076 + ret = sb_verify_image_header(ictx, fp, filesize);
  2077 + if (ret)
  2078 + goto err_verify;
  2079 +
  2080 + /* Load and verify sections and commands */
  2081 + ret = sb_verify_sections_cmds(ictx, fp);
  2082 + if (ret)
  2083 + goto err_verify;
  2084 +
  2085 + ret = sb_verify_image_end(ictx, fp, filesize);
  2086 + if (ret)
  2087 + goto err_verify;
  2088 +
  2089 + ret = 0;
  2090 +
  2091 +err_verify:
  2092 + soprintf(ictx, "-------------------- Result -------------------\n");
  2093 + soprintf(ictx, "Verification %s\n", ret ? "FAILED" : "PASSED");
  2094 +
  2095 + /* Stop the encryption session. */
  2096 + sb_aes_deinit(&ictx->cipher_ctx);
  2097 +
  2098 + fclose(fp);
  2099 + return ret;
  2100 +
  2101 +err_file:
  2102 + fclose(fp);
  2103 +err_open:
  2104 + fprintf(stderr, "ERR: Failed to load file \"%s\"\n",
  2105 + ictx->input_filename);
  2106 + return -EINVAL;
  2107 +}
  2108 +
  2109 +static void sb_free_image(struct sb_image_ctx *ictx)
  2110 +{
  2111 + struct sb_section_ctx *sctx = ictx->sect_head, *s_head;
  2112 + struct sb_dcd_ctx *dctx = ictx->dcd_head, *d_head;
  2113 + struct sb_cmd_ctx *cctx, *c_head;
  2114 +
  2115 + while (sctx) {
  2116 + s_head = sctx;
  2117 + c_head = sctx->cmd_head;
  2118 +
  2119 + while (c_head) {
  2120 + cctx = c_head;
  2121 + c_head = c_head->cmd;
  2122 + if (cctx->data)
  2123 + free(cctx->data);
  2124 + free(cctx);
  2125 + }
  2126 +
  2127 + sctx = sctx->sect;
  2128 + free(s_head);
  2129 + }
  2130 +
  2131 + while (dctx) {
  2132 + d_head = dctx;
  2133 + dctx = dctx->dcd;
  2134 + free(d_head->payload);
  2135 + free(d_head);
  2136 + }
  2137 +}
  2138 +
  2139 +/*
  2140 + * MXSSB-MKIMAGE glue code.
  2141 + */
  2142 +static int mxsimage_check_image_types(uint8_t type)
  2143 +{
  2144 + if (type == IH_TYPE_MXSIMAGE)
  2145 + return EXIT_SUCCESS;
  2146 + else
  2147 + return EXIT_FAILURE;
  2148 +}
  2149 +
  2150 +static void mxsimage_set_header(void *ptr, struct stat *sbuf, int ifd,
  2151 + struct mkimage_params *params)
  2152 +{
  2153 +}
  2154 +
  2155 +int mxsimage_check_params(struct mkimage_params *params)
  2156 +{
  2157 + if (!params)
  2158 + return -1;
  2159 + if (!strlen(params->imagename)) {
  2160 + fprintf(stderr,
  2161 + "Error: %s - Configuration file not specified, it is needed for mxsimage generation\n",
  2162 + params->cmdname);
  2163 + return -1;
  2164 + }
  2165 +
  2166 + /*
  2167 + * Check parameters:
  2168 + * XIP is not allowed and verify that incompatible
  2169 + * parameters are not sent at the same time
  2170 + * For example, if list is required a data image must not be provided
  2171 + */
  2172 + return (params->dflag && (params->fflag || params->lflag)) ||
  2173 + (params->fflag && (params->dflag || params->lflag)) ||
  2174 + (params->lflag && (params->dflag || params->fflag)) ||
  2175 + (params->xflag) || !(strlen(params->imagename));
  2176 +}
  2177 +
  2178 +static int mxsimage_verify_print_header(char *file, int silent)
  2179 +{
  2180 + int ret;
  2181 + struct sb_image_ctx ctx;
  2182 +
  2183 + memset(&ctx, 0, sizeof(ctx));
  2184 +
  2185 + ctx.input_filename = file;
  2186 + ctx.silent_dump = silent;
  2187 +
  2188 + ret = sb_build_tree_from_img(&ctx);
  2189 + sb_free_image(&ctx);
  2190 +
  2191 + return ret;
  2192 +}
  2193 +
  2194 +char *imagefile;
  2195 +static int mxsimage_verify_header(unsigned char *ptr, int image_size,
  2196 + struct mkimage_params *params)
  2197 +{
  2198 + struct sb_boot_image_header *hdr;
  2199 +
  2200 + if (!ptr)
  2201 + return -EINVAL;
  2202 +
  2203 + hdr = (struct sb_boot_image_header *)ptr;
  2204 +
  2205 + /*
  2206 + * Check if the header contains the MXS image signatures,
  2207 + * if so, do a full-image verification.
  2208 + */
  2209 + if (memcmp(hdr->signature1, "STMP", 4) ||
  2210 + memcmp(hdr->signature2, "sgtl", 4))
  2211 + return -EINVAL;
  2212 +
  2213 + imagefile = params->imagefile;
  2214 +
  2215 + return mxsimage_verify_print_header(params->imagefile, 1);
  2216 +}
  2217 +
  2218 +static void mxsimage_print_header(const void *hdr)
  2219 +{
  2220 + if (imagefile)
  2221 + mxsimage_verify_print_header(imagefile, 0);
  2222 +}
  2223 +
  2224 +static int sb_build_image(struct sb_image_ctx *ictx,
  2225 + struct image_type_params *tparams)
  2226 +{
  2227 + struct sb_boot_image_header *sb_header = &ictx->payload;
  2228 + struct sb_section_ctx *sctx;
  2229 + struct sb_cmd_ctx *cctx;
  2230 + struct sb_command *ccmd;
  2231 + struct sb_key_dictionary_key *sb_dict_key = &ictx->sb_dict_key;
  2232 +
  2233 + uint8_t *image, *iptr;
  2234 +
  2235 + /* Calculate image size. */
  2236 + uint32_t size = sizeof(*sb_header) +
  2237 + ictx->sect_count * sizeof(struct sb_sections_header) +
  2238 + sizeof(*sb_dict_key) + sizeof(ictx->digest);
  2239 +
  2240 + sctx = ictx->sect_head;
  2241 + while (sctx) {
  2242 + size += sctx->size;
  2243 + sctx = sctx->sect;
  2244 + };
  2245 +
  2246 + image = malloc(size);
  2247 + if (!image)
  2248 + return -ENOMEM;
  2249 + iptr = image;
  2250 +
  2251 + memcpy(iptr, sb_header, sizeof(*sb_header));
  2252 + iptr += sizeof(*sb_header);
  2253 +
  2254 + sctx = ictx->sect_head;
  2255 + while (sctx) {
  2256 + memcpy(iptr, &sctx->payload, sizeof(struct sb_sections_header));
  2257 + iptr += sizeof(struct sb_sections_header);
  2258 + sctx = sctx->sect;
  2259 + };
  2260 +
  2261 + memcpy(iptr, sb_dict_key, sizeof(*sb_dict_key));
  2262 + iptr += sizeof(*sb_dict_key);
  2263 +
  2264 + sctx = ictx->sect_head;
  2265 + while (sctx) {
  2266 + cctx = sctx->cmd_head;
  2267 + while (cctx) {
  2268 + ccmd = &cctx->payload;
  2269 +
  2270 + memcpy(iptr, &cctx->c_payload, sizeof(cctx->payload));
  2271 + iptr += sizeof(cctx->payload);
  2272 +
  2273 + if (ccmd->header.tag == ROM_LOAD_CMD) {
  2274 + memcpy(iptr, cctx->data, cctx->length);
  2275 + iptr += cctx->length;
  2276 + }
  2277 +
  2278 + cctx = cctx->cmd;
  2279 + }
  2280 +
  2281 + sctx = sctx->sect;
  2282 + };
  2283 +
  2284 + memcpy(iptr, ictx->digest, sizeof(ictx->digest));
  2285 + iptr += sizeof(ictx->digest);
  2286 +
  2287 + /* Configure the mkimage */
  2288 + tparams->hdr = image;
  2289 + tparams->header_size = size;
  2290 +
  2291 + return 0;
  2292 +}
  2293 +
  2294 +static int mxsimage_generate(struct mkimage_params *params,
  2295 + struct image_type_params *tparams)
  2296 +{
  2297 + int ret;
  2298 + struct sb_image_ctx ctx;
  2299 +
  2300 + /* Do not copy the U-Boot image! */
  2301 + params->skipcpy = 1;
  2302 +
  2303 + memset(&ctx, 0, sizeof(ctx));
  2304 +
  2305 + ctx.cfg_filename = params->imagename;
  2306 + ctx.output_filename = params->imagefile;
  2307 + ctx.verbose_boot = 1;
  2308 +
  2309 + ret = sb_build_tree_from_cfg(&ctx);
  2310 + if (ret)
  2311 + goto fail;
  2312 +
  2313 + ret = sb_encrypt_image(&ctx);
  2314 + if (!ret)
  2315 + ret = sb_build_image(&ctx, tparams);
  2316 +
  2317 +fail:
  2318 + sb_free_image(&ctx);
  2319 +
  2320 + return ret;
  2321 +}
  2322 +
  2323 +/*
  2324 + * mxsimage parameters
  2325 + */
  2326 +static struct image_type_params mxsimage_params = {
  2327 + .name = "Freescale MXS Boot Image support",
  2328 + .header_size = 0,
  2329 + .hdr = NULL,
  2330 + .check_image_type = mxsimage_check_image_types,
  2331 + .verify_header = mxsimage_verify_header,
  2332 + .print_header = mxsimage_print_header,
  2333 + .set_header = mxsimage_set_header,
  2334 + .check_params = mxsimage_check_params,
  2335 + .vrec_header = mxsimage_generate,
  2336 +};
  2337 +
  2338 +void init_mxs_image_type(void)
  2339 +{
  2340 + mkimage_register(&mxsimage_params);
  2341 +}
  2342 +
  2343 +#else
  2344 +void init_mxs_image_type(void)
  2345 +{
  2346 +}
  2347 +#endif
  1 +/*
  2 + * Freescale i.MX28 SB image generator
  3 + *
  4 + * Copyright (C) 2012 Marek Vasut <marex@denx.de>
  5 + *
  6 + * SPDX-License-Identifier: GPL-2.0+
  7 + */
  8 +
  9 +#ifndef __MXSSB_H__
  10 +#define __MXSSB_H__
  11 +
  12 +#include <stdint.h>
  13 +#include <arpa/inet.h>
  14 +
  15 +#define SB_BLOCK_SIZE 16
  16 +
  17 +#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
  18 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
  19 +
  20 +struct sb_boot_image_version {
  21 + uint16_t major;
  22 + uint16_t pad0;
  23 + uint16_t minor;
  24 + uint16_t pad1;
  25 + uint16_t revision;
  26 + uint16_t pad2;
  27 +};
  28 +
  29 +struct sb_boot_image_header {
  30 + union {
  31 + /* SHA1 of the header. */
  32 + uint8_t digest[20];
  33 + struct {
  34 + /* CBC-MAC initialization vector. */
  35 + uint8_t iv[16];
  36 + uint8_t extra[4];
  37 + };
  38 + };
  39 + /* 'STMP' */
  40 + uint8_t signature1[4];
  41 + /* Major version of the image format. */
  42 + uint8_t major_version;
  43 + /* Minor version of the image format. */
  44 + uint8_t minor_version;
  45 + /* Flags associated with the image. */
  46 + uint16_t flags;
  47 + /* Size of the image in 16b blocks. */
  48 + uint32_t image_blocks;
  49 + /* Offset of the first tag in 16b blocks. */
  50 + uint32_t first_boot_tag_block;
  51 + /* ID of the section to boot from. */
  52 + uint32_t first_boot_section_id;
  53 + /* Amount of crypto keys. */
  54 + uint16_t key_count;
  55 + /* Offset to the key dictionary in 16b blocks. */
  56 + uint16_t key_dictionary_block;
  57 + /* Size of this header in 16b blocks. */
  58 + uint16_t header_blocks;
  59 + /* Amount of section headers. */
  60 + uint16_t section_count;
  61 + /* Section header size in 16b blocks. */
  62 + uint16_t section_header_size;
  63 + /* Padding to align timestamp to uint64_t. */
  64 + uint8_t padding0[2];
  65 + /* 'sgtl' (since v1.1) */
  66 + uint8_t signature2[4];
  67 + /* Image generation date, in microseconds since 1.1.2000 . */
  68 + uint64_t timestamp_us;
  69 + /* Product version. */
  70 + struct sb_boot_image_version
  71 + product_version;
  72 + /* Component version. */
  73 + struct sb_boot_image_version
  74 + component_version;
  75 + /* Drive tag for the system drive. (since v1.1) */
  76 + uint16_t drive_tag;
  77 + /* Padding. */
  78 + uint8_t padding1[6];
  79 +};
  80 +
  81 +#define SB_VERSION_MAJOR 1
  82 +#define SB_VERSION_MINOR 1
  83 +
  84 +/* Enable to HTLLC verbose boot report. */
  85 +#define SB_IMAGE_FLAG_VERBOSE (1 << 0)
  86 +
  87 +struct sb_key_dictionary_key {
  88 + /* The CBC-MAC of image and sections header. */
  89 + uint8_t cbc_mac[SB_BLOCK_SIZE];
  90 + /* The AES key encrypted by image key (zero). */
  91 + uint8_t key[SB_BLOCK_SIZE];
  92 +};
  93 +
  94 +struct sb_ivt_header {
  95 + uint32_t header;
  96 + uint32_t entry;
  97 + uint32_t reserved1;
  98 + uint32_t dcd;
  99 + uint32_t boot_data;
  100 + uint32_t self;
  101 + uint32_t csf;
  102 + uint32_t reserved2;
  103 +};
  104 +
  105 +#define SB_HAB_IVT_TAG 0xd1UL
  106 +#define SB_HAB_DCD_TAG 0xd2UL
  107 +
  108 +#define SB_HAB_VERSION 0x40UL
  109 +
  110 +/*
  111 + * The "size" field in the IVT header is not naturally aligned,
  112 + * use this macro to fill first 4 bytes of the IVT header without
  113 + * causing issues on some systems (esp. M68k, PPC, MIPS-BE, ARM-BE).
  114 + */
  115 +static inline uint32_t sb_hab_ivt_header(void)
  116 +{
  117 + uint32_t ret = 0;
  118 + ret |= SB_HAB_IVT_TAG << 24;
  119 + ret |= sizeof(struct sb_ivt_header) << 16;
  120 + ret |= SB_HAB_VERSION;
  121 + return htonl(ret);
  122 +}
  123 +
  124 +struct sb_sections_header {
  125 + /* Section number. */
  126 + uint32_t section_number;
  127 + /* Offset of this sections first instruction after "TAG". */
  128 + uint32_t section_offset;
  129 + /* Size of the section in 16b blocks. */
  130 + uint32_t section_size;
  131 + /* Section flags. */
  132 + uint32_t section_flags;
  133 +};
  134 +
  135 +#define SB_SECTION_FLAG_BOOTABLE (1 << 0)
  136 +
  137 +struct sb_command {
  138 + struct {
  139 + uint8_t checksum;
  140 + uint8_t tag;
  141 + uint16_t flags;
  142 +#define ROM_TAG_CMD_FLAG_ROM_LAST_TAG 0x1
  143 +#define ROM_LOAD_CMD_FLAG_DCD_LOAD 0x1 /* MX28 only */
  144 +#define ROM_JUMP_CMD_FLAG_HAB 0x1 /* MX28 only */
  145 +#define ROM_CALL_CMD_FLAG_HAB 0x1 /* MX28 only */
  146 + } header;
  147 +
  148 + union {
  149 + struct {
  150 + uint32_t reserved[3];
  151 + } nop;
  152 + struct {
  153 + uint32_t section_number;
  154 + uint32_t section_length;
  155 + uint32_t section_flags;
  156 + } tag;
  157 + struct {
  158 + uint32_t address;
  159 + uint32_t count;
  160 + uint32_t crc32;
  161 + } load;
  162 + struct {
  163 + uint32_t address;
  164 + uint32_t count;
  165 + uint32_t pattern;
  166 + } fill;
  167 + struct {
  168 + uint32_t address;
  169 + uint32_t reserved;
  170 + /* Passed in register r0 before JUMP */
  171 + uint32_t argument;
  172 + } jump;
  173 + struct {
  174 + uint32_t address;
  175 + uint32_t reserved;
  176 + /* Passed in register r0 before CALL */
  177 + uint32_t argument;
  178 + } call;
  179 + struct {
  180 + uint32_t reserved1;
  181 + uint32_t reserved2;
  182 + uint32_t mode;
  183 + } mode;
  184 +
  185 + };
  186 +};
  187 +
  188 +/*
  189 + * Most of the mode names are same or at least similar
  190 + * on i.MX23 and i.MX28, but some of the mode names
  191 + * differ. The "name" field represents the mode name
  192 + * on i.MX28 as seen in Table 12-2 of the datasheet.
  193 + * The "altname" field represents the differently named
  194 + * fields on i.MX23 as seen in Table 35-3 of the
  195 + * datasheet.
  196 + */
  197 +static const struct {
  198 + const char *name;
  199 + const char *altname;
  200 + const uint8_t mode;
  201 +} modetable[] = {
  202 + { "USB", NULL, 0x00 },
  203 + { "I2C", NULL, 0x01 },
  204 + { "SPI2_FLASH", "SPI1_FLASH", 0x02 },
  205 + { "SPI3_FLASH", "SPI2_FLASH", 0x03 },
  206 + { "NAND_BCH", NULL, 0x04 },
  207 + { "JTAG", NULL, 0x06 },
  208 + { "SPI3_EEPROM", "SPI2_EEPROM", 0x08 },
  209 + { "SD_SSP0", NULL, 0x09 },
  210 + { "SD_SSP1", NULL, 0x0A }
  211 +};
  212 +
  213 +enum sb_tag {
  214 + ROM_NOP_CMD = 0x00,
  215 + ROM_TAG_CMD = 0x01,
  216 + ROM_LOAD_CMD = 0x02,
  217 + ROM_FILL_CMD = 0x03,
  218 + ROM_JUMP_CMD = 0x04,
  219 + ROM_CALL_CMD = 0x05,
  220 + ROM_MODE_CMD = 0x06
  221 +};
  222 +
  223 +struct sb_source_entry {
  224 + uint8_t tag;
  225 + uint32_t address;
  226 + uint32_t flags;
  227 + char *filename;
  228 +};
  229 +
  230 +#endif /* __MXSSB_H__ */