/* * Copyright 2017 NXP * * SPDX-License-Identifier: GPL-2.0+ * derived from u-boot's mkimage utility * */ #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS #endif #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef O_BINARY #define O_BINARY 0 #endif typedef enum option_type { NO_IMG = 0, DCD, SCFW, SECO, M4, AP, OUTPUT, SCD, CSF, FLAG, DEVICE, NEW_CONTAINER, APPEND, DATA, PARTITION, FILEOFF, MSG_BLOCK, DUMMY_V2X, SENTINEL, UPOWER } option_type_t; typedef struct { option_type_t option; char* filename; uint64_t src; uint64_t dst; uint64_t entry;/* image entry address or general purpose num */ uint64_t ext; uint64_t mu; uint64_t part; } image_t; typedef enum REVISION_TYPE { NO_REV = 0, A0, B0 } rev_type_t; typedef enum SOC_TYPE { NONE = 0, QX, QM, DXL, ULP, } soc_type_t; typedef struct { uint32_t addr; uint32_t value; } dcd_addr_data_t; typedef struct { uint8_t tag; uint16_t length; uint8_t version; } __attribute__((packed)) ivt_header_t; typedef struct { uint8_t tag; uint16_t length; uint8_t param; } __attribute__((packed)) write_dcd_command_t; #define MAX_HW_CFG_SIZE_V2 359 struct dcd_v2_cmd { write_dcd_command_t write_dcd_command; /*4*/ dcd_addr_data_t addr_data[MAX_HW_CFG_SIZE_V2]; /*2872*/ } __attribute__((packed)); typedef struct { ivt_header_t header; /*4*/ struct dcd_v2_cmd dcd_cmd; /*2876*/ } __attribute__((packed)) dcd_v2_t; /*2880*/ #define CORE_SC 0x1 #define CORE_CM4_0 0x2 #define CORE_CM4_1 0x3 #define CORE_CA53 0x4 #define CORE_CA35 0x4 #define CORE_CA72 0x5 #define CORE_SECO 0x6 #define CORE_V2X_P 0x9 #define CORE_V2X_S 0xA #define CORE_ULP_CM33 0x1 #define CORE_ULP_CA35 0x2 #define CORE_ULP_UPOWER 0x4 #define CORE_ULP_SENTINEL 0x6 #define SC_R_OTP 357U #define SC_R_DEBUG 354U #define SC_R_ROM_0 236U #define SC_R_PWM_0 191U #define SC_R_SNVS 356U #define MSG_DEBUG_EN SC_R_DEBUG #define MSG_FUSE SC_R_OTP #define MSG_FIELD SC_R_ROM_0 #define MSG_PATCH SC_R_SNVS #define IMG_TYPE_CSF 0x01 /* CSF image type */ #define IMG_TYPE_SCD 0x02 /* SCD image type */ #define IMG_TYPE_EXEC 0x03 /* Executable image type */ #define IMG_TYPE_DATA 0x04 /* Data image type */ #define IMG_TYPE_DCD_DDR 0x05 /* DCD/DDR image type */ #define IMG_TYPE_SECO 0x06 /* SECO image type */ #define IMG_TYPE_SENTINEL 0x06 /* SENTINEL image type */ #define IMG_TYPE_PROV 0x07 /* Provisioning image type */ #define IMG_TYPE_DEK 0x08 /* DEK validation type */ #define IMG_TYPE_PRIM_V2X 0x0B /* Primary V2X FW image */ #define IMG_TYPE_SEC_V2X 0x0C /* Secondary V2X FW image*/ #define IMG_TYPE_V2X_ROM 0x0D /* V2X ROM Patch image */ #define IMG_TYPE_V2X_DUMMY 0x0E /* V2X Dummy image */ #define IMG_TYPE_SHIFT 0 #define IMG_TYPE_MASK 0x1f #define IMG_TYPE(x) (((x) & IMG_TYPE_MASK) >> IMG_TYPE_SHIFT) #define BOOT_IMG_FLAGS_CORE_MASK 0xF #define BOOT_IMG_FLAGS_CORE_SHIFT 0x04 #define BOOT_IMG_FLAGS_CPU_RID_MASK 0x3FF0 #define BOOT_IMG_FLAGS_CPU_RID_SHIFT 4 #define BOOT_IMG_FLAGS_MU_RID_MASK 0xFFC000 #define BOOT_IMG_FLAGS_MU_RID_SHIFT 14 #define BOOT_IMG_FLAGS_PARTITION_ID_MASK 0x1F000000 #define BOOT_IMG_FLAGS_PARTITION_ID_SHIFT 24 #define SC_R_A35_0 508 #define SC_R_A53_0 1 #define SC_R_A72_0 6 #define SC_R_MU_0A 213 #define SC_R_MU_3A 216 #define SC_R_M4_0_PID0 278 #define SC_R_M4_0_MU_1A 297 #define SC_R_M4_1_PID0 298 #define SC_R_M4_1_MU_1A 317 #define PARTITION_ID_M4 0 #define PARTITION_ID_AP 1 #define PARTITION_ID_AP2 3 /* Command tags and parameters */ #define HAB_DATA_WIDTH_BYTE 1 /* 8-bit value */ #define HAB_DATA_WIDTH_HALF 2 /* 16-bit value */ #define HAB_DATA_WIDTH_WORD 4 /* 32-bit value */ #define HAB_CMD_WRT_DAT_MSK 1 /* mask/value flag */ #define HAB_CMD_WRT_DAT_SET 2 /* set/clear flag */ #define HAB_CMD_CHK_DAT_SET 2 /* set/clear flag */ #define HAB_CMD_CHK_DAT_ANY 4 /* any/all flag */ #define HAB_CMD_WRT_DAT_FLAGS_WIDTH 5 /* flags field width */ #define HAB_CMD_WRT_DAT_FLAGS_SHIFT 3 /* flags field offset */ #define HAB_CMD_WRT_DAT_BYTES_WIDTH 3 /* bytes field width */ #define HAB_CMD_WRT_DAT_BYTES_SHIFT 0 /* bytes field offset */ #define IVT_VER 0x01 #define IVT_VERSION 0x43 #define DCD_HEADER_TAG 0xD2 #define DCD_VERSION 0x43 #define DCD_WRITE_DATA_COMMAND_TAG 0xCC #define DCD_WRITE_DATA_PARAM (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT) /* 0x4 */ #define DCD_WRITE_CLR_BIT_PARAM ((HAB_CMD_WRT_DAT_MSK << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT)) /* 0xC */ #define DCD_WRITE_SET_BIT_PARAM ((HAB_CMD_WRT_DAT_MSK << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_CMD_WRT_DAT_SET << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT)) /* 0x1C */ #define DCD_CHECK_DATA_COMMAND_TAG 0xCF #define DCD_CHECK_BITS_CLR_PARAM (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT) /* 0x04 */ #define DCD_CHECK_BITS_SET_PARAM ((HAB_CMD_CHK_DAT_SET << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT)) /* 0x14 */ #define DCD_CHECK_ANY_BIT_CLR_PARAM ((HAB_CMD_CHK_DAT_ANY << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT)) /* 0x24 */ #define DCD_CHECK_ANY_BIT_SET_PARAM ((HAB_CMD_CHK_DAT_ANY << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_CMD_CHK_DAT_SET << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT)) /* 0x34 */ #define IVT_OFFSET_NAND (0x400) #define IVT_OFFSET_I2C (0x400) #define IVT_OFFSET_FLEXSPI (0x1000) #define IVT_OFFSET_SD (0x400) #define IVT_OFFSET_SATA (0x400) #define IVT_OFFSET_EMMC (0x400) #define CSF_DATA_SIZE (0x4000) #define INITIAL_LOAD_ADDR_SCU_ROM 0x2000e000 #define INITIAL_LOAD_ADDR_AP_ROM 0x00110000 #define INITIAL_LOAD_ADDR_FLEXSPI 0x08000000 #define IMG_AUTO_ALIGN 0x10 #define ALIGN(x,a) __ALIGN_MASK((x),(__typeof__(x))(a)-1) #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) #define uswap_16(x) \ ((((x) & 0xff00) >> 8) | \ (((x) & 0x00ff) << 8)) #define uswap_32(x) \ ((((x) & 0xff000000) >> 24) | \ (((x) & 0x00ff0000) >> 8) | \ (((x) & 0x0000ff00) << 8) | \ (((x) & 0x000000ff) << 24)) #define _uswap_64(x, sfx) \ ((((x) & 0xff00000000000000##sfx) >> 56) | \ (((x) & 0x00ff000000000000##sfx) >> 40) | \ (((x) & 0x0000ff0000000000##sfx) >> 24) | \ (((x) & 0x000000ff00000000##sfx) >> 8) | \ (((x) & 0x00000000ff000000##sfx) << 8) | \ (((x) & 0x0000000000ff0000##sfx) << 24) | \ (((x) & 0x000000000000ff00##sfx) << 40) | \ (((x) & 0x00000000000000ff##sfx) << 56)) #if defined(__GNUC__) # define uswap_64(x) _uswap_64(x, ull) #else #error # define uswap_64(x) _uswap_64(x, ) #endif #if __BYTE_ORDER == __LITTLE_ENDIAN # define cpu_to_le16(x) (x) # define cpu_to_le32(x) (x) # define cpu_to_le64(x) (x) # define le16_to_cpu(x) (x) # define le32_to_cpu(x) (x) # define le64_to_cpu(x) (x) # define cpu_to_be16(x) uswap_16(x) # define cpu_to_be32(x) uswap_32(x) # define cpu_to_be64(x) uswap_64(x) # define be16_to_cpu(x) uswap_16(x) # define be32_to_cpu(x) uswap_32(x) # define be64_to_cpu(x) uswap_64(x) #else #error # define cpu_to_le16(x) uswap_16(x) # define cpu_to_le32(x) uswap_32(x) # define cpu_to_le64(x) uswap_64(x) # define le16_to_cpu(x) uswap_16(x) # define le32_to_cpu(x) uswap_32(x) # define le64_to_cpu(x) uswap_64(x) # define cpu_to_be16(x) (x) # define cpu_to_be32(x) (x) # define cpu_to_be64(x) (x) # define be16_to_cpu(x) (x) # define be32_to_cpu(x) (x) # define be64_to_cpu(x) (x) #endif #define UNDEFINED 0xFFFFFFFF #if 0 enum imximage_fld_types { CFG_INVALID = -1, CFG_COMMAND, CFG_REG_SIZE, CFG_REG_ADDRESS, CFG_REG_VALUE }; enum imximage_cmd { CMD_INVALID, CMD_IMAGE_VERSION, CMD_BOOT_FROM, CMD_BOOT_OFFSET, CMD_WRITE_DATA, CMD_WRITE_CLR_BIT, CMD_WRITE_SET_BIT, CMD_CHECK_BITS_SET, CMD_CHECK_BITS_CLR, CMD_CHECK_ANY_BIT_SET, CMD_CHECK_ANY_BIT_CLR, CMD_CSF, CMD_PLUGIN, }; typedef struct table_entry { int id; char *sname; /* short (input) name to find table entry */ char *lname; /* long (output) name to print for messages */ } table_entry_t; /* * Supported commands for configuration file */ static table_entry_t imximage_cmds[] = { {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, {CMD_BOOT_OFFSET, "BOOT_OFFSET", "Boot offset", }, {CMD_WRITE_DATA, "DATA", "Reg Write Data", }, {CMD_WRITE_CLR_BIT, "CLR_BIT", "Reg clear bit", }, {CMD_WRITE_SET_BIT, "SET_BIT", "Reg set bit", }, {CMD_CHECK_BITS_SET, "CHECK_BITS_SET", "Reg Check all bits set", }, {CMD_CHECK_BITS_CLR, "CHECK_BITS_CLR", "Reg Check all bits clr", }, {CMD_CHECK_ANY_BIT_SET, "CHECK_ANY_BIT_SET", "Reg Check any bit set", }, {CMD_CHECK_ANY_BIT_CLR, "CHECK_ANY_BIT_CLR", "Reg Check any bit clr", }, {CMD_CSF, "CSF", "Command Sequence File", }, {CMD_IMAGE_VERSION, "IMAGE_VERSION", "image version", }, {-1, "", "", }, }; #endif void check_file(struct stat* sbuf,char * filename); void copy_file (int ifd, const char *datafile, int pad, int offset); uint32_t get_cfg_value(char *token, char *name, int linenr); void set_dcd_param_v2(dcd_v2_t *dcd_v2, uint32_t dcd_len, int32_t cmd); void set_dcd_val_v2(dcd_v2_t *dcd_v2, char *name, int lineno, int fld, uint32_t value, uint32_t off); void set_dcd_rst_v2(dcd_v2_t *dcd_v2, uint32_t dcd_len, char *name, int lineno); void parse_cfg_cmd(dcd_v2_t *dcd_v2, int32_t cmd, char *token, char *name, int lineno, int fld, int dcd_len); void parse_cfg_fld(dcd_v2_t *dcd_v2, int32_t *cmd, char *token, char *name, int lineno, int fld, int *dcd_len); uint32_t parse_cfg_file(dcd_v2_t *dcd_v2, char *name); int build_container_qm(uint32_t sector_size, uint32_t ivt_offset, char * out_file, bool emmc_fastboot, image_t* image_stack); int build_container_qx(uint32_t sector_size, uint32_t ivt_offset, char * out_file, bool emmc_fastboot, image_t* image_stack); int build_container_qx_qm_b0(soc_type_t soc, uint32_t sector_size, uint32_t ivt_offset, char * out_file, bool emmc_fastboot, image_t* image_stack, bool dcd_skip, uint8_t fuse_version, uint16_t sw_version, char *images_hash); int parse_container_hdrs_qx_qm_b0(char *ifname, bool extract, soc_type_t soc);