18edcde5eSStefano Babic /* 28edcde5eSStefano Babic * (C) Copyright 2009 38edcde5eSStefano Babic * Stefano Babic, DENX Software Engineering, sbabic@denx.de. 48edcde5eSStefano Babic * 58edcde5eSStefano Babic * (C) Copyright 2008 68edcde5eSStefano Babic * Marvell Semiconductor <www.marvell.com> 78edcde5eSStefano Babic * Written-by: Prafulla Wadaskar <prafulla@marvell.com> 88edcde5eSStefano Babic * 91a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 108edcde5eSStefano Babic */ 118edcde5eSStefano Babic 12f86ed6a8SGuilherme Maciel Ferreira #include "imagetool.h" 138edcde5eSStefano Babic #include <image.h> 148edcde5eSStefano Babic #include "imximage.h" 158edcde5eSStefano Babic 160187c985SStefano Babic #define UNDEFINED 0xFFFFFFFF 170187c985SStefano Babic 188edcde5eSStefano Babic /* 198edcde5eSStefano Babic * Supported commands for configuration file 208edcde5eSStefano Babic */ 218edcde5eSStefano Babic static table_entry_t imximage_cmds[] = { 22f581e3a2SStefano Babic {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, 236cb83829SMarek Vasut {CMD_BOOT_OFFSET, "BOOT_OFFSET", "Boot offset", }, 248edcde5eSStefano Babic {CMD_DATA, "DATA", "Reg Write Data", }, 250187c985SStefano Babic {CMD_CSF, "CSF", "Command Sequence File", }, 268a1edd7dSLiu Hui-R64343 {CMD_IMAGE_VERSION, "IMAGE_VERSION", "image version", }, 278edcde5eSStefano Babic {-1, "", "", }, 288edcde5eSStefano Babic }; 298edcde5eSStefano Babic 308edcde5eSStefano Babic /* 318edcde5eSStefano Babic * Supported Boot options for configuration file 328edcde5eSStefano Babic * this is needed to set the correct flash offset 338edcde5eSStefano Babic */ 34377e367aSStefano Babic static table_entry_t imximage_boot_offset[] = { 358edcde5eSStefano Babic {FLASH_OFFSET_ONENAND, "onenand", "OneNAND Flash",}, 36bd25864cSDirk Behme {FLASH_OFFSET_NAND, "nand", "NAND Flash", }, 3719b409c0SDirk Behme {FLASH_OFFSET_NOR, "nor", "NOR Flash", }, 3819b409c0SDirk Behme {FLASH_OFFSET_SATA, "sata", "SATA Disk", }, 39bd25864cSDirk Behme {FLASH_OFFSET_SD, "sd", "SD Card", }, 40bd25864cSDirk Behme {FLASH_OFFSET_SPI, "spi", "SPI Flash", }, 418edcde5eSStefano Babic {-1, "", "Invalid", }, 428edcde5eSStefano Babic }; 438edcde5eSStefano Babic 448a1edd7dSLiu Hui-R64343 /* 45377e367aSStefano Babic * Supported Boot options for configuration file 46377e367aSStefano Babic * this is needed to determine the initial load size 47377e367aSStefano Babic */ 48377e367aSStefano Babic static table_entry_t imximage_boot_loadsize[] = { 49377e367aSStefano Babic {FLASH_LOADSIZE_ONENAND, "onenand", "OneNAND Flash",}, 50377e367aSStefano Babic {FLASH_LOADSIZE_NAND, "nand", "NAND Flash", }, 51377e367aSStefano Babic {FLASH_LOADSIZE_NOR, "nor", "NOR Flash", }, 52377e367aSStefano Babic {FLASH_LOADSIZE_SATA, "sata", "SATA Disk", }, 53377e367aSStefano Babic {FLASH_LOADSIZE_SD, "sd", "SD Card", }, 54377e367aSStefano Babic {FLASH_LOADSIZE_SPI, "spi", "SPI Flash", }, 55377e367aSStefano Babic {-1, "", "Invalid", }, 56377e367aSStefano Babic }; 57377e367aSStefano Babic 58377e367aSStefano Babic /* 598a1edd7dSLiu Hui-R64343 * IMXIMAGE version definition for i.MX chips 608a1edd7dSLiu Hui-R64343 */ 618a1edd7dSLiu Hui-R64343 static table_entry_t imximage_versions[] = { 628a1edd7dSLiu Hui-R64343 {IMXIMAGE_V1, "", " (i.MX25/35/51 compatible)", }, 6319b409c0SDirk Behme {IMXIMAGE_V2, "", " (i.MX53/6 compatible)", }, 648a1edd7dSLiu Hui-R64343 {-1, "", " (Invalid)", }, 658a1edd7dSLiu Hui-R64343 }; 668edcde5eSStefano Babic 678edcde5eSStefano Babic static struct imx_header imximage_header; 688a1edd7dSLiu Hui-R64343 static uint32_t imximage_version; 690187c985SStefano Babic /* 700187c985SStefano Babic * Image Vector Table Offset 710187c985SStefano Babic * Initialized to a wrong not 4-bytes aligned address to 720187c985SStefano Babic * check if it is was set by the cfg file. 730187c985SStefano Babic */ 740187c985SStefano Babic static uint32_t imximage_ivt_offset = UNDEFINED; 750187c985SStefano Babic static uint32_t imximage_csf_size = UNDEFINED; 76377e367aSStefano Babic /* Initial Load Region Size */ 77377e367aSStefano Babic static uint32_t imximage_init_loadsize; 788a1edd7dSLiu Hui-R64343 798a1edd7dSLiu Hui-R64343 static set_dcd_val_t set_dcd_val; 808a1edd7dSLiu Hui-R64343 static set_dcd_rst_t set_dcd_rst; 818a1edd7dSLiu Hui-R64343 static set_imx_hdr_t set_imx_hdr; 824d5fa985STroy Kisky static uint32_t max_dcd_entries; 8324331982STroy Kisky static uint32_t *header_size_ptr; 840187c985SStefano Babic static uint32_t *csf_ptr; 858edcde5eSStefano Babic 868edcde5eSStefano Babic static uint32_t get_cfg_value(char *token, char *name, int linenr) 878edcde5eSStefano Babic { 888edcde5eSStefano Babic char *endptr; 898edcde5eSStefano Babic uint32_t value; 908edcde5eSStefano Babic 918edcde5eSStefano Babic errno = 0; 928edcde5eSStefano Babic value = strtoul(token, &endptr, 16); 938edcde5eSStefano Babic if (errno || (token == endptr)) { 948edcde5eSStefano Babic fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", 958edcde5eSStefano Babic name, linenr, token); 968edcde5eSStefano Babic exit(EXIT_FAILURE); 978edcde5eSStefano Babic } 988edcde5eSStefano Babic return value; 998edcde5eSStefano Babic } 1008edcde5eSStefano Babic 1018a1edd7dSLiu Hui-R64343 static uint32_t detect_imximage_version(struct imx_header *imx_hdr) 1028edcde5eSStefano Babic { 1038a1edd7dSLiu Hui-R64343 imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1; 1048a1edd7dSLiu Hui-R64343 imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2; 1058a1edd7dSLiu Hui-R64343 flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; 1068a1edd7dSLiu Hui-R64343 flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; 1078a1edd7dSLiu Hui-R64343 1088a1edd7dSLiu Hui-R64343 /* Try to detect V1 */ 1098a1edd7dSLiu Hui-R64343 if ((fhdr_v1->app_code_barker == APP_CODE_BARKER) && 1108a1edd7dSLiu Hui-R64343 (hdr_v1->dcd_table.preamble.barker == DCD_BARKER)) 1118a1edd7dSLiu Hui-R64343 return IMXIMAGE_V1; 1128a1edd7dSLiu Hui-R64343 1138a1edd7dSLiu Hui-R64343 /* Try to detect V2 */ 1148a1edd7dSLiu Hui-R64343 if ((fhdr_v2->header.tag == IVT_HEADER_TAG) && 1158a1edd7dSLiu Hui-R64343 (hdr_v2->dcd_table.header.tag == DCD_HEADER_TAG)) 1168a1edd7dSLiu Hui-R64343 return IMXIMAGE_V2; 1178a1edd7dSLiu Hui-R64343 1188a1edd7dSLiu Hui-R64343 return IMXIMAGE_VER_INVALID; 1198edcde5eSStefano Babic } 1208edcde5eSStefano Babic 1218a1edd7dSLiu Hui-R64343 static void err_imximage_version(int version) 1228edcde5eSStefano Babic { 1238edcde5eSStefano Babic fprintf(stderr, 1248a1edd7dSLiu Hui-R64343 "Error: Unsupported imximage version:%d\n", version); 1258a1edd7dSLiu Hui-R64343 1268edcde5eSStefano Babic exit(EXIT_FAILURE); 1278edcde5eSStefano Babic } 1288edcde5eSStefano Babic 1298a1edd7dSLiu Hui-R64343 static void set_dcd_val_v1(struct imx_header *imxhdr, char *name, int lineno, 1308a1edd7dSLiu Hui-R64343 int fld, uint32_t value, uint32_t off) 1318a1edd7dSLiu Hui-R64343 { 1328a1edd7dSLiu Hui-R64343 dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table; 1338edcde5eSStefano Babic 1348a1edd7dSLiu Hui-R64343 switch (fld) { 1358a1edd7dSLiu Hui-R64343 case CFG_REG_SIZE: 1368a1edd7dSLiu Hui-R64343 /* Byte, halfword, word */ 1378a1edd7dSLiu Hui-R64343 if ((value != 1) && (value != 2) && (value != 4)) { 1388a1edd7dSLiu Hui-R64343 fprintf(stderr, "Error: %s[%d] - " 1398a1edd7dSLiu Hui-R64343 "Invalid register size " "(%d)\n", 1408a1edd7dSLiu Hui-R64343 name, lineno, value); 1418a1edd7dSLiu Hui-R64343 exit(EXIT_FAILURE); 1428a1edd7dSLiu Hui-R64343 } 1438a1edd7dSLiu Hui-R64343 dcd_v1->addr_data[off].type = value; 1448a1edd7dSLiu Hui-R64343 break; 1458a1edd7dSLiu Hui-R64343 case CFG_REG_ADDRESS: 1468a1edd7dSLiu Hui-R64343 dcd_v1->addr_data[off].addr = value; 1478a1edd7dSLiu Hui-R64343 break; 1488a1edd7dSLiu Hui-R64343 case CFG_REG_VALUE: 1498a1edd7dSLiu Hui-R64343 dcd_v1->addr_data[off].value = value; 1508a1edd7dSLiu Hui-R64343 break; 1518a1edd7dSLiu Hui-R64343 default: 1528a1edd7dSLiu Hui-R64343 break; 1538a1edd7dSLiu Hui-R64343 1548a1edd7dSLiu Hui-R64343 } 1558edcde5eSStefano Babic } 1568edcde5eSStefano Babic 1578a1edd7dSLiu Hui-R64343 static void set_dcd_val_v2(struct imx_header *imxhdr, char *name, int lineno, 1588a1edd7dSLiu Hui-R64343 int fld, uint32_t value, uint32_t off) 1598a1edd7dSLiu Hui-R64343 { 1608a1edd7dSLiu Hui-R64343 dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; 1618a1edd7dSLiu Hui-R64343 1628a1edd7dSLiu Hui-R64343 switch (fld) { 1638a1edd7dSLiu Hui-R64343 case CFG_REG_ADDRESS: 1648a1edd7dSLiu Hui-R64343 dcd_v2->addr_data[off].addr = cpu_to_be32(value); 1658a1edd7dSLiu Hui-R64343 break; 1668a1edd7dSLiu Hui-R64343 case CFG_REG_VALUE: 1678a1edd7dSLiu Hui-R64343 dcd_v2->addr_data[off].value = cpu_to_be32(value); 1688a1edd7dSLiu Hui-R64343 break; 1698a1edd7dSLiu Hui-R64343 default: 1708a1edd7dSLiu Hui-R64343 break; 1718a1edd7dSLiu Hui-R64343 1728a1edd7dSLiu Hui-R64343 } 1738a1edd7dSLiu Hui-R64343 } 1748a1edd7dSLiu Hui-R64343 1758a1edd7dSLiu Hui-R64343 /* 1768a1edd7dSLiu Hui-R64343 * Complete setting up the rest field of DCD of V1 1778a1edd7dSLiu Hui-R64343 * such as barker code and DCD data length. 1788a1edd7dSLiu Hui-R64343 */ 1798a1edd7dSLiu Hui-R64343 static void set_dcd_rst_v1(struct imx_header *imxhdr, uint32_t dcd_len, 1808a1edd7dSLiu Hui-R64343 char *name, int lineno) 1818a1edd7dSLiu Hui-R64343 { 1828a1edd7dSLiu Hui-R64343 dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table; 1838a1edd7dSLiu Hui-R64343 1848a1edd7dSLiu Hui-R64343 dcd_v1->preamble.barker = DCD_BARKER; 1858a1edd7dSLiu Hui-R64343 dcd_v1->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t); 1868a1edd7dSLiu Hui-R64343 } 1878a1edd7dSLiu Hui-R64343 1888a1edd7dSLiu Hui-R64343 /* 1898a1edd7dSLiu Hui-R64343 * Complete setting up the reset field of DCD of V2 1908a1edd7dSLiu Hui-R64343 * such as DCD tag, version, length, etc. 1918a1edd7dSLiu Hui-R64343 */ 1928a1edd7dSLiu Hui-R64343 static void set_dcd_rst_v2(struct imx_header *imxhdr, uint32_t dcd_len, 1938a1edd7dSLiu Hui-R64343 char *name, int lineno) 1948a1edd7dSLiu Hui-R64343 { 1958a1edd7dSLiu Hui-R64343 dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; 1968a1edd7dSLiu Hui-R64343 1978a1edd7dSLiu Hui-R64343 dcd_v2->header.tag = DCD_HEADER_TAG; 1988a1edd7dSLiu Hui-R64343 dcd_v2->header.length = cpu_to_be16( 1998a1edd7dSLiu Hui-R64343 dcd_len * sizeof(dcd_addr_data_t) + 8); 2008a1edd7dSLiu Hui-R64343 dcd_v2->header.version = DCD_VERSION; 2018a1edd7dSLiu Hui-R64343 dcd_v2->write_dcd_command.tag = DCD_COMMAND_TAG; 2028a1edd7dSLiu Hui-R64343 dcd_v2->write_dcd_command.length = cpu_to_be16( 2038a1edd7dSLiu Hui-R64343 dcd_len * sizeof(dcd_addr_data_t) + 4); 2048a1edd7dSLiu Hui-R64343 dcd_v2->write_dcd_command.param = DCD_COMMAND_PARAM; 2058a1edd7dSLiu Hui-R64343 } 2068a1edd7dSLiu Hui-R64343 2078a1edd7dSLiu Hui-R64343 static void set_imx_hdr_v1(struct imx_header *imxhdr, uint32_t dcd_len, 208ad0826dcSTroy Kisky uint32_t entry_point, uint32_t flash_offset) 2098a1edd7dSLiu Hui-R64343 { 2108a1edd7dSLiu Hui-R64343 imx_header_v1_t *hdr_v1 = &imxhdr->header.hdr_v1; 2118a1edd7dSLiu Hui-R64343 flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; 2128a1edd7dSLiu Hui-R64343 dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table; 213ab857f26STroy Kisky uint32_t hdr_base; 21424331982STroy Kisky uint32_t header_length = (((char *)&dcd_v1->addr_data[dcd_len].addr) 21524331982STroy Kisky - ((char *)imxhdr)); 2168a1edd7dSLiu Hui-R64343 2178a1edd7dSLiu Hui-R64343 /* Set magic number */ 2188a1edd7dSLiu Hui-R64343 fhdr_v1->app_code_barker = APP_CODE_BARKER; 2198a1edd7dSLiu Hui-R64343 220377e367aSStefano Babic /* TODO: check i.MX image V1 handling, for now use 'old' style */ 221377e367aSStefano Babic hdr_base = entry_point - 4096; 222ab857f26STroy Kisky fhdr_v1->app_dest_ptr = hdr_base - flash_offset; 223ad0826dcSTroy Kisky fhdr_v1->app_code_jump_vector = entry_point; 2248a1edd7dSLiu Hui-R64343 225ab857f26STroy Kisky fhdr_v1->dcd_ptr_ptr = hdr_base + offsetof(flash_header_v1_t, dcd_ptr); 226ab857f26STroy Kisky fhdr_v1->dcd_ptr = hdr_base + offsetof(imx_header_v1_t, dcd_table); 2278a1edd7dSLiu Hui-R64343 2288a1edd7dSLiu Hui-R64343 /* Security feature are not supported */ 2298a1edd7dSLiu Hui-R64343 fhdr_v1->app_code_csf = 0; 2308a1edd7dSLiu Hui-R64343 fhdr_v1->super_root_key = 0; 23124331982STroy Kisky header_size_ptr = (uint32_t *)(((char *)imxhdr) + header_length - 4); 2328a1edd7dSLiu Hui-R64343 } 2338a1edd7dSLiu Hui-R64343 2348a1edd7dSLiu Hui-R64343 static void set_imx_hdr_v2(struct imx_header *imxhdr, uint32_t dcd_len, 235ad0826dcSTroy Kisky uint32_t entry_point, uint32_t flash_offset) 2368a1edd7dSLiu Hui-R64343 { 2378a1edd7dSLiu Hui-R64343 imx_header_v2_t *hdr_v2 = &imxhdr->header.hdr_v2; 2388a1edd7dSLiu Hui-R64343 flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; 239ab857f26STroy Kisky uint32_t hdr_base; 2408a1edd7dSLiu Hui-R64343 2418a1edd7dSLiu Hui-R64343 /* Set magic number */ 2428a1edd7dSLiu Hui-R64343 fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */ 2438a1edd7dSLiu Hui-R64343 fhdr_v2->header.length = cpu_to_be16(sizeof(flash_header_v2_t)); 2448a1edd7dSLiu Hui-R64343 fhdr_v2->header.version = IVT_VERSION; /* 0x40 */ 2458a1edd7dSLiu Hui-R64343 246ad0826dcSTroy Kisky fhdr_v2->entry = entry_point; 2478a1edd7dSLiu Hui-R64343 fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0; 248377e367aSStefano Babic hdr_base = entry_point - imximage_init_loadsize + 249377e367aSStefano Babic flash_offset; 250377e367aSStefano Babic fhdr_v2->self = hdr_base; 251ab857f26STroy Kisky fhdr_v2->dcd_ptr = hdr_base + offsetof(imx_header_v2_t, dcd_table); 252ab857f26STroy Kisky fhdr_v2->boot_data_ptr = hdr_base 253ab857f26STroy Kisky + offsetof(imx_header_v2_t, boot_data); 254377e367aSStefano Babic hdr_v2->boot_data.start = entry_point - imximage_init_loadsize; 2558a1edd7dSLiu Hui-R64343 2568a1edd7dSLiu Hui-R64343 fhdr_v2->csf = 0; 2570187c985SStefano Babic 25824331982STroy Kisky header_size_ptr = &hdr_v2->boot_data.size; 2590187c985SStefano Babic csf_ptr = &fhdr_v2->csf; 2608a1edd7dSLiu Hui-R64343 } 2618a1edd7dSLiu Hui-R64343 26272048bc3SYork Sun static void set_hdr_func(void) 2638a1edd7dSLiu Hui-R64343 { 2648a1edd7dSLiu Hui-R64343 switch (imximage_version) { 2658a1edd7dSLiu Hui-R64343 case IMXIMAGE_V1: 2668a1edd7dSLiu Hui-R64343 set_dcd_val = set_dcd_val_v1; 2678a1edd7dSLiu Hui-R64343 set_dcd_rst = set_dcd_rst_v1; 2688a1edd7dSLiu Hui-R64343 set_imx_hdr = set_imx_hdr_v1; 2694d5fa985STroy Kisky max_dcd_entries = MAX_HW_CFG_SIZE_V1; 2708a1edd7dSLiu Hui-R64343 break; 2718a1edd7dSLiu Hui-R64343 case IMXIMAGE_V2: 2728a1edd7dSLiu Hui-R64343 set_dcd_val = set_dcd_val_v2; 2738a1edd7dSLiu Hui-R64343 set_dcd_rst = set_dcd_rst_v2; 2748a1edd7dSLiu Hui-R64343 set_imx_hdr = set_imx_hdr_v2; 2754d5fa985STroy Kisky max_dcd_entries = MAX_HW_CFG_SIZE_V2; 2768a1edd7dSLiu Hui-R64343 break; 2778a1edd7dSLiu Hui-R64343 default: 2788a1edd7dSLiu Hui-R64343 err_imximage_version(imximage_version); 2798a1edd7dSLiu Hui-R64343 break; 2808a1edd7dSLiu Hui-R64343 } 2818a1edd7dSLiu Hui-R64343 } 2828a1edd7dSLiu Hui-R64343 2838a1edd7dSLiu Hui-R64343 static void print_hdr_v1(struct imx_header *imx_hdr) 2848a1edd7dSLiu Hui-R64343 { 2858a1edd7dSLiu Hui-R64343 imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1; 2868a1edd7dSLiu Hui-R64343 flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; 2878a1edd7dSLiu Hui-R64343 dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table; 2888a1edd7dSLiu Hui-R64343 uint32_t size, length, ver; 2898a1edd7dSLiu Hui-R64343 2908a1edd7dSLiu Hui-R64343 size = dcd_v1->preamble.length; 2918a1edd7dSLiu Hui-R64343 if (size > (MAX_HW_CFG_SIZE_V1 * sizeof(dcd_type_addr_data_t))) { 2928a1edd7dSLiu Hui-R64343 fprintf(stderr, 2938a1edd7dSLiu Hui-R64343 "Error: Image corrupt DCD size %d exceed maximum %d\n", 2948a1edd7dSLiu Hui-R64343 (uint32_t)(size / sizeof(dcd_type_addr_data_t)), 2958a1edd7dSLiu Hui-R64343 MAX_HW_CFG_SIZE_V1); 2968a1edd7dSLiu Hui-R64343 exit(EXIT_FAILURE); 2978a1edd7dSLiu Hui-R64343 } 2988a1edd7dSLiu Hui-R64343 2998a1edd7dSLiu Hui-R64343 length = dcd_v1->preamble.length / sizeof(dcd_type_addr_data_t); 3008a1edd7dSLiu Hui-R64343 ver = detect_imximage_version(imx_hdr); 3018a1edd7dSLiu Hui-R64343 3028a1edd7dSLiu Hui-R64343 printf("Image Type: Freescale IMX Boot Image\n"); 3038a1edd7dSLiu Hui-R64343 printf("Image Ver: %x", ver); 3048a1edd7dSLiu Hui-R64343 printf("%s\n", get_table_entry_name(imximage_versions, NULL, ver)); 3058a1edd7dSLiu Hui-R64343 printf("Data Size: "); 3068a1edd7dSLiu Hui-R64343 genimg_print_size(dcd_v1->addr_data[length].type); 3078a1edd7dSLiu Hui-R64343 printf("Load Address: %08x\n", (uint32_t)fhdr_v1->app_dest_ptr); 3088a1edd7dSLiu Hui-R64343 printf("Entry Point: %08x\n", (uint32_t)fhdr_v1->app_code_jump_vector); 3098a1edd7dSLiu Hui-R64343 } 3108a1edd7dSLiu Hui-R64343 3118a1edd7dSLiu Hui-R64343 static void print_hdr_v2(struct imx_header *imx_hdr) 3128a1edd7dSLiu Hui-R64343 { 3138a1edd7dSLiu Hui-R64343 imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2; 3148a1edd7dSLiu Hui-R64343 flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; 3158a1edd7dSLiu Hui-R64343 dcd_v2_t *dcd_v2 = &hdr_v2->dcd_table; 3168a1edd7dSLiu Hui-R64343 uint32_t size, version; 3178a1edd7dSLiu Hui-R64343 3188a1edd7dSLiu Hui-R64343 size = be16_to_cpu(dcd_v2->header.length) - 8; 3198a1edd7dSLiu Hui-R64343 if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t))) { 3208a1edd7dSLiu Hui-R64343 fprintf(stderr, 3218a1edd7dSLiu Hui-R64343 "Error: Image corrupt DCD size %d exceed maximum %d\n", 3228a1edd7dSLiu Hui-R64343 (uint32_t)(size / sizeof(dcd_addr_data_t)), 3238a1edd7dSLiu Hui-R64343 MAX_HW_CFG_SIZE_V2); 3248a1edd7dSLiu Hui-R64343 exit(EXIT_FAILURE); 3258a1edd7dSLiu Hui-R64343 } 3268a1edd7dSLiu Hui-R64343 3278a1edd7dSLiu Hui-R64343 version = detect_imximage_version(imx_hdr); 3288a1edd7dSLiu Hui-R64343 3298a1edd7dSLiu Hui-R64343 printf("Image Type: Freescale IMX Boot Image\n"); 3308a1edd7dSLiu Hui-R64343 printf("Image Ver: %x", version); 3318a1edd7dSLiu Hui-R64343 printf("%s\n", get_table_entry_name(imximage_versions, NULL, version)); 3328a1edd7dSLiu Hui-R64343 printf("Data Size: "); 3338a1edd7dSLiu Hui-R64343 genimg_print_size(hdr_v2->boot_data.size); 3348a1edd7dSLiu Hui-R64343 printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr); 3358a1edd7dSLiu Hui-R64343 printf("Entry Point: %08x\n", (uint32_t)fhdr_v2->entry); 3360187c985SStefano Babic if (fhdr_v2->csf && (imximage_ivt_offset != UNDEFINED) && 3370187c985SStefano Babic (imximage_csf_size != UNDEFINED)) { 3380187c985SStefano Babic printf("HAB Blocks: %08x %08x %08x\n", 3390187c985SStefano Babic (uint32_t)fhdr_v2->self, 0, 3400187c985SStefano Babic hdr_v2->boot_data.size - imximage_ivt_offset - 3410187c985SStefano Babic imximage_csf_size); 3420187c985SStefano Babic } 3438a1edd7dSLiu Hui-R64343 } 3448a1edd7dSLiu Hui-R64343 3458a1edd7dSLiu Hui-R64343 static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token, 3468a1edd7dSLiu Hui-R64343 char *name, int lineno, int fld, int dcd_len) 3478a1edd7dSLiu Hui-R64343 { 3488a1edd7dSLiu Hui-R64343 int value; 3498a1edd7dSLiu Hui-R64343 static int cmd_ver_first = ~0; 3508a1edd7dSLiu Hui-R64343 3518a1edd7dSLiu Hui-R64343 switch (cmd) { 3528a1edd7dSLiu Hui-R64343 case CMD_IMAGE_VERSION: 3538a1edd7dSLiu Hui-R64343 imximage_version = get_cfg_value(token, name, lineno); 3548a1edd7dSLiu Hui-R64343 if (cmd_ver_first == 0) { 3558a1edd7dSLiu Hui-R64343 fprintf(stderr, "Error: %s[%d] - IMAGE_VERSION " 3568a1edd7dSLiu Hui-R64343 "command need be the first before other " 3578a1edd7dSLiu Hui-R64343 "valid command in the file\n", name, lineno); 3588a1edd7dSLiu Hui-R64343 exit(EXIT_FAILURE); 3598a1edd7dSLiu Hui-R64343 } 3608a1edd7dSLiu Hui-R64343 cmd_ver_first = 1; 36172048bc3SYork Sun set_hdr_func(); 3628a1edd7dSLiu Hui-R64343 break; 3638a1edd7dSLiu Hui-R64343 case CMD_BOOT_FROM: 364377e367aSStefano Babic imximage_ivt_offset = get_table_entry_id(imximage_boot_offset, 3658a1edd7dSLiu Hui-R64343 "imximage boot option", token); 3663150f92cSStefano Babic if (imximage_ivt_offset == -1) { 3678a1edd7dSLiu Hui-R64343 fprintf(stderr, "Error: %s[%d] -Invalid boot device" 3688a1edd7dSLiu Hui-R64343 "(%s)\n", name, lineno, token); 3698a1edd7dSLiu Hui-R64343 exit(EXIT_FAILURE); 3708a1edd7dSLiu Hui-R64343 } 371377e367aSStefano Babic 372377e367aSStefano Babic imximage_init_loadsize = 373377e367aSStefano Babic get_table_entry_id(imximage_boot_loadsize, 374377e367aSStefano Babic "imximage boot option", token); 375377e367aSStefano Babic 376377e367aSStefano Babic if (imximage_init_loadsize == -1) { 377377e367aSStefano Babic fprintf(stderr, 378377e367aSStefano Babic "Error: %s[%d] -Invalid boot device(%s)\n", 379377e367aSStefano Babic name, lineno, token); 380377e367aSStefano Babic exit(EXIT_FAILURE); 381377e367aSStefano Babic } 38201390affSStefano Babic 38301390affSStefano Babic /* 38401390affSStefano Babic * The SOC loads from the storage starting at address 0 38501390affSStefano Babic * then ensures that the load size contains the offset 38601390affSStefano Babic */ 38701390affSStefano Babic if (imximage_init_loadsize < imximage_ivt_offset) 38801390affSStefano Babic imximage_init_loadsize = imximage_ivt_offset; 3898a1edd7dSLiu Hui-R64343 if (unlikely(cmd_ver_first != 1)) 3908a1edd7dSLiu Hui-R64343 cmd_ver_first = 0; 3918a1edd7dSLiu Hui-R64343 break; 3926cb83829SMarek Vasut case CMD_BOOT_OFFSET: 3933150f92cSStefano Babic imximage_ivt_offset = get_cfg_value(token, name, lineno); 3946cb83829SMarek Vasut if (unlikely(cmd_ver_first != 1)) 3956cb83829SMarek Vasut cmd_ver_first = 0; 3966cb83829SMarek Vasut break; 3978a1edd7dSLiu Hui-R64343 case CMD_DATA: 3988a1edd7dSLiu Hui-R64343 value = get_cfg_value(token, name, lineno); 3998a1edd7dSLiu Hui-R64343 (*set_dcd_val)(imxhdr, name, lineno, fld, value, dcd_len); 4008a1edd7dSLiu Hui-R64343 if (unlikely(cmd_ver_first != 1)) 4018a1edd7dSLiu Hui-R64343 cmd_ver_first = 0; 4028a1edd7dSLiu Hui-R64343 break; 4030187c985SStefano Babic case CMD_CSF: 4040187c985SStefano Babic if (imximage_version != 2) { 4050187c985SStefano Babic fprintf(stderr, 4060187c985SStefano Babic "Error: %s[%d] - CSF only supported for VERSION 2(%s)\n", 4070187c985SStefano Babic name, lineno, token); 4080187c985SStefano Babic exit(EXIT_FAILURE); 4090187c985SStefano Babic } 4100187c985SStefano Babic imximage_csf_size = get_cfg_value(token, name, lineno); 4110187c985SStefano Babic if (unlikely(cmd_ver_first != 1)) 4120187c985SStefano Babic cmd_ver_first = 0; 4130187c985SStefano Babic break; 4148a1edd7dSLiu Hui-R64343 } 4158a1edd7dSLiu Hui-R64343 } 4168a1edd7dSLiu Hui-R64343 4178a1edd7dSLiu Hui-R64343 static void parse_cfg_fld(struct imx_header *imxhdr, int32_t *cmd, 4188a1edd7dSLiu Hui-R64343 char *token, char *name, int lineno, int fld, int *dcd_len) 4198a1edd7dSLiu Hui-R64343 { 4208a1edd7dSLiu Hui-R64343 int value; 4218a1edd7dSLiu Hui-R64343 4228a1edd7dSLiu Hui-R64343 switch (fld) { 4238a1edd7dSLiu Hui-R64343 case CFG_COMMAND: 4248a1edd7dSLiu Hui-R64343 *cmd = get_table_entry_id(imximage_cmds, 4258a1edd7dSLiu Hui-R64343 "imximage commands", token); 4268a1edd7dSLiu Hui-R64343 if (*cmd < 0) { 4278a1edd7dSLiu Hui-R64343 fprintf(stderr, "Error: %s[%d] - Invalid command" 4288a1edd7dSLiu Hui-R64343 "(%s)\n", name, lineno, token); 4298a1edd7dSLiu Hui-R64343 exit(EXIT_FAILURE); 4308a1edd7dSLiu Hui-R64343 } 4318a1edd7dSLiu Hui-R64343 break; 4328a1edd7dSLiu Hui-R64343 case CFG_REG_SIZE: 4338a1edd7dSLiu Hui-R64343 parse_cfg_cmd(imxhdr, *cmd, token, name, lineno, fld, *dcd_len); 4348a1edd7dSLiu Hui-R64343 break; 4358a1edd7dSLiu Hui-R64343 case CFG_REG_ADDRESS: 4368a1edd7dSLiu Hui-R64343 case CFG_REG_VALUE: 4378a1edd7dSLiu Hui-R64343 if (*cmd != CMD_DATA) 4388a1edd7dSLiu Hui-R64343 return; 4398a1edd7dSLiu Hui-R64343 4408a1edd7dSLiu Hui-R64343 value = get_cfg_value(token, name, lineno); 4418a1edd7dSLiu Hui-R64343 (*set_dcd_val)(imxhdr, name, lineno, fld, value, *dcd_len); 4428a1edd7dSLiu Hui-R64343 4434d5fa985STroy Kisky if (fld == CFG_REG_VALUE) { 4448a1edd7dSLiu Hui-R64343 (*dcd_len)++; 4454d5fa985STroy Kisky if (*dcd_len > max_dcd_entries) { 4464d5fa985STroy Kisky fprintf(stderr, "Error: %s[%d] -" 4474d5fa985STroy Kisky "DCD table exceeds maximum size(%d)\n", 4484d5fa985STroy Kisky name, lineno, max_dcd_entries); 4494d5fa985STroy Kisky exit(EXIT_FAILURE); 4504d5fa985STroy Kisky } 4514d5fa985STroy Kisky } 4528a1edd7dSLiu Hui-R64343 break; 4538a1edd7dSLiu Hui-R64343 default: 4548a1edd7dSLiu Hui-R64343 break; 4558a1edd7dSLiu Hui-R64343 } 4568a1edd7dSLiu Hui-R64343 } 4578a1edd7dSLiu Hui-R64343 static uint32_t parse_cfg_file(struct imx_header *imxhdr, char *name) 4588edcde5eSStefano Babic { 4598edcde5eSStefano Babic FILE *fd = NULL; 4608edcde5eSStefano Babic char *line = NULL; 4618edcde5eSStefano Babic char *token, *saveptr1, *saveptr2; 4628edcde5eSStefano Babic int lineno = 0; 4638a1edd7dSLiu Hui-R64343 int fld; 4640ad22703SKim Phillips size_t len; 4658edcde5eSStefano Babic int dcd_len = 0; 4668edcde5eSStefano Babic int32_t cmd; 4678edcde5eSStefano Babic 4688edcde5eSStefano Babic fd = fopen(name, "r"); 4698edcde5eSStefano Babic if (fd == 0) { 4708edcde5eSStefano Babic fprintf(stderr, "Error: %s - Can't open DCD file\n", name); 4718edcde5eSStefano Babic exit(EXIT_FAILURE); 4728edcde5eSStefano Babic } 4738edcde5eSStefano Babic 47401390affSStefano Babic /* 47501390affSStefano Babic * Very simple parsing, line starting with # are comments 4768edcde5eSStefano Babic * and are dropped 4778edcde5eSStefano Babic */ 4788edcde5eSStefano Babic while ((getline(&line, &len, fd)) > 0) { 4798edcde5eSStefano Babic lineno++; 4808edcde5eSStefano Babic 4818edcde5eSStefano Babic token = strtok_r(line, "\r\n", &saveptr1); 4828edcde5eSStefano Babic if (token == NULL) 4838edcde5eSStefano Babic continue; 4848edcde5eSStefano Babic 4858edcde5eSStefano Babic /* Check inside the single line */ 4868edcde5eSStefano Babic for (fld = CFG_COMMAND, cmd = CMD_INVALID, 4878edcde5eSStefano Babic line = token; ; line = NULL, fld++) { 4888edcde5eSStefano Babic token = strtok_r(line, " \t", &saveptr2); 4898edcde5eSStefano Babic if (token == NULL) 4908edcde5eSStefano Babic break; 4918edcde5eSStefano Babic 4928edcde5eSStefano Babic /* Drop all text starting with '#' as comments */ 4938edcde5eSStefano Babic if (token[0] == '#') 4948edcde5eSStefano Babic break; 4958edcde5eSStefano Babic 4968a1edd7dSLiu Hui-R64343 parse_cfg_fld(imxhdr, &cmd, token, name, 4978a1edd7dSLiu Hui-R64343 lineno, fld, &dcd_len); 4988edcde5eSStefano Babic } 4998edcde5eSStefano Babic 5008edcde5eSStefano Babic } 5018edcde5eSStefano Babic 5028a1edd7dSLiu Hui-R64343 (*set_dcd_rst)(imxhdr, dcd_len, name, lineno); 5038edcde5eSStefano Babic fclose(fd); 5048edcde5eSStefano Babic 5058d8cc828STroy Kisky /* Exit if there is no BOOT_FROM field specifying the flash_offset */ 5063150f92cSStefano Babic if (imximage_ivt_offset == FLASH_OFFSET_UNDEFINED) { 5078d8cc828STroy Kisky fprintf(stderr, "Error: No BOOT_FROM tag in %s\n", name); 5088d8cc828STroy Kisky exit(EXIT_FAILURE); 5098d8cc828STroy Kisky } 5105b28e913SStefano Babic return dcd_len; 5118edcde5eSStefano Babic } 5128edcde5eSStefano Babic 5138a1edd7dSLiu Hui-R64343 5148a1edd7dSLiu Hui-R64343 static int imximage_check_image_types(uint8_t type) 5158a1edd7dSLiu Hui-R64343 { 5168a1edd7dSLiu Hui-R64343 if (type == IH_TYPE_IMXIMAGE) 5178a1edd7dSLiu Hui-R64343 return EXIT_SUCCESS; 5188a1edd7dSLiu Hui-R64343 else 5198a1edd7dSLiu Hui-R64343 return EXIT_FAILURE; 5208a1edd7dSLiu Hui-R64343 } 5218a1edd7dSLiu Hui-R64343 5228a1edd7dSLiu Hui-R64343 static int imximage_verify_header(unsigned char *ptr, int image_size, 523f86ed6a8SGuilherme Maciel Ferreira struct image_tool_params *params) 5248a1edd7dSLiu Hui-R64343 { 5258a1edd7dSLiu Hui-R64343 struct imx_header *imx_hdr = (struct imx_header *) ptr; 5268a1edd7dSLiu Hui-R64343 5278a1edd7dSLiu Hui-R64343 if (detect_imximage_version(imx_hdr) == IMXIMAGE_VER_INVALID) 5288a1edd7dSLiu Hui-R64343 return -FDT_ERR_BADSTRUCTURE; 5298a1edd7dSLiu Hui-R64343 5308a1edd7dSLiu Hui-R64343 return 0; 5318a1edd7dSLiu Hui-R64343 } 5328a1edd7dSLiu Hui-R64343 5338a1edd7dSLiu Hui-R64343 static void imximage_print_header(const void *ptr) 5348a1edd7dSLiu Hui-R64343 { 5358a1edd7dSLiu Hui-R64343 struct imx_header *imx_hdr = (struct imx_header *) ptr; 5368a1edd7dSLiu Hui-R64343 uint32_t version = detect_imximage_version(imx_hdr); 5378a1edd7dSLiu Hui-R64343 5388a1edd7dSLiu Hui-R64343 switch (version) { 5398a1edd7dSLiu Hui-R64343 case IMXIMAGE_V1: 5408a1edd7dSLiu Hui-R64343 print_hdr_v1(imx_hdr); 5418a1edd7dSLiu Hui-R64343 break; 5428a1edd7dSLiu Hui-R64343 case IMXIMAGE_V2: 5438a1edd7dSLiu Hui-R64343 print_hdr_v2(imx_hdr); 5448a1edd7dSLiu Hui-R64343 break; 5458a1edd7dSLiu Hui-R64343 default: 5468a1edd7dSLiu Hui-R64343 err_imximage_version(version); 5478a1edd7dSLiu Hui-R64343 break; 5488a1edd7dSLiu Hui-R64343 } 5498a1edd7dSLiu Hui-R64343 } 5508a1edd7dSLiu Hui-R64343 5518edcde5eSStefano Babic static void imximage_set_header(void *ptr, struct stat *sbuf, int ifd, 552f86ed6a8SGuilherme Maciel Ferreira struct image_tool_params *params) 5538edcde5eSStefano Babic { 5548a1edd7dSLiu Hui-R64343 struct imx_header *imxhdr = (struct imx_header *)ptr; 5558a1edd7dSLiu Hui-R64343 uint32_t dcd_len; 5568edcde5eSStefano Babic 5578a1edd7dSLiu Hui-R64343 /* 5588a1edd7dSLiu Hui-R64343 * In order to not change the old imx cfg file 5598a1edd7dSLiu Hui-R64343 * by adding VERSION command into it, here need 5608a1edd7dSLiu Hui-R64343 * set up function ptr group to V1 by default. 5618a1edd7dSLiu Hui-R64343 */ 5628a1edd7dSLiu Hui-R64343 imximage_version = IMXIMAGE_V1; 56349d3e272SDirk Behme /* Be able to detect if the cfg file has no BOOT_FROM tag */ 5643150f92cSStefano Babic imximage_ivt_offset = FLASH_OFFSET_UNDEFINED; 5650187c985SStefano Babic imximage_csf_size = 0; 56672048bc3SYork Sun set_hdr_func(); 5678edcde5eSStefano Babic 5688edcde5eSStefano Babic /* Parse dcd configuration file */ 5698a1edd7dSLiu Hui-R64343 dcd_len = parse_cfg_file(imxhdr, params->imagename); 5708edcde5eSStefano Babic 57103ea24b2SYe.Li if (imximage_version == IMXIMAGE_V2) { 57203ea24b2SYe.Li if (imximage_init_loadsize < imximage_ivt_offset + 57303ea24b2SYe.Li sizeof(imx_header_v2_t)) 57403ea24b2SYe.Li imximage_init_loadsize = imximage_ivt_offset + 57503ea24b2SYe.Li sizeof(imx_header_v2_t); 57603ea24b2SYe.Li } 57703ea24b2SYe.Li 5788a1edd7dSLiu Hui-R64343 /* Set the imx header */ 5793150f92cSStefano Babic (*set_imx_hdr)(imxhdr, dcd_len, params->ep, imximage_ivt_offset); 5801411fb37SFabio Estevam 5811411fb37SFabio Estevam /* 5821411fb37SFabio Estevam * ROM bug alert 583895d9966SMarek Vasut * 584895d9966SMarek Vasut * MX53 only loads 512 byte multiples in case of SD boot. 585895d9966SMarek Vasut * MX53 only loads NAND page multiples in case of NAND boot and 586895d9966SMarek Vasut * supports up to 4096 byte large pages, thus align to 4096. 587895d9966SMarek Vasut * 588895d9966SMarek Vasut * The remaining fraction of a block bytes would not be loaded! 5891411fb37SFabio Estevam */ 590*de979804SYe.Li *header_size_ptr = ROUND((sbuf->st_size + imximage_ivt_offset), 4096); 5910187c985SStefano Babic 5920187c985SStefano Babic if (csf_ptr && imximage_csf_size) { 5930187c985SStefano Babic *csf_ptr = params->ep - imximage_init_loadsize + 5940187c985SStefano Babic *header_size_ptr; 5950187c985SStefano Babic *header_size_ptr += imximage_csf_size; 5960187c985SStefano Babic } 5978edcde5eSStefano Babic } 5988edcde5eSStefano Babic 599f86ed6a8SGuilherme Maciel Ferreira int imximage_check_params(struct image_tool_params *params) 6008edcde5eSStefano Babic { 6018edcde5eSStefano Babic if (!params) 6028edcde5eSStefano Babic return CFG_INVALID; 6038edcde5eSStefano Babic if (!strlen(params->imagename)) { 6048edcde5eSStefano Babic fprintf(stderr, "Error: %s - Configuration file not specified, " 6058edcde5eSStefano Babic "it is needed for imximage generation\n", 6068edcde5eSStefano Babic params->cmdname); 6078edcde5eSStefano Babic return CFG_INVALID; 6088edcde5eSStefano Babic } 6098edcde5eSStefano Babic /* 6108edcde5eSStefano Babic * Check parameters: 6118edcde5eSStefano Babic * XIP is not allowed and verify that incompatible 6128edcde5eSStefano Babic * parameters are not sent at the same time 6138edcde5eSStefano Babic * For example, if list is required a data image must not be provided 6148edcde5eSStefano Babic */ 6158edcde5eSStefano Babic return (params->dflag && (params->fflag || params->lflag)) || 6168edcde5eSStefano Babic (params->fflag && (params->dflag || params->lflag)) || 6178edcde5eSStefano Babic (params->lflag && (params->dflag || params->fflag)) || 6188edcde5eSStefano Babic (params->xflag) || !(strlen(params->imagename)); 6198edcde5eSStefano Babic } 6208edcde5eSStefano Babic 621f86ed6a8SGuilherme Maciel Ferreira static int imximage_generate(struct image_tool_params *params, 62201390affSStefano Babic struct image_type_params *tparams) 62301390affSStefano Babic { 62401390affSStefano Babic struct imx_header *imxhdr; 62501390affSStefano Babic size_t alloc_len; 62601390affSStefano Babic struct stat sbuf; 62701390affSStefano Babic char *datafile = params->datafile; 62801390affSStefano Babic uint32_t pad_len; 62901390affSStefano Babic 63001390affSStefano Babic memset(&imximage_header, 0, sizeof(imximage_header)); 63101390affSStefano Babic 63201390affSStefano Babic /* 63301390affSStefano Babic * In order to not change the old imx cfg file 63401390affSStefano Babic * by adding VERSION command into it, here need 63501390affSStefano Babic * set up function ptr group to V1 by default. 63601390affSStefano Babic */ 63701390affSStefano Babic imximage_version = IMXIMAGE_V1; 63801390affSStefano Babic /* Be able to detect if the cfg file has no BOOT_FROM tag */ 63901390affSStefano Babic imximage_ivt_offset = FLASH_OFFSET_UNDEFINED; 64001390affSStefano Babic imximage_csf_size = 0; 64172048bc3SYork Sun set_hdr_func(); 64201390affSStefano Babic 64301390affSStefano Babic /* Parse dcd configuration file */ 64401390affSStefano Babic parse_cfg_file(&imximage_header, params->imagename); 64501390affSStefano Babic 64601390affSStefano Babic /* TODO: check i.MX image V1 handling, for now use 'old' style */ 64701390affSStefano Babic if (imximage_version == IMXIMAGE_V1) { 64801390affSStefano Babic alloc_len = 4096; 64901390affSStefano Babic } else { 65001390affSStefano Babic if (imximage_init_loadsize < imximage_ivt_offset + 65101390affSStefano Babic sizeof(imx_header_v2_t)) 65201390affSStefano Babic imximage_init_loadsize = imximage_ivt_offset + 65301390affSStefano Babic sizeof(imx_header_v2_t); 65401390affSStefano Babic alloc_len = imximage_init_loadsize - imximage_ivt_offset; 65501390affSStefano Babic } 65601390affSStefano Babic 65701390affSStefano Babic if (alloc_len < sizeof(struct imx_header)) { 65801390affSStefano Babic fprintf(stderr, "%s: header error\n", 65901390affSStefano Babic params->cmdname); 66001390affSStefano Babic exit(EXIT_FAILURE); 66101390affSStefano Babic } 66201390affSStefano Babic 66301390affSStefano Babic imxhdr = malloc(alloc_len); 66401390affSStefano Babic 66501390affSStefano Babic if (!imxhdr) { 66601390affSStefano Babic fprintf(stderr, "%s: malloc return failure: %s\n", 66701390affSStefano Babic params->cmdname, strerror(errno)); 66801390affSStefano Babic exit(EXIT_FAILURE); 66901390affSStefano Babic } 67001390affSStefano Babic 67101390affSStefano Babic memset(imxhdr, 0, alloc_len); 67201390affSStefano Babic 67301390affSStefano Babic tparams->header_size = alloc_len; 67401390affSStefano Babic tparams->hdr = imxhdr; 67501390affSStefano Babic 67601390affSStefano Babic /* determine data image file length */ 67701390affSStefano Babic 67801390affSStefano Babic if (stat(datafile, &sbuf) < 0) { 67901390affSStefano Babic fprintf(stderr, "%s: Can't stat %s: %s\n", 68001390affSStefano Babic params->cmdname, datafile, strerror(errno)); 68101390affSStefano Babic exit(EXIT_FAILURE); 68201390affSStefano Babic } 68301390affSStefano Babic 68401390affSStefano Babic pad_len = ROUND(sbuf.st_size, 4096) - sbuf.st_size; 68501390affSStefano Babic 68601390affSStefano Babic /* TODO: check i.MX image V1 handling, for now use 'old' style */ 68701390affSStefano Babic if (imximage_version == IMXIMAGE_V1) 68801390affSStefano Babic return 0; 68901390affSStefano Babic else 69001390affSStefano Babic return pad_len; 69101390affSStefano Babic } 69201390affSStefano Babic 69301390affSStefano Babic 6948edcde5eSStefano Babic /* 6958edcde5eSStefano Babic * imximage parameters 6968edcde5eSStefano Babic */ 6978edcde5eSStefano Babic static struct image_type_params imximage_params = { 6986e083857SFabio Estevam .name = "Freescale i.MX Boot Image support", 69901390affSStefano Babic .header_size = 0, 70001390affSStefano Babic .hdr = NULL, 7018edcde5eSStefano Babic .check_image_type = imximage_check_image_types, 7028edcde5eSStefano Babic .verify_header = imximage_verify_header, 7038edcde5eSStefano Babic .print_header = imximage_print_header, 7048edcde5eSStefano Babic .set_header = imximage_set_header, 7058edcde5eSStefano Babic .check_params = imximage_check_params, 70601390affSStefano Babic .vrec_header = imximage_generate, 7078edcde5eSStefano Babic }; 7088edcde5eSStefano Babic 7098edcde5eSStefano Babic void init_imx_image_type(void) 7108edcde5eSStefano Babic { 711f86ed6a8SGuilherme Maciel Ferreira register_image_type(&imximage_params); 7128edcde5eSStefano Babic } 713