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