1 /* 2 * Copyright 2021 NXP 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 */ 7 8 #include <stdbool.h> 9 #include <stdint.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 #include <getopt.h> 15 #include <unistd.h> 16 17 #define NUM_MEM_BLOCK 1 18 #define FOUR_BYTE_ALIGN 4 19 #define EIGHT_BYTE_ALIGN 8 20 #define SIZE_TWO_PBL_CMD 24 21 22 /* Define for add_boot_ptr_cmd() */ 23 #define BOOTPTR_ADDR 0x09570604 24 #define CSF_ADDR_SB 0x09ee0200 25 /* CCSR write command to address 0x1e00400 i.e BOOTLOCPTR */ 26 #define BOOTPTR_ADDR_CH3 0x31e00400 27 /* Load CSF header command */ 28 #define CSF_ADDR_SB_CH3 0x80220000 29 30 #define MAND_ARG_MASK 0xFFF3 31 #define ARG_INIT_MASK 0xFF00 32 #define RCW_FILE_NAME_ARG_MASK 0x0080 33 #define IN_FILE_NAME_ARG_MASK 0x0040 34 #define CHASSIS_ARG_MASK 0x0020 35 #define BOOT_SRC_ARG_MASK 0x0010 36 #define ENTRY_POINT_ADDR_ARG_MASK 0x0008 37 #define BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK 0x0004 38 #define BL2_BIN_CPY_DEST_ADDR_ARG_MASK 0x0002 39 #define OP_FILE_NAME_ARG_MASK 0x0001 40 41 /* Define for add_cpy_cmd() */ 42 #define OFFSET_MASK 0x00ffffff 43 #define WRITE_CMD_BASE 0x81000000 44 #define MAX_PBI_DATA_LEN_BYTE 64 45 46 /* 140 Bytes = Preamble + LOAD RCW command + RCW (128 bytes) + Checksum */ 47 #define CHS3_CRC_PAYLOAD_START_OFFSET 140 48 49 #define PBI_CRC_POLYNOMIAL 0x04c11db7 50 51 typedef enum { 52 CHASSIS_UNKNOWN, 53 CHASSIS_2, 54 CHASSIS_3, 55 CHASSIS_3_2, 56 CHASSIS_MAX /* must be last item in list */ 57 } chassis_t; 58 59 typedef enum { 60 UNKNOWN_BOOT = 0, 61 IFC_NOR_BOOT, 62 IFC_NAND_BOOT, 63 QSPI_BOOT, 64 SD_BOOT, 65 EMMC_BOOT, 66 FLXSPI_NOR_BOOT, 67 FLXSPI_NAND_BOOT, 68 FLXSPI_NAND4K_BOOT, 69 MAX_BOOT /* must be last item in list */ 70 } boot_src_t; 71 72 /* Base Addresses where PBL image is copied depending on the boot source. 73 * Boot address map varies as per Chassis architecture. 74 */ 75 #define BASE_ADDR_UNDEFINED 0xFFFFFFFF 76 #define BASE_ADDR_QSPI 0x20000000 77 #define BASE_ADDR_SD 0x00001000 78 #define BASE_ADDR_IFC_NOR 0x30000000 79 #define BASE_ADDR_EMMC 0x00001000 80 #define BASE_ADDR_FLX_NOR 0x20000000 81 #define BASE_ADDR_NAND 0x20000000 82 83 uint32_t base_addr_ch3[MAX_BOOT] = { 84 BASE_ADDR_UNDEFINED, 85 BASE_ADDR_IFC_NOR, 86 BASE_ADDR_UNDEFINED, /*IFC NAND */ 87 BASE_ADDR_QSPI, 88 BASE_ADDR_SD, 89 BASE_ADDR_EMMC, 90 BASE_ADDR_UNDEFINED, /*FLXSPI NOR */ 91 BASE_ADDR_UNDEFINED, /*FLXSPI NAND 2K */ 92 BASE_ADDR_UNDEFINED /*FLXSPI NAND 4K */ 93 }; 94 95 uint32_t base_addr_ch32[MAX_BOOT] = { 96 BASE_ADDR_UNDEFINED, 97 BASE_ADDR_UNDEFINED, /* IFC NOR */ 98 BASE_ADDR_UNDEFINED, /* IFC NAND */ 99 BASE_ADDR_UNDEFINED, /* QSPI */ 100 BASE_ADDR_SD, 101 BASE_ADDR_EMMC, 102 BASE_ADDR_FLX_NOR, 103 BASE_ADDR_UNDEFINED, /*FLXSPI NAND 2K */ 104 BASE_ADDR_UNDEFINED /*FLXSPI NAND 4K */ 105 }; 106 107 /* for Chassis 3 */ 108 uint32_t blk_cpy_hdr_map_ch3[] = { 109 110 0, /* Unknown Boot Source */ 111 0x80000020, /* NOR_BOOT */ 112 0x0, /* NAND_BOOT */ 113 0x80000062, /* QSPI_BOOT */ 114 0x80000040, /* SD_BOOT */ 115 0x80000041, /* EMMC_BOOT */ 116 0x0, /* FLEXSPI NOR_BOOT */ 117 0x0, /* FLEX SPI NAND2K BOOT */ 118 0x0, /* CHASIS3_2_NAND4K_BOOT */ 119 }; 120 121 uint32_t blk_cpy_hdr_map_ch32[] = { 122 0, /* Unknown Boot Source */ 123 0x0, /* NOR_BOOT */ 124 0x0, /* NAND_BOOT */ 125 0x0, /* QSPI_BOOT */ 126 0x80000008, /* SD_BOOT */ 127 0x80000009, /* EMMC_BOOT */ 128 0x8000000F, /* FLEXSPI NOR_BOOT */ 129 0x8000000C, /* FLEX SPI NAND2K BOOT */ 130 0x8000000D, /* CHASIS3_2_NAND4K_BOOT */ 131 }; 132 133 char *boot_src_string[] = { 134 "UNKNOWN_BOOT", 135 "IFC_NOR_BOOT", 136 "IFC_NAND_BOOT", 137 "QSPI_BOOT", 138 "SD_BOOT", 139 "EMMC_BOOT", 140 "FLXSPI_NOR_BOOT", 141 "FLXSPI_NAND_BOOT", 142 "FLXSPI_NAND4K_BOOT", 143 }; 144 145 enum stop_command { 146 STOP_COMMAND = 0, 147 CRC_STOP_COMMAND 148 }; 149 150 /* Structure will get populated in the main function 151 * as part of parsing the command line arguments. 152 * All member parameters are mandatory except: 153 * -ep 154 * -src_addr 155 */ 156 struct pbl_image { 157 char *rcw_nm; /* Input RCW File */ 158 char *sec_imgnm; /* Input BL2 binary */ 159 char *imagefile; /* Generated output file */ 160 boot_src_t boot_src; /* Boot Source - QSPI, SD, NOR, NAND etc */ 161 uint32_t src_addr; /* Source Address */ 162 uint32_t addr; /* Load address */ 163 uint32_t ep; /* Entry point <opt> default is load address */ 164 chassis_t chassis; /* Chassis type */ 165 } pblimg; 166 167 #define SUCCESS 0 168 #define FAILURE -1 169 #define CRC_STOP_CMD_ARM 0x08610040 170 #define CRC_STOP_CMD_ARM_CH3 0x808f0000 171 #define STOP_CMD_ARM_CH3 0x80ff0000 172 #define BYTE_SWAP_32(word) ((((word) & 0xff000000) >> 24)| \ 173 (((word) & 0x00ff0000) >> 8) | \ 174 (((word) & 0x0000ff00) << 8) | \ 175 (((word) & 0x000000ff) << 24)) 176 177 #define PBI_LEN_MASK 0xFFF00000 178 #define PBI_LEN_SHIFT 20 179 #define NUM_RCW_WORD 35 180 #define PBI_LEN_ADD 6 181 182 #define MAX_CRC_ENTRIES 256 183 184 /* SoC numeric identifier */ 185 #define SOC_LS1012 1012 186 #define SOC_LS1023 1023 187 #define SOC_LS1026 1026 188 #define SOC_LS1028 1028 189 #define SOC_LS1043 1043 190 #define SOC_LS1046 1046 191 #define SOC_LS1088 1088 192 #define SOC_LS2080 2080 193 #define SOC_LS2088 2088 194 #define SOC_LX2160 2160 195 196 static uint32_t pbl_size; 197 bool sb_flag; 198 199 /*************************************************************************** 200 * Description : CRC32 Lookup Table 201 ***************************************************************************/ 202 static uint32_t crc32_lookup[] = { 203 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 204 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 205 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 206 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 207 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 208 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 209 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 210 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 211 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 212 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 213 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 214 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 215 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 216 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 217 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 218 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 219 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 220 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 221 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 222 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 223 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 224 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 225 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 226 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 227 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 228 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 229 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 230 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 231 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 232 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 233 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 234 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 235 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 236 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 237 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 238 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 239 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 240 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 241 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 242 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 243 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 244 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 245 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 246 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 247 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 248 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 249 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 250 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 251 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 252 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 253 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 254 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 255 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 256 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 257 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 258 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 259 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 260 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 261 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 262 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 263 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 264 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 265 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 266 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 267 }; 268 269 270 static void print_usage(void) 271 { 272 printf("\nCorrect Usage of Tool is:\n"); 273 printf("\n ./create_pbl [options] (mentioned below):\n\n"); 274 printf("\t-r <RCW file-name> - name of RCW binary file.\n"); 275 printf("\t-i <BL2 Bin file-name> - file to be added to rcw file.\n"); 276 printf("\t-c <Number> - Chassis Architecture (=2 or =3\n"); 277 printf("\t or =4 for 3.2).\n"); 278 printf("\t-b <qspi/nor/nand/sd> - Boot source.\n"); 279 printf("\t-d <Address> - Destination address where BL2\n"); 280 printf("\t image is to be copied\n"); 281 printf("\t-o <output filename> - Name of PBL image generated\n"); 282 printf("\t as an output of the tool.\n"); 283 printf("\t-f <Address> - BL2 image Src Offset\n"); 284 printf("\t on Boot Source for block copy.\n"); 285 printf("\t command for chassis >=3.)\n"); 286 printf("\t-e <Address> - [Optional] Entry Point Address\n"); 287 printf("\t of the BL2.bin\n"); 288 printf("\t-s Secure Boot.\n"); 289 printf("\t-h Help.\n"); 290 printf("\n\n"); 291 exit(0); 292 293 } 294 295 /*************************************************************************** 296 * Function : crypto_calculate_checksum() 297 * Arguments : data - Pointer to FILE 298 * num - Number of 32 bit words for checksum 299 * Return : Checksum Value 300 * Description : Calculate Checksum over the data 301 ***************************************************************************/ 302 uint32_t crypto_calculate_checksum(FILE *fp_rcw_pbi_op, uint32_t num) 303 { 304 uint32_t i; 305 uint64_t sum = 0; 306 uint32_t word; 307 308 fseek(fp_rcw_pbi_op, 0L, SEEK_SET); 309 for (i = 0; i < num ; i++) { 310 if ((fread(&word, sizeof(word), NUM_MEM_BLOCK, fp_rcw_pbi_op)) 311 < NUM_MEM_BLOCK) { 312 printf("%s: Error reading word.\n", __func__); 313 return FAILURE; 314 } 315 sum = sum + word; 316 sum = sum & 0xFFFFFFFF; 317 } 318 return (uint32_t)sum; 319 } 320 321 /*************************************************************************** 322 * Function : add_pbi_stop_cmd 323 * Arguments : fp_rcw_pbi_op - output rcw_pbi file pointer 324 * Return : SUCCESS or FAILURE 325 * Description : This function insert pbi stop command. 326 ***************************************************************************/ 327 int add_pbi_stop_cmd(FILE *fp_rcw_pbi_op, enum stop_command flag) 328 { 329 int ret = FAILURE; 330 int32_t pbi_stop_cmd; 331 uint32_t pbi_crc = 0xffffffff, i, j, c; 332 uint32_t crc_table[MAX_CRC_ENTRIES]; 333 uint8_t data; 334 335 switch (pblimg.chassis) { 336 case CHASSIS_2: 337 pbi_stop_cmd = BYTE_SWAP_32(CRC_STOP_CMD_ARM); 338 break; 339 case CHASSIS_3: 340 case CHASSIS_3_2: 341 /* Based on flag add the corresponsding cmd 342 * -- stop cmd or stop with CRC cmd 343 */ 344 if (flag == CRC_STOP_COMMAND) { 345 pbi_stop_cmd = CRC_STOP_CMD_ARM_CH3; 346 } else { 347 pbi_stop_cmd = STOP_CMD_ARM_CH3; 348 } 349 break; 350 case CHASSIS_UNKNOWN: 351 case CHASSIS_MAX: 352 default: 353 printf("Internal Error: Invalid Chassis val = %d.\n", 354 pblimg.chassis); 355 goto pbi_stop_err; 356 } 357 358 if (fwrite(&pbi_stop_cmd, sizeof(pbi_stop_cmd), NUM_MEM_BLOCK, 359 fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 360 printf("%s: Error in Writing PBI STOP CMD\n", __func__); 361 goto pbi_stop_err; 362 } 363 364 if (flag == CRC_STOP_COMMAND) { 365 for (i = 0; i < MAX_CRC_ENTRIES; i++) { 366 c = i << 24; 367 for (j = 0; j < 8; j++) { 368 c = (c & 0x80000000) ? 369 PBI_CRC_POLYNOMIAL ^ (c << 1) : c << 1; 370 } 371 372 crc_table[i] = c; 373 } 374 } 375 376 switch (pblimg.chassis) { 377 case CHASSIS_2: 378 /* Chassis 2: CRC is calculated on RCW + PBL cmd.*/ 379 fseek(fp_rcw_pbi_op, 0L, SEEK_SET); 380 break; 381 case CHASSIS_3: 382 case CHASSIS_3_2: 383 /* Chassis 3: CRC is calculated on PBL cmd only. */ 384 fseek(fp_rcw_pbi_op, CHS3_CRC_PAYLOAD_START_OFFSET, SEEK_SET); 385 break; 386 case CHASSIS_UNKNOWN: 387 case CHASSIS_MAX: 388 printf("%s: Unknown Chassis.\n", __func__); 389 goto pbi_stop_err; 390 } 391 392 while ((fread(&data, sizeof(data), NUM_MEM_BLOCK, fp_rcw_pbi_op)) 393 == NUM_MEM_BLOCK) { 394 if (flag == CRC_STOP_COMMAND) { 395 if (pblimg.chassis == CHASSIS_2) { 396 pbi_crc = crc_table 397 [((pbi_crc >> 24) ^ (data)) & 0xff] ^ 398 (pbi_crc << 8); 399 } else { 400 pbi_crc = (pbi_crc >> 8) ^ 401 crc32_lookup[((pbi_crc) ^ 402 (data)) & 0xff]; 403 } 404 } 405 } 406 407 switch (pblimg.chassis) { 408 case CHASSIS_2: 409 pbi_crc = BYTE_SWAP_32(pbi_crc); 410 break; 411 case CHASSIS_3: 412 case CHASSIS_3_2: 413 if (flag == CRC_STOP_COMMAND) { 414 pbi_crc = pbi_crc ^ 0xFFFFFFFF; 415 } else { 416 pbi_crc = 0x00000000; 417 } 418 break; 419 case CHASSIS_UNKNOWN: 420 case CHASSIS_MAX: 421 printf("%s: Unknown Chassis.\n", __func__); 422 goto pbi_stop_err; 423 } 424 425 if (fwrite(&pbi_crc, sizeof(pbi_crc), NUM_MEM_BLOCK, fp_rcw_pbi_op) 426 != NUM_MEM_BLOCK) { 427 printf("%s: Error in Writing PBI PBI CRC\n", __func__); 428 goto pbi_stop_err; 429 } 430 ret = SUCCESS; 431 432 pbi_stop_err: 433 return ret; 434 } 435 436 /* 437 * Returns: 438 * File size in bytes, on Success. 439 * FAILURE, on failure. 440 */ 441 int get_filesize(const char *c) 442 { 443 FILE *fp; 444 int ret = FAILURE; 445 446 fp = fopen(c, "rb"); 447 if (fp == NULL) { 448 fprintf(stderr, "%s: Error in opening the file: %s\n", 449 __func__, c); 450 goto filesize_err; 451 } 452 453 fseek(fp, 0L, SEEK_END); 454 ret = ftell(fp); 455 fclose(fp); 456 457 filesize_err: 458 return ret; 459 } 460 461 /*************************************************************************** 462 * Function : get_bootptr 463 * Arguments : fp_rcw_pbi_op - Pointer to output file 464 * Return : SUCCESS or FAILURE 465 * Description : Add bootptr pbi command to output file 466 ***************************************************************************/ 467 int add_boot_ptr_cmd(FILE *fp_rcw_pbi_op) 468 { 469 uint32_t bootptr_addr; 470 int ret = FAILURE; 471 472 switch (pblimg.chassis) { 473 case CHASSIS_2: 474 if (sb_flag == true) 475 bootptr_addr = BYTE_SWAP_32(CSF_ADDR_SB); 476 else 477 bootptr_addr = BYTE_SWAP_32(BOOTPTR_ADDR); 478 pblimg.ep = BYTE_SWAP_32(pblimg.ep); 479 break; 480 case CHASSIS_3: 481 case CHASSIS_3_2: 482 if (sb_flag == true) 483 bootptr_addr = CSF_ADDR_SB_CH3; 484 else 485 bootptr_addr = BOOTPTR_ADDR_CH3; 486 break; 487 case CHASSIS_UNKNOWN: 488 case CHASSIS_MAX: 489 default: 490 printf("Internal Error: Invalid Chassis val = %d.\n", 491 pblimg.chassis); 492 goto bootptr_err; 493 } 494 495 if (fwrite(&bootptr_addr, sizeof(bootptr_addr), NUM_MEM_BLOCK, 496 fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 497 printf("%s: Error in Writing PBI Words:[%d].\n", 498 __func__, ret); 499 goto bootptr_err; 500 } 501 502 if (pblimg.ep != 0) { 503 if (fwrite(&pblimg.ep, sizeof(pblimg.ep), NUM_MEM_BLOCK, 504 fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 505 printf("%s: Error in Writing PBI Words\n", __func__); 506 goto bootptr_err; 507 } 508 } 509 510 printf("\nBoot Location Pointer= %x\n", BYTE_SWAP_32(pblimg.ep)); 511 ret = SUCCESS; 512 513 bootptr_err: 514 return ret; 515 } 516 517 /*************************************************************************** 518 * Function : add_blk_cpy_cmd 519 * Arguments : pbi_word - pointer to pbi commands 520 * args - Command line args flag. 521 * Return : SUCCESS or FAILURE 522 * Description : Add pbi commands for block copy cmd in pbi_words 523 ***************************************************************************/ 524 int add_blk_cpy_cmd(FILE *fp_rcw_pbi_op, uint16_t args) 525 { 526 uint32_t blk_cpy_hdr; 527 uint32_t file_size, new_file_size; 528 uint32_t align = 4; 529 int ret = FAILURE; 530 int num_pad_bytes = 0; 531 532 if ((args & BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK) == 0) { 533 printf("ERROR: Offset not specified for Block Copy Cmd.\n"); 534 printf("\tSee Usage and use -f option\n"); 535 goto blk_copy_err; 536 } 537 538 switch (pblimg.chassis) { 539 case CHASSIS_3: 540 /* Block copy command */ 541 blk_cpy_hdr = blk_cpy_hdr_map_ch3[pblimg.boot_src]; 542 pblimg.src_addr += base_addr_ch3[pblimg.boot_src]; 543 break; 544 case CHASSIS_3_2: 545 /* Block copy command */ 546 blk_cpy_hdr = blk_cpy_hdr_map_ch32[pblimg.boot_src]; 547 pblimg.src_addr += base_addr_ch32[pblimg.boot_src]; 548 break; 549 default: 550 printf("%s: Error invalid chassis type for this command.\n", 551 __func__); 552 goto blk_copy_err; 553 } 554 555 file_size = get_filesize(pblimg.sec_imgnm); 556 if (file_size > 0) { 557 new_file_size = (file_size + (file_size % align)); 558 559 /* Add Block copy command */ 560 if (fwrite(&blk_cpy_hdr, sizeof(blk_cpy_hdr), NUM_MEM_BLOCK, 561 fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 562 printf("%s: Error writing blk_cpy_hdr to the file.\n", 563 __func__); 564 goto blk_copy_err; 565 } 566 567 if ((args & BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK) == 0) 568 num_pad_bytes = pblimg.src_addr % 4; 569 570 /* Add Src address word */ 571 if (fwrite(&pblimg.src_addr + num_pad_bytes, 572 sizeof(pblimg.src_addr), NUM_MEM_BLOCK, 573 fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 574 printf("%s: Error writing BLK SRC Addr to the file.\n", 575 __func__); 576 goto blk_copy_err; 577 } 578 579 /* Add Dest address word */ 580 if (fwrite(&pblimg.addr, sizeof(pblimg.addr), 581 NUM_MEM_BLOCK, fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 582 printf("%s: Error writing DST Addr to the file.\n", 583 __func__); 584 goto blk_copy_err; 585 } 586 587 /* Add size */ 588 if (fwrite(&new_file_size, sizeof(new_file_size), 589 NUM_MEM_BLOCK, fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 590 printf("%s: Error writing size to the file.\n", 591 __func__); 592 goto blk_copy_err; 593 } 594 } 595 596 ret = SUCCESS; 597 598 blk_copy_err: 599 return ret; 600 } 601 602 /*************************************************************************** 603 * Function : add_cpy_cmd 604 * Arguments : pbi_word - pointer to pbi commands 605 * Return : SUCCESS or FAILURE 606 * Description : Append pbi commands for copying BL2 image to the 607 * load address stored in pbl_image.addr 608 ***************************************************************************/ 609 int add_cpy_cmd(FILE *fp_rcw_pbi_op) 610 { 611 uint32_t ALTCBAR_ADDRESS = BYTE_SWAP_32(0x09570158); 612 uint32_t WAIT_CMD_WRITE_ADDRESS = BYTE_SWAP_32(0x096100c0); 613 uint32_t WAIT_CMD = BYTE_SWAP_32(0x000FFFFF); 614 int file_size; 615 uint32_t pbi_cmd, altcbar; 616 uint8_t pbi_data[MAX_PBI_DATA_LEN_BYTE]; 617 uint32_t dst_offset; 618 FILE *fp_img = NULL; 619 int ret = FAILURE; 620 621 altcbar = pblimg.addr; 622 dst_offset = pblimg.addr; 623 fp_img = fopen(pblimg.sec_imgnm, "rb"); 624 if (fp_img == NULL) { 625 printf("%s: Error in opening the file: %s\n", __func__, 626 pblimg.sec_imgnm); 627 goto add_cpy_err; 628 } 629 file_size = get_filesize(pblimg.sec_imgnm); 630 altcbar = 0xfff00000 & altcbar; 631 altcbar = BYTE_SWAP_32(altcbar >> 16); 632 if (fwrite(&ALTCBAR_ADDRESS, sizeof(ALTCBAR_ADDRESS), NUM_MEM_BLOCK, 633 fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 634 printf("%s: Error in writing address of ALTCFG CMD.\n", 635 __func__); 636 goto add_cpy_err; 637 } 638 if (fwrite(&altcbar, sizeof(altcbar), NUM_MEM_BLOCK, fp_rcw_pbi_op) 639 != NUM_MEM_BLOCK) { 640 printf("%s: Error in writing ALTCFG CMD.\n", __func__); 641 goto add_cpy_err; 642 } 643 if (fwrite(&WAIT_CMD_WRITE_ADDRESS, sizeof(WAIT_CMD_WRITE_ADDRESS), 644 NUM_MEM_BLOCK, fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 645 printf("%s: Error in writing address of WAIT_CMD.\n", 646 __func__); 647 goto add_cpy_err; 648 } 649 if (fwrite(&WAIT_CMD, sizeof(WAIT_CMD), NUM_MEM_BLOCK, fp_rcw_pbi_op) 650 != NUM_MEM_BLOCK) { 651 printf("%s: Error in writing WAIT_CMD.\n", __func__); 652 goto add_cpy_err; 653 } 654 do { 655 memset(pbi_data, 0, MAX_PBI_DATA_LEN_BYTE); 656 657 ret = fread(&pbi_data, MAX_PBI_DATA_LEN_BYTE, 658 NUM_MEM_BLOCK, fp_img); 659 if ((ret != NUM_MEM_BLOCK) && (!feof(fp_img))) { 660 printf("%s: Error writing ALTCFG Word: [%d].\n", 661 __func__, ret); 662 goto add_cpy_err; 663 } 664 665 dst_offset &= OFFSET_MASK; 666 pbi_cmd = WRITE_CMD_BASE | dst_offset; 667 pbi_cmd = BYTE_SWAP_32(pbi_cmd); 668 if (fwrite(&pbi_cmd, sizeof(pbi_cmd), NUM_MEM_BLOCK, 669 fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 670 printf("%s: Error writing ALTCFG Word write cmd.\n", 671 __func__); 672 goto add_cpy_err; 673 } 674 if (fwrite(&pbi_data, MAX_PBI_DATA_LEN_BYTE, NUM_MEM_BLOCK, 675 fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 676 printf("%s: Error writing ALTCFG_Word.\n", __func__); 677 goto add_cpy_err; 678 } 679 dst_offset += MAX_PBI_DATA_LEN_BYTE; 680 file_size -= MAX_PBI_DATA_LEN_BYTE; 681 } while (!feof(fp_img)); 682 683 ret = SUCCESS; 684 685 add_cpy_err: 686 if (fp_img != NULL) { 687 fclose(fp_img); 688 } 689 return ret; 690 } 691 692 int main(int argc, char **argv) 693 { 694 FILE *file = NULL; 695 char *ptr; 696 int opt; 697 int tmp; 698 uint16_t args = ARG_INIT_MASK; 699 FILE *fp_rcw_pbi_ip = NULL, *fp_rcw_pbi_op = NULL; 700 uint32_t word, word_1; 701 int ret = FAILURE; 702 bool bootptr_flag = false; 703 enum stop_command flag_stop_cmd = CRC_STOP_COMMAND; 704 705 /* Initializing the global structure to zero. */ 706 memset(&pblimg, 0x0, sizeof(struct pbl_image)); 707 708 while ((opt = getopt(argc, argv, 709 ":b:f:r:i:e:d:c:o:h:s")) != -1) { 710 switch (opt) { 711 case 'd': 712 pblimg.addr = strtoull(optarg, &ptr, 16); 713 if (*ptr != 0) { 714 fprintf(stderr, "CMD Error: invalid load or destination address %s\n", optarg); 715 goto exit_main; 716 } 717 args |= BL2_BIN_CPY_DEST_ADDR_ARG_MASK; 718 break; 719 case 'r': 720 pblimg.rcw_nm = optarg; 721 file = fopen(pblimg.rcw_nm, "r"); 722 if (file == NULL) { 723 printf("CMD Error: Opening the RCW File.\n"); 724 goto exit_main; 725 } else { 726 args |= RCW_FILE_NAME_ARG_MASK; 727 fclose(file); 728 } 729 break; 730 case 'e': 731 bootptr_flag = true; 732 pblimg.ep = strtoull(optarg, &ptr, 16); 733 if (*ptr != 0) { 734 fprintf(stderr, 735 "CMD Error: Invalid entry point %s\n", optarg); 736 goto exit_main; 737 } 738 break; 739 case 'h': 740 print_usage(); 741 break; 742 case 'i': 743 pblimg.sec_imgnm = optarg; 744 file = fopen(pblimg.sec_imgnm, "r"); 745 if (file == NULL) { 746 printf("CMD Error: Opening Input file.\n"); 747 goto exit_main; 748 } else { 749 args |= IN_FILE_NAME_ARG_MASK; 750 fclose(file); 751 } 752 break; 753 case 'c': 754 tmp = atoi(optarg); 755 switch (tmp) { 756 case SOC_LS1012: 757 case SOC_LS1023: 758 case SOC_LS1026: 759 case SOC_LS1043: 760 case SOC_LS1046: 761 pblimg.chassis = CHASSIS_2; 762 break; 763 case SOC_LS1088: 764 case SOC_LS2080: 765 case SOC_LS2088: 766 pblimg.chassis = CHASSIS_3; 767 break; 768 case SOC_LS1028: 769 case SOC_LX2160: 770 pblimg.chassis = CHASSIS_3_2; 771 break; 772 default: 773 printf("CMD Error: Invalid SoC Val = %d.\n", tmp); 774 goto exit_main; 775 } 776 777 args |= CHASSIS_ARG_MASK; 778 break; 779 case 'o': 780 pblimg.imagefile = optarg; 781 args |= OP_FILE_NAME_ARG_MASK; 782 break; 783 case 's': 784 sb_flag = true; 785 break; 786 case 'b': 787 if (strcmp(optarg, "qspi") == 0) { 788 pblimg.boot_src = QSPI_BOOT; 789 } else if (strcmp(optarg, "nor") == 0) { 790 pblimg.boot_src = IFC_NOR_BOOT; 791 } else if (strcmp(optarg, "nand") == 0) { 792 pblimg.boot_src = IFC_NAND_BOOT; 793 } else if (strcmp(optarg, "sd") == 0) { 794 pblimg.boot_src = SD_BOOT; 795 } else if (strcmp(optarg, "emmc") == 0) { 796 pblimg.boot_src = EMMC_BOOT; 797 } else if (strcmp(optarg, "flexspi_nor") == 0) { 798 pblimg.boot_src = FLXSPI_NOR_BOOT; 799 } else if (strcmp(optarg, "flexspi_nand") == 0) { 800 pblimg.boot_src = FLXSPI_NAND_BOOT; 801 } else if (strcmp(optarg, "flexspi_nand2k") == 0) { 802 pblimg.boot_src = FLXSPI_NAND4K_BOOT; 803 } else { 804 printf("CMD Error: Invalid boot source.\n"); 805 goto exit_main; 806 } 807 args |= BOOT_SRC_ARG_MASK; 808 break; 809 case 'f': 810 pblimg.src_addr = strtoull(optarg, &ptr, 16); 811 if (*ptr != 0) { 812 fprintf(stderr, 813 "CMD Error: Invalid src offset %s\n", optarg); 814 goto exit_main; 815 } 816 args |= BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK; 817 break; 818 default: 819 /* issue a warning and skip the unknown arg */ 820 printf("Cmd Warning: Invalid Arg = %c.\n", opt); 821 } 822 } 823 824 if ((args & MAND_ARG_MASK) != MAND_ARG_MASK) { 825 print_usage(); 826 } 827 828 fp_rcw_pbi_ip = fopen(pblimg.rcw_nm, "rb"); 829 if (fp_rcw_pbi_ip == NULL) { 830 printf("%s: Error in opening the rcw file: %s\n", 831 __func__, pblimg.rcw_nm); 832 goto exit_main; 833 } 834 835 fp_rcw_pbi_op = fopen(pblimg.imagefile, "wb+"); 836 if (fp_rcw_pbi_op == NULL) { 837 printf("%s: Error opening the input file: %s\n", 838 __func__, pblimg.imagefile); 839 goto exit_main; 840 } 841 842 printf("\nInput Boot Source: %s\n", boot_src_string[pblimg.boot_src]); 843 printf("Input RCW File: %s\n", pblimg.rcw_nm); 844 printf("Input BL2 Binary File: %s\n", pblimg.sec_imgnm); 845 printf("Input load address for BL2 Binary File: 0x%x\n", pblimg.addr); 846 847 printf("Chassis Type: %d\n", pblimg.chassis); 848 switch (pblimg.chassis) { 849 case CHASSIS_2: 850 if (fread(&word, sizeof(word), NUM_MEM_BLOCK, fp_rcw_pbi_ip) 851 != NUM_MEM_BLOCK) { 852 printf("%s: Error in reading word from the rcw file.\n", 853 __func__); 854 goto exit_main; 855 } 856 while (BYTE_SWAP_32(word) != 0x08610040) { 857 if (BYTE_SWAP_32(word) == 0x09550000 858 || BYTE_SWAP_32(word) == 0x000f400c) { 859 break; 860 } 861 if (fwrite(&word, sizeof(word), NUM_MEM_BLOCK, 862 fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 863 printf("%s: [CH2] Error in Writing PBI Words\n", 864 __func__); 865 goto exit_main; 866 } 867 if (fread(&word, sizeof(word), NUM_MEM_BLOCK, 868 fp_rcw_pbi_ip) != NUM_MEM_BLOCK) { 869 printf("%s: [CH2] Error in Reading PBI Words\n", 870 __func__); 871 goto exit_main; 872 } 873 } 874 875 if (bootptr_flag == true) { 876 /* Add command to set boot_loc ptr */ 877 ret = add_boot_ptr_cmd(fp_rcw_pbi_op); 878 if (ret != SUCCESS) { 879 goto exit_main; 880 } 881 } 882 883 /* Write acs write commands to output file */ 884 ret = add_cpy_cmd(fp_rcw_pbi_op); 885 if (ret != SUCCESS) { 886 goto exit_main; 887 } 888 889 /* Add stop command after adding pbi commands 890 * For Chasis 2.0 platforms it is always CRC & 891 * Stop command 892 */ 893 flag_stop_cmd = CRC_STOP_COMMAND; 894 ret = add_pbi_stop_cmd(fp_rcw_pbi_op, flag_stop_cmd); 895 if (ret != SUCCESS) { 896 goto exit_main; 897 } 898 899 break; 900 901 case CHASSIS_3: 902 case CHASSIS_3_2: 903 if (fread(&word, sizeof(word), NUM_MEM_BLOCK, fp_rcw_pbi_ip) 904 != NUM_MEM_BLOCK) { 905 printf("%s: Error reading PBI Cmd.\n", __func__); 906 goto exit_main; 907 } 908 while (word != 0x808f0000 && word != 0x80ff0000) { 909 pbl_size++; 910 /* 11th words in RCW has PBL length. Update it 911 * with new length. 2 comamnds get added 912 * Block copy + CCSR Write/CSF header write 913 */ 914 if (pbl_size == 11) { 915 word_1 = (word & PBI_LEN_MASK) 916 + (PBI_LEN_ADD << 20); 917 word = word & ~PBI_LEN_MASK; 918 word = word | word_1; 919 } 920 /* Update the CRC command */ 921 /* Check load command.. 922 * add a check if command is Stop with CRC 923 * or stop without checksum 924 */ 925 if (pbl_size == 35) { 926 word = crypto_calculate_checksum(fp_rcw_pbi_op, 927 NUM_RCW_WORD - 1); 928 if (word == FAILURE) { 929 goto exit_main; 930 } 931 } 932 if (fwrite(&word, sizeof(word), NUM_MEM_BLOCK, 933 fp_rcw_pbi_op) != NUM_MEM_BLOCK) { 934 printf("%s: [CH3] Error in Writing PBI Words\n", 935 __func__); 936 goto exit_main; 937 } 938 if (fread(&word, sizeof(word), NUM_MEM_BLOCK, 939 fp_rcw_pbi_ip) != NUM_MEM_BLOCK) { 940 printf("%s: [CH3] Error in Reading PBI Words\n", 941 __func__); 942 goto exit_main; 943 } 944 945 if (word == CRC_STOP_CMD_ARM_CH3) { 946 flag_stop_cmd = CRC_STOP_COMMAND; 947 } else if (word == STOP_CMD_ARM_CH3) { 948 flag_stop_cmd = STOP_COMMAND; 949 } 950 } 951 if (bootptr_flag == true) { 952 /* Add command to set boot_loc ptr */ 953 ret = add_boot_ptr_cmd(fp_rcw_pbi_op); 954 if (ret != SUCCESS) { 955 printf("%s: add_boot_ptr_cmd return failure.\n", 956 __func__); 957 goto exit_main; 958 } 959 } 960 961 /* Write acs write commands to output file */ 962 ret = add_blk_cpy_cmd(fp_rcw_pbi_op, args); 963 if (ret != SUCCESS) { 964 printf("%s: Function add_blk_cpy_cmd return failure.\n", 965 __func__); 966 goto exit_main; 967 } 968 969 /* Add stop command after adding pbi commands */ 970 ret = add_pbi_stop_cmd(fp_rcw_pbi_op, flag_stop_cmd); 971 if (ret != SUCCESS) { 972 goto exit_main; 973 } 974 975 break; 976 977 default: 978 printf("%s: Unknown chassis type.\n", 979 __func__); 980 } 981 982 if (ret == SUCCESS) { 983 printf("Output file successfully created with name: %s\n\n", 984 pblimg.imagefile); 985 } 986 987 exit_main: 988 if (fp_rcw_pbi_op != NULL) { 989 fclose(fp_rcw_pbi_op); 990 } 991 if (fp_rcw_pbi_ip != NULL) { 992 fclose(fp_rcw_pbi_ip); 993 } 994 995 return ret; 996 } 997