1 /*
2 * Copyright 2021-2022 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
print_usage(void)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 ***************************************************************************/
crypto_calculate_checksum(FILE * fp_rcw_pbi_op,uint32_t num)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 ***************************************************************************/
add_pbi_stop_cmd(FILE * fp_rcw_pbi_op,enum stop_command flag)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 */
get_filesize(const char * c)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 ***************************************************************************/
add_boot_ptr_cmd(FILE * fp_rcw_pbi_op)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= 0x%x\n",
511 pblimg.chassis == CHASSIS_2 ? BYTE_SWAP_32(pblimg.ep) :
512 pblimg.ep);
513 ret = SUCCESS;
514
515 bootptr_err:
516 return ret;
517 }
518
519 /***************************************************************************
520 * Function : add_blk_cpy_cmd
521 * Arguments : pbi_word - pointer to pbi commands
522 * args - Command line args flag.
523 * Return : SUCCESS or FAILURE
524 * Description : Add pbi commands for block copy cmd in pbi_words
525 ***************************************************************************/
add_blk_cpy_cmd(FILE * fp_rcw_pbi_op,uint16_t args)526 int add_blk_cpy_cmd(FILE *fp_rcw_pbi_op, uint16_t args)
527 {
528 uint32_t blk_cpy_hdr;
529 uint32_t file_size, new_file_size;
530 uint32_t align = 4;
531 int ret = FAILURE;
532 int num_pad_bytes = 0;
533
534 if ((args & BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK) == 0) {
535 printf("ERROR: Offset not specified for Block Copy Cmd.\n");
536 printf("\tSee Usage and use -f option\n");
537 goto blk_copy_err;
538 }
539
540 switch (pblimg.chassis) {
541 case CHASSIS_3:
542 /* Block copy command */
543 blk_cpy_hdr = blk_cpy_hdr_map_ch3[pblimg.boot_src];
544 pblimg.src_addr += base_addr_ch3[pblimg.boot_src];
545 break;
546 case CHASSIS_3_2:
547 /* Block copy command */
548 blk_cpy_hdr = blk_cpy_hdr_map_ch32[pblimg.boot_src];
549 pblimg.src_addr += base_addr_ch32[pblimg.boot_src];
550 break;
551 default:
552 printf("%s: Error invalid chassis type for this command.\n",
553 __func__);
554 goto blk_copy_err;
555 }
556
557 file_size = get_filesize(pblimg.sec_imgnm);
558 if (file_size > 0) {
559 new_file_size = (file_size + (file_size % align));
560
561 /* Add Block copy command */
562 if (fwrite(&blk_cpy_hdr, sizeof(blk_cpy_hdr), NUM_MEM_BLOCK,
563 fp_rcw_pbi_op) != NUM_MEM_BLOCK) {
564 printf("%s: Error writing blk_cpy_hdr to the file.\n",
565 __func__);
566 goto blk_copy_err;
567 }
568
569 if ((args & BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK) == 0)
570 num_pad_bytes = pblimg.src_addr % 4;
571
572 /* Add Src address word */
573 if (fwrite(&pblimg.src_addr + num_pad_bytes,
574 sizeof(pblimg.src_addr), NUM_MEM_BLOCK,
575 fp_rcw_pbi_op) != NUM_MEM_BLOCK) {
576 printf("%s: Error writing BLK SRC Addr to the file.\n",
577 __func__);
578 goto blk_copy_err;
579 }
580
581 /* Add Dest address word */
582 if (fwrite(&pblimg.addr, sizeof(pblimg.addr),
583 NUM_MEM_BLOCK, fp_rcw_pbi_op) != NUM_MEM_BLOCK) {
584 printf("%s: Error writing DST Addr to the file.\n",
585 __func__);
586 goto blk_copy_err;
587 }
588
589 /* Add size */
590 if (fwrite(&new_file_size, sizeof(new_file_size),
591 NUM_MEM_BLOCK, fp_rcw_pbi_op) != NUM_MEM_BLOCK) {
592 printf("%s: Error writing size to the file.\n",
593 __func__);
594 goto blk_copy_err;
595 }
596 }
597
598 ret = SUCCESS;
599
600 blk_copy_err:
601 return ret;
602 }
603
604 /***************************************************************************
605 * Function : add_cpy_cmd
606 * Arguments : pbi_word - pointer to pbi commands
607 * Return : SUCCESS or FAILURE
608 * Description : Append pbi commands for copying BL2 image to the
609 * load address stored in pbl_image.addr
610 ***************************************************************************/
add_cpy_cmd(FILE * fp_rcw_pbi_op)611 int add_cpy_cmd(FILE *fp_rcw_pbi_op)
612 {
613 uint32_t ALTCBAR_ADDRESS = BYTE_SWAP_32(0x09570158);
614 uint32_t WAIT_CMD_WRITE_ADDRESS = BYTE_SWAP_32(0x096100c0);
615 uint32_t WAIT_CMD = BYTE_SWAP_32(0x000FFFFF);
616 int file_size;
617 uint32_t pbi_cmd, altcbar;
618 uint8_t pbi_data[MAX_PBI_DATA_LEN_BYTE];
619 uint32_t dst_offset;
620 FILE *fp_img = NULL;
621 int ret = FAILURE;
622
623 altcbar = pblimg.addr;
624 dst_offset = pblimg.addr;
625 fp_img = fopen(pblimg.sec_imgnm, "rb");
626 if (fp_img == NULL) {
627 printf("%s: Error in opening the file: %s\n", __func__,
628 pblimg.sec_imgnm);
629 goto add_cpy_err;
630 }
631 file_size = get_filesize(pblimg.sec_imgnm);
632 altcbar = 0xfff00000 & altcbar;
633 altcbar = BYTE_SWAP_32(altcbar >> 16);
634 if (fwrite(&ALTCBAR_ADDRESS, sizeof(ALTCBAR_ADDRESS), NUM_MEM_BLOCK,
635 fp_rcw_pbi_op) != NUM_MEM_BLOCK) {
636 printf("%s: Error in writing address of ALTCFG CMD.\n",
637 __func__);
638 goto add_cpy_err;
639 }
640 if (fwrite(&altcbar, sizeof(altcbar), NUM_MEM_BLOCK, fp_rcw_pbi_op)
641 != NUM_MEM_BLOCK) {
642 printf("%s: Error in writing ALTCFG CMD.\n", __func__);
643 goto add_cpy_err;
644 }
645 if (fwrite(&WAIT_CMD_WRITE_ADDRESS, sizeof(WAIT_CMD_WRITE_ADDRESS),
646 NUM_MEM_BLOCK, fp_rcw_pbi_op) != NUM_MEM_BLOCK) {
647 printf("%s: Error in writing address of WAIT_CMD.\n",
648 __func__);
649 goto add_cpy_err;
650 }
651 if (fwrite(&WAIT_CMD, sizeof(WAIT_CMD), NUM_MEM_BLOCK, fp_rcw_pbi_op)
652 != NUM_MEM_BLOCK) {
653 printf("%s: Error in writing WAIT_CMD.\n", __func__);
654 goto add_cpy_err;
655 }
656 do {
657 memset(pbi_data, 0, MAX_PBI_DATA_LEN_BYTE);
658
659 ret = fread(&pbi_data, MAX_PBI_DATA_LEN_BYTE,
660 NUM_MEM_BLOCK, fp_img);
661 if ((ret != NUM_MEM_BLOCK) && (!feof(fp_img))) {
662 printf("%s: Error writing ALTCFG Word: [%d].\n",
663 __func__, ret);
664 goto add_cpy_err;
665 }
666
667 dst_offset &= OFFSET_MASK;
668 pbi_cmd = WRITE_CMD_BASE | dst_offset;
669 pbi_cmd = BYTE_SWAP_32(pbi_cmd);
670 if (fwrite(&pbi_cmd, sizeof(pbi_cmd), NUM_MEM_BLOCK,
671 fp_rcw_pbi_op) != NUM_MEM_BLOCK) {
672 printf("%s: Error writing ALTCFG Word write cmd.\n",
673 __func__);
674 goto add_cpy_err;
675 }
676 if (fwrite(&pbi_data, MAX_PBI_DATA_LEN_BYTE, NUM_MEM_BLOCK,
677 fp_rcw_pbi_op) != NUM_MEM_BLOCK) {
678 printf("%s: Error writing ALTCFG_Word.\n", __func__);
679 goto add_cpy_err;
680 }
681 dst_offset += MAX_PBI_DATA_LEN_BYTE;
682 file_size -= MAX_PBI_DATA_LEN_BYTE;
683 } while (!feof(fp_img));
684
685 ret = SUCCESS;
686
687 add_cpy_err:
688 if (fp_img != NULL) {
689 fclose(fp_img);
690 }
691 return ret;
692 }
693
main(int argc,char ** argv)694 int main(int argc, char **argv)
695 {
696 FILE *file = NULL;
697 char *ptr;
698 int opt;
699 int tmp;
700 uint16_t args = ARG_INIT_MASK;
701 FILE *fp_rcw_pbi_ip = NULL, *fp_rcw_pbi_op = NULL;
702 uint32_t word, word_1;
703 int ret = FAILURE;
704 bool bootptr_flag = false;
705 enum stop_command flag_stop_cmd = CRC_STOP_COMMAND;
706
707 /* Initializing the global structure to zero. */
708 memset(&pblimg, 0x0, sizeof(struct pbl_image));
709
710 while ((opt = getopt(argc, argv,
711 ":b:f:r:i:e:d:c:o:h:s")) != -1) {
712 switch (opt) {
713 case 'd':
714 pblimg.addr = strtoull(optarg, &ptr, 16);
715 if (*ptr != 0) {
716 fprintf(stderr, "CMD Error: invalid load or destination address %s\n", optarg);
717 goto exit_main;
718 }
719 args |= BL2_BIN_CPY_DEST_ADDR_ARG_MASK;
720 break;
721 case 'r':
722 pblimg.rcw_nm = optarg;
723 file = fopen(pblimg.rcw_nm, "r");
724 if (file == NULL) {
725 printf("CMD Error: Opening the RCW File.\n");
726 goto exit_main;
727 } else {
728 args |= RCW_FILE_NAME_ARG_MASK;
729 fclose(file);
730 }
731 break;
732 case 'e':
733 bootptr_flag = true;
734 pblimg.ep = strtoull(optarg, &ptr, 16);
735 if (*ptr != 0) {
736 fprintf(stderr,
737 "CMD Error: Invalid entry point %s\n", optarg);
738 goto exit_main;
739 }
740 break;
741 case 'h':
742 print_usage();
743 break;
744 case 'i':
745 pblimg.sec_imgnm = optarg;
746 file = fopen(pblimg.sec_imgnm, "r");
747 if (file == NULL) {
748 printf("CMD Error: Opening Input file.\n");
749 goto exit_main;
750 } else {
751 args |= IN_FILE_NAME_ARG_MASK;
752 fclose(file);
753 }
754 break;
755 case 'c':
756 tmp = atoi(optarg);
757 switch (tmp) {
758 case SOC_LS1012:
759 case SOC_LS1023:
760 case SOC_LS1026:
761 case SOC_LS1043:
762 case SOC_LS1046:
763 pblimg.chassis = CHASSIS_2;
764 break;
765 case SOC_LS1088:
766 case SOC_LS2080:
767 case SOC_LS2088:
768 pblimg.chassis = CHASSIS_3;
769 break;
770 case SOC_LS1028:
771 case SOC_LX2160:
772 pblimg.chassis = CHASSIS_3_2;
773 break;
774 default:
775 printf("CMD Error: Invalid SoC Val = %d.\n", tmp);
776 goto exit_main;
777 }
778
779 args |= CHASSIS_ARG_MASK;
780 break;
781 case 'o':
782 pblimg.imagefile = optarg;
783 args |= OP_FILE_NAME_ARG_MASK;
784 break;
785 case 's':
786 sb_flag = true;
787 break;
788 case 'b':
789 if (strcmp(optarg, "qspi") == 0) {
790 pblimg.boot_src = QSPI_BOOT;
791 } else if (strcmp(optarg, "nor") == 0) {
792 pblimg.boot_src = IFC_NOR_BOOT;
793 } else if (strcmp(optarg, "nand") == 0) {
794 pblimg.boot_src = IFC_NAND_BOOT;
795 } else if (strcmp(optarg, "sd") == 0) {
796 pblimg.boot_src = SD_BOOT;
797 } else if (strcmp(optarg, "emmc") == 0) {
798 pblimg.boot_src = EMMC_BOOT;
799 } else if (strcmp(optarg, "flexspi_nor") == 0) {
800 pblimg.boot_src = FLXSPI_NOR_BOOT;
801 } else if (strcmp(optarg, "flexspi_nand") == 0) {
802 pblimg.boot_src = FLXSPI_NAND_BOOT;
803 } else if (strcmp(optarg, "flexspi_nand2k") == 0) {
804 pblimg.boot_src = FLXSPI_NAND4K_BOOT;
805 } else {
806 printf("CMD Error: Invalid boot source.\n");
807 goto exit_main;
808 }
809 args |= BOOT_SRC_ARG_MASK;
810 break;
811 case 'f':
812 pblimg.src_addr = strtoull(optarg, &ptr, 16);
813 if (*ptr != 0) {
814 fprintf(stderr,
815 "CMD Error: Invalid src offset %s\n", optarg);
816 goto exit_main;
817 }
818 args |= BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK;
819 break;
820 default:
821 /* issue a warning and skip the unknown arg */
822 printf("Cmd Warning: Invalid Arg = %c.\n", opt);
823 }
824 }
825
826 if ((args & MAND_ARG_MASK) != MAND_ARG_MASK
827 || pblimg.rcw_nm == NULL
828 || pblimg.imagefile == NULL) {
829 print_usage();
830 }
831
832 fp_rcw_pbi_ip = fopen(pblimg.rcw_nm, "rb");
833 if (fp_rcw_pbi_ip == NULL) {
834 printf("%s: Error in opening the rcw file: %s\n",
835 __func__, pblimg.rcw_nm);
836 goto exit_main;
837 }
838
839 fp_rcw_pbi_op = fopen(pblimg.imagefile, "wb+");
840 if (fp_rcw_pbi_op == NULL) {
841 printf("%s: Error opening the input file: %s\n",
842 __func__, pblimg.imagefile);
843 goto exit_main;
844 }
845
846 printf("\nInput Boot Source: %s\n", boot_src_string[pblimg.boot_src]);
847 printf("Input RCW File: %s\n", pblimg.rcw_nm);
848 printf("Input BL2 Binary File: %s\n", pblimg.sec_imgnm);
849 printf("Input load address for BL2 Binary File: 0x%x\n", pblimg.addr);
850
851 printf("Chassis Type: %d\n", pblimg.chassis);
852 switch (pblimg.chassis) {
853 case CHASSIS_2:
854 if (fread(&word, sizeof(word), NUM_MEM_BLOCK, fp_rcw_pbi_ip)
855 != NUM_MEM_BLOCK) {
856 printf("%s: Error in reading word from the rcw file.\n",
857 __func__);
858 goto exit_main;
859 }
860 while (BYTE_SWAP_32(word) != 0x08610040) {
861 if (BYTE_SWAP_32(word) == 0x09550000
862 || BYTE_SWAP_32(word) == 0x000f400c) {
863 break;
864 }
865 if (fwrite(&word, sizeof(word), NUM_MEM_BLOCK,
866 fp_rcw_pbi_op) != NUM_MEM_BLOCK) {
867 printf("%s: [CH2] Error in Writing PBI Words\n",
868 __func__);
869 goto exit_main;
870 }
871 if (fread(&word, sizeof(word), NUM_MEM_BLOCK,
872 fp_rcw_pbi_ip) != NUM_MEM_BLOCK) {
873 printf("%s: [CH2] Error in Reading PBI Words\n",
874 __func__);
875 goto exit_main;
876 }
877 }
878
879 if (bootptr_flag == true) {
880 /* Add command to set boot_loc ptr */
881 ret = add_boot_ptr_cmd(fp_rcw_pbi_op);
882 if (ret != SUCCESS) {
883 goto exit_main;
884 }
885 }
886
887 /* Write acs write commands to output file */
888 ret = add_cpy_cmd(fp_rcw_pbi_op);
889 if (ret != SUCCESS) {
890 goto exit_main;
891 }
892
893 /* Add stop command after adding pbi commands
894 * For Chasis 2.0 platforms it is always CRC &
895 * Stop command
896 */
897 flag_stop_cmd = CRC_STOP_COMMAND;
898 ret = add_pbi_stop_cmd(fp_rcw_pbi_op, flag_stop_cmd);
899 if (ret != SUCCESS) {
900 goto exit_main;
901 }
902
903 break;
904
905 case CHASSIS_3:
906 case CHASSIS_3_2:
907 if (fread(&word, sizeof(word), NUM_MEM_BLOCK, fp_rcw_pbi_ip)
908 != NUM_MEM_BLOCK) {
909 printf("%s: Error reading PBI Cmd.\n", __func__);
910 goto exit_main;
911 }
912 while (word != 0x808f0000 && word != 0x80ff0000) {
913 pbl_size++;
914 /* 11th words in RCW has PBL length. Update it
915 * with new length. 2 commands get added
916 * Block copy + CCSR Write/CSF header write
917 */
918 if (pbl_size == 11) {
919 word_1 = (word & PBI_LEN_MASK)
920 + (PBI_LEN_ADD << 20);
921 word = word & ~PBI_LEN_MASK;
922 word = word | word_1;
923 }
924 /* Update the CRC command */
925 /* Check load command..
926 * add a check if command is Stop with CRC
927 * or stop without checksum
928 */
929 if (pbl_size == 35) {
930 word = crypto_calculate_checksum(fp_rcw_pbi_op,
931 NUM_RCW_WORD - 1);
932 if (word == FAILURE) {
933 goto exit_main;
934 }
935 }
936 if (fwrite(&word, sizeof(word), NUM_MEM_BLOCK,
937 fp_rcw_pbi_op) != NUM_MEM_BLOCK) {
938 printf("%s: [CH3] Error in Writing PBI Words\n",
939 __func__);
940 goto exit_main;
941 }
942 if (fread(&word, sizeof(word), NUM_MEM_BLOCK,
943 fp_rcw_pbi_ip) != NUM_MEM_BLOCK) {
944 printf("%s: [CH3] Error in Reading PBI Words\n",
945 __func__);
946 goto exit_main;
947 }
948
949 if (word == CRC_STOP_CMD_ARM_CH3) {
950 flag_stop_cmd = CRC_STOP_COMMAND;
951 } else if (word == STOP_CMD_ARM_CH3) {
952 flag_stop_cmd = STOP_COMMAND;
953 }
954 }
955 if (bootptr_flag == true) {
956 /* Add command to set boot_loc ptr */
957 ret = add_boot_ptr_cmd(fp_rcw_pbi_op);
958 if (ret != SUCCESS) {
959 printf("%s: add_boot_ptr_cmd return failure.\n",
960 __func__);
961 goto exit_main;
962 }
963 }
964
965 /* Write acs write commands to output file */
966 ret = add_blk_cpy_cmd(fp_rcw_pbi_op, args);
967 if (ret != SUCCESS) {
968 printf("%s: Function add_blk_cpy_cmd return failure.\n",
969 __func__);
970 goto exit_main;
971 }
972
973 /* Add stop command after adding pbi commands */
974 ret = add_pbi_stop_cmd(fp_rcw_pbi_op, flag_stop_cmd);
975 if (ret != SUCCESS) {
976 goto exit_main;
977 }
978
979 break;
980
981 default:
982 printf("%s: Unknown chassis type.\n",
983 __func__);
984 }
985
986 if (ret == SUCCESS) {
987 printf("Output file successfully created with name: %s\n\n",
988 pblimg.imagefile);
989 }
990
991 exit_main:
992 if (fp_rcw_pbi_op != NULL) {
993 fclose(fp_rcw_pbi_op);
994 }
995 if (fp_rcw_pbi_ip != NULL) {
996 fclose(fp_rcw_pbi_ip);
997 }
998
999 return ret;
1000 }
1001