"Das U-Boot" Source Tree
at master 341 lines 7.7 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2012-2014 Freescale Semiconductor, Inc. 4 */ 5#include "imagetool.h" 6#include <image.h> 7#include "pblimage.h" 8#include "pbl_crc32.h" 9#include <u-boot/crc.h> 10 11#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) 12#define PBL_ACS_CONT_CMD 0x81000000 13#define PBL_ADDR_24BIT_MASK 0x00ffffff 14 15/* 16 * Initialize to an invalid value. 17 */ 18static uint32_t next_pbl_cmd = 0x82000000; 19/* 20 * need to store all bytes in memory for calculating crc32, then write the 21 * bytes to image file for PBL boot. 22 */ 23static unsigned char mem_buf[1000000]; 24static unsigned char *pmem_buf = mem_buf; 25static int pbl_size; 26static char *fname = "Unknown"; 27static int lineno = -1; 28static struct pbl_header pblimage_header; 29static int uboot_size; 30static int arch_flag; 31 32static uint32_t pbl_cmd_initaddr; 33static uint32_t pbi_crc_cmd1; 34static uint32_t pbi_crc_cmd2; 35static uint32_t pbl_end_cmd[4]; 36 37static union 38{ 39 char c[4]; 40 unsigned char l; 41} endian_test = { {'l', '?', '?', 'b'} }; 42 43#define ENDIANNESS ((char)endian_test.l) 44 45/* 46 * The PBL can load up to 64 bytes at a time, so we split the U-Boot 47 * image into 64 byte chunks. PBL needs a command for each piece, of 48 * the form "81xxxxxx", where "xxxxxx" is the offset. Calculate the 49 * start offset by subtracting the size of the u-boot image from the 50 * top of the allowable 24-bit range. 51 */ 52static void generate_pbl_cmd(void) 53{ 54 uint32_t val = next_pbl_cmd; 55 next_pbl_cmd += 0x40; 56 int i; 57 58 for (i = 3; i >= 0; i--) { 59 *pmem_buf++ = (val >> (i * 8)) & 0xff; 60 pbl_size++; 61 } 62} 63 64static void pbl_fget(size_t size, FILE *stream) 65{ 66 unsigned char c = 0xff; 67 int c_temp; 68 69 while (size) { 70 c_temp = fgetc(stream); 71 if (c_temp != EOF) 72 c = (unsigned char)c_temp; 73 else if ((c_temp == EOF) && (arch_flag == IH_ARCH_ARM)) 74 c = 0xff; 75 *pmem_buf++ = c; 76 pbl_size++; 77 size--; 78 } 79} 80 81/* load split u-boot with PBI command 81xxxxxx. */ 82static void load_uboot(FILE *fp_uboot) 83{ 84 next_pbl_cmd = pbl_cmd_initaddr - uboot_size; 85 while (next_pbl_cmd < pbl_cmd_initaddr) { 86 generate_pbl_cmd(); 87 pbl_fget(64, fp_uboot); 88 } 89} 90 91static void check_get_hexval(char *token) 92{ 93 uint32_t hexval; 94 int i; 95 96 if (!sscanf(token, "%x", &hexval)) { 97 printf("Error:%s[%d] - Invalid hex data(%s)\n", fname, 98 lineno, token); 99 exit(EXIT_FAILURE); 100 } 101 for (i = 3; i >= 0; i--) { 102 *pmem_buf++ = (hexval >> (i * 8)) & 0xff; 103 pbl_size++; 104 } 105} 106 107static void pbl_parser(char *name) 108{ 109 FILE *fd = NULL; 110 char *line = NULL; 111 char *token, *saveptr1, *saveptr2; 112 size_t len = 0; 113 114 fname = name; 115 fd = fopen(name, "r"); 116 if (fd == NULL) { 117 printf("Error:%s - Can't open\n", fname); 118 exit(EXIT_FAILURE); 119 } 120 121 while ((getline(&line, &len, fd)) > 0) { 122 lineno++; 123 token = strtok_r(line, "\r\n", &saveptr1); 124 /* drop all lines with zero tokens (= empty lines) */ 125 if (token == NULL) 126 continue; 127 for (line = token;; line = NULL) { 128 token = strtok_r(line, " \t", &saveptr2); 129 if (token == NULL) 130 break; 131 /* Drop all text starting with '#' as comments */ 132 if (token[0] == '#') 133 break; 134 check_get_hexval(token); 135 } 136 } 137 if (line) 138 free(line); 139 fclose(fd); 140} 141 142static uint32_t reverse_byte(uint32_t val) 143{ 144 uint32_t temp; 145 unsigned char *p1; 146 int j; 147 148 temp = val; 149 p1 = (unsigned char *)&temp; 150 for (j = 3; j >= 0; j--) 151 *p1++ = (val >> (j * 8)) & 0xff; 152 return temp; 153} 154 155/* write end command and crc command to memory. */ 156static void add_end_cmd(void) 157{ 158 uint32_t crc32_pbl; 159 int i; 160 unsigned char *p = (unsigned char *)&pbl_end_cmd; 161 162 if (ENDIANNESS == 'l') { 163 for (i = 0; i < 4; i++) 164 pbl_end_cmd[i] = reverse_byte(pbl_end_cmd[i]); 165 } 166 167 for (i = 0; i < 16; i++) { 168 *pmem_buf++ = *p++; 169 pbl_size++; 170 } 171 172 /* Add PBI CRC command. */ 173 *pmem_buf++ = 0x08; 174 *pmem_buf++ = pbi_crc_cmd1; 175 *pmem_buf++ = pbi_crc_cmd2; 176 *pmem_buf++ = 0x40; 177 pbl_size += 4; 178 179 /* calculated CRC32 and write it to memory. */ 180 crc32_pbl = pbl_crc32(0, (const char *)mem_buf, pbl_size); 181 *pmem_buf++ = (crc32_pbl >> 24) & 0xff; 182 *pmem_buf++ = (crc32_pbl >> 16) & 0xff; 183 *pmem_buf++ = (crc32_pbl >> 8) & 0xff; 184 *pmem_buf++ = (crc32_pbl) & 0xff; 185 pbl_size += 4; 186} 187 188void pbl_load_uboot(int ifd, struct image_tool_params *params) 189{ 190 FILE *fp_uboot; 191 int size, ret; 192 193 /* parse the rcw.cfg file. */ 194 pbl_parser(params->imagename); 195 196 /* parse the pbi.cfg file. */ 197 if (params->imagename2[0] != '\0') 198 pbl_parser(params->imagename2); 199 200 if (params->datafile) { 201 fp_uboot = fopen(params->datafile, "r"); 202 if (fp_uboot == NULL) { 203 printf("Error: %s open failed\n", params->datafile); 204 exit(EXIT_FAILURE); 205 } 206 207 load_uboot(fp_uboot); 208 fclose(fp_uboot); 209 } 210 add_end_cmd(); 211 ret = lseek(ifd, 0, SEEK_SET); 212 if (ret < 0) { 213 fprintf(stderr, "%s: lseek error %s\n", 214 __func__, strerror(errno)); 215 exit(EXIT_FAILURE); 216 } 217 218 size = pbl_size; 219 if (write(ifd, (const void *)&mem_buf, size) != size) { 220 fprintf(stderr, "Write error on %s: %s\n", 221 params->imagefile, strerror(errno)); 222 exit(EXIT_FAILURE); 223 } 224} 225 226static int pblimage_check_image_types(uint8_t type) 227{ 228 if (type == IH_TYPE_PBLIMAGE) 229 return EXIT_SUCCESS; 230 else 231 return EXIT_FAILURE; 232} 233 234static int pblimage_verify_header(unsigned char *ptr, int image_size, 235 struct image_tool_params *params) 236{ 237 struct pbl_header *pbl_hdr = (struct pbl_header *) ptr; 238 uint32_t rcwheader; 239 240 if (params->arch == IH_ARCH_ARM) 241 rcwheader = RCW_ARM_HEADER; 242 else 243 rcwheader = RCW_PPC_HEADER; 244 245 /* Only a few checks can be done: search for magic numbers */ 246 if (ENDIANNESS == 'l') { 247 if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE)) 248 return -FDT_ERR_BADSTRUCTURE; 249 250 if (pbl_hdr->rcwheader != reverse_byte(rcwheader)) 251 return -FDT_ERR_BADSTRUCTURE; 252 } else { 253 if (pbl_hdr->preamble != RCW_PREAMBLE) 254 return -FDT_ERR_BADSTRUCTURE; 255 256 if (pbl_hdr->rcwheader != rcwheader) 257 return -FDT_ERR_BADSTRUCTURE; 258 } 259 return 0; 260} 261 262static void pblimage_print_header(const void *ptr, struct image_tool_params *params) 263{ 264 printf("Image Type: Freescale PBL Boot Image\n"); 265} 266 267static void pblimage_set_header(void *ptr, struct stat *sbuf, int ifd, 268 struct image_tool_params *params) 269{ 270 /*nothing need to do, pbl_load_uboot takes care of whole file. */ 271} 272 273int pblimage_check_params(struct image_tool_params *params) 274{ 275 FILE *fp_uboot; 276 int fd; 277 struct stat st; 278 279 if (!params) 280 return EXIT_FAILURE; 281 282 if (params->datafile) { 283 fp_uboot = fopen(params->datafile, "r"); 284 if (fp_uboot == NULL) { 285 printf("Error: %s open failed\n", params->datafile); 286 exit(EXIT_FAILURE); 287 } 288 fd = fileno(fp_uboot); 289 290 if (fstat(fd, &st) == -1) { 291 printf("Error: Could not determine u-boot image size. %s\n", 292 strerror(errno)); 293 exit(EXIT_FAILURE); 294 } 295 296 /* For the variable size, pad it to 64 byte boundary */ 297 uboot_size = roundup(st.st_size, 64); 298 fclose(fp_uboot); 299 } 300 301 if (params->arch == IH_ARCH_ARM) { 302 arch_flag = IH_ARCH_ARM; 303 pbi_crc_cmd1 = 0x61; 304 pbi_crc_cmd2 = 0; 305 pbl_cmd_initaddr = params->addr & PBL_ADDR_24BIT_MASK; 306 pbl_cmd_initaddr |= PBL_ACS_CONT_CMD; 307 pbl_cmd_initaddr += uboot_size; 308 pbl_end_cmd[0] = 0x09610000; 309 pbl_end_cmd[1] = 0x00000000; 310 pbl_end_cmd[2] = 0x096100c0; 311 pbl_end_cmd[3] = 0x00000000; 312 } else if (params->arch == IH_ARCH_PPC) { 313 arch_flag = IH_ARCH_PPC; 314 pbi_crc_cmd1 = 0x13; 315 pbi_crc_cmd2 = 0x80; 316 pbl_cmd_initaddr = 0x82000000; 317 pbl_end_cmd[0] = 0x091380c0; 318 pbl_end_cmd[1] = 0x00000000; 319 pbl_end_cmd[2] = 0x091380c0; 320 pbl_end_cmd[3] = 0x00000000; 321 } 322 323 next_pbl_cmd = pbl_cmd_initaddr; 324 return 0; 325}; 326 327/* pblimage parameters */ 328U_BOOT_IMAGE_TYPE( 329 pblimage, 330 "Freescale PBL Boot Image support", 331 sizeof(struct pbl_header), 332 (void *)&pblimage_header, 333 pblimage_check_params, 334 pblimage_verify_header, 335 pblimage_print_header, 336 pblimage_set_header, 337 NULL, 338 pblimage_check_image_types, 339 NULL, 340 NULL 341);