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; 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 lseek(ifd, 0, SEEK_SET); 212 213 size = pbl_size; 214 if (write(ifd, (const void *)&mem_buf, size) != size) { 215 fprintf(stderr, "Write error on %s: %s\n", 216 params->imagefile, strerror(errno)); 217 exit(EXIT_FAILURE); 218 } 219} 220 221static int pblimage_check_image_types(uint8_t type) 222{ 223 if (type == IH_TYPE_PBLIMAGE) 224 return EXIT_SUCCESS; 225 else 226 return EXIT_FAILURE; 227} 228 229static int pblimage_verify_header(unsigned char *ptr, int image_size, 230 struct image_tool_params *params) 231{ 232 struct pbl_header *pbl_hdr = (struct pbl_header *) ptr; 233 uint32_t rcwheader; 234 235 if (params->arch == IH_ARCH_ARM) 236 rcwheader = RCW_ARM_HEADER; 237 else 238 rcwheader = RCW_PPC_HEADER; 239 240 /* Only a few checks can be done: search for magic numbers */ 241 if (ENDIANNESS == 'l') { 242 if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE)) 243 return -FDT_ERR_BADSTRUCTURE; 244 245 if (pbl_hdr->rcwheader != reverse_byte(rcwheader)) 246 return -FDT_ERR_BADSTRUCTURE; 247 } else { 248 if (pbl_hdr->preamble != RCW_PREAMBLE) 249 return -FDT_ERR_BADSTRUCTURE; 250 251 if (pbl_hdr->rcwheader != rcwheader) 252 return -FDT_ERR_BADSTRUCTURE; 253 } 254 return 0; 255} 256 257static void pblimage_print_header(const void *ptr, struct image_tool_params *params) 258{ 259 printf("Image Type: Freescale PBL Boot Image\n"); 260} 261 262static void pblimage_set_header(void *ptr, struct stat *sbuf, int ifd, 263 struct image_tool_params *params) 264{ 265 /*nothing need to do, pbl_load_uboot takes care of whole file. */ 266} 267 268int pblimage_check_params(struct image_tool_params *params) 269{ 270 FILE *fp_uboot; 271 int fd; 272 struct stat st; 273 274 if (!params) 275 return EXIT_FAILURE; 276 277 if (params->datafile) { 278 fp_uboot = fopen(params->datafile, "r"); 279 if (fp_uboot == NULL) { 280 printf("Error: %s open failed\n", params->datafile); 281 exit(EXIT_FAILURE); 282 } 283 fd = fileno(fp_uboot); 284 285 if (fstat(fd, &st) == -1) { 286 printf("Error: Could not determine u-boot image size. %s\n", 287 strerror(errno)); 288 exit(EXIT_FAILURE); 289 } 290 291 /* For the variable size, pad it to 64 byte boundary */ 292 uboot_size = roundup(st.st_size, 64); 293 fclose(fp_uboot); 294 } 295 296 if (params->arch == IH_ARCH_ARM) { 297 arch_flag = IH_ARCH_ARM; 298 pbi_crc_cmd1 = 0x61; 299 pbi_crc_cmd2 = 0; 300 pbl_cmd_initaddr = params->addr & PBL_ADDR_24BIT_MASK; 301 pbl_cmd_initaddr |= PBL_ACS_CONT_CMD; 302 pbl_cmd_initaddr += uboot_size; 303 pbl_end_cmd[0] = 0x09610000; 304 pbl_end_cmd[1] = 0x00000000; 305 pbl_end_cmd[2] = 0x096100c0; 306 pbl_end_cmd[3] = 0x00000000; 307 } else if (params->arch == IH_ARCH_PPC) { 308 arch_flag = IH_ARCH_PPC; 309 pbi_crc_cmd1 = 0x13; 310 pbi_crc_cmd2 = 0x80; 311 pbl_cmd_initaddr = 0x82000000; 312 pbl_end_cmd[0] = 0x091380c0; 313 pbl_end_cmd[1] = 0x00000000; 314 pbl_end_cmd[2] = 0x091380c0; 315 pbl_end_cmd[3] = 0x00000000; 316 } 317 318 next_pbl_cmd = pbl_cmd_initaddr; 319 return 0; 320}; 321 322/* pblimage parameters */ 323U_BOOT_IMAGE_TYPE( 324 pblimage, 325 "Freescale PBL Boot Image support", 326 sizeof(struct pbl_header), 327 (void *)&pblimage_header, 328 pblimage_check_params, 329 pblimage_verify_header, 330 pblimage_print_header, 331 pblimage_set_header, 332 NULL, 333 pblimage_check_image_types, 334 NULL, 335 NULL 336); 337