1 /* 2 * (C) Copyright 2011 3 * Heiko Schocher, DENX Software Engineering, hs@denx.de. 4 * 5 * Based on: 6 * (C) Copyright 2009 7 * Stefano Babic, DENX Software Engineering, sbabic@denx.de. 8 * 9 * (C) Copyright 2008 10 * Marvell Semiconductor <www.marvell.com> 11 * Written-by: Prafulla Wadaskar <prafulla@marvell.com> 12 * 13 * SPDX-License-Identifier: GPL-2.0+ 14 */ 15 16 #include "imagetool.h" 17 #include <image.h> 18 #include "ublimage.h" 19 20 /* 21 * Supported commands for configuration file 22 */ 23 static table_entry_t ublimage_cmds[] = { 24 {CMD_BOOT_MODE, "MODE", "UBL special modes", }, 25 {CMD_ENTRY, "ENTRY", "Entry point addr for bootloader", }, 26 {CMD_PAGE, "PAGES", 27 "number of pages (size of bootloader)", }, 28 {CMD_ST_BLOCK, "START_BLOCK", 29 "block number where bootloader is present", }, 30 {CMD_ST_PAGE, "START_PAGE", 31 "page number where bootloader is present", }, 32 {CMD_LD_ADDR, "LD_ADDR", 33 "load addr", }, 34 {-1, "", "", }, 35 }; 36 37 /* 38 * Supported Boot options for configuration file 39 * this is needed to set the correct flash offset 40 */ 41 static table_entry_t ublimage_bootops[] = { 42 {UBL_MAGIC_SAFE, "safe", "Safe boot mode", }, 43 {-1, "", "Invalid", }, 44 }; 45 46 static struct ubl_header ublimage_header; 47 48 static uint32_t get_cfg_value(char *token, char *name, int linenr) 49 { 50 char *endptr; 51 uint32_t value; 52 53 errno = 0; 54 value = strtoul(token, &endptr, 16); 55 if (errno || (token == endptr)) { 56 fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", 57 name, linenr, token); 58 exit(EXIT_FAILURE); 59 } 60 return value; 61 } 62 63 static void print_hdr(struct ubl_header *ubl_hdr) 64 { 65 printf("Image Type : Davinci UBL Boot Image\n"); 66 printf("UBL magic : %08x\n", ubl_hdr->magic); 67 printf("Entry Point: %08x\n", ubl_hdr->entry); 68 printf("nr of pages: %08x\n", ubl_hdr->pages); 69 printf("start block: %08x\n", ubl_hdr->block); 70 printf("start page : %08x\n", ubl_hdr->page); 71 } 72 73 static void parse_cfg_cmd(struct ubl_header *ublhdr, int32_t cmd, char *token, 74 char *name, int lineno, int fld, int dcd_len) 75 { 76 static int cmd_ver_first = ~0; 77 78 switch (cmd) { 79 case CMD_BOOT_MODE: 80 ublhdr->magic = get_table_entry_id(ublimage_bootops, 81 "ublimage special boot mode", token); 82 if (ublhdr->magic == -1) { 83 fprintf(stderr, "Error: %s[%d] -Invalid boot mode" 84 "(%s)\n", name, lineno, token); 85 exit(EXIT_FAILURE); 86 } 87 ublhdr->magic += UBL_MAGIC_BASE; 88 if (unlikely(cmd_ver_first != 1)) 89 cmd_ver_first = 0; 90 break; 91 case CMD_ENTRY: 92 ublhdr->entry = get_cfg_value(token, name, lineno); 93 break; 94 case CMD_PAGE: 95 ublhdr->pages = get_cfg_value(token, name, lineno); 96 break; 97 case CMD_ST_BLOCK: 98 ublhdr->block = get_cfg_value(token, name, lineno); 99 break; 100 case CMD_ST_PAGE: 101 ublhdr->page = get_cfg_value(token, name, lineno); 102 break; 103 case CMD_LD_ADDR: 104 ublhdr->pll_m = get_cfg_value(token, name, lineno); 105 break; 106 } 107 } 108 109 static void parse_cfg_fld(struct ubl_header *ublhdr, int32_t *cmd, 110 char *token, char *name, int lineno, int fld, int *dcd_len) 111 { 112 113 switch (fld) { 114 case CFG_COMMAND: 115 *cmd = get_table_entry_id(ublimage_cmds, 116 "ublimage commands", token); 117 if (*cmd < 0) { 118 fprintf(stderr, "Error: %s[%d] - Invalid command" 119 "(%s)\n", name, lineno, token); 120 exit(EXIT_FAILURE); 121 } 122 break; 123 case CFG_REG_VALUE: 124 parse_cfg_cmd(ublhdr, *cmd, token, name, lineno, fld, *dcd_len); 125 break; 126 default: 127 break; 128 } 129 } 130 static uint32_t parse_cfg_file(struct ubl_header *ublhdr, char *name) 131 { 132 FILE *fd = NULL; 133 char *line = NULL; 134 char *token, *saveptr1, *saveptr2; 135 int lineno = 0; 136 int i; 137 char *ptr = (char *)ublhdr; 138 int fld; 139 size_t len; 140 int dcd_len = 0; 141 int32_t cmd; 142 int ublhdrlen = sizeof(struct ubl_header); 143 144 fd = fopen(name, "r"); 145 if (fd == 0) { 146 fprintf(stderr, "Error: %s - Can't open DCD file\n", name); 147 exit(EXIT_FAILURE); 148 } 149 150 /* Fill header with 0xff */ 151 for (i = 0; i < ublhdrlen; i++) { 152 *ptr = 0xff; 153 ptr++; 154 } 155 156 /* 157 * Very simple parsing, line starting with # are comments 158 * and are dropped 159 */ 160 while ((getline(&line, &len, fd)) > 0) { 161 lineno++; 162 163 token = strtok_r(line, "\r\n", &saveptr1); 164 if (token == NULL) 165 continue; 166 167 /* Check inside the single line */ 168 for (fld = CFG_COMMAND, cmd = CMD_INVALID, 169 line = token; ; line = NULL, fld++) { 170 token = strtok_r(line, " \t", &saveptr2); 171 if (token == NULL) 172 break; 173 174 /* Drop all text starting with '#' as comments */ 175 if (token[0] == '#') 176 break; 177 178 parse_cfg_fld(ublhdr, &cmd, token, name, 179 lineno, fld, &dcd_len); 180 } 181 } 182 fclose(fd); 183 184 return dcd_len; 185 } 186 187 static int ublimage_check_image_types(uint8_t type) 188 { 189 if (type == IH_TYPE_UBLIMAGE) 190 return EXIT_SUCCESS; 191 else 192 return EXIT_FAILURE; 193 } 194 195 static int ublimage_verify_header(unsigned char *ptr, int image_size, 196 struct image_tool_params *params) 197 { 198 struct ubl_header *ubl_hdr = (struct ubl_header *)ptr; 199 200 if ((ubl_hdr->magic & 0xFFFFFF00) != UBL_MAGIC_BASE) 201 return -1; 202 203 return 0; 204 } 205 206 static void ublimage_print_header(const void *ptr) 207 { 208 struct ubl_header *ubl_hdr = (struct ubl_header *) ptr; 209 210 print_hdr(ubl_hdr); 211 } 212 213 static void ublimage_set_header(void *ptr, struct stat *sbuf, int ifd, 214 struct image_tool_params *params) 215 { 216 struct ubl_header *ublhdr = (struct ubl_header *)ptr; 217 218 /* Parse configuration file */ 219 parse_cfg_file(ublhdr, params->imagename); 220 } 221 222 int ublimage_check_params(struct image_tool_params *params) 223 { 224 if (!params) 225 return CFG_INVALID; 226 if (!strlen(params->imagename)) { 227 fprintf(stderr, "Error: %s - Configuration file not" 228 "specified, it is needed for ublimage generation\n", 229 params->cmdname); 230 return CFG_INVALID; 231 } 232 /* 233 * Check parameters: 234 * XIP is not allowed and verify that incompatible 235 * parameters are not sent at the same time 236 * For example, if list is required a data image must not be provided 237 */ 238 return (params->dflag && (params->fflag || params->lflag)) || 239 (params->fflag && (params->dflag || params->lflag)) || 240 (params->lflag && (params->dflag || params->fflag)) || 241 (params->xflag) || !(strlen(params->imagename)); 242 } 243 244 /* 245 * ublimage parameters 246 */ 247 U_BOOT_IMAGE_TYPE( 248 ublimage, 249 "Davinci UBL boot support", 250 sizeof(struct ubl_header), 251 (void *)&ublimage_header, 252 ublimage_check_params, 253 ublimage_verify_header, 254 ublimage_print_header, 255 ublimage_set_header, 256 NULL, 257 ublimage_check_image_types, 258 NULL, 259 NULL 260 ); 261