1 /* 2 * (C) Copyright 2009 3 * Stefano Babic, DENX Software Engineering, sbabic@denx.de. 4 * 5 * (C) Copyright 2008 6 * Marvell Semiconductor <www.marvell.com> 7 * Written-by: Prafulla Wadaskar <prafulla@marvell.com> 8 * 9 * See file CREDITS for list of people who contributed to this 10 * project. 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License as 14 * published by the Free Software Foundation; either version 2 of 15 * the License, or (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 25 * MA 02111-1307 USA 26 */ 27 28 #include "mkimage.h" 29 #include <image.h> 30 #include "imximage.h" 31 32 /* 33 * Supported commands for configuration file 34 */ 35 static table_entry_t imximage_cmds[] = { 36 {CMD_BOOT_FROM, "BOOT_FROM", "boot comand", }, 37 {CMD_DATA, "DATA", "Reg Write Data", }, 38 {-1, "", "", }, 39 }; 40 41 /* 42 * Supported Boot options for configuration file 43 * this is needed to set the correct flash offset 44 */ 45 static table_entry_t imximage_bootops[] = { 46 {FLASH_OFFSET_SPI, "spi", "SPI Flash", }, 47 {FLASH_OFFSET_NAND, "nand", "NAND Flash", }, 48 {FLASH_OFFSET_SD, "sd", "SD Card", }, 49 {FLASH_OFFSET_ONENAND, "onenand", "OneNAND Flash",}, 50 {-1, "", "Invalid", }, 51 }; 52 53 54 static struct imx_header imximage_header; 55 56 static uint32_t get_cfg_value(char *token, char *name, int linenr) 57 { 58 char *endptr; 59 uint32_t value; 60 61 errno = 0; 62 value = strtoul(token, &endptr, 16); 63 if (errno || (token == endptr)) { 64 fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", 65 name, linenr, token); 66 exit(EXIT_FAILURE); 67 } 68 return value; 69 } 70 71 static int imximage_check_image_types(uint8_t type) 72 { 73 if (type == IH_TYPE_IMXIMAGE) 74 return EXIT_SUCCESS; 75 else 76 return EXIT_FAILURE; 77 } 78 79 static int imximage_verify_header(unsigned char *ptr, int image_size, 80 struct mkimage_params *params) 81 { 82 83 struct imx_header *imx_hdr = (struct imx_header *) ptr; 84 flash_header_t *hdr = &imx_hdr->fhdr; 85 86 /* Only a few checks can be done: search for magic numbers */ 87 if (hdr->app_code_barker != APP_CODE_BARKER) 88 return -FDT_ERR_BADSTRUCTURE; 89 90 if (imx_hdr->dcd_table.preamble.barker != DCD_BARKER) 91 return -FDT_ERR_BADSTRUCTURE; 92 93 return 0; 94 } 95 96 static void imximage_print_header(const void *ptr) 97 { 98 struct imx_header *imx_hdr = (struct imx_header *) ptr; 99 flash_header_t *hdr = &imx_hdr->fhdr; 100 uint32_t size; 101 flash_cfg_parms_t *ext_header; 102 103 size = imx_hdr->dcd_table.preamble.length; 104 if (size > (MAX_HW_CFG_SIZE * sizeof(dcd_type_addr_data_t))) { 105 fprintf(stderr, 106 "Error: Image corrupt DCD size %d exceed maximum %d\n", 107 size / sizeof(dcd_type_addr_data_t), MAX_HW_CFG_SIZE); 108 exit(EXIT_FAILURE); 109 } 110 111 ext_header = (flash_cfg_parms_t *) ((uint32_t)&imx_hdr->dcd_table + 112 sizeof(dcd_preamble_t) + size); 113 114 printf("Image Type: Freescale IMX Boot Image\n"); 115 printf("Data Size: "); 116 genimg_print_size(ext_header->length); 117 printf("Load Address: %08x\n", (unsigned int)hdr->app_dest_ptr); 118 printf("Entry Point: %08x\n", (unsigned int)hdr->app_code_jump_vector); 119 } 120 121 static uint32_t imximage_parse_cfg_file(struct imx_header *imxhdr, char *name) 122 { 123 FILE *fd = NULL; 124 char *line = NULL; 125 char *token, *saveptr1, *saveptr2; 126 int lineno = 0; 127 int fld, value; 128 uint32_t len; 129 int dcd_len = 0; 130 dcd_t *dcd = &imxhdr->dcd_table; 131 int32_t cmd; 132 133 fd = fopen(name, "r"); 134 if (fd == 0) { 135 fprintf(stderr, "Error: %s - Can't open DCD file\n", name); 136 exit(EXIT_FAILURE); 137 } 138 139 /* Very simple parsing, line starting with # are comments 140 * and are dropped 141 */ 142 while ((getline(&line, &len, fd)) > 0) { 143 lineno++; 144 145 token = strtok_r(line, "\r\n", &saveptr1); 146 if (token == NULL) 147 continue; 148 149 /* Check inside the single line */ 150 for (fld = CFG_COMMAND, cmd = CMD_INVALID, 151 line = token; ; line = NULL, fld++) { 152 token = strtok_r(line, " \t", &saveptr2); 153 if (token == NULL) 154 break; 155 156 /* Drop all text starting with '#' as comments */ 157 if (token[0] == '#') 158 break; 159 160 /* parse all fields in a single line */ 161 switch (fld) { 162 case CFG_COMMAND: 163 cmd = get_table_entry_id(imximage_cmds, 164 "imximage commands", token); 165 if (cmd < 0) { 166 fprintf(stderr, 167 "Error: %s[%d] - " 168 "Invalid command (%s)\n", 169 name, lineno, token); 170 exit(EXIT_FAILURE); 171 } 172 break; 173 case CFG_REG_SIZE: 174 switch (cmd) { 175 case CMD_BOOT_FROM: 176 /* Get flash header offset */ 177 imxhdr->flash_offset = 178 get_table_entry_id( 179 imximage_bootops, 180 "imximage boot option", 181 token); 182 if (imxhdr->flash_offset == -1) { 183 fprintf(stderr, 184 "Error: %s[%d] -" 185 "Invalid boot device" 186 "(%s)\n", 187 name, lineno, token); 188 exit(EXIT_FAILURE); 189 } 190 break; 191 case CMD_DATA: 192 value = get_cfg_value(token, 193 name, lineno); 194 195 /* Byte, halfword, word */ 196 if ((value != 1) && 197 (value != 2) && (value != 4)) { 198 fprintf(stderr, 199 "Error: %s[%d] - " 200 "Invalid register size " 201 "(%d)\n", 202 name, lineno, value); 203 exit(EXIT_FAILURE); 204 } 205 dcd->addr_data[dcd_len].type = value; 206 break; 207 } 208 209 case CFG_REG_ADDRESS: 210 if (cmd == CMD_DATA) 211 dcd->addr_data[dcd_len].addr = 212 get_cfg_value(token, 213 name, lineno); 214 break; 215 case CFG_REG_VALUE: 216 if (cmd == CMD_DATA) { 217 dcd->addr_data[dcd_len].value = 218 get_cfg_value(token, 219 name, lineno); 220 dcd_len++; 221 } 222 break; 223 } 224 } 225 226 if (dcd_len > MAX_HW_CFG_SIZE) { 227 fprintf(stderr, 228 "Error: %s[%d] -" 229 "DCD table exceeds maximum size(%d)\n", 230 name, lineno, MAX_HW_CFG_SIZE); 231 } 232 } 233 dcd->preamble.barker = DCD_BARKER; 234 dcd->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t); 235 fclose(fd); 236 237 return dcd->preamble.length; 238 } 239 240 static void imximage_set_header(void *ptr, struct stat *sbuf, int ifd, 241 struct mkimage_params *params) 242 { 243 struct imx_header *hdr = (struct imx_header *)ptr; 244 flash_header_t *fhdr = &hdr->fhdr; 245 int dcd_len; 246 flash_cfg_parms_t *ext_header; 247 uint32_t base_offset; 248 249 /* Set default offset */ 250 hdr->flash_offset = FLASH_OFFSET_STANDARD; 251 252 /* Set magic number */ 253 fhdr->app_code_barker = APP_CODE_BARKER; 254 255 /* Parse dcd configuration file */ 256 dcd_len = imximage_parse_cfg_file(hdr, params->imagename); 257 258 fhdr->app_dest_ptr = params->addr; 259 fhdr->app_dest_ptr = params->ep - hdr->flash_offset - 260 sizeof(struct imx_header); 261 fhdr->app_code_jump_vector = params->ep; 262 263 base_offset = fhdr->app_dest_ptr + hdr->flash_offset ; 264 fhdr->dcd_ptr_ptr = (uint32_t) ((uint32_t)&fhdr->dcd_ptr - 265 (uint32_t)&fhdr->app_code_jump_vector) + base_offset ; 266 267 fhdr->dcd_ptr = base_offset + 268 ((uint32_t)&hdr->dcd_table - 269 (uint32_t)&hdr->fhdr); 270 271 /* The external flash header must be at the end of the DCD table */ 272 ext_header = (flash_cfg_parms_t *) ((uint32_t)&hdr->dcd_table + 273 dcd_len + 274 sizeof(dcd_preamble_t)); 275 ext_header->length = sbuf->st_size + 276 hdr->flash_offset + 277 sizeof(struct imx_header); 278 279 /* Security feature are not supported */ 280 fhdr->app_code_csf = 0; 281 fhdr->super_root_key = NULL; 282 283 } 284 285 int imximage_check_params(struct mkimage_params *params) 286 { 287 if (!params) 288 return CFG_INVALID; 289 if (!strlen(params->imagename)) { 290 fprintf(stderr, "Error: %s - Configuration file not specified, " 291 "it is needed for imximage generation\n", 292 params->cmdname); 293 return CFG_INVALID; 294 } 295 /* 296 * Check parameters: 297 * XIP is not allowed and verify that incompatible 298 * parameters are not sent at the same time 299 * For example, if list is required a data image must not be provided 300 */ 301 return (params->dflag && (params->fflag || params->lflag)) || 302 (params->fflag && (params->dflag || params->lflag)) || 303 (params->lflag && (params->dflag || params->fflag)) || 304 (params->xflag) || !(strlen(params->imagename)); 305 } 306 307 /* 308 * imximage parameters 309 */ 310 static struct image_type_params imximage_params = { 311 .name = "Freescale i.MX 51 Boot Image support", 312 .header_size = sizeof(struct imx_header), 313 .hdr = (void *)&imximage_header, 314 .check_image_type = imximage_check_image_types, 315 .verify_header = imximage_verify_header, 316 .print_header = imximage_print_header, 317 .set_header = imximage_set_header, 318 .check_params = imximage_check_params, 319 }; 320 321 void init_imx_image_type(void) 322 { 323 mkimage_register(&imximage_params); 324 } 325