Commit 19d829fa60fc4e6df514a046142faaaf9fc8185d

Authored by Albert ARIBAUD
Exists in master and in 56 other branches 8qm-imx_v2020.04_5.4.70_2.3.0, emb_lf-6.6.52-2.2.0, emb_lf_v2022.04, emb_lf_v2023.04, emb_lf_v2024.04, imx_v2015.04_4.1.15_1.0.0_ga, pitx_8mp_lf_v2020.04, smarc-8m-android-10.0.0_2.6.0, smarc-8m-android-11.0.0_2.0.0, smarc-8mp-android-11.0.0_2.0.0, smarc-emmc-imx_v2014.04_3.10.53_1.1.0_ga, smarc-emmc-imx_v2014.04_3.14.28_1.0.0_ga, smarc-imx-l5.0.0_1.0.0-ga, smarc-imx6_v2018.03_4.14.98_2.0.0_ga, smarc-imx7_v2017.03_4.9.11_1.0.0_ga, smarc-imx7_v2018.03_4.14.98_2.0.0_ga, smarc-imx_v2014.04_3.14.28_1.0.0_ga, smarc-imx_v2015.04_4.1.15_1.0.0_ga, smarc-imx_v2017.03_4.9.11_1.0.0_ga, smarc-imx_v2017.03_4.9.88_2.0.0_ga, smarc-imx_v2017.03_o8.1.0_1.3.0_8m, smarc-imx_v2018.03_4.14.78_1.0.0_ga, smarc-m6.0.1_2.1.0-ga, smarc-n7.1.2_2.0.0-ga, smarc-rel_imx_4.1.15_2.0.0_ga, smarc_8m-imx_v2018.03_4.14.98_2.0.0_ga, smarc_8m-imx_v2019.04_4.19.35_1.1.0, smarc_8m_00d0-imx_v2018.03_4.14.98_2.0.0_ga, smarc_8mm-imx_v2018.03_4.14.98_2.0.0_ga, smarc_8mm-imx_v2019.04_4.19.35_1.1.0, smarc_8mm-imx_v2020.04_5.4.24_2.1.0, smarc_8mp_lf_v2020.04, smarc_8mq-imx_v2020.04_5.4.24_2.1.0, smarc_8mq_lf_v2020.04, ti-u-boot-2015.07, v2013.10, v2013.10-smarct33, v2013.10-smartmen, v2014.01, v2014.04, v2014.04-smarct33, v2014.04-smarct33-emmc, v2014.04-smartmen, v2014.07, v2014.07-smarct33, v2014.07-smartmen, v2015.07-smarct33, v2015.07-smarct33-emmc, v2015.07-smarct4x, v2016.05-dlt, v2016.05-smarct3x, v2016.05-smarct3x-emmc, v2016.05-smarct4x, v2017.01-smarct3x, v2017.01-smarct3x-emmc, v2017.01-smarct4x

Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'

Conflicts:
	drivers/serial/serial.c

The conflict above was a trivial case of adding one init
function in each branch, and manually resolved in merge.

Showing 33 changed files 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
arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
... ... @@ -36,7 +36,7 @@
36 36 CLKCTRL_CLKSEQ_BYPASS_CPU);
37 37 }
38 38  
39   -static void mxs_power_clear_auto_restart(void)
  39 +static void mxs_power_set_auto_restart(void)
40 40 {
41 41 struct mxs_rtc_regs *rtc_regs =
42 42 (struct mxs_rtc_regs *)MXS_RTC_BASE;
... ... @@ -49,10 +49,7 @@
49 49 while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
50 50 ;
51 51  
52   - /*
53   - * Due to the hardware design bug of mx28 EVK-A
54   - * we need to set the AUTO_RESTART bit.
55   - */
  52 + /* Do nothing if flag already set */
56 53 if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
57 54 return;
58 55  
... ... @@ -911,7 +908,7 @@
911 908 mxs_ungate_power();
912 909  
913 910 mxs_power_clock2xtal();
914   - mxs_power_clear_auto_restart();
  911 + mxs_power_set_auto_restart();
915 912 mxs_power_set_linreg();
916 913 mxs_power_setup_5v_detect();
917 914  
arch/arm/cpu/armv7/mx6/Makefile
... ... @@ -11,10 +11,11 @@
11 11  
12 12 LIB = $(obj)lib$(SOC).o
13 13  
14   -COBJS = soc.o clock.o
  14 +COBJS-y = soc.o clock.o
  15 +COBJS-$(CONFIG_SECURE_BOOT) += hab.o
15 16  
16   -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
17   -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
  17 +SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
  18 +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
18 19  
19 20 all: $(obj).depend $(LIB)
20 21  
arch/arm/cpu/armv7/mx6/hab.c
  1 +/*
  2 + * Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#include <common.h>
  8 +#include <asm/io.h>
  9 +#include <asm/arch/hab.h>
  10 +
  11 +/* -------- start of HAB API updates ------------*/
  12 +#define hab_rvt_report_event ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT)
  13 +#define hab_rvt_report_status ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS)
  14 +#define hab_rvt_authenticate_image \
  15 + ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE)
  16 +#define hab_rvt_entry ((hab_rvt_entry_t *)HAB_RVT_ENTRY)
  17 +#define hab_rvt_exit ((hab_rvt_exit_t *)HAB_RVT_EXIT)
  18 +#define hab_rvt_clock_init HAB_RVT_CLOCK_INIT
  19 +
  20 +bool is_hab_enabled(void)
  21 +{
  22 + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
  23 + struct fuse_bank *bank = &ocotp->bank[0];
  24 + struct fuse_bank0_regs *fuse =
  25 + (struct fuse_bank0_regs *)bank->fuse_regs;
  26 + uint32_t reg = readl(&fuse->cfg5);
  27 +
  28 + return (reg & 0x2) == 0x2;
  29 +}
  30 +
  31 +void display_event(uint8_t *event_data, size_t bytes)
  32 +{
  33 + uint32_t i;
  34 +
  35 + if (!(event_data && bytes > 0))
  36 + return;
  37 +
  38 + for (i = 0; i < bytes; i++) {
  39 + if (i == 0)
  40 + printf("\t0x%02x", event_data[i]);
  41 + else if ((i % 8) == 0)
  42 + printf("\n\t0x%02x", event_data[i]);
  43 + else
  44 + printf(" 0x%02x", event_data[i]);
  45 + }
  46 +}
  47 +
  48 +int get_hab_status(void)
  49 +{
  50 + uint32_t index = 0; /* Loop index */
  51 + uint8_t event_data[128]; /* Event data buffer */
  52 + size_t bytes = sizeof(event_data); /* Event size in bytes */
  53 + enum hab_config config = 0;
  54 + enum hab_state state = 0;
  55 +
  56 + if (is_hab_enabled())
  57 + puts("\nSecure boot enabled\n");
  58 + else
  59 + puts("\nSecure boot disabled\n");
  60 +
  61 + /* Check HAB status */
  62 + if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) {
  63 + printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
  64 + config, state);
  65 +
  66 + /* Display HAB Error events */
  67 + while (hab_rvt_report_event(HAB_FAILURE, index, event_data,
  68 + &bytes) == HAB_SUCCESS) {
  69 + puts("\n");
  70 + printf("--------- HAB Event %d -----------------\n",
  71 + index + 1);
  72 + puts("event data:\n");
  73 + display_event(event_data, bytes);
  74 + puts("\n");
  75 + bytes = sizeof(event_data);
  76 + index++;
  77 + }
  78 + }
  79 + /* Display message if no HAB events are found */
  80 + else {
  81 + printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
  82 + config, state);
  83 + puts("No HAB Events Found!\n\n");
  84 + }
  85 + return 0;
  86 +}
  87 +
  88 +int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  89 +{
  90 + if ((argc != 1)) {
  91 + cmd_usage(cmdtp);
  92 + return 1;
  93 + }
  94 +
  95 + get_hab_status();
  96 +
  97 + return 0;
  98 +}
  99 +
  100 +U_BOOT_CMD(
  101 + hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
  102 + "display HAB status",
  103 + ""
  104 + );
arch/arm/cpu/armv7/mx6/soc.c
... ... @@ -213,6 +213,34 @@
213 213  
214 214 void s_init(void)
215 215 {
  216 + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
  217 + int is_6q = is_cpu_type(MXC_CPU_MX6Q);
  218 + u32 mask480;
  219 + u32 mask528;
  220 +
  221 + /* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs
  222 + * to make sure PFD is working right, otherwise, PFDs may
  223 + * not output clock after reset, MX6DL and MX6SL have added 396M pfd
  224 + * workaround in ROM code, as bus clock need it
  225 + */
  226 +
  227 + mask480 = ANATOP_PFD_CLKGATE_MASK(0) |
  228 + ANATOP_PFD_CLKGATE_MASK(1) |
  229 + ANATOP_PFD_CLKGATE_MASK(2) |
  230 + ANATOP_PFD_CLKGATE_MASK(3);
  231 + mask528 = ANATOP_PFD_CLKGATE_MASK(0) |
  232 + ANATOP_PFD_CLKGATE_MASK(1) |
  233 + ANATOP_PFD_CLKGATE_MASK(3);
  234 +
  235 + /*
  236 + * Don't reset PFD2 on DL/S
  237 + */
  238 + if (is_6q)
  239 + mask528 |= ANATOP_PFD_CLKGATE_MASK(2);
  240 + writel(mask480, &anatop->pfd_480_set);
  241 + writel(mask528, &anatop->pfd_528_set);
  242 + writel(mask480, &anatop->pfd_480_clr);
  243 + writel(mask528, &anatop->pfd_528_clr);
216 244 }
217 245  
218 246 #ifdef CONFIG_IMX_HDMI
arch/arm/include/asm/arch-mx6/hab.h
  1 +/*
  2 + * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + *
  6 +*/
  7 +
  8 +#ifndef __SECURE_MX6Q_H__
  9 +#define __SECURE_MX6Q_H__
  10 +
  11 +#include <linux/types.h>
  12 +
  13 +/* -------- start of HAB API updates ------------*/
  14 +/* The following are taken from HAB4 SIS */
  15 +
  16 +/* Status definitions */
  17 +enum hab_status {
  18 + HAB_STS_ANY = 0x00,
  19 + HAB_FAILURE = 0x33,
  20 + HAB_WARNING = 0x69,
  21 + HAB_SUCCESS = 0xf0
  22 +};
  23 +
  24 +/* Security Configuration definitions */
  25 +enum hab_config {
  26 + HAB_CFG_RETURN = 0x33, /**< Field Return IC */
  27 + HAB_CFG_OPEN = 0xf0, /**< Non-secure IC */
  28 + HAB_CFG_CLOSED = 0xcc /**< Secure IC */
  29 +};
  30 +
  31 +/* State definitions */
  32 +enum hab_state {
  33 + HAB_STATE_INITIAL = 0x33, /**< Initialising state (transitory) */
  34 + HAB_STATE_CHECK = 0x55, /**< Check state (non-secure) */
  35 + HAB_STATE_NONSECURE = 0x66, /**< Non-secure state */
  36 + HAB_STATE_TRUSTED = 0x99, /**< Trusted state */
  37 + HAB_STATE_SECURE = 0xaa, /**< Secure state */
  38 + HAB_STATE_FAIL_SOFT = 0xcc, /**< Soft fail state */
  39 + HAB_STATE_FAIL_HARD = 0xff, /**< Hard fail state (terminal) */
  40 + HAB_STATE_NONE = 0xf0, /**< No security state machine */
  41 + HAB_STATE_MAX
  42 +};
  43 +
  44 +/*Function prototype description*/
  45 +typedef enum hab_status hab_rvt_report_event_t(enum hab_status, uint32_t,
  46 + uint8_t* , size_t*);
  47 +typedef enum hab_status hab_rvt_report_status_t(enum hab_config *,
  48 + enum hab_state *);
  49 +typedef enum hab_status hab_loader_callback_f_t(void**, size_t*, const void*);
  50 +typedef enum hab_status hab_rvt_entry_t(void);
  51 +typedef enum hab_status hab_rvt_exit_t(void);
  52 +typedef void *hab_rvt_authenticate_image_t(uint8_t, ptrdiff_t,
  53 + void **, size_t *, hab_loader_callback_f_t);
  54 +typedef void hapi_clock_init_t(void);
  55 +
  56 +#define HAB_RVT_REPORT_EVENT (*(uint32_t *)0x000000B4)
  57 +#define HAB_RVT_REPORT_STATUS (*(uint32_t *)0x000000B8)
  58 +#define HAB_RVT_AUTHENTICATE_IMAGE (*(uint32_t *)0x000000A4)
  59 +#define HAB_RVT_ENTRY (*(uint32_t *)0x00000098)
  60 +#define HAB_RVT_EXIT (*(uint32_t *)0x0000009C)
  61 +#define HAB_RVT_CLOCK_INIT ((hapi_clock_init_t *)0x0000024D)
  62 +
  63 +#define HAB_CID_ROM 0 /**< ROM Caller ID */
  64 +#define HAB_CID_UBOOT 1 /**< UBOOT Caller ID*/
  65 +/* ----------- end of HAB API updates ------------*/
  66 +
  67 +#endif
arch/arm/include/asm/arch-mx6/imx-regs.h
... ... @@ -456,7 +456,13 @@
456 456 u32 uid_low;
457 457 u32 rsvd1[3];
458 458 u32 uid_high;
459   - u32 rsvd2[0x17];
  459 + u32 rsvd2[3];
  460 + u32 rsvd3[4];
  461 + u32 rsvd4[4];
  462 + u32 rsvd5[4];
  463 + u32 cfg5;
  464 + u32 rsvd6[3];
  465 + u32 rsvd7[4];
460 466 };
461 467  
462 468 struct fuse_bank4_regs {
... ... @@ -629,29 +635,12 @@
629 635 u32 digprog_sololite; /* 0x280 */
630 636 };
631 637  
632   -#define ANATOP_PFD_480_PFD0_FRAC_SHIFT 0
633   -#define ANATOP_PFD_480_PFD0_FRAC_MASK (0x3f<<ANATOP_PFD_480_PFD0_FRAC_SHIFT)
634   -#define ANATOP_PFD_480_PFD0_STABLE_SHIFT 6
635   -#define ANATOP_PFD_480_PFD0_STABLE_MASK (1<<ANATOP_PFD_480_PFD0_STABLE_SHIFT)
636   -#define ANATOP_PFD_480_PFD0_CLKGATE_SHIFT 7
637   -#define ANATOP_PFD_480_PFD0_CLKGATE_MASK (1<<ANATOP_PFD_480_PFD0_CLKGATE_SHIFT)
638   -#define ANATOP_PFD_480_PFD1_FRAC_SHIFT 8
639   -#define ANATOP_PFD_480_PFD1_FRAC_MASK (0x3f<<ANATOP_PFD_480_PFD1_FRAC_SHIFT)
640   -#define ANATOP_PFD_480_PFD1_STABLE_SHIFT 14
641   -#define ANATOP_PFD_480_PFD1_STABLE_MASK (1<<ANATOP_PFD_480_PFD1_STABLE_SHIFT)
642   -#define ANATOP_PFD_480_PFD1_CLKGATE_SHIFT 15
643   -#define ANATOP_PFD_480_PFD1_CLKGATE_MASK (0x3f<<ANATOP_PFD_480_PFD1_CLKGATE_SHIFT)
644   -#define ANATOP_PFD_480_PFD2_FRAC_SHIFT 16
645   -#define ANATOP_PFD_480_PFD2_FRAC_MASK (1<<ANATOP_PFD_480_PFD2_FRAC_SHIFT)
646   -#define ANATOP_PFD_480_PFD2_STABLE_SHIFT 22
647   -#define ANATOP_PFD_480_PFD2_STABLE_MASK (1<<ANATOP_PFD_480_PFD2_STABLE_SHIFT)
648   -#define ANATOP_PFD_480_PFD2_CLKGATE_SHIFT 23
649   -#define ANATOP_PFD_480_PFD2_CLKGATE_MASK (0x3f<<ANATOP_PFD_480_PFD2_CLKGATE_SHIFT)
650   -#define ANATOP_PFD_480_PFD3_FRAC_SHIFT 24
651   -#define ANATOP_PFD_480_PFD3_FRAC_MASK (1<<ANATOP_PFD_480_PFD3_FRAC_SHIFT)
652   -#define ANATOP_PFD_480_PFD3_STABLE_SHIFT 30
653   -#define ANATOP_PFD_480_PFD3_STABLE_MASK (1<<ANATOP_PFD_480_PFD3_STABLE_SHIFT)
654   -#define ANATOP_PFD_480_PFD3_CLKGATE_SHIFT 31
  638 +#define ANATOP_PFD_FRAC_SHIFT(n) ((n)*8)
  639 +#define ANATOP_PFD_FRAC_MASK(n) (0x3f<<ANATOP_PFD_FRAC_SHIFT(n))
  640 +#define ANATOP_PFD_STABLE_SHIFT(n) (6+((n)*8))
  641 +#define ANATOP_PFD_STABLE_MASK(n) (1<<ANATOP_PFD_STABLE_SHIFT(n))
  642 +#define ANATOP_PFD_CLKGATE_SHIFT(n) (7+((n)*8))
  643 +#define ANATOP_PFD_CLKGATE_MASK(n) (1<<ANATOP_PFD_CLKGATE_SHIFT(n))
655 644  
656 645 struct iomuxc_base_regs {
657 646 u32 gpr[14]; /* 0x000 */
arch/arm/include/asm/arch-mx6/sys_proto.h
... ... @@ -19,6 +19,13 @@
19 19  
20 20 #define is_soc_rev(rev) ((get_cpu_rev() & 0xFF) - rev)
21 21 u32 get_cpu_rev(void);
  22 +
  23 +/* returns MXC_CPU_ value */
  24 +#define cpu_type(rev) (((rev) >> 12)&0xff)
  25 +
  26 +/* use with MXC_CPU_ constants */
  27 +#define is_cpu_type(cpu) (cpu_type(get_cpu_rev()) == cpu)
  28 +
22 29 const char *get_imx_type(u32 imxtype);
23 30 unsigned imx_ddr_size(void);
24 31  
arch/arm/include/asm/arch-mxs/regs-uartapp.h
  1 +/*
  2 + * Freescale MXS UARTAPP Register Definitions
  3 + *
  4 + * Copyright (C) 2013 Andreas Wass <andreas.wass@dalelven.com>
  5 + *
  6 + * Based on code from LTIB:
  7 + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
  8 + *
  9 + * SPDX-License-Identifier: GPL-2.0+
  10 + */
  11 +
  12 +#ifndef __ARCH_ARM___MXS_UARTAPP_H
  13 +#define __ARCH_ARM___MXS_UARTAPP_H
  14 +
  15 +#include <asm/imx-common/regs-common.h>
  16 +
  17 +#ifndef __ASSEMBLY__
  18 +struct mxs_uartapp_regs {
  19 + mxs_reg_32(hw_uartapp_ctrl0)
  20 + mxs_reg_32(hw_uartapp_ctrl1)
  21 + mxs_reg_32(hw_uartapp_ctrl2)
  22 + mxs_reg_32(hw_uartapp_linectrl)
  23 + mxs_reg_32(hw_uartapp_linectrl2)
  24 + mxs_reg_32(hw_uartapp_intr)
  25 + mxs_reg_32(hw_uartapp_data)
  26 + mxs_reg_32(hw_uartapp_stat)
  27 + mxs_reg_32(hw_uartapp_debug)
  28 + mxs_reg_32(hw_uartapp_version)
  29 + mxs_reg_32(hw_uartapp_autobaud)
  30 +};
  31 +#endif
  32 +
  33 +#define UARTAPP_CTRL0_SFTRST_MASK (1 << 31)
  34 +#define UARTAPP_CTRL0_CLKGATE_MASK (1 << 30)
  35 +#define UARTAPP_CTRL0_RUN_MASK (1 << 29)
  36 +#define UARTAPP_CTRL0_RX_SOURCE_MASK (1 << 28)
  37 +#define UARTAPP_CTRL0_RXTO_ENABLE_MASK (1 << 27)
  38 +#define UARTAPP_CTRL0_RXTIMEOUT_OFFSET 16
  39 +#define UARTAPP_CTRL0_RXTIMEOUT_MASK (0x7FF << 16)
  40 +#define UARTAPP_CTRL0_XFER_COUNT_OFFSET 0
  41 +#define UARTAPP_CTRL0_XFER_COUNT_MASK 0xFFFF
  42 +
  43 +#define UARTAPP_CTRL1_RUN_MASK (1 << 28)
  44 +
  45 +#define UARTAPP_CTRL1_XFER_COUNT_OFFSET 0
  46 +#define UARTAPP_CTRL1_XFER_COUNT_MASK 0xFFFF
  47 +
  48 +#define UARTAPP_CTRL2_INVERT_RTS_MASK (1 << 31)
  49 +#define UARTAPP_CTRL2_INVERT_CTS_MASK (1 << 30)
  50 +#define UARTAPP_CTRL2_INVERT_TX_MASK (1 << 29)
  51 +#define UARTAPP_CTRL2_INVERT_RX_MASK (1 << 28)
  52 +#define UARTAPP_CTRL2_RTS_SEMAPHORE_MASK (1 << 27)
  53 +#define UARTAPP_CTRL2_DMAONERR_MASK (1 << 26)
  54 +#define UARTAPP_CTRL2_TXDMAE_MASK (1 << 25)
  55 +#define UARTAPP_CTRL2_RXDMAE_MASK (1 << 24)
  56 +#define UARTAPP_CTRL2_RXIFLSEL_OFFSET 20
  57 +#define UARTAPP_CTRL2_RXIFLSEL_MASK (0x7 << 20)
  58 +
  59 +#define UARTAPP_CTRL2_RXIFLSEL_NOT_EMPTY (0x0 << 20)
  60 +#define UARTAPP_CTRL2_RXIFLSEL_ONE_QUARTER (0x1 << 20)
  61 +#define UARTAPP_CTRL2_RXIFLSEL_ONE_HALF (0x2 << 20)
  62 +#define UARTAPP_CTRL2_RXIFLSEL_THREE_QUARTERS (0x3 << 20)
  63 +#define UARTAPP_CTRL2_RXIFLSEL_SEVEN_EIGHTHS (0x4 << 20)
  64 +#define UARTAPP_CTRL2_RXIFLSEL_INVALID5 (0x5 << 20)
  65 +#define UARTAPP_CTRL2_RXIFLSEL_INVALID6 (0x6 << 20)
  66 +#define UARTAPP_CTRL2_RXIFLSEL_INVALID7 (0x7 << 20)
  67 +#define UARTAPP_CTRL2_TXIFLSEL_OFFSET 16
  68 +#define UARTAPP_CTRL2_TXIFLSEL_MASK (0x7 << 16)
  69 +#define UARTAPP_CTRL2_TXIFLSEL_EMPTY (0x0 << 16)
  70 +#define UARTAPP_CTRL2_TXIFLSEL_ONE_QUARTER (0x1 << 16)
  71 +#define UARTAPP_CTRL2_TXIFLSEL_ONE_HALF (0x2 << 16)
  72 +#define UARTAPP_CTRL2_TXIFLSEL_THREE_QUARTERS (0x3 << 16)
  73 +#define UARTAPP_CTRL2_TXIFLSEL_SEVEN_EIGHTHS (0x4 << 16)
  74 +#define UARTAPP_CTRL2_TXIFLSEL_INVALID5 (0x5 << 16)
  75 +#define UARTAPP_CTRL2_TXIFLSEL_INVALID6 (0x6 << 16)
  76 +#define UARTAPP_CTRL2_TXIFLSEL_INVALID7 (0x7 << 16)
  77 +#define UARTAPP_CTRL2_CTSEN_MASK (1 << 15)
  78 +#define UARTAPP_CTRL2_RTSEN_MASK (1 << 14)
  79 +#define UARTAPP_CTRL2_OUT2_MASK (1 << 13)
  80 +#define UARTAPP_CTRL2_OUT1_MASK (1 << 12)
  81 +#define UARTAPP_CTRL2_RTS_MASK (1 << 11)
  82 +#define UARTAPP_CTRL2_DTR_MASK (1 << 10)
  83 +#define UARTAPP_CTRL2_RXE_MASK (1 << 9)
  84 +#define UARTAPP_CTRL2_TXE_MASK (1 << 8)
  85 +#define UARTAPP_CTRL2_LBE_MASK (1 << 7)
  86 +#define UARTAPP_CTRL2_USE_LCR2_MASK (1 << 6)
  87 +
  88 +#define UARTAPP_CTRL2_SIRLP_MASK (1 << 2)
  89 +#define UARTAPP_CTRL2_SIREN_MASK (1 << 1)
  90 +#define UARTAPP_CTRL2_UARTEN_MASK 0x01
  91 +
  92 +#define UARTAPP_LINECTRL_BAUD_DIVINT_OFFSET 16
  93 +#define UARTAPP_LINECTRL_BAUD_DIVINT_MASK (0xFFFF << 16)
  94 +#define UARTAPP_LINECTRL_EXTRACT_BAUD_DIVINT_OFFSET 6
  95 +
  96 +#define UARTAPP_LINECTRL_BAUD_DIVFRAC_OFFSET 8
  97 +#define UARTAPP_LINECTRL_BAUD_DIVFRAC_MASK (0x3F << 8)
  98 +#define UARTAPP_LINECTRL_EXTRACT_BAUD_DIVFRAC_MASK 0x3F
  99 +
  100 +#define UARTAPP_LINECTRL_SPS_MASK (1 << 7)
  101 +#define UARTAPP_LINECTRL_WLEN_OFFSET 5
  102 +#define UARTAPP_LINECTRL_WLEN_MASK (0x03 << 5)
  103 +#define UARTAPP_LINECTRL_WLEN_5BITS (0x00 << 5)
  104 +#define UARTAPP_LINECTRL_WLEN_6BITS (0x01 << 5)
  105 +#define UARTAPP_LINECTRL_WLEN_7BITS (0x02 << 5)
  106 +#define UARTAPP_LINECTRL_WLEN_8BITS (0x03 << 5)
  107 +
  108 +#define UARTAPP_LINECTRL_FEN_MASK (1 << 4)
  109 +#define UARTAPP_LINECTRL_STP2_MASK (1 << 3)
  110 +#define UARTAPP_LINECTRL_EPS_MASK (1 << 2)
  111 +#define UARTAPP_LINECTRL_PEN_MASK (1 << 1)
  112 +#define UARTAPP_LINECTRL_BRK_MASK 1
  113 +
  114 +#define UARTAPP_LINECTRL2_BAUD_DIVINT_OFFSET 16
  115 +#define UARTAPP_LINECTRL2_BAUD_DIVINT_MASK (0xFFFF << 16)
  116 +#define UARTAPP_LINECTRL2_EXTRACT_BAUD_DIVINT_OFFSET 6
  117 +
  118 +#define UARTAPP_LINECTRL2_BAUD_DIVFRAC_OFFSET 8
  119 +#define UARTAPP_LINECTRL2_BAUD_DIVFRAC_MASK (0x3F << 8)
  120 +#define UARTAPP_LINECTRL2_EXTRACT_BAUD_DIVFRAC_MASK 0x3F
  121 +
  122 +#define UARTAPP_LINECTRL2_SPS_MASK (1 << 7)
  123 +#define UARTAPP_LINECTRL2_WLEN_OFFSET 5
  124 +#define UARTAPP_LINECTRL2_WLEN_MASK (0x03 << 5)
  125 +#define UARTAPP_LINECTRL2_WLEN_5BITS (0x00 << 5)
  126 +#define UARTAPP_LINECTRL2_WLEN_6BITS (0x01 << 5)
  127 +#define UARTAPP_LINECTRL2_WLEN_7BITS (0x02 << 5)
  128 +#define UARTAPP_LINECTRL2_WLEN_8BITS (0x03 << 5)
  129 +
  130 +#define UARTAPP_LINECTRL2_FEN_MASK (1 << 4)
  131 +#define UARTAPP_LINECTRL2_STP2_MASK (1 << 3)
  132 +#define UARTAPP_LINECTRL2_EPS_MASK (1 << 2)
  133 +#define UARTAPP_LINECTRL2_PEN_MASK (1 << 1)
  134 +
  135 +#define UARTAPP_INTR_ABDIEN_MASK (1 << 27)
  136 +#define UARTAPP_INTR_OEIEN_MASK (1 << 26)
  137 +#define UARTAPP_INTR_BEIEN_MASK (1 << 25)
  138 +#define UARTAPP_INTR_PEIEN_MASK (1 << 24)
  139 +#define UARTAPP_INTR_FEIEN_MASK (1 << 23)
  140 +#define UARTAPP_INTR_RTIEN_MASK (1 << 22)
  141 +#define UARTAPP_INTR_TXIEN_MASK (1 << 21)
  142 +#define UARTAPP_INTR_RXIEN_MASK (1 << 20)
  143 +#define UARTAPP_INTR_DSRMIEN_MASK (1 << 19)
  144 +#define UARTAPP_INTR_DCDMIEN_MASK (1 << 18)
  145 +#define UARTAPP_INTR_CTSMIEN_MASK (1 << 17)
  146 +#define UARTAPP_INTR_RIMIEN_MASK (1 << 16)
  147 +
  148 +#define UARTAPP_INTR_ABDIS_MASK (1 << 11)
  149 +#define UARTAPP_INTR_OEIS_MASK (1 << 10)
  150 +#define UARTAPP_INTR_BEIS_MASK (1 << 9)
  151 +#define UARTAPP_INTR_PEIS_MASK (1 << 8)
  152 +#define UARTAPP_INTR_FEIS_MASK (1 << 7)
  153 +#define UARTAPP_INTR_RTIS_MASK (1 << 6)
  154 +#define UARTAPP_INTR_TXIS_MASK (1 << 5)
  155 +#define UARTAPP_INTR_RXIS_MASK (1 << 4)
  156 +#define UARTAPP_INTR_DSRMIS_MASK (1 << 3)
  157 +#define UARTAPP_INTR_DCDMIS_MASK (1 << 2)
  158 +#define UARTAPP_INTR_CTSMIS_MASK (1 << 1)
  159 +#define UARTAPP_INTR_RIMIS_MASK 0x1
  160 +
  161 +#define UARTAPP_DATA_DATA_OFFSET 0
  162 +#define UARTAPP_DATA_DATA_MASK 0xFFFFFFFF
  163 +#define UARTAPP_STAT_PRESENT_MASK (1 << 31)
  164 +#define UARTAPP_STAT_PRESENT_UNAVAILABLE (0x0 << 31)
  165 +#define UARTAPP_STAT_PRESENT_AVAILABLE (0x1 << 31)
  166 +
  167 +#define UARTAPP_STAT_HISPEED_MASK (1 << 30)
  168 +#define UARTAPP_STAT_HISPEED_UNAVAILABLE (0x0 << 30)
  169 +#define UARTAPP_STAT_HISPEED_AVAILABLE (0x1 << 30)
  170 +
  171 +#define UARTAPP_STAT_BUSY_MASK (1 << 29)
  172 +#define UARTAPP_STAT_CTS_MASK (1 << 28)
  173 +#define UARTAPP_STAT_TXFE_MASK (1 << 27)
  174 +#define UARTAPP_STAT_RXFF_MASK (1 << 26)
  175 +#define UARTAPP_STAT_TXFF_MASK (1 << 25)
  176 +#define UARTAPP_STAT_RXFE_MASK (1 << 24)
  177 +#define UARTAPP_STAT_RXBYTE_INVALID_OFFSET 20
  178 +#define UARTAPP_STAT_RXBYTE_INVALID_MASK (0xF << 20)
  179 +
  180 +#define UARTAPP_STAT_OERR_MASK (1 << 19)
  181 +#define UARTAPP_STAT_BERR_MASK (1 << 18)
  182 +#define UARTAPP_STAT_PERR_MASK (1 << 17)
  183 +#define UARTAPP_STAT_FERR_MASK (1 << 16)
  184 +#define UARTAPP_STAT_RXCOUNT_OFFSET 0
  185 +#define UARTAPP_STAT_RXCOUNT_MASK 0xFFFF
  186 +
  187 +#define UARTAPP_DEBUG_RXIBAUD_DIV_OFFSET 16
  188 +#define UARTAPP_DEBUG_RXIBAUD_DIV_MASK (0xFFFF << 16)
  189 +
  190 +#define UARTAPP_DEBUG_RXFBAUD_DIV_OFFSET 10
  191 +#define UARTAPP_DEBUG_RXFBAUD_DIV_MASK (0x3F << 10)
  192 +
  193 +#define UARTAPP_DEBUG_TXDMARUN_MASK (1 << 5)
  194 +#define UARTAPP_DEBUG_RXDMARUN_MASK (1 << 4)
  195 +#define UARTAPP_DEBUG_TXCMDEND_MASK (1 << 3)
  196 +#define UARTAPP_DEBUG_RXCMDEND_MASK (1 << 2)
  197 +#define UARTAPP_DEBUG_TXDMARQ_MASK (1 << 1)
  198 +#define UARTAPP_DEBUG_RXDMARQ_MASK 0x01
  199 +
  200 +#define UARTAPP_VERSION_MAJOR_OFFSET 24
  201 +#define UARTAPP_VERSION_MAJOR_MASK (0xFF << 24)
  202 +
  203 +#define UARTAPP_VERSION_MINOR_OFFSET 16
  204 +#define UARTAPP_VERSION_MINOR_MASK (0xFF << 16)
  205 +
  206 +#define UARTAPP_VERSION_STEP_OFFSET 0
  207 +#define UARTAPP_VERSION_STEP_MASK 0xFFFF
  208 +
  209 +#define UARTAPP_AUTOBAUD_REFCHAR1_OFFSET 24
  210 +#define UARTAPP_AUTOBAUD_REFCHAR1_MASK (0xFF << 24)
  211 +
  212 +#define UARTAPP_AUTOBAUD_REFCHAR0_OFFSET 16
  213 +#define UARTAPP_AUTOBAUD_REFCHAR0_MASK (0xFF << 16)
  214 +
  215 +#define UARTAPP_AUTOBAUD_UPDATE_TX_MASK (1 << 4)
  216 +#define UARTAPP_AUTOBAUD_TWO_REF_CHARS_MASK (1 << 3)
  217 +#define UARTAPP_AUTOBAUD_START_WITH_RUNBIT_MASK (1 << 2)
  218 +#define UARTAPP_AUTOBAUD_START_BAUD_DETECT_MASK (1 << 1)
  219 +#define UARTAPP_AUTOBAUD_BAUD_DETECT_ENABLE_MASK 0x01
  220 +#endif /* __ARCH_ARM___UARTAPP_H */
board/boundary/nitrogen6x/nitrogen6x.c
... ... @@ -622,7 +622,6 @@
622 622 static void setup_display(void)
623 623 {
624 624 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
625   - struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
626 625 struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
627 626 int reg;
628 627  
... ... @@ -633,10 +632,6 @@
633 632 reg |= MXC_CCM_CCGR3_LDB_DI0_MASK;
634 633 writel(reg, &mxc_ccm->CCGR3);
635 634  
636   - /* set PFD1_FRAC to 0x13 == 455 MHz (480*18)/0x13 */
637   - writel(ANATOP_PFD_480_PFD1_FRAC_MASK, &anatop->pfd_480_clr);
638   - writel(0x13<<ANATOP_PFD_480_PFD1_FRAC_SHIFT, &anatop->pfd_480_set);
639   -
640 635 /* set LDB0, LDB1 clk select to 011/011 */
641 636 reg = readl(&mxc_ccm->cs2cdr);
642 637 reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK
... ... @@ -666,7 +661,8 @@
666 661 writel(reg, &iomux->gpr[2]);
667 662  
668 663 reg = readl(&iomux->gpr[3]);
669   - reg = (reg & ~IOMUXC_GPR3_LVDS0_MUX_CTL_MASK)
  664 + reg = (reg & ~(IOMUXC_GPR3_LVDS0_MUX_CTL_MASK
  665 + |IOMUXC_GPR3_HDMI_MUX_CTL_MASK))
670 666 | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
671 667 <<IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET);
672 668 writel(reg, &iomux->gpr[3]);
board/congatec/cgtqmx6eval/README
... ... @@ -7,8 +7,7 @@
7 7 1. Boot source, boot from SD card
8 8 ---------------------------------
9 9  
10   -This version of u-boot works only on the SD card. By default, the
11   -Congatec board can boot only from the SPI-NOR.
  10 +By default, the Congatec board can boot only from the SPI-NOR.
12 11 But, with the u-boot version provided with the board you can write boot
13 12 registers to force the board to reboot and boot from the SD slot. If
14 13 "bmode" command is not available from your pre-installed u-boot, these
... ... @@ -204,6 +204,7 @@
204 204 m28evk arm arm926ejs m28evk denx mxs m28evk
205 205 mx28evk arm arm926ejs mx28evk freescale mxs mx28evk:ENV_IS_IN_MMC
206 206 mx28evk_nand arm arm926ejs mx28evk freescale mxs mx28evk:ENV_IS_IN_NAND
  207 +mx28evk_auart_console arm arm926ejs mx28evk freescale mxs mx28evk:MXS_AUART,MXS_AUART_BASE=MXS_UARTAPP3_BASE,ENV_IS_IN_MMC
207 208 sc_sps_1 arm arm926ejs sc_sps_1 schulercontrol mxs
208 209 nhk8815 arm arm926ejs nhk8815 st nomadik
209 210 nhk8815_onenand arm arm926ejs nhk8815 st nomadik nhk8815:BOOT_ONENAND
... ... @@ -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  
... ... @@ -220,6 +220,15 @@
220 220 endif
221 221  
222 222 # TODO(sjg@chromium.org): Is this correct on Mac OS?
  223 +
  224 +# MXSImage needs LibSSL
  225 +ifneq ($(CONFIG_MX23)$(CONFIG_MX28),)
  226 +HOSTLIBS += -lssl -lcrypto
  227 +# Add CONFIG_MXS into host CFLAGS, so we can check whether or not register
  228 +# the mxsimage support within tools/mxsimage.c .
  229 +HOSTCFLAGS += -DCONFIG_MXS
  230 +endif
  231 +
223 232 ifdef CONFIG_FIT_SIGNATURE
224 233 HOSTLIBS += -lssl -lcrypto
225 234  
... ... @@ -15,9 +15,6 @@
15 15 For more details refer Chapter 2 - System Boot and section 2.14
16 16 (flash header description) of the processor's manual.
17 17  
18   -This implementation does not use at the moment the secure boot feature
19   -of the processor. The image is generated disabling all security fields.
20   -
21 18 Command syntax:
22 19 --------------
23 20 ./tools/mkimage -l <mx u-boot_file>
... ... @@ -85,6 +82,33 @@
85 82  
86 83 Example:
87 84 BOOT_FROM spi
  85 +
  86 + CSF value
  87 +
  88 + Total size of CSF (Command Sequence File)
  89 + used for Secure Boot/ High Assurance Boot
  90 + (HAB).
  91 +
  92 + Using this command will populate the IVT
  93 + (Initial Vector Table) CSF pointer and adjust
  94 + the length fields only. The CSF itself needs
  95 + to be generated with Freescale tools and
  96 + 'manually' appended to the u-boot.imx file.
  97 +
  98 + The CSF is then simply concatenated
  99 + to the u-boot image, making a signed bootloader,
  100 + that the processor can verify
  101 + if the fuses for the keys are burned.
  102 +
  103 + Further infos how to configure the SOC to verify
  104 + the bootloader can be found in the "High
  105 + Assurance Boot Version Application Programming
  106 + Interface Reference Manual" as part of the
  107 + Freescale Code Signing Tool, available on the
  108 + manufacturer's website.
  109 +
  110 + Example:
  111 + CSF 0x2000
88 112  
89 113 DATA type address value
90 114  
  1 +High Assurance Boot (HAB) for i.MX6 CPUs
  2 +
  3 +To authenticate U-Boot only by the CPU there is no code required in
  4 +U-Boot itself. However, the U-Boot image to be programmed into the
  5 +boot media needs to be properly constructed, i.e. it must contain a
  6 +proper Command Sequence File (CSF).
  7 +
  8 +The Initial Vector Table contains a pointer to the CSF. Please see
  9 +doc/README.imximage for how to prepare u-boot.imx.
  10 +
  11 +The CSF itself is being generated by Freescale HAB tools.
  12 +
  13 +mkimage will output additional information about "HAB Blocks"
  14 +which can be used in the Freescale tooling to authenticate U-Boot
  15 +(entries in the CSF file).
  16 +
  17 +Image Type: Freescale IMX Boot Image
  18 +Image Ver: 2 (i.MX53/6 compatible)
  19 +Data Size: 327680 Bytes = 320.00 kB = 0.31 MB
  20 +Load Address: 177ff420
  21 +Entry Point: 17800000
  22 +HAB Blocks: 177ff400 00000000 0004dc00
  23 + ^^^^^^^^ ^^^^^^^^ ^^^^^^^^
  24 + | | |
  25 + | | -------- (1)
  26 + | |
  27 + | ------------------- (2)
  28 + |
  29 + --------------------------- (3)
  30 +
  31 +(1) Size of area in file u-boot.imx to sign
  32 + This area should include the IVT, the Boot Data the DCD
  33 + and U-Boot itself.
  34 +(2) Start of area in u-boot.imx to sign
  35 +(3) Start of area in RAM to authenticate
  36 +
  37 +CONFIG_SECURE_BOOT currently enables only an additional command
  38 +'hab_status' in U-Boot to retrieve the HAB status and events. This
  39 +can be useful while developing and testing HAB.
  40 +
  41 +Commands to generate a signed U-Boot using Freescale HAB tools:
  42 +cst --o U-Boot_CSF.bin < U-Boot.CSF
  43 +objcopy -I binary -O binary --pad-to 0x2000 --gap-fill=0x00 \
  44 + U-Boot_CSF.bin U-Boot_CSF_pad.bin
  45 +cat u-boot.imx U-Boot_CSF_pad.bin > u-boot-signed.imx
  46 +
  47 +NOTE: U-Boot_CSF.bin needs to be padded to the value specified in
  48 +the imximage.cfg file.
  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.
drivers/mmc/mxsmmc.c
... ... @@ -410,7 +410,8 @@
410 410 mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
411 411  
412 412 mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
413   - MMC_MODE_HS_52MHz | MMC_MODE_HS;
  413 + MMC_MODE_HS_52MHz | MMC_MODE_HS |
  414 + MMC_MODE_HC;
414 415  
415 416 /*
416 417 * SSPCLK = 480 * 18 / 29 / 1 = 297.731 MHz
drivers/net/fec_mxc.c
... ... @@ -980,6 +980,8 @@
980 980 if (fec_get_hwaddr(edev, dev_id, ethaddr) == 0) {
981 981 debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr);
982 982 memcpy(edev->enetaddr, ethaddr, 6);
  983 + if (!getenv("ethaddr"))
  984 + eth_setenv_enetaddr("ethaddr", ethaddr);
983 985 }
984 986 return ret;
985 987 err3:
drivers/serial/Makefile
... ... @@ -38,6 +38,7 @@
38 38 COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
39 39 COBJS-$(CONFIG_BFIN_SERIAL) += serial_bfin.o
40 40 COBJS-$(CONFIG_FSL_LPUART) += serial_lpuart.o
  41 +COBJS-$(CONFIG_MXS_AUART) += mxs_auart.o
41 42  
42 43 ifndef CONFIG_SPL_BUILD
43 44 COBJS-$(CONFIG_USB_TTY) += usbtty.o
drivers/serial/mxs_auart.c
  1 +/*
  2 + * Freescale i.MX23/i.MX28 AUART driver
  3 + *
  4 + * Copyright (C) 2013 Andreas Wass <andreas.wass@dalelven.com>
  5 + *
  6 + * Based on the MXC serial driver:
  7 + *
  8 + * (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>
  9 + *
  10 + * Further based on the Linux mxs-auart.c driver:
  11 + *
  12 + * Freescale STMP37XX/STMP38X Application UART drkiver
  13 + * Copyright 2008-2010 Freescale Semiconductor, Inc.
  14 + *
  15 + * SPDX-License-Identifier: GPL-2.0+
  16 + */
  17 +#include <common.h>
  18 +#include <asm/io.h>
  19 +#include <serial.h>
  20 +#include <linux/compiler.h>
  21 +#include <asm/arch/regs-base.h>
  22 +#include <asm/arch/regs-uartapp.h>
  23 +#include <asm/arch/sys_proto.h>
  24 +
  25 +DECLARE_GLOBAL_DATA_PTR;
  26 +
  27 +#ifndef CONFIG_MXS_AUART_BASE
  28 +#error "CONFIG_MXS_AUART_BASE must be set to the base UART to use"
  29 +#endif
  30 +
  31 +/* AUART clock always supplied by XTAL and always 24MHz */
  32 +#define MXS_AUART_CLK 24000000
  33 +
  34 +static struct mxs_uartapp_regs *get_uartapp_registers(void)
  35 +{
  36 + return (struct mxs_uartapp_regs *)CONFIG_MXS_AUART_BASE;
  37 +}
  38 +
  39 +/**
  40 + * Sets the baud rate and settings.
  41 + * The settings are: 8 data bits, no parit and 1 stop bit.
  42 + */
  43 +void mxs_auart_setbrg(void)
  44 +{
  45 + u32 div;
  46 + u32 linectrl = 0;
  47 + struct mxs_uartapp_regs *regs = get_uartapp_registers();
  48 +
  49 + if (!gd->baudrate)
  50 + gd->baudrate = CONFIG_BAUDRATE;
  51 +
  52 + /*
  53 + * From i.MX28 datasheet:
  54 + * div is calculated by calculating UARTCLK*32/baudrate, rounded to int
  55 + * div must be between 0xEC and 0x003FFFC0 inclusive
  56 + * Lowest 6 bits of div goes in BAUD_DIVFRAC part of LINECTRL register
  57 + * Next 16 bits goes in BAUD_DIVINT part of LINECTRL register
  58 + */
  59 + div = (MXS_AUART_CLK * 32) / gd->baudrate;
  60 + if (div < 0xEC || div > 0x003FFFC0)
  61 + return;
  62 +
  63 + linectrl |= ((div & UARTAPP_LINECTRL_EXTRACT_BAUD_DIVFRAC_MASK) <<
  64 + UARTAPP_LINECTRL_BAUD_DIVFRAC_OFFSET) &
  65 + UARTAPP_LINECTRL_BAUD_DIVFRAC_MASK;
  66 + linectrl |= ((div >> UARTAPP_LINECTRL_EXTRACT_BAUD_DIVINT_OFFSET) <<
  67 + UARTAPP_LINECTRL_BAUD_DIVINT_OFFSET) &
  68 + UARTAPP_LINECTRL_BAUD_DIVINT_MASK;
  69 +
  70 + /* Word length: 8 bits */
  71 + linectrl |= UARTAPP_LINECTRL_WLEN_8BITS;
  72 +
  73 + /* Enable FIFOs. */
  74 + linectrl |= UARTAPP_LINECTRL_FEN_MASK;
  75 +
  76 + /* Write above settings, no parity, 1 stop bit */
  77 + writel(linectrl, &regs->hw_uartapp_linectrl);
  78 +}
  79 +
  80 +int mxs_auart_init(void)
  81 +{
  82 + struct mxs_uartapp_regs *regs = get_uartapp_registers();
  83 + /* Reset everything */
  84 + mxs_reset_block(&regs->hw_uartapp_ctrl0_reg);
  85 + /* Disable interrupts */
  86 + writel(0, &regs->hw_uartapp_intr);
  87 + /* Set baud rate and settings */
  88 + serial_setbrg();
  89 + /* Disable RTS and CTS, ignore LINECTRL2 register */
  90 + writel(UARTAPP_CTRL2_RTSEN_MASK |
  91 + UARTAPP_CTRL2_CTSEN_MASK |
  92 + UARTAPP_CTRL2_USE_LCR2_MASK,
  93 + &regs->hw_uartapp_ctrl2_clr);
  94 + /* Enable receiver, transmitter and UART */
  95 + writel(UARTAPP_CTRL2_RXE_MASK |
  96 + UARTAPP_CTRL2_TXE_MASK |
  97 + UARTAPP_CTRL2_UARTEN_MASK,
  98 + &regs->hw_uartapp_ctrl2_set);
  99 + return 0;
  100 +}
  101 +
  102 +void mxs_auart_putc(const char c)
  103 +{
  104 + struct mxs_uartapp_regs *regs = get_uartapp_registers();
  105 + /* Wait in loop while the transmit FIFO is full */
  106 + while (readl(&regs->hw_uartapp_stat) & UARTAPP_STAT_TXFF_MASK)
  107 + ;
  108 +
  109 + writel(c, &regs->hw_uartapp_data);
  110 +
  111 + if (c == '\n')
  112 + mxs_auart_putc('\r');
  113 +}
  114 +
  115 +int mxs_auart_tstc(void)
  116 +{
  117 + struct mxs_uartapp_regs *regs = get_uartapp_registers();
  118 + /* Checks if receive FIFO is empty */
  119 + return !(readl(&regs->hw_uartapp_stat) & UARTAPP_STAT_RXFE_MASK);
  120 +}
  121 +
  122 +int mxs_auart_getc(void)
  123 +{
  124 + struct mxs_uartapp_regs *regs = get_uartapp_registers();
  125 + /* Wait until a character is available to read */
  126 + while (!mxs_auart_tstc())
  127 + ;
  128 + /* Read the character from the data register */
  129 + return readl(&regs->hw_uartapp_data) & 0xFF;
  130 +}
  131 +
  132 +static struct serial_device mxs_auart_drv = {
  133 + .name = "mxs_auart_serial",
  134 + .start = mxs_auart_init,
  135 + .stop = NULL,
  136 + .setbrg = mxs_auart_setbrg,
  137 + .putc = mxs_auart_putc,
  138 + .puts = default_serial_puts,
  139 + .getc = mxs_auart_getc,
  140 + .tstc = mxs_auart_tstc,
  141 +};
  142 +
  143 +void mxs_auart_initialize(void)
  144 +{
  145 + serial_register(&mxs_auart_drv);
  146 +}
  147 +
  148 +__weak struct serial_device *default_serial_console(void)
  149 +{
  150 + return &mxs_auart_drv;
  151 +}
drivers/serial/serial.c
... ... @@ -160,6 +160,7 @@
160 160 serial_initfunc(sa1100_serial_initialize);
161 161 serial_initfunc(sh_serial_initialize);
162 162 serial_initfunc(arm_dcc_initialize);
  163 +serial_initfunc(mxs_auart_initialize);
163 164  
164 165 /**
165 166 * serial_register() - Register serial driver with serial driver core
... ... @@ -253,6 +254,7 @@
253 254 sa1100_serial_initialize();
254 255 sh_serial_initialize();
255 256 arm_dcc_initialize();
  257 + mxs_auart_initialize();
256 258  
257 259 serial_assign(default_serial_console()->name);
258 260 }
include/configs/mxs.h
... ... @@ -119,11 +119,16 @@
119 119 /* GPIO */
120 120 #define CONFIG_MXS_GPIO
121 121  
122   -/* DUART Serial Driver */
  122 +/*
  123 + * DUART Serial Driver.
  124 + * Conflicts with AUART driver which can be set by board.
  125 + */
  126 +#ifndef CONFIG_MXS_AUART
123 127 #define CONFIG_PL011_SERIAL
124 128 #define CONFIG_PL011_CLOCK 24000000
125 129 #define CONFIG_PL01x_PORTS { (void *)MXS_UARTDBG_BASE }
126 130 #define CONFIG_CONS_INDEX 0
  131 +#endif
127 132 /* Default baudrate can be overriden by board! */
128 133 #ifndef CONFIG_BAUDRATE
129 134 #define CONFIG_BAUDRATE 115200
... ... @@ -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
... ... @@ -70,31 +70,32 @@
70 70 EXT_OBJ_FILES-y += lib/sha1.o
71 71  
72 72 # Source files located in the tools directory
73   -OBJ_FILES-$(CONFIG_LCD_LOGO) += bmp_logo.o
74   -OBJ_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo.o
  73 +NOPED_OBJ_FILES-y += aisimage.o
75 74 NOPED_OBJ_FILES-y += default_image.o
76   -NOPED_OBJ_FILES-y += proftool.o
77   -OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc.o
78 75 NOPED_OBJ_FILES-y += fit_image.o
79   -OBJ_FILES-$(CONFIG_CMD_NET) += gen_eth_addr.o
80   -OBJ_FILES-$(CONFIG_CMD_LOADS) += img2srec.o
81   -OBJ_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes.o
82   -NOPED_OBJ_FILES-y += aisimage.o
83   -NOPED_OBJ_FILES-y += kwbimage.o
84   -NOPED_OBJ_FILES-y += pblimage.o
85   -NOPED_OBJ_FILES-y += imximage.o
86 76 NOPED_OBJ_FILES-y += image-host.o
87   -NOPED_OBJ_FILES-y += omapimage.o
  77 +NOPED_OBJ_FILES-y += imximage.o
  78 +NOPED_OBJ_FILES-y += kwbimage.o
88 79 NOPED_OBJ_FILES-y += mkenvimage.o
89 80 NOPED_OBJ_FILES-y += mkimage.o
90   -OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o
  81 +NOPED_OBJ_FILES-y += mxsimage.o
  82 +NOPED_OBJ_FILES-y += omapimage.o
  83 +NOPED_OBJ_FILES-y += os_support.o
  84 +NOPED_OBJ_FILES-y += pblimage.o
  85 +NOPED_OBJ_FILES-y += proftool.o
  86 +NOPED_OBJ_FILES-y += ublimage.o
  87 +OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc.o
  88 +OBJ_FILES-$(CONFIG_CMD_LOADS) += img2srec.o
  89 +OBJ_FILES-$(CONFIG_CMD_NET) += gen_eth_addr.o
  90 +OBJ_FILES-$(CONFIG_KIRKWOOD) += kwboot.o
  91 +OBJ_FILES-$(CONFIG_LCD_LOGO) += bmp_logo.o
91 92 OBJ_FILES-$(CONFIG_MX23) += mxsboot.o
92 93 OBJ_FILES-$(CONFIG_MX28) += mxsboot.o
93 94 OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
94   -NOPED_OBJ_FILES-y += os_support.o
95 95 OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o
96   -NOPED_OBJ_FILES-y += ublimage.o
97   -OBJ_FILES-$(CONFIG_KIRKWOOD) += kwboot.o
  96 +OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o
  97 +OBJ_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo.o
  98 +OBJ_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes.o
98 99  
99 100 # Don't build by default
100 101 #ifeq ($(ARCH),ppc)
101 102  
102 103  
103 104  
104 105  
105 106  
... ... @@ -203,20 +204,21 @@
203 204 $(HOSTSTRIP) $@
204 205  
205 206 $(obj)mkimage$(SFX): $(obj)aisimage.o \
  207 + $(FIT_SIG_OBJS) \
206 208 $(obj)crc32.o \
207 209 $(obj)default_image.o \
208 210 $(obj)fit_image.o \
209 211 $(obj)image-fit.o \
210   - $(obj)image.o \
211 212 $(obj)image-host.o \
212   - $(FIT_SIG_OBJS) \
  213 + $(obj)image.o \
213 214 $(obj)imximage.o \
214 215 $(obj)kwbimage.o \
215   - $(obj)pblimage.o \
216 216 $(obj)md5.o \
217 217 $(obj)mkimage.o \
218   - $(obj)os_support.o \
  218 + $(obj)mxsimage.o \
219 219 $(obj)omapimage.o \
  220 + $(obj)os_support.o \
  221 + $(obj)pblimage.o \
220 222 $(obj)sha1.o \
221 223 $(obj)ublimage.o \
222 224 $(LIBFDT_OBJS) \
... ... @@ -13,6 +13,8 @@
13 13 #include <image.h>
14 14 #include "imximage.h"
15 15  
  16 +#define UNDEFINED 0xFFFFFFFF
  17 +
16 18 /*
17 19 * Supported commands for configuration file
18 20 */
... ... @@ -20,6 +22,7 @@
20 22 {CMD_BOOT_FROM, "BOOT_FROM", "boot command", },
21 23 {CMD_BOOT_OFFSET, "BOOT_OFFSET", "Boot offset", },
22 24 {CMD_DATA, "DATA", "Reg Write Data", },
  25 + {CMD_CSF, "CSF", "Command Sequence File", },
23 26 {CMD_IMAGE_VERSION, "IMAGE_VERSION", "image version", },
24 27 {-1, "", "", },
25 28 };
... ... @@ -28,7 +31,7 @@
28 31 * Supported Boot options for configuration file
29 32 * this is needed to set the correct flash offset
30 33 */
31   -static table_entry_t imximage_bootops[] = {
  34 +static table_entry_t imximage_boot_offset[] = {
32 35 {FLASH_OFFSET_ONENAND, "onenand", "OneNAND Flash",},
33 36 {FLASH_OFFSET_NAND, "nand", "NAND Flash", },
34 37 {FLASH_OFFSET_NOR, "nor", "NOR Flash", },
... ... @@ -39,6 +42,20 @@
39 42 };
40 43  
41 44 /*
  45 + * Supported Boot options for configuration file
  46 + * this is needed to determine the initial load size
  47 + */
  48 +static table_entry_t imximage_boot_loadsize[] = {
  49 + {FLASH_LOADSIZE_ONENAND, "onenand", "OneNAND Flash",},
  50 + {FLASH_LOADSIZE_NAND, "nand", "NAND Flash", },
  51 + {FLASH_LOADSIZE_NOR, "nor", "NOR Flash", },
  52 + {FLASH_LOADSIZE_SATA, "sata", "SATA Disk", },
  53 + {FLASH_LOADSIZE_SD, "sd", "SD Card", },
  54 + {FLASH_LOADSIZE_SPI, "spi", "SPI Flash", },
  55 + {-1, "", "Invalid", },
  56 +};
  57 +
  58 +/*
42 59 * IMXIMAGE version definition for i.MX chips
43 60 */
44 61 static table_entry_t imximage_versions[] = {
45 62  
... ... @@ -49,12 +66,22 @@
49 66  
50 67 static struct imx_header imximage_header;
51 68 static uint32_t imximage_version;
  69 +/*
  70 + * Image Vector Table Offset
  71 + * Initialized to a wrong not 4-bytes aligned address to
  72 + * check if it is was set by the cfg file.
  73 + */
  74 +static uint32_t imximage_ivt_offset = UNDEFINED;
  75 +static uint32_t imximage_csf_size = UNDEFINED;
  76 +/* Initial Load Region Size */
  77 +static uint32_t imximage_init_loadsize;
52 78  
53 79 static set_dcd_val_t set_dcd_val;
54 80 static set_dcd_rst_t set_dcd_rst;
55 81 static set_imx_hdr_t set_imx_hdr;
56 82 static uint32_t max_dcd_entries;
57 83 static uint32_t *header_size_ptr;
  84 +static uint32_t *csf_ptr;
58 85  
59 86 static uint32_t get_cfg_value(char *token, char *name, int linenr)
60 87 {
... ... @@ -190,7 +217,8 @@
190 217 /* Set magic number */
191 218 fhdr_v1->app_code_barker = APP_CODE_BARKER;
192 219  
193   - hdr_base = entry_point - sizeof(struct imx_header);
  220 + /* TODO: check i.MX image V1 handling, for now use 'old' style */
  221 + hdr_base = entry_point - 4096;
194 222 fhdr_v1->app_dest_ptr = hdr_base - flash_offset;
195 223 fhdr_v1->app_code_jump_vector = entry_point;
196 224  
197 225  
198 226  
199 227  
200 228  
... ... @@ -217,16 +245,18 @@
217 245  
218 246 fhdr_v2->entry = entry_point;
219 247 fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0;
220   - fhdr_v2->self = hdr_base = entry_point - sizeof(struct imx_header);
221   -
  248 + hdr_base = entry_point - imximage_init_loadsize +
  249 + flash_offset;
  250 + fhdr_v2->self = hdr_base;
222 251 fhdr_v2->dcd_ptr = hdr_base + offsetof(imx_header_v2_t, dcd_table);
223 252 fhdr_v2->boot_data_ptr = hdr_base
224 253 + offsetof(imx_header_v2_t, boot_data);
225   - hdr_v2->boot_data.start = hdr_base - flash_offset;
  254 + hdr_v2->boot_data.start = entry_point - imximage_init_loadsize;
226 255  
227   - /* Security feature are not supported */
228 256 fhdr_v2->csf = 0;
  257 +
229 258 header_size_ptr = &hdr_v2->boot_data.size;
  259 + csf_ptr = &fhdr_v2->csf;
230 260 }
231 261  
232 262 static void set_hdr_func(struct imx_header *imxhdr)
... ... @@ -303,6 +333,13 @@
303 333 genimg_print_size(hdr_v2->boot_data.size);
304 334 printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr);
305 335 printf("Entry Point: %08x\n", (uint32_t)fhdr_v2->entry);
  336 + if (fhdr_v2->csf && (imximage_ivt_offset != UNDEFINED) &&
  337 + (imximage_csf_size != UNDEFINED)) {
  338 + printf("HAB Blocks: %08x %08x %08x\n",
  339 + (uint32_t)fhdr_v2->self, 0,
  340 + hdr_v2->boot_data.size - imximage_ivt_offset -
  341 + imximage_csf_size);
  342 + }
306 343 }
307 344  
308 345 static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token,
309 346  
310 347  
311 348  
... ... @@ -324,18 +361,36 @@
324 361 set_hdr_func(imxhdr);
325 362 break;
326 363 case CMD_BOOT_FROM:
327   - imxhdr->flash_offset = get_table_entry_id(imximage_bootops,
  364 + imximage_ivt_offset = get_table_entry_id(imximage_boot_offset,
328 365 "imximage boot option", token);
329   - if (imxhdr->flash_offset == -1) {
  366 + if (imximage_ivt_offset == -1) {
330 367 fprintf(stderr, "Error: %s[%d] -Invalid boot device"
331 368 "(%s)\n", name, lineno, token);
332 369 exit(EXIT_FAILURE);
333 370 }
  371 +
  372 + imximage_init_loadsize =
  373 + get_table_entry_id(imximage_boot_loadsize,
  374 + "imximage boot option", token);
  375 +
  376 + if (imximage_init_loadsize == -1) {
  377 + fprintf(stderr,
  378 + "Error: %s[%d] -Invalid boot device(%s)\n",
  379 + name, lineno, token);
  380 + exit(EXIT_FAILURE);
  381 + }
  382 +
  383 + /*
  384 + * The SOC loads from the storage starting at address 0
  385 + * then ensures that the load size contains the offset
  386 + */
  387 + if (imximage_init_loadsize < imximage_ivt_offset)
  388 + imximage_init_loadsize = imximage_ivt_offset;
334 389 if (unlikely(cmd_ver_first != 1))
335 390 cmd_ver_first = 0;
336 391 break;
337 392 case CMD_BOOT_OFFSET:
338   - imxhdr->flash_offset = get_cfg_value(token, name, lineno);
  393 + imximage_ivt_offset = get_cfg_value(token, name, lineno);
339 394 if (unlikely(cmd_ver_first != 1))
340 395 cmd_ver_first = 0;
341 396 break;
... ... @@ -345,6 +400,17 @@
345 400 if (unlikely(cmd_ver_first != 1))
346 401 cmd_ver_first = 0;
347 402 break;
  403 + case CMD_CSF:
  404 + if (imximage_version != 2) {
  405 + fprintf(stderr,
  406 + "Error: %s[%d] - CSF only supported for VERSION 2(%s)\n",
  407 + name, lineno, token);
  408 + exit(EXIT_FAILURE);
  409 + }
  410 + imximage_csf_size = get_cfg_value(token, name, lineno);
  411 + if (unlikely(cmd_ver_first != 1))
  412 + cmd_ver_first = 0;
  413 + break;
348 414 }
349 415 }
350 416  
... ... @@ -405,7 +471,8 @@
405 471 exit(EXIT_FAILURE);
406 472 }
407 473  
408   - /* Very simple parsing, line starting with # are comments
  474 + /*
  475 + * Very simple parsing, line starting with # are comments
409 476 * and are dropped
410 477 */
411 478 while ((getline(&line, &len, fd)) > 0) {
... ... @@ -436,7 +503,7 @@
436 503 fclose(fd);
437 504  
438 505 /* Exit if there is no BOOT_FROM field specifying the flash_offset */
439   - if (imxhdr->flash_offset == FLASH_OFFSET_UNDEFINED) {
  506 + if (imximage_ivt_offset == FLASH_OFFSET_UNDEFINED) {
440 507 fprintf(stderr, "Error: No BOOT_FROM tag in %s\n", name);
441 508 exit(EXIT_FAILURE);
442 509 }
443 510  
... ... @@ -494,14 +561,15 @@
494 561 */
495 562 imximage_version = IMXIMAGE_V1;
496 563 /* Be able to detect if the cfg file has no BOOT_FROM tag */
497   - imxhdr->flash_offset = FLASH_OFFSET_UNDEFINED;
  564 + imximage_ivt_offset = FLASH_OFFSET_UNDEFINED;
  565 + imximage_csf_size = 0;
498 566 set_hdr_func(imxhdr);
499 567  
500 568 /* Parse dcd configuration file */
501 569 dcd_len = parse_cfg_file(imxhdr, params->imagename);
502 570  
503 571 /* Set the imx header */
504   - (*set_imx_hdr)(imxhdr, dcd_len, params->ep, imxhdr->flash_offset);
  572 + (*set_imx_hdr)(imxhdr, dcd_len, params->ep, imximage_ivt_offset);
505 573  
506 574 /*
507 575 * ROM bug alert
... ... @@ -512,7 +580,13 @@
512 580 *
513 581 * The remaining fraction of a block bytes would not be loaded!
514 582 */
515   - *header_size_ptr = ROUND(sbuf->st_size + imxhdr->flash_offset, 4096);
  583 + *header_size_ptr = ROUND(sbuf->st_size, 4096);
  584 +
  585 + if (csf_ptr && imximage_csf_size) {
  586 + *csf_ptr = params->ep - imximage_init_loadsize +
  587 + *header_size_ptr;
  588 + *header_size_ptr += imximage_csf_size;
  589 + }
516 590 }
517 591  
518 592 int imximage_check_params(struct mkimage_params *params)
519 593  
520 594  
... ... @@ -537,18 +611,92 @@
537 611 (params->xflag) || !(strlen(params->imagename));
538 612 }
539 613  
  614 +static int imximage_generate(struct mkimage_params *params,
  615 + struct image_type_params *tparams)
  616 +{
  617 + struct imx_header *imxhdr;
  618 + size_t alloc_len;
  619 + struct stat sbuf;
  620 + char *datafile = params->datafile;
  621 + uint32_t pad_len;
  622 +
  623 + memset(&imximage_header, 0, sizeof(imximage_header));
  624 +
  625 + /*
  626 + * In order to not change the old imx cfg file
  627 + * by adding VERSION command into it, here need
  628 + * set up function ptr group to V1 by default.
  629 + */
  630 + imximage_version = IMXIMAGE_V1;
  631 + /* Be able to detect if the cfg file has no BOOT_FROM tag */
  632 + imximage_ivt_offset = FLASH_OFFSET_UNDEFINED;
  633 + imximage_csf_size = 0;
  634 + set_hdr_func(imxhdr);
  635 +
  636 + /* Parse dcd configuration file */
  637 + parse_cfg_file(&imximage_header, params->imagename);
  638 +
  639 + /* TODO: check i.MX image V1 handling, for now use 'old' style */
  640 + if (imximage_version == IMXIMAGE_V1) {
  641 + alloc_len = 4096;
  642 + } else {
  643 + if (imximage_init_loadsize < imximage_ivt_offset +
  644 + sizeof(imx_header_v2_t))
  645 + imximage_init_loadsize = imximage_ivt_offset +
  646 + sizeof(imx_header_v2_t);
  647 + alloc_len = imximage_init_loadsize - imximage_ivt_offset;
  648 + }
  649 +
  650 + if (alloc_len < sizeof(struct imx_header)) {
  651 + fprintf(stderr, "%s: header error\n",
  652 + params->cmdname);
  653 + exit(EXIT_FAILURE);
  654 + }
  655 +
  656 + imxhdr = malloc(alloc_len);
  657 +
  658 + if (!imxhdr) {
  659 + fprintf(stderr, "%s: malloc return failure: %s\n",
  660 + params->cmdname, strerror(errno));
  661 + exit(EXIT_FAILURE);
  662 + }
  663 +
  664 + memset(imxhdr, 0, alloc_len);
  665 +
  666 + tparams->header_size = alloc_len;
  667 + tparams->hdr = imxhdr;
  668 +
  669 + /* determine data image file length */
  670 +
  671 + if (stat(datafile, &sbuf) < 0) {
  672 + fprintf(stderr, "%s: Can't stat %s: %s\n",
  673 + params->cmdname, datafile, strerror(errno));
  674 + exit(EXIT_FAILURE);
  675 + }
  676 +
  677 + pad_len = ROUND(sbuf.st_size, 4096) - sbuf.st_size;
  678 +
  679 + /* TODO: check i.MX image V1 handling, for now use 'old' style */
  680 + if (imximage_version == IMXIMAGE_V1)
  681 + return 0;
  682 + else
  683 + return pad_len;
  684 +}
  685 +
  686 +
540 687 /*
541 688 * imximage parameters
542 689 */
543 690 static struct image_type_params imximage_params = {
544 691 .name = "Freescale i.MX Boot Image support",
545   - .header_size = sizeof(struct imx_header),
546   - .hdr = (void *)&imximage_header,
  692 + .header_size = 0,
  693 + .hdr = NULL,
547 694 .check_image_type = imximage_check_image_types,
548 695 .verify_header = imximage_verify_header,
549 696 .print_header = imximage_print_header,
550 697 .set_header = imximage_set_header,
551 698 .check_params = imximage_check_params,
  699 + .vrec_header = imximage_generate,
552 700 };
553 701  
554 702 void init_imx_image_type(void)
... ... @@ -13,14 +13,14 @@
13 13 #define APP_CODE_BARKER 0xB1
14 14 #define DCD_BARKER 0xB17219E9
15 15  
16   -#define HEADER_OFFSET 0x400
17   -
18 16 /*
19 17 * NOTE: This file must be kept in sync with arch/arm/include/asm/\
20 18 * imx-common/imximage.cfg because tools/imximage.c can not
21 19 * cross-include headers from arch/arm/ and vice-versa.
22 20 */
23 21 #define CMD_DATA_STR "DATA"
  22 +
  23 +/* Initial Vector Table Offset */
24 24 #define FLASH_OFFSET_UNDEFINED 0xFFFFFFFF
25 25 #define FLASH_OFFSET_STANDARD 0x400
26 26 #define FLASH_OFFSET_NAND FLASH_OFFSET_STANDARD
... ... @@ -30,6 +30,16 @@
30 30 #define FLASH_OFFSET_NOR 0x1000
31 31 #define FLASH_OFFSET_SATA FLASH_OFFSET_STANDARD
32 32  
  33 +/* Initial Load Region Size */
  34 +#define FLASH_LOADSIZE_UNDEFINED 0xFFFFFFFF
  35 +#define FLASH_LOADSIZE_STANDARD 0x1000
  36 +#define FLASH_LOADSIZE_NAND FLASH_LOADSIZE_STANDARD
  37 +#define FLASH_LOADSIZE_SD FLASH_LOADSIZE_STANDARD
  38 +#define FLASH_LOADSIZE_SPI FLASH_LOADSIZE_STANDARD
  39 +#define FLASH_LOADSIZE_ONENAND 0x400
  40 +#define FLASH_LOADSIZE_NOR 0x0 /* entire image */
  41 +#define FLASH_LOADSIZE_SATA FLASH_LOADSIZE_STANDARD
  42 +
33 43 #define IVT_HEADER_TAG 0xD1
34 44 #define IVT_VERSION 0x40
35 45 #define DCD_HEADER_TAG 0xD2
... ... @@ -42,7 +52,8 @@
42 52 CMD_IMAGE_VERSION,
43 53 CMD_BOOT_FROM,
44 54 CMD_BOOT_OFFSET,
45   - CMD_DATA
  55 + CMD_DATA,
  56 + CMD_CSF,
46 57 };
47 58  
48 59 enum imximage_fld_types {
... ... @@ -147,8 +158,7 @@
147 158 imx_header_v1_t hdr_v1;
148 159 imx_header_v2_t hdr_v2;
149 160 } header;
150   - uint32_t flash_offset;
151   -} __attribute__((aligned(4096)));
  161 +};
152 162  
153 163 typedef void (*set_dcd_val_t)(struct imx_header *imxhdr,
154 164 char *name, int lineno,
... ... @@ -137,6 +137,7 @@
137 137 char *ptr;
138 138 int retval = 0;
139 139 struct image_type_params *tparams = NULL;
  140 + int pad_len = 0;
140 141  
141 142 /* Init Freescale PBL Boot image generation/list support */
142 143 init_pbl_image_type();
... ... @@ -144,6 +145,8 @@
144 145 init_kwb_image_type ();
145 146 /* Init Freescale imx Boot image generation/list support */
146 147 init_imx_image_type ();
  148 + /* Init Freescale mxs Boot image generation/list support */
  149 + init_mxs_image_type();
147 150 /* Init FIT image generation/list support */
148 151 init_fit_image_type ();
149 152 /* Init TI OMAP Boot image generation/list support */
... ... @@ -391,7 +394,7 @@
391 394 * allocate memory for the header itself.
392 395 */
393 396 if (tparams->vrec_header)
394   - tparams->vrec_header(&params, tparams);
  397 + pad_len = tparams->vrec_header(&params, tparams);
395 398 else
396 399 memset(tparams->hdr, 0, tparams->header_size);
397 400  
... ... @@ -463,7 +466,7 @@
463 466 /* PBL has special Image format, implements its' own */
464 467 pbl_load_uboot(ifd, &params);
465 468 } else {
466   - copy_file (ifd, params.datafile, 0);
  469 + copy_file(ifd, params.datafile, pad_len);
467 470 }
468 471 }
469 472  
470 473  
... ... @@ -537,10 +540,19 @@
537 540 unsigned char *ptr;
538 541 int tail;
539 542 int zero = 0;
  543 + uint8_t zeros[4096];
540 544 int offset = 0;
541 545 int size;
542 546 struct image_type_params *tparams = mkimage_get_type (params.type);
543 547  
  548 + if (pad >= sizeof(zeros)) {
  549 + fprintf(stderr, "%s: Can't pad to %d\n",
  550 + params.cmdname, pad);
  551 + exit(EXIT_FAILURE);
  552 + }
  553 +
  554 + memset(zeros, 0, sizeof(zeros));
  555 +
544 556 if (params.vflag) {
545 557 fprintf (stderr, "Adding Image %s\n", datafile);
546 558 }
547 559  
... ... @@ -598,13 +610,21 @@
598 610 exit (EXIT_FAILURE);
599 611 }
600 612  
601   - if (pad && ((tail = size % 4) != 0)) {
  613 + tail = size % 4;
  614 + if ((pad == 1) && (tail != 0)) {
602 615  
603 616 if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
604 617 fprintf (stderr, "%s: Write error on %s: %s\n",
605 618 params.cmdname, params.imagefile,
606 619 strerror(errno));
607 620 exit (EXIT_FAILURE);
  621 + }
  622 + } else if (pad > 1) {
  623 + if (write(ifd, (char *)&zeros, pad) != pad) {
  624 + fprintf(stderr, "%s: Write error on %s: %s\n",
  625 + params.cmdname, params.imagefile,
  626 + strerror(errno));
  627 + exit(EXIT_FAILURE);
608 628 }
609 629 }
610 630  
... ... @@ -132,7 +132,10 @@
132 132 /*
133 133 * This callback function will be executed for variable size record
134 134 * It is expected to build this header in memory and return its length
135   - * and a pointer to it
  135 + * and a pointer to it by using image_type_params.header_size and
  136 + * image_type_params.hdr. The return value shall indicate if an
  137 + * additional padding should be used when copying the data image
  138 + * by returning the padding length.
136 139 */
137 140 int (*vrec_header) (struct mkimage_params *,
138 141 struct image_type_params *);
... ... @@ -158,6 +161,7 @@
158 161 void init_ais_image_type(void);
159 162 void init_kwb_image_type (void);
160 163 void init_imx_image_type (void);
  164 +void init_mxs_image_type(void);
161 165 void init_default_image_type (void);
162 166 void init_fit_image_type (void);
163 167 void init_ubl_image_type(void);
... ... @@ -28,14 +28,14 @@
28 28 *
29 29 * TWEAK this if you have different kind of NAND chip.
30 30 */
31   -uint32_t nand_writesize = 2048;
32   -uint32_t nand_oobsize = 64;
33   -uint32_t nand_erasesize = 128 * 1024;
  31 +static uint32_t nand_writesize = 2048;
  32 +static uint32_t nand_oobsize = 64;
  33 +static uint32_t nand_erasesize = 128 * 1024;
34 34  
35 35 /*
36 36 * Sector on which the SigmaTel boot partition (0x53) starts.
37 37 */
38   -uint32_t sd_sector = 2048;
  38 +static uint32_t sd_sector = 2048;
39 39  
40 40 /*
41 41 * Each of the U-Boot bootstreams is at maximum 1MB big.
... ... @@ -434,7 +434,7 @@
434 434 return 0;
435 435 }
436 436  
437   -void usage(void)
  437 +static void usage(void)
438 438 {
439 439 printf(
440 440 "Usage: mxsboot [ops] <type> <infile> <outfile>\n"
... ... @@ -575,7 +575,7 @@
575 575 return ret;
576 576 }
577 577  
578   -int parse_ops(int argc, char **argv)
  578 +static int parse_ops(int argc, char **argv)
579 579 {
580 580 int i;
581 581 int tmp;
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__ */