1 /* 2 * Copyright 2012 Freescale Semiconductor, Inc. 3 * 4 * See file CREDITS for list of people who contributed to this 5 * project. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 * MA 02111-1307 USA 21 */ 22 #define _GNU_SOURCE 23 24 #include "mkimage.h" 25 #include <image.h> 26 #include "pblimage.h" 27 28 /* 29 * Initialize to an invalid value. 30 */ 31 static uint32_t next_pbl_cmd = 0x82000000; 32 /* 33 * need to store all bytes in memory for calculating crc32, then write the 34 * bytes to image file for PBL boot. 35 */ 36 static unsigned char mem_buf[1000000]; 37 static unsigned char *pmem_buf = mem_buf; 38 static int pbl_size; 39 static char *fname = "Unknown"; 40 static int lineno = -1; 41 static struct pbl_header pblimage_header; 42 43 static union 44 { 45 char c[4]; 46 unsigned char l; 47 } endian_test = { {'l', '?', '?', 'b'} }; 48 49 #define ENDIANNESS ((char)endian_test.l) 50 51 /* 52 * The PBL can load up to 64 bytes at a time, so we split the U-Boot 53 * image into 64 byte chunks. PBL needs a command for each piece, of 54 * the form "81xxxxxx", where "xxxxxx" is the offset. Calculate the 55 * start offset by subtracting the size of the u-boot image from the 56 * top of the allowable 24-bit range. 57 */ 58 static void init_next_pbl_cmd(FILE *fp_uboot) 59 { 60 struct stat st; 61 int fd = fileno(fp_uboot); 62 63 if (fstat(fd, &st) == -1) { 64 printf("Error: Could not determine u-boot image size. %s\n", 65 strerror(errno)); 66 exit(EXIT_FAILURE); 67 } 68 69 next_pbl_cmd = 0x82000000 - st.st_size; 70 } 71 72 static void generate_pbl_cmd(void) 73 { 74 uint32_t val = next_pbl_cmd; 75 next_pbl_cmd += 0x40; 76 int i; 77 78 for (i = 3; i >= 0; i--) { 79 *pmem_buf++ = (val >> (i * 8)) & 0xff; 80 pbl_size++; 81 } 82 } 83 84 static void pbl_fget(size_t size, FILE *stream) 85 { 86 unsigned char c; 87 int c_temp; 88 89 while (size && (c_temp = fgetc(stream)) != EOF) { 90 c = (unsigned char)c_temp; 91 *pmem_buf++ = c; 92 pbl_size++; 93 size--; 94 } 95 } 96 97 /* load split u-boot with PBI command 81xxxxxx. */ 98 static void load_uboot(FILE *fp_uboot) 99 { 100 init_next_pbl_cmd(fp_uboot); 101 while (next_pbl_cmd < 0x82000000) { 102 generate_pbl_cmd(); 103 pbl_fget(64, fp_uboot); 104 } 105 } 106 107 static void check_get_hexval(char *token) 108 { 109 uint32_t hexval; 110 int i; 111 112 if (!sscanf(token, "%x", &hexval)) { 113 printf("Error:%s[%d] - Invalid hex data(%s)\n", fname, 114 lineno, token); 115 exit(EXIT_FAILURE); 116 } 117 for (i = 3; i >= 0; i--) { 118 *pmem_buf++ = (hexval >> (i * 8)) & 0xff; 119 pbl_size++; 120 } 121 } 122 123 static void pbl_parser(char *name) 124 { 125 FILE *fd = NULL; 126 char *line = NULL; 127 char *token, *saveptr1, *saveptr2; 128 size_t len = 0; 129 130 fname = name; 131 fd = fopen(name, "r"); 132 if (fd == NULL) { 133 printf("Error:%s - Can't open\n", fname); 134 exit(EXIT_FAILURE); 135 } 136 137 while ((getline(&line, &len, fd)) > 0) { 138 lineno++; 139 token = strtok_r(line, "\r\n", &saveptr1); 140 /* drop all lines with zero tokens (= empty lines) */ 141 if (token == NULL) 142 continue; 143 for (line = token;; line = NULL) { 144 token = strtok_r(line, " \t", &saveptr2); 145 if (token == NULL) 146 break; 147 /* Drop all text starting with '#' as comments */ 148 if (token[0] == '#') 149 break; 150 check_get_hexval(token); 151 } 152 } 153 if (line) 154 free(line); 155 fclose(fd); 156 } 157 158 static uint32_t crc_table[256]; 159 160 static void make_crc_table(void) 161 { 162 uint32_t mask; 163 int i, j; 164 uint32_t poly; /* polynomial exclusive-or pattern */ 165 166 /* 167 * the polynomial used by PBL is 1 + x1 + x2 + x4 + x5 + x7 + x8 + x10 168 * + x11 + x12 + x16 + x22 + x23 + x26 + x32. 169 */ 170 poly = 0x04c11db7; 171 172 for (i = 0; i < 256; i++) { 173 mask = i << 24; 174 for (j = 0; j < 8; j++) { 175 if (mask & 0x80000000) 176 mask = (mask << 1) ^ poly; 177 else 178 mask <<= 1; 179 } 180 crc_table[i] = mask; 181 } 182 } 183 184 unsigned long pbl_crc32(unsigned long crc, const char *buf, uint32_t len) 185 { 186 uint32_t crc32_val = 0xffffffff; 187 uint32_t xor = 0x0; 188 int i; 189 190 make_crc_table(); 191 192 for (i = 0; i < len; i++) 193 crc32_val = (crc32_val << 8) ^ 194 crc_table[(crc32_val >> 24) ^ (*buf++ & 0xff)]; 195 196 crc32_val = crc32_val ^ xor; 197 if (crc32_val < 0) { 198 crc32_val += 0xffffffff; 199 crc32_val += 1; 200 } 201 return crc32_val; 202 } 203 204 static uint32_t reverse_byte(uint32_t val) 205 { 206 uint32_t temp; 207 unsigned char *p1; 208 int j; 209 210 temp = val; 211 p1 = (unsigned char *)&temp; 212 for (j = 3; j >= 0; j--) 213 *p1++ = (val >> (j * 8)) & 0xff; 214 return temp; 215 } 216 217 /* write end command and crc command to memory. */ 218 static void add_end_cmd(void) 219 { 220 uint32_t pbl_end_cmd[4] = {0x09138000, 0x00000000, 221 0x091380c0, 0x00000000}; 222 uint32_t crc32_pbl; 223 int i; 224 unsigned char *p = (unsigned char *)&pbl_end_cmd; 225 226 if (ENDIANNESS == 'l') { 227 for (i = 0; i < 4; i++) 228 pbl_end_cmd[i] = reverse_byte(pbl_end_cmd[i]); 229 } 230 231 for (i = 0; i < 16; i++) { 232 *pmem_buf++ = *p++; 233 pbl_size++; 234 } 235 236 /* Add PBI CRC command. */ 237 *pmem_buf++ = 0x08; 238 *pmem_buf++ = 0x13; 239 *pmem_buf++ = 0x80; 240 *pmem_buf++ = 0x40; 241 pbl_size += 4; 242 243 /* calculated CRC32 and write it to memory. */ 244 crc32_pbl = pbl_crc32(0, (const char *)mem_buf, pbl_size); 245 *pmem_buf++ = (crc32_pbl >> 24) & 0xff; 246 *pmem_buf++ = (crc32_pbl >> 16) & 0xff; 247 *pmem_buf++ = (crc32_pbl >> 8) & 0xff; 248 *pmem_buf++ = (crc32_pbl) & 0xff; 249 pbl_size += 4; 250 251 if ((pbl_size % 16) != 0) { 252 for (i = 0; i < 8; i++) { 253 *pmem_buf++ = 0x0; 254 pbl_size++; 255 } 256 } 257 if ((pbl_size % 16 != 0)) { 258 printf("Error: Bad size of image file\n"); 259 exit(EXIT_FAILURE); 260 } 261 } 262 263 void pbl_load_uboot(int ifd, struct mkimage_params *params) 264 { 265 FILE *fp_uboot; 266 int size; 267 268 /* parse the rcw.cfg file. */ 269 pbl_parser(params->imagename); 270 271 /* parse the pbi.cfg file. */ 272 pbl_parser(params->imagename2); 273 274 fp_uboot = fopen(params->datafile, "r"); 275 if (fp_uboot == NULL) { 276 printf("Error: %s open failed\n", params->datafile); 277 exit(EXIT_FAILURE); 278 } 279 280 load_uboot(fp_uboot); 281 add_end_cmd(); 282 fclose(fp_uboot); 283 lseek(ifd, 0, SEEK_SET); 284 285 size = pbl_size; 286 if (write(ifd, (const void *)&mem_buf, size) != size) { 287 fprintf(stderr, "Write error on %s: %s\n", 288 params->imagefile, strerror(errno)); 289 exit(EXIT_FAILURE); 290 } 291 } 292 293 static int pblimage_check_image_types(uint8_t type) 294 { 295 if (type == IH_TYPE_PBLIMAGE) 296 return EXIT_SUCCESS; 297 else 298 return EXIT_FAILURE; 299 } 300 301 static int pblimage_verify_header(unsigned char *ptr, int image_size, 302 struct mkimage_params *params) 303 { 304 struct pbl_header *pbl_hdr = (struct pbl_header *) ptr; 305 306 /* Only a few checks can be done: search for magic numbers */ 307 if (ENDIANNESS == 'l') { 308 if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE)) 309 return -FDT_ERR_BADSTRUCTURE; 310 311 if (pbl_hdr->rcwheader != reverse_byte(RCW_HEADER)) 312 return -FDT_ERR_BADSTRUCTURE; 313 } else { 314 if (pbl_hdr->preamble != RCW_PREAMBLE) 315 return -FDT_ERR_BADSTRUCTURE; 316 317 if (pbl_hdr->rcwheader != RCW_HEADER) 318 return -FDT_ERR_BADSTRUCTURE; 319 } 320 return 0; 321 } 322 323 static void pblimage_print_header(const void *ptr) 324 { 325 printf("Image Type: Freescale PBL Boot Image\n"); 326 } 327 328 static void pblimage_set_header(void *ptr, struct stat *sbuf, int ifd, 329 struct mkimage_params *params) 330 { 331 /*nothing need to do, pbl_load_uboot takes care of whole file. */ 332 } 333 334 /* pblimage parameters */ 335 static struct image_type_params pblimage_params = { 336 .name = "Freescale PBL Boot Image support", 337 .header_size = sizeof(struct pbl_header), 338 .hdr = (void *)&pblimage_header, 339 .check_image_type = pblimage_check_image_types, 340 .verify_header = pblimage_verify_header, 341 .print_header = pblimage_print_header, 342 .set_header = pblimage_set_header, 343 }; 344 345 void init_pbl_image_type(void) 346 { 347 pbl_size = 0; 348 mkimage_register(&pblimage_params); 349 } 350