blob: 244b0fbd85d25162c0fe1ec63c94af001e121940 [file] [log] [blame]
Pankaj Guptae55f6c42020-12-09 14:02:39 +05301/*
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
51typedef 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
59typedef 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
83uint32_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
95uint32_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 */
108uint32_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
121uint32_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
133char *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
145enum 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 */
156struct 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
196static uint32_t pbl_size;
197bool sb_flag;
198
199/***************************************************************************
200 * Description : CRC32 Lookup Table
201 ***************************************************************************/
202static 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
270static 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 ***************************************************************************/
302uint32_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 ***************************************************************************/
327int 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
432pbi_stop_err:
433 return ret;
434}
435
436/*
437 * Returns:
438 * File size in bytes, on Success.
439 * FAILURE, on failure.
440 */
441int 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
457filesize_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 ***************************************************************************/
467int 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
513bootptr_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 ***************************************************************************/
524int 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
598blk_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 ***************************************************************************/
609int 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
685add_cpy_err:
686 if (fp_img != NULL) {
687 fclose(fp_img);
688 }
689 return ret;
690}
691
692int 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
987exit_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}