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 
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= %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  ***************************************************************************/
add_blk_cpy_cmd(FILE * fp_rcw_pbi_op,uint16_t args)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  ***************************************************************************/
add_cpy_cmd(FILE * fp_rcw_pbi_op)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 
main(int argc,char ** argv)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