1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Freescale i.MX28 image generator
4 *
5 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
6 * on behalf of DENX Software Engineering GmbH
7 */
8
9#include <fcntl.h>
10#include <sys/stat.h>
11#include <sys/types.h>
12#include <unistd.h>
13
14#include "compiler.h"
15
16/* Taken from <linux/kernel.h> */
17#define __round_mask(x, y) ((__typeof__(x))((y)-1))
18#define round_down(x, y) ((x) & ~__round_mask(x, y))
19
20/*
21 * Default BCB layout.
22 *
23 * TWEAK this if you have blown any OCOTP fuses.
24 */
25#define	STRIDE_PAGES		64
26#define	STRIDE_COUNT		4
27
28/*
29 * Layout for 256Mb big NAND with 2048b page size, 64b OOB size and
30 * 128kb erase size.
31 *
32 * TWEAK this if you have different kind of NAND chip.
33 */
34static uint32_t nand_writesize = 2048;
35static uint32_t nand_oobsize = 64;
36static uint32_t nand_erasesize = 128 * 1024;
37
38/*
39 * Sector on which the SigmaTel boot partition (0x53) starts.
40 */
41static uint32_t sd_sector = 2048;
42
43/*
44 * Each of the U-Boot bootstreams is at maximum 1MB big.
45 *
46 * TWEAK this if, for some wild reason, you need to boot bigger image.
47 */
48#define	MAX_BOOTSTREAM_SIZE	(1 * 1024 * 1024)
49
50/* i.MX28 NAND controller-specific constants. DO NOT TWEAK! */
51#define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
52#define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE		512
53#define	MXS_NAND_METADATA_SIZE			10
54#define	MXS_NAND_BITS_PER_ECC_LEVEL		13
55#define	MXS_NAND_COMMAND_BUFFER_SIZE		32
56
57struct mx28_nand_fcb {
58	uint32_t		checksum;
59	uint32_t		fingerprint;
60	uint32_t		version;
61	struct {
62		uint8_t			data_setup;
63		uint8_t			data_hold;
64		uint8_t			address_setup;
65		uint8_t			dsample_time;
66		uint8_t			nand_timing_state;
67		uint8_t			rea;
68		uint8_t			rloh;
69		uint8_t			rhoh;
70	}			timing;
71	uint32_t		page_data_size;
72	uint32_t		total_page_size;
73	uint32_t		sectors_per_block;
74	uint32_t		number_of_nands;		/* Ignored */
75	uint32_t		total_internal_die;		/* Ignored */
76	uint32_t		cell_type;			/* Ignored */
77	uint32_t		ecc_block_n_ecc_type;
78	uint32_t		ecc_block_0_size;
79	uint32_t		ecc_block_n_size;
80	uint32_t		ecc_block_0_ecc_type;
81	uint32_t		metadata_bytes;
82	uint32_t		num_ecc_blocks_per_page;
83	uint32_t		ecc_block_n_ecc_level_sdk;	/* Ignored */
84	uint32_t		ecc_block_0_size_sdk;		/* Ignored */
85	uint32_t		ecc_block_n_size_sdk;		/* Ignored */
86	uint32_t		ecc_block_0_ecc_level_sdk;	/* Ignored */
87	uint32_t		num_ecc_blocks_per_page_sdk;	/* Ignored */
88	uint32_t		metadata_bytes_sdk;		/* Ignored */
89	uint32_t		erase_threshold;
90	uint32_t		boot_patch;
91	uint32_t		patch_sectors;
92	uint32_t		firmware1_starting_sector;
93	uint32_t		firmware2_starting_sector;
94	uint32_t		sectors_in_firmware1;
95	uint32_t		sectors_in_firmware2;
96	uint32_t		dbbt_search_area_start_address;
97	uint32_t		badblock_marker_byte;
98	uint32_t		badblock_marker_start_bit;
99	uint32_t		bb_marker_physical_offset;
100};
101
102struct mx28_nand_dbbt {
103	uint32_t		checksum;
104	uint32_t		fingerprint;
105	uint32_t		version;
106	uint32_t		number_bb;
107	uint32_t		number_2k_pages_bb;
108};
109
110struct mx28_nand_bbt {
111	uint32_t		nand;
112	uint32_t		number_bb;
113	uint32_t		badblock[510];
114};
115
116struct mx28_sd_drive_info {
117	uint32_t		chip_num;
118	uint32_t		drive_type;
119	uint32_t		tag;
120	uint32_t		first_sector_number;
121	uint32_t		sector_count;
122};
123
124struct mx28_sd_config_block {
125	uint32_t			signature;
126	uint32_t			primary_boot_tag;
127	uint32_t			secondary_boot_tag;
128	uint32_t			num_copies;
129	struct mx28_sd_drive_info	drv_info[1];
130};
131
132static inline uint32_t mx28_nand_ecc_chunk_cnt(uint32_t page_data_size)
133{
134	return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
135}
136
137static inline uint32_t mx28_nand_ecc_size_in_bits(uint32_t ecc_strength)
138{
139	return ecc_strength * MXS_NAND_BITS_PER_ECC_LEVEL;
140}
141
142static inline uint32_t mx28_nand_get_ecc_strength(uint32_t page_data_size,
143						uint32_t page_oob_size)
144{
145	int ecc_strength;
146
147	/*
148	 * Determine the ECC layout with the formula:
149	 *	ECC bits per chunk = (total page spare data bits) /
150	 *		(bits per ECC level) / (chunks per page)
151	 * where:
152	 *	total page spare data bits =
153	 *		(page oob size - meta data size) * (bits per byte)
154	 */
155	ecc_strength = ((page_oob_size - MXS_NAND_METADATA_SIZE) * 8)
156			/ (MXS_NAND_BITS_PER_ECC_LEVEL *
157				mx28_nand_ecc_chunk_cnt(page_data_size));
158
159	return round_down(ecc_strength, 2);
160}
161
162static inline uint32_t mx28_nand_get_mark_offset(uint32_t page_data_size,
163						uint32_t ecc_strength)
164{
165	uint32_t chunk_data_size_in_bits;
166	uint32_t chunk_ecc_size_in_bits;
167	uint32_t chunk_total_size_in_bits;
168	uint32_t block_mark_chunk_number;
169	uint32_t block_mark_chunk_bit_offset;
170	uint32_t block_mark_bit_offset;
171
172	chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8;
173	chunk_ecc_size_in_bits  = mx28_nand_ecc_size_in_bits(ecc_strength);
174
175	chunk_total_size_in_bits =
176			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
177
178	/* Compute the bit offset of the block mark within the physical page. */
179	block_mark_bit_offset = page_data_size * 8;
180
181	/* Subtract the metadata bits. */
182	block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
183
184	/*
185	 * Compute the chunk number (starting at zero) in which the block mark
186	 * appears.
187	 */
188	block_mark_chunk_number =
189			block_mark_bit_offset / chunk_total_size_in_bits;
190
191	/*
192	 * Compute the bit offset of the block mark within its chunk, and
193	 * validate it.
194	 */
195	block_mark_chunk_bit_offset = block_mark_bit_offset -
196			(block_mark_chunk_number * chunk_total_size_in_bits);
197
198	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
199		return 1;
200
201	/*
202	 * Now that we know the chunk number in which the block mark appears,
203	 * we can subtract all the ECC bits that appear before it.
204	 */
205	block_mark_bit_offset -=
206		block_mark_chunk_number * chunk_ecc_size_in_bits;
207
208	return block_mark_bit_offset;
209}
210
211static inline uint32_t mx28_nand_mark_byte_offset(void)
212{
213	uint32_t ecc_strength;
214	ecc_strength = mx28_nand_get_ecc_strength(nand_writesize, nand_oobsize);
215	return mx28_nand_get_mark_offset(nand_writesize, ecc_strength) >> 3;
216}
217
218static inline uint32_t mx28_nand_mark_bit_offset(void)
219{
220	uint32_t ecc_strength;
221	ecc_strength = mx28_nand_get_ecc_strength(nand_writesize, nand_oobsize);
222	return mx28_nand_get_mark_offset(nand_writesize, ecc_strength) & 0x7;
223}
224
225static uint32_t mx28_nand_block_csum(uint8_t *block, uint32_t size)
226{
227	uint32_t csum = 0;
228	int i;
229
230	for (i = 0; i < size; i++)
231		csum += block[i];
232
233	return csum ^ 0xffffffff;
234}
235
236static struct mx28_nand_fcb *mx28_nand_get_fcb(uint32_t size)
237{
238	struct mx28_nand_fcb *fcb;
239	uint32_t bcb_size_bytes;
240	uint32_t stride_size_bytes;
241	uint32_t bootstream_size_pages;
242	uint32_t fw1_start_page;
243	uint32_t fw2_start_page;
244
245	fcb = malloc(nand_writesize);
246	if (!fcb) {
247		printf("MX28 NAND: Unable to allocate FCB\n");
248		return NULL;
249	}
250
251	memset(fcb, 0, nand_writesize);
252
253	fcb->fingerprint =			0x20424346;
254	fcb->version =				0x01000000;
255
256	/*
257	 * FIXME: These here are default values as found in kobs-ng. We should
258	 * probably retrieve the data from NAND or something.
259	 */
260	fcb->timing.data_setup =		80;
261	fcb->timing.data_hold =			60;
262	fcb->timing.address_setup =		25;
263	fcb->timing.dsample_time =		6;
264
265	fcb->page_data_size =		nand_writesize;
266	fcb->total_page_size =		nand_writesize + nand_oobsize;
267	fcb->sectors_per_block =	nand_erasesize / nand_writesize;
268
269	fcb->num_ecc_blocks_per_page =	(nand_writesize / 512) - 1;
270	fcb->ecc_block_0_size =		512;
271	fcb->ecc_block_n_size =		512;
272	fcb->metadata_bytes =		10;
273	fcb->ecc_block_n_ecc_type = mx28_nand_get_ecc_strength(
274					nand_writesize, nand_oobsize) >> 1;
275	fcb->ecc_block_0_ecc_type = mx28_nand_get_ecc_strength(
276					nand_writesize, nand_oobsize) >> 1;
277	if (fcb->ecc_block_n_ecc_type == 0) {
278		printf("MX28 NAND: Unsupported NAND geometry\n");
279		goto err;
280	}
281
282	fcb->boot_patch =			0;
283	fcb->patch_sectors =			0;
284
285	fcb->badblock_marker_byte =	mx28_nand_mark_byte_offset();
286	fcb->badblock_marker_start_bit = mx28_nand_mark_bit_offset();
287	fcb->bb_marker_physical_offset = nand_writesize;
288
289	stride_size_bytes = STRIDE_PAGES * nand_writesize;
290	bcb_size_bytes = stride_size_bytes * STRIDE_COUNT;
291
292	bootstream_size_pages = (size + (nand_writesize - 1)) /
293					nand_writesize;
294
295	fw1_start_page = 2 * bcb_size_bytes / nand_writesize;
296	fw2_start_page = (2 * bcb_size_bytes + MAX_BOOTSTREAM_SIZE) /
297				nand_writesize;
298
299	fcb->firmware1_starting_sector =	fw1_start_page;
300	fcb->firmware2_starting_sector =	fw2_start_page;
301	fcb->sectors_in_firmware1 =		bootstream_size_pages;
302	fcb->sectors_in_firmware2 =		bootstream_size_pages;
303
304	fcb->dbbt_search_area_start_address =	STRIDE_PAGES * STRIDE_COUNT;
305
306	return fcb;
307
308err:
309	free(fcb);
310	return NULL;
311}
312
313static struct mx28_nand_dbbt *mx28_nand_get_dbbt(void)
314{
315	struct mx28_nand_dbbt *dbbt;
316
317	dbbt = malloc(nand_writesize);
318	if (!dbbt) {
319		printf("MX28 NAND: Unable to allocate DBBT\n");
320		return NULL;
321	}
322
323	memset(dbbt, 0, nand_writesize);
324
325	dbbt->fingerprint	= 0x54424244;
326	dbbt->version		= 0x1;
327
328	return dbbt;
329}
330
331static inline uint8_t mx28_nand_parity_13_8(const uint8_t b)
332{
333	uint32_t parity = 0, tmp;
334
335	tmp = ((b >> 6) ^ (b >> 5) ^ (b >> 3) ^ (b >> 2)) & 1;
336	parity |= tmp << 0;
337
338	tmp = ((b >> 7) ^ (b >> 5) ^ (b >> 4) ^ (b >> 2) ^ (b >> 1)) & 1;
339	parity |= tmp << 1;
340
341	tmp = ((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ (b >> 1) ^ (b >> 0)) & 1;
342	parity |= tmp << 2;
343
344	tmp = ((b >> 7) ^ (b >> 4) ^ (b >> 3) ^ (b >> 0)) & 1;
345	parity |= tmp << 3;
346
347	tmp = ((b >> 6) ^ (b >> 4) ^ (b >> 3) ^
348		(b >> 2) ^ (b >> 1) ^ (b >> 0)) & 1;
349	parity |= tmp << 4;
350
351	return parity;
352}
353
354static uint8_t *mx28_nand_fcb_block(struct mx28_nand_fcb *fcb)
355{
356	uint8_t *block;
357	uint8_t *ecc;
358	int i;
359
360	block = malloc(nand_writesize + nand_oobsize);
361	if (!block) {
362		printf("MX28 NAND: Unable to allocate FCB block\n");
363		return NULL;
364	}
365
366	memset(block, 0, nand_writesize + nand_oobsize);
367
368	/* Update the FCB checksum */
369	fcb->checksum = mx28_nand_block_csum(((uint8_t *)fcb) + 4, 508);
370
371	/* Figure 12-11. in iMX28RM, rev. 1, says FCB is at offset 12 */
372	memcpy(block + 12, fcb, sizeof(struct mx28_nand_fcb));
373
374	/* ECC is at offset 12 + 512 */
375	ecc = block + 12 + 512;
376
377	/* Compute the ECC parity */
378	for (i = 0; i < sizeof(struct mx28_nand_fcb); i++)
379		ecc[i] = mx28_nand_parity_13_8(block[i + 12]);
380
381	return block;
382}
383
384static int mx28_nand_write_fcb(struct mx28_nand_fcb *fcb, uint8_t *buf)
385{
386	uint32_t offset;
387	uint8_t *fcbblock;
388	int ret = 0;
389	int i;
390
391	fcbblock = mx28_nand_fcb_block(fcb);
392	if (!fcbblock)
393		return -1;
394
395	for (i = 0; i < STRIDE_PAGES * STRIDE_COUNT; i += STRIDE_PAGES) {
396		offset = i * nand_writesize;
397		memcpy(buf + offset, fcbblock, nand_writesize + nand_oobsize);
398		/* Mark the NAND page is OK. */
399		buf[offset + nand_writesize] = 0xff;
400	}
401
402	free(fcbblock);
403	return ret;
404}
405
406static int mx28_nand_write_dbbt(struct mx28_nand_dbbt *dbbt, uint8_t *buf)
407{
408	uint32_t offset;
409	int i = STRIDE_PAGES * STRIDE_COUNT;
410
411	for (; i < 2 * STRIDE_PAGES * STRIDE_COUNT; i += STRIDE_PAGES) {
412		offset = i * nand_writesize;
413		memcpy(buf + offset, dbbt, sizeof(struct mx28_nand_dbbt));
414	}
415
416	return 0;
417}
418
419static int mx28_nand_write_firmware(struct mx28_nand_fcb *fcb, int infd,
420				    uint8_t *buf)
421{
422	int ret;
423	off_t size;
424	uint32_t offset1, offset2;
425
426	size = lseek(infd, 0, SEEK_END);
427	lseek(infd, 0, SEEK_SET);
428
429	offset1 = fcb->firmware1_starting_sector * nand_writesize;
430	offset2 = fcb->firmware2_starting_sector * nand_writesize;
431
432	ret = read(infd, buf + offset1, size);
433	if (ret != size)
434		return -1;
435
436	memcpy(buf + offset2, buf + offset1, size);
437
438	return 0;
439}
440
441static void usage(void)
442{
443	printf(
444		"Usage: mxsboot [ops] <type> <infile> <outfile>\n"
445		"Augment BootStream file with a proper header for i.MX28 boot\n"
446		"\n"
447		"  <type>	type of image:\n"
448		"                 \"nand\" for NAND image\n"
449		"                 \"sd\" for SD image\n"
450		"  <infile>     input file, the u-boot.sb bootstream\n"
451		"  <outfile>    output file, the bootable image\n"
452		"\n");
453	printf(
454		"For NAND boot, these options are accepted:\n"
455		"  -w <size>    NAND page size\n"
456		"  -o <size>    NAND OOB size\n"
457		"  -e <size>    NAND erase size\n"
458		"\n"
459		"For SD boot, these options are accepted:\n"
460		"  -p <sector>  Sector where the SGTL partition starts\n"
461	);
462}
463
464static int mx28_create_nand_image(int infd, int outfd)
465{
466	struct mx28_nand_fcb *fcb;
467	struct mx28_nand_dbbt *dbbt;
468	int ret = -1;
469	uint8_t *buf;
470	int size;
471	ssize_t wr_size;
472
473	size = nand_writesize * 512 + 2 * MAX_BOOTSTREAM_SIZE;
474
475	buf = malloc(size);
476	if (!buf) {
477		printf("Can not allocate output buffer of %d bytes\n", size);
478		goto err0;
479	}
480
481	memset(buf, 0xff, size);
482
483	fcb = mx28_nand_get_fcb(MAX_BOOTSTREAM_SIZE);
484	if (!fcb) {
485		printf("Unable to compile FCB\n");
486		goto err1;
487	}
488
489	dbbt = mx28_nand_get_dbbt();
490	if (!dbbt) {
491		printf("Unable to compile DBBT\n");
492		goto err2;
493	}
494
495	ret = mx28_nand_write_fcb(fcb, buf);
496	if (ret) {
497		printf("Unable to write FCB to buffer\n");
498		goto err3;
499	}
500
501	ret = mx28_nand_write_dbbt(dbbt, buf);
502	if (ret) {
503		printf("Unable to write DBBT to buffer\n");
504		goto err3;
505	}
506
507	ret = mx28_nand_write_firmware(fcb, infd, buf);
508	if (ret) {
509		printf("Unable to write firmware to buffer\n");
510		goto err3;
511	}
512
513	wr_size = write(outfd, buf, size);
514	if (wr_size != size) {
515		ret = -1;
516		goto err3;
517	}
518
519	ret = 0;
520
521err3:
522	free(dbbt);
523err2:
524	free(fcb);
525err1:
526	free(buf);
527err0:
528	return ret;
529}
530
531static int mx28_create_sd_image(int infd, int outfd)
532{
533	int ret = -1;
534	uint32_t *buf;
535	int size;
536	off_t fsize;
537	ssize_t wr_size;
538	struct mx28_sd_config_block *cb;
539
540	fsize = lseek(infd, 0, SEEK_END);
541	lseek(infd, 0, SEEK_SET);
542	size = fsize + 4 * 512;
543
544	buf = malloc(size);
545	if (!buf) {
546		printf("Can not allocate output buffer of %d bytes\n", size);
547		goto err0;
548	}
549
550	ret = read(infd, (uint8_t *)buf + 4 * 512, fsize);
551	if (ret != fsize) {
552		ret = -1;
553		goto err1;
554	}
555
556	cb = (struct mx28_sd_config_block *)buf;
557
558	cb->signature = cpu_to_le32(0x00112233);
559	cb->primary_boot_tag = cpu_to_le32(0x1);
560	cb->secondary_boot_tag = cpu_to_le32(0x1);
561	cb->num_copies = cpu_to_le32(1);
562	cb->drv_info[0].chip_num = cpu_to_le32(0x0);
563	cb->drv_info[0].drive_type = cpu_to_le32(0x0);
564	cb->drv_info[0].tag = cpu_to_le32(0x1);
565	cb->drv_info[0].first_sector_number = cpu_to_le32(sd_sector + 4);
566	cb->drv_info[0].sector_count = cpu_to_le32((size - 4) / 512);
567
568	wr_size = write(outfd, buf, size);
569	if (wr_size != size) {
570		ret = -1;
571		goto err1;
572	}
573
574	ret = 0;
575
576err1:
577	free(buf);
578err0:
579	return ret;
580}
581
582static int parse_ops(int argc, char **argv)
583{
584	int i;
585	int tmp;
586	char *end;
587	enum param {
588		PARAM_WRITE,
589		PARAM_OOB,
590		PARAM_ERASE,
591		PARAM_PART,
592		PARAM_SD,
593		PARAM_NAND
594	};
595	int type;
596
597	if (argc < 4)
598		return -1;
599
600	for (i = 1; i < argc; i++) {
601		if (!strncmp(argv[i], "-w", 2))
602			type = PARAM_WRITE;
603		else if (!strncmp(argv[i], "-o", 2))
604			type = PARAM_OOB;
605		else if (!strncmp(argv[i], "-e", 2))
606			type = PARAM_ERASE;
607		else if (!strncmp(argv[i], "-p", 2))
608			type = PARAM_PART;
609		else	/* SD/MMC */
610			break;
611
612		tmp = strtol(argv[++i], &end, 10);
613		if (tmp % 2)
614			return -1;
615		if (tmp <= 0)
616			return -1;
617
618		if (type == PARAM_WRITE)
619			nand_writesize = tmp;
620		if (type == PARAM_OOB)
621			nand_oobsize = tmp;
622		if (type == PARAM_ERASE)
623			nand_erasesize = tmp;
624		if (type == PARAM_PART)
625			sd_sector = tmp;
626	}
627
628	if (strcmp(argv[i], "sd") && strcmp(argv[i], "nand"))
629		return -1;
630
631	if (i + 3 != argc)
632		return -1;
633
634	return i;
635}
636
637int main(int argc, char **argv)
638{
639	int infd, outfd;
640	int ret = 0;
641	int offset;
642
643	offset = parse_ops(argc, argv);
644	if (offset < 0) {
645		usage();
646		ret = 1;
647		goto err1;
648	}
649
650	infd = open(argv[offset + 1], O_RDONLY);
651	if (infd < 0) {
652		printf("Input BootStream file can not be opened\n");
653		ret = 2;
654		goto err1;
655	}
656
657	outfd = open(argv[offset + 2], O_CREAT | O_TRUNC | O_WRONLY,
658					S_IRUSR | S_IWUSR);
659	if (outfd < 0) {
660		printf("Output file can not be created\n");
661		ret = 3;
662		goto err2;
663	}
664
665	if (!strcmp(argv[offset], "sd"))
666		ret = mx28_create_sd_image(infd, outfd);
667	else if (!strcmp(argv[offset], "nand"))
668		ret = mx28_create_nand_image(infd, outfd);
669
670	close(outfd);
671err2:
672	close(infd);
673err1:
674	return ret;
675}
676