xref: /rk3399_rockchip-uboot/cmd/mvebu/bubt.c (revision fa61ef6b4980dbc009e93baadbfcb1daa359d74b)
1*fa61ef6bSKonstantin Porotchkin /*
2*fa61ef6bSKonstantin Porotchkin  * Copyright (C) 2016 Marvell International Ltd.
3*fa61ef6bSKonstantin Porotchkin  *
4*fa61ef6bSKonstantin Porotchkin  * SPDX-License-Identifier:	GPL-2.0
5*fa61ef6bSKonstantin Porotchkin  * https://spdx.org/licenses
6*fa61ef6bSKonstantin Porotchkin  */
7*fa61ef6bSKonstantin Porotchkin 
8*fa61ef6bSKonstantin Porotchkin #include <config.h>
9*fa61ef6bSKonstantin Porotchkin #include <common.h>
10*fa61ef6bSKonstantin Porotchkin #include <command.h>
11*fa61ef6bSKonstantin Porotchkin #include <vsprintf.h>
12*fa61ef6bSKonstantin Porotchkin #include <errno.h>
13*fa61ef6bSKonstantin Porotchkin #include <dm.h>
14*fa61ef6bSKonstantin Porotchkin 
15*fa61ef6bSKonstantin Porotchkin #include <spi_flash.h>
16*fa61ef6bSKonstantin Porotchkin #include <spi.h>
17*fa61ef6bSKonstantin Porotchkin #include <nand.h>
18*fa61ef6bSKonstantin Porotchkin #include <usb.h>
19*fa61ef6bSKonstantin Porotchkin #include <fs.h>
20*fa61ef6bSKonstantin Porotchkin #include <mmc.h>
21*fa61ef6bSKonstantin Porotchkin #include <u-boot/sha1.h>
22*fa61ef6bSKonstantin Porotchkin #include <u-boot/sha256.h>
23*fa61ef6bSKonstantin Porotchkin 
24*fa61ef6bSKonstantin Porotchkin #ifndef CONFIG_SYS_MMC_ENV_DEV
25*fa61ef6bSKonstantin Porotchkin #define CONFIG_SYS_MMC_ENV_DEV	0
26*fa61ef6bSKonstantin Porotchkin #endif
27*fa61ef6bSKonstantin Porotchkin 
28*fa61ef6bSKonstantin Porotchkin #if defined(CONFIG_ARMADA_8K)
29*fa61ef6bSKonstantin Porotchkin #define MAIN_HDR_MAGIC		0xB105B002
30*fa61ef6bSKonstantin Porotchkin 
31*fa61ef6bSKonstantin Porotchkin struct mvebu_image_header {
32*fa61ef6bSKonstantin Porotchkin 	u32	magic;			/*  0-3  */
33*fa61ef6bSKonstantin Porotchkin 	u32	prolog_size;		/*  4-7  */
34*fa61ef6bSKonstantin Porotchkin 	u32	prolog_checksum;	/*  8-11 */
35*fa61ef6bSKonstantin Porotchkin 	u32	boot_image_size;	/* 12-15 */
36*fa61ef6bSKonstantin Porotchkin 	u32	boot_image_checksum;	/* 16-19 */
37*fa61ef6bSKonstantin Porotchkin 	u32	rsrvd0;			/* 20-23 */
38*fa61ef6bSKonstantin Porotchkin 	u32	load_addr;		/* 24-27 */
39*fa61ef6bSKonstantin Porotchkin 	u32	exec_addr;		/* 28-31 */
40*fa61ef6bSKonstantin Porotchkin 	u8	uart_cfg;		/*  32   */
41*fa61ef6bSKonstantin Porotchkin 	u8	baudrate;		/*  33   */
42*fa61ef6bSKonstantin Porotchkin 	u8	ext_count;		/*  34   */
43*fa61ef6bSKonstantin Porotchkin 	u8	aux_flags;		/*  35   */
44*fa61ef6bSKonstantin Porotchkin 	u32	io_arg_0;		/* 36-39 */
45*fa61ef6bSKonstantin Porotchkin 	u32	io_arg_1;		/* 40-43 */
46*fa61ef6bSKonstantin Porotchkin 	u32	io_arg_2;		/* 43-47 */
47*fa61ef6bSKonstantin Porotchkin 	u32	io_arg_3;		/* 48-51 */
48*fa61ef6bSKonstantin Porotchkin 	u32	rsrvd1;			/* 52-55 */
49*fa61ef6bSKonstantin Porotchkin 	u32	rsrvd2;			/* 56-59 */
50*fa61ef6bSKonstantin Porotchkin 	u32	rsrvd3;			/* 60-63 */
51*fa61ef6bSKonstantin Porotchkin };
52*fa61ef6bSKonstantin Porotchkin #elif defined(CONFIG_ARMADA_3700)	/* A3700 */
53*fa61ef6bSKonstantin Porotchkin #define HASH_SUM_LEN		16
54*fa61ef6bSKonstantin Porotchkin #define IMAGE_VERSION_3_6_0	0x030600
55*fa61ef6bSKonstantin Porotchkin #define IMAGE_VERSION_3_5_0	0x030500
56*fa61ef6bSKonstantin Porotchkin 
57*fa61ef6bSKonstantin Porotchkin struct common_tim_data {
58*fa61ef6bSKonstantin Porotchkin 	u32	version;
59*fa61ef6bSKonstantin Porotchkin 	u32	identifier;
60*fa61ef6bSKonstantin Porotchkin 	u32	trusted;
61*fa61ef6bSKonstantin Porotchkin 	u32	issue_date;
62*fa61ef6bSKonstantin Porotchkin 	u32	oem_unique_id;
63*fa61ef6bSKonstantin Porotchkin 	u32	reserved[5];		/* Reserve 20 bytes */
64*fa61ef6bSKonstantin Porotchkin 	u32	boot_flash_sign;
65*fa61ef6bSKonstantin Porotchkin 	u32	num_images;
66*fa61ef6bSKonstantin Porotchkin 	u32	num_keys;
67*fa61ef6bSKonstantin Porotchkin 	u32	size_of_reserved;
68*fa61ef6bSKonstantin Porotchkin };
69*fa61ef6bSKonstantin Porotchkin 
70*fa61ef6bSKonstantin Porotchkin struct mvebu_image_info {
71*fa61ef6bSKonstantin Porotchkin 	u32	image_id;
72*fa61ef6bSKonstantin Porotchkin 	u32	next_image_id;
73*fa61ef6bSKonstantin Porotchkin 	u32	flash_entry_addr;
74*fa61ef6bSKonstantin Porotchkin 	u32	load_addr;
75*fa61ef6bSKonstantin Porotchkin 	u32	image_size;
76*fa61ef6bSKonstantin Porotchkin 	u32	image_size_to_hash;
77*fa61ef6bSKonstantin Porotchkin 	u32	hash_algorithm_id;
78*fa61ef6bSKonstantin Porotchkin 	u32	hash[HASH_SUM_LEN];	/* Reserve 512 bits for the hash */
79*fa61ef6bSKonstantin Porotchkin 	u32	partition_number;
80*fa61ef6bSKonstantin Porotchkin 	u32	enc_algorithm_id;
81*fa61ef6bSKonstantin Porotchkin 	u32	encrypt_start_offset;
82*fa61ef6bSKonstantin Porotchkin 	u32	encrypt_size;
83*fa61ef6bSKonstantin Porotchkin };
84*fa61ef6bSKonstantin Porotchkin #endif /* CONFIG_ARMADA_XXX */
85*fa61ef6bSKonstantin Porotchkin 
86*fa61ef6bSKonstantin Porotchkin struct bubt_dev {
87*fa61ef6bSKonstantin Porotchkin 	char name[8];
88*fa61ef6bSKonstantin Porotchkin 	size_t (*read)(const char *file_name);
89*fa61ef6bSKonstantin Porotchkin 	int (*write)(size_t image_size);
90*fa61ef6bSKonstantin Porotchkin 	int (*active)(void);
91*fa61ef6bSKonstantin Porotchkin };
92*fa61ef6bSKonstantin Porotchkin 
93*fa61ef6bSKonstantin Porotchkin static ulong get_load_addr(void)
94*fa61ef6bSKonstantin Porotchkin {
95*fa61ef6bSKonstantin Porotchkin 	const char *addr_str;
96*fa61ef6bSKonstantin Porotchkin 	unsigned long addr;
97*fa61ef6bSKonstantin Porotchkin 
98*fa61ef6bSKonstantin Porotchkin 	addr_str = getenv("loadaddr");
99*fa61ef6bSKonstantin Porotchkin 	if (addr_str)
100*fa61ef6bSKonstantin Porotchkin 		addr = simple_strtoul(addr_str, NULL, 16);
101*fa61ef6bSKonstantin Porotchkin 	else
102*fa61ef6bSKonstantin Porotchkin 		addr = CONFIG_SYS_LOAD_ADDR;
103*fa61ef6bSKonstantin Porotchkin 
104*fa61ef6bSKonstantin Porotchkin 	return addr;
105*fa61ef6bSKonstantin Porotchkin }
106*fa61ef6bSKonstantin Porotchkin 
107*fa61ef6bSKonstantin Porotchkin /********************************************************************
108*fa61ef6bSKonstantin Porotchkin  *     eMMC services
109*fa61ef6bSKonstantin Porotchkin  ********************************************************************/
110*fa61ef6bSKonstantin Porotchkin #ifdef CONFIG_DM_MMC
111*fa61ef6bSKonstantin Porotchkin static int mmc_burn_image(size_t image_size)
112*fa61ef6bSKonstantin Porotchkin {
113*fa61ef6bSKonstantin Porotchkin 	struct mmc	*mmc;
114*fa61ef6bSKonstantin Porotchkin 	lbaint_t	start_lba;
115*fa61ef6bSKonstantin Porotchkin 	lbaint_t	blk_count;
116*fa61ef6bSKonstantin Porotchkin 	ulong		blk_written;
117*fa61ef6bSKonstantin Porotchkin 	int		err;
118*fa61ef6bSKonstantin Porotchkin 	const u8	mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
119*fa61ef6bSKonstantin Porotchkin 
120*fa61ef6bSKonstantin Porotchkin 	mmc = find_mmc_device(mmc_dev_num);
121*fa61ef6bSKonstantin Porotchkin 	if (!mmc) {
122*fa61ef6bSKonstantin Porotchkin 		printf("No SD/MMC/eMMC card found\n");
123*fa61ef6bSKonstantin Porotchkin 		return -ENOMEDIUM;
124*fa61ef6bSKonstantin Porotchkin 	}
125*fa61ef6bSKonstantin Porotchkin 
126*fa61ef6bSKonstantin Porotchkin 	err = mmc_init(mmc);
127*fa61ef6bSKonstantin Porotchkin 	if (err) {
128*fa61ef6bSKonstantin Porotchkin 		printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
129*fa61ef6bSKonstantin Porotchkin 		       mmc_dev_num);
130*fa61ef6bSKonstantin Porotchkin 		return err;
131*fa61ef6bSKonstantin Porotchkin 	}
132*fa61ef6bSKonstantin Porotchkin 
133*fa61ef6bSKonstantin Porotchkin #ifdef CONFIG_SYS_MMC_ENV_PART
134*fa61ef6bSKonstantin Porotchkin 	if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART) {
135*fa61ef6bSKonstantin Porotchkin 		err = mmc_switch_part(mmc_dev_num, CONFIG_SYS_MMC_ENV_PART);
136*fa61ef6bSKonstantin Porotchkin 		if (err) {
137*fa61ef6bSKonstantin Porotchkin 			printf("MMC partition switch failed\n");
138*fa61ef6bSKonstantin Porotchkin 			return err;
139*fa61ef6bSKonstantin Porotchkin 		}
140*fa61ef6bSKonstantin Porotchkin 	}
141*fa61ef6bSKonstantin Porotchkin #endif
142*fa61ef6bSKonstantin Porotchkin 
143*fa61ef6bSKonstantin Porotchkin 	/* SD reserves LBA-0 for MBR and boots from LBA-1,
144*fa61ef6bSKonstantin Porotchkin 	 * MMC/eMMC boots from LBA-0
145*fa61ef6bSKonstantin Porotchkin 	 */
146*fa61ef6bSKonstantin Porotchkin 	start_lba = IS_SD(mmc) ? 1 : 0;
147*fa61ef6bSKonstantin Porotchkin 	blk_count = image_size / mmc->block_dev.blksz;
148*fa61ef6bSKonstantin Porotchkin 	if (image_size % mmc->block_dev.blksz)
149*fa61ef6bSKonstantin Porotchkin 		blk_count += 1;
150*fa61ef6bSKonstantin Porotchkin 
151*fa61ef6bSKonstantin Porotchkin 	blk_written = mmc->block_dev.block_write(mmc_dev_num,
152*fa61ef6bSKonstantin Porotchkin 						start_lba, blk_count,
153*fa61ef6bSKonstantin Porotchkin 						(void *)get_load_addr());
154*fa61ef6bSKonstantin Porotchkin 	if (blk_written != blk_count) {
155*fa61ef6bSKonstantin Porotchkin 		printf("Error - written %#lx blocks\n", blk_written);
156*fa61ef6bSKonstantin Porotchkin 		return -ENOSPC;
157*fa61ef6bSKonstantin Porotchkin 	}
158*fa61ef6bSKonstantin Porotchkin 	printf("Done!\n");
159*fa61ef6bSKonstantin Porotchkin 
160*fa61ef6bSKonstantin Porotchkin #ifdef CONFIG_SYS_MMC_ENV_PART
161*fa61ef6bSKonstantin Porotchkin 	if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART)
162*fa61ef6bSKonstantin Porotchkin 		mmc_switch_part(mmc_dev_num, mmc->part_num);
163*fa61ef6bSKonstantin Porotchkin #endif
164*fa61ef6bSKonstantin Porotchkin 
165*fa61ef6bSKonstantin Porotchkin 	return 0;
166*fa61ef6bSKonstantin Porotchkin }
167*fa61ef6bSKonstantin Porotchkin 
168*fa61ef6bSKonstantin Porotchkin static size_t mmc_read_file(const char *file_name)
169*fa61ef6bSKonstantin Porotchkin {
170*fa61ef6bSKonstantin Porotchkin 	loff_t		act_read = 0;
171*fa61ef6bSKonstantin Porotchkin 	int		rc;
172*fa61ef6bSKonstantin Porotchkin 	struct mmc	*mmc;
173*fa61ef6bSKonstantin Porotchkin 	const u8	mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
174*fa61ef6bSKonstantin Porotchkin 
175*fa61ef6bSKonstantin Porotchkin 	mmc = find_mmc_device(mmc_dev_num);
176*fa61ef6bSKonstantin Porotchkin 	if (!mmc) {
177*fa61ef6bSKonstantin Porotchkin 		printf("No SD/MMC/eMMC card found\n");
178*fa61ef6bSKonstantin Porotchkin 		return 0;
179*fa61ef6bSKonstantin Porotchkin 	}
180*fa61ef6bSKonstantin Porotchkin 
181*fa61ef6bSKonstantin Porotchkin 	if (mmc_init(mmc)) {
182*fa61ef6bSKonstantin Porotchkin 		printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
183*fa61ef6bSKonstantin Porotchkin 		       mmc_dev_num);
184*fa61ef6bSKonstantin Porotchkin 		return 0;
185*fa61ef6bSKonstantin Porotchkin 	}
186*fa61ef6bSKonstantin Porotchkin 
187*fa61ef6bSKonstantin Porotchkin 	/* Load from data partition (0) */
188*fa61ef6bSKonstantin Porotchkin 	if (fs_set_blk_dev("mmc", "0", FS_TYPE_ANY)) {
189*fa61ef6bSKonstantin Porotchkin 		printf("Error: MMC 0 not found\n");
190*fa61ef6bSKonstantin Porotchkin 		return 0;
191*fa61ef6bSKonstantin Porotchkin 	}
192*fa61ef6bSKonstantin Porotchkin 
193*fa61ef6bSKonstantin Porotchkin 	/* Perfrom file read */
194*fa61ef6bSKonstantin Porotchkin 	rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
195*fa61ef6bSKonstantin Porotchkin 	if (rc)
196*fa61ef6bSKonstantin Porotchkin 		return 0;
197*fa61ef6bSKonstantin Porotchkin 
198*fa61ef6bSKonstantin Porotchkin 	return act_read;
199*fa61ef6bSKonstantin Porotchkin }
200*fa61ef6bSKonstantin Porotchkin 
201*fa61ef6bSKonstantin Porotchkin static int is_mmc_active(void)
202*fa61ef6bSKonstantin Porotchkin {
203*fa61ef6bSKonstantin Porotchkin 	return 1;
204*fa61ef6bSKonstantin Porotchkin }
205*fa61ef6bSKonstantin Porotchkin #else /* CONFIG_DM_MMC */
206*fa61ef6bSKonstantin Porotchkin static int mmc_burn_image(size_t image_size)
207*fa61ef6bSKonstantin Porotchkin {
208*fa61ef6bSKonstantin Porotchkin 	return -ENODEV;
209*fa61ef6bSKonstantin Porotchkin }
210*fa61ef6bSKonstantin Porotchkin 
211*fa61ef6bSKonstantin Porotchkin static size_t mmc_read_file(const char *file_name)
212*fa61ef6bSKonstantin Porotchkin {
213*fa61ef6bSKonstantin Porotchkin 	return 0;
214*fa61ef6bSKonstantin Porotchkin }
215*fa61ef6bSKonstantin Porotchkin 
216*fa61ef6bSKonstantin Porotchkin static int is_mmc_active(void)
217*fa61ef6bSKonstantin Porotchkin {
218*fa61ef6bSKonstantin Porotchkin 	return 0;
219*fa61ef6bSKonstantin Porotchkin }
220*fa61ef6bSKonstantin Porotchkin #endif /* CONFIG_DM_MMC */
221*fa61ef6bSKonstantin Porotchkin 
222*fa61ef6bSKonstantin Porotchkin /********************************************************************
223*fa61ef6bSKonstantin Porotchkin  *     SPI services
224*fa61ef6bSKonstantin Porotchkin  ********************************************************************/
225*fa61ef6bSKonstantin Porotchkin #ifdef CONFIG_SPI_FLASH
226*fa61ef6bSKonstantin Porotchkin static int spi_burn_image(size_t image_size)
227*fa61ef6bSKonstantin Porotchkin {
228*fa61ef6bSKonstantin Porotchkin 	int ret;
229*fa61ef6bSKonstantin Porotchkin 	struct spi_flash *flash;
230*fa61ef6bSKonstantin Porotchkin 	u32 erase_bytes;
231*fa61ef6bSKonstantin Porotchkin 
232*fa61ef6bSKonstantin Porotchkin 	/* Probe the SPI bus to get the flash device */
233*fa61ef6bSKonstantin Porotchkin 	flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
234*fa61ef6bSKonstantin Porotchkin 				CONFIG_ENV_SPI_CS,
235*fa61ef6bSKonstantin Porotchkin 				CONFIG_SF_DEFAULT_SPEED,
236*fa61ef6bSKonstantin Porotchkin 				CONFIG_SF_DEFAULT_MODE);
237*fa61ef6bSKonstantin Porotchkin 	if (!flash) {
238*fa61ef6bSKonstantin Porotchkin 		printf("Failed to probe SPI Flash\n");
239*fa61ef6bSKonstantin Porotchkin 		return -ENOMEDIUM;
240*fa61ef6bSKonstantin Porotchkin 	}
241*fa61ef6bSKonstantin Porotchkin 
242*fa61ef6bSKonstantin Porotchkin #ifdef CONFIG_SPI_FLASH_PROTECTION
243*fa61ef6bSKonstantin Porotchkin 	spi_flash_protect(flash, 0);
244*fa61ef6bSKonstantin Porotchkin #endif
245*fa61ef6bSKonstantin Porotchkin 	erase_bytes = image_size +
246*fa61ef6bSKonstantin Porotchkin 		(flash->erase_size - image_size % flash->erase_size);
247*fa61ef6bSKonstantin Porotchkin 	printf("Erasing %d bytes (%d blocks) at offset 0 ...",
248*fa61ef6bSKonstantin Porotchkin 	       erase_bytes, erase_bytes / flash->erase_size);
249*fa61ef6bSKonstantin Porotchkin 	ret = spi_flash_erase(flash, 0, erase_bytes);
250*fa61ef6bSKonstantin Porotchkin 	if (ret)
251*fa61ef6bSKonstantin Porotchkin 		printf("Error!\n");
252*fa61ef6bSKonstantin Porotchkin 	else
253*fa61ef6bSKonstantin Porotchkin 		printf("Done!\n");
254*fa61ef6bSKonstantin Porotchkin 
255*fa61ef6bSKonstantin Porotchkin 	printf("Writing %d bytes from 0x%lx to offset 0 ...",
256*fa61ef6bSKonstantin Porotchkin 	       (int)image_size, get_load_addr());
257*fa61ef6bSKonstantin Porotchkin 	ret = spi_flash_write(flash, 0, image_size, (void *)get_load_addr());
258*fa61ef6bSKonstantin Porotchkin 	if (ret)
259*fa61ef6bSKonstantin Porotchkin 		printf("Error!\n");
260*fa61ef6bSKonstantin Porotchkin 	else
261*fa61ef6bSKonstantin Porotchkin 		printf("Done!\n");
262*fa61ef6bSKonstantin Porotchkin 
263*fa61ef6bSKonstantin Porotchkin #ifdef CONFIG_SPI_FLASH_PROTECTION
264*fa61ef6bSKonstantin Porotchkin 	spi_flash_protect(flash, 1);
265*fa61ef6bSKonstantin Porotchkin #endif
266*fa61ef6bSKonstantin Porotchkin 
267*fa61ef6bSKonstantin Porotchkin 	return ret;
268*fa61ef6bSKonstantin Porotchkin }
269*fa61ef6bSKonstantin Porotchkin 
270*fa61ef6bSKonstantin Porotchkin static int is_spi_active(void)
271*fa61ef6bSKonstantin Porotchkin {
272*fa61ef6bSKonstantin Porotchkin 	return 1;
273*fa61ef6bSKonstantin Porotchkin }
274*fa61ef6bSKonstantin Porotchkin 
275*fa61ef6bSKonstantin Porotchkin #else /* CONFIG_SPI_FLASH */
276*fa61ef6bSKonstantin Porotchkin static int spi_burn_image(size_t image_size)
277*fa61ef6bSKonstantin Porotchkin {
278*fa61ef6bSKonstantin Porotchkin 	return -ENODEV;
279*fa61ef6bSKonstantin Porotchkin }
280*fa61ef6bSKonstantin Porotchkin 
281*fa61ef6bSKonstantin Porotchkin static int is_spi_active(void)
282*fa61ef6bSKonstantin Porotchkin {
283*fa61ef6bSKonstantin Porotchkin 	return 0;
284*fa61ef6bSKonstantin Porotchkin }
285*fa61ef6bSKonstantin Porotchkin #endif /* CONFIG_SPI_FLASH */
286*fa61ef6bSKonstantin Porotchkin 
287*fa61ef6bSKonstantin Porotchkin /********************************************************************
288*fa61ef6bSKonstantin Porotchkin  *     NAND services
289*fa61ef6bSKonstantin Porotchkin  ********************************************************************/
290*fa61ef6bSKonstantin Porotchkin #ifdef CONFIG_CMD_NAND
291*fa61ef6bSKonstantin Porotchkin static int nand_burn_image(size_t image_size)
292*fa61ef6bSKonstantin Porotchkin {
293*fa61ef6bSKonstantin Porotchkin 	int ret, block_size;
294*fa61ef6bSKonstantin Porotchkin 	nand_info_t *nand;
295*fa61ef6bSKonstantin Porotchkin 	int dev = nand_curr_device;
296*fa61ef6bSKonstantin Porotchkin 
297*fa61ef6bSKonstantin Porotchkin 	if ((dev < 0) || (dev >= CONFIG_SYS_MAX_NAND_DEVICE) ||
298*fa61ef6bSKonstantin Porotchkin 	    (!nand_info[dev].name)) {
299*fa61ef6bSKonstantin Porotchkin 		puts("\nno devices available\n");
300*fa61ef6bSKonstantin Porotchkin 		return -ENOMEDIUM;
301*fa61ef6bSKonstantin Porotchkin 	}
302*fa61ef6bSKonstantin Porotchkin 	nand = &nand_info[dev];
303*fa61ef6bSKonstantin Porotchkin 	block_size = nand->erasesize;
304*fa61ef6bSKonstantin Porotchkin 
305*fa61ef6bSKonstantin Porotchkin 	/* Align U-Boot size to currently used blocksize */
306*fa61ef6bSKonstantin Porotchkin 	image_size = ((image_size + (block_size - 1)) & (~(block_size - 1)));
307*fa61ef6bSKonstantin Porotchkin 
308*fa61ef6bSKonstantin Porotchkin 	/* Erase the U-BOOT image space */
309*fa61ef6bSKonstantin Porotchkin 	printf("Erasing 0x%x - 0x%x:...", 0, (int)image_size);
310*fa61ef6bSKonstantin Porotchkin 	ret = nand_erase(nand, 0, image_size);
311*fa61ef6bSKonstantin Porotchkin 	if (ret) {
312*fa61ef6bSKonstantin Porotchkin 		printf("Error!\n");
313*fa61ef6bSKonstantin Porotchkin 		goto error;
314*fa61ef6bSKonstantin Porotchkin 	}
315*fa61ef6bSKonstantin Porotchkin 	printf("Done!\n");
316*fa61ef6bSKonstantin Porotchkin 
317*fa61ef6bSKonstantin Porotchkin 	/* Write the image to flash */
318*fa61ef6bSKonstantin Porotchkin 	printf("Writing image:...");
319*fa61ef6bSKonstantin Porotchkin 	printf("&image_size = 0x%p\n", (void *)&image_size);
320*fa61ef6bSKonstantin Porotchkin 	ret = nand_write(nand, 0, &image_size, (void *)get_load_addr());
321*fa61ef6bSKonstantin Porotchkin 	if (ret)
322*fa61ef6bSKonstantin Porotchkin 		printf("Error!\n");
323*fa61ef6bSKonstantin Porotchkin 	else
324*fa61ef6bSKonstantin Porotchkin 		printf("Done!\n");
325*fa61ef6bSKonstantin Porotchkin 
326*fa61ef6bSKonstantin Porotchkin error:
327*fa61ef6bSKonstantin Porotchkin 	return ret;
328*fa61ef6bSKonstantin Porotchkin }
329*fa61ef6bSKonstantin Porotchkin 
330*fa61ef6bSKonstantin Porotchkin static int is_nand_active(void)
331*fa61ef6bSKonstantin Porotchkin {
332*fa61ef6bSKonstantin Porotchkin 	return 1;
333*fa61ef6bSKonstantin Porotchkin }
334*fa61ef6bSKonstantin Porotchkin 
335*fa61ef6bSKonstantin Porotchkin #else /* CONFIG_CMD_NAND */
336*fa61ef6bSKonstantin Porotchkin static int nand_burn_image(size_t image_size)
337*fa61ef6bSKonstantin Porotchkin {
338*fa61ef6bSKonstantin Porotchkin 	return -ENODEV;
339*fa61ef6bSKonstantin Porotchkin }
340*fa61ef6bSKonstantin Porotchkin 
341*fa61ef6bSKonstantin Porotchkin static int is_nand_active(void)
342*fa61ef6bSKonstantin Porotchkin {
343*fa61ef6bSKonstantin Porotchkin 	return 0;
344*fa61ef6bSKonstantin Porotchkin }
345*fa61ef6bSKonstantin Porotchkin #endif /* CONFIG_CMD_NAND */
346*fa61ef6bSKonstantin Porotchkin 
347*fa61ef6bSKonstantin Porotchkin /********************************************************************
348*fa61ef6bSKonstantin Porotchkin  *     USB services
349*fa61ef6bSKonstantin Porotchkin  ********************************************************************/
350*fa61ef6bSKonstantin Porotchkin #if defined(CONFIG_USB_STORAGE) && defined(CONFIG_BLK)
351*fa61ef6bSKonstantin Porotchkin static size_t usb_read_file(const char *file_name)
352*fa61ef6bSKonstantin Porotchkin {
353*fa61ef6bSKonstantin Porotchkin 	loff_t act_read = 0;
354*fa61ef6bSKonstantin Porotchkin 	struct udevice *dev;
355*fa61ef6bSKonstantin Porotchkin 	int rc;
356*fa61ef6bSKonstantin Porotchkin 
357*fa61ef6bSKonstantin Porotchkin 	usb_stop();
358*fa61ef6bSKonstantin Porotchkin 
359*fa61ef6bSKonstantin Porotchkin 	if (usb_init() < 0) {
360*fa61ef6bSKonstantin Porotchkin 		printf("Error: usb_init failed\n");
361*fa61ef6bSKonstantin Porotchkin 		return 0;
362*fa61ef6bSKonstantin Porotchkin 	}
363*fa61ef6bSKonstantin Porotchkin 
364*fa61ef6bSKonstantin Porotchkin 	/* Try to recognize storage devices immediately */
365*fa61ef6bSKonstantin Porotchkin 	blk_first_device(IF_TYPE_USB, &dev);
366*fa61ef6bSKonstantin Porotchkin 	if (!dev) {
367*fa61ef6bSKonstantin Porotchkin 		printf("Error: USB storage device not found\n");
368*fa61ef6bSKonstantin Porotchkin 		return 0;
369*fa61ef6bSKonstantin Porotchkin 	}
370*fa61ef6bSKonstantin Porotchkin 
371*fa61ef6bSKonstantin Porotchkin 	/* Always load from usb 0 */
372*fa61ef6bSKonstantin Porotchkin 	if (fs_set_blk_dev("usb", "0", FS_TYPE_ANY)) {
373*fa61ef6bSKonstantin Porotchkin 		printf("Error: USB 0 not found\n");
374*fa61ef6bSKonstantin Porotchkin 		return 0;
375*fa61ef6bSKonstantin Porotchkin 	}
376*fa61ef6bSKonstantin Porotchkin 
377*fa61ef6bSKonstantin Porotchkin 	/* Perfrom file read */
378*fa61ef6bSKonstantin Porotchkin 	rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
379*fa61ef6bSKonstantin Porotchkin 	if (rc)
380*fa61ef6bSKonstantin Porotchkin 		return 0;
381*fa61ef6bSKonstantin Porotchkin 
382*fa61ef6bSKonstantin Porotchkin 	return act_read;
383*fa61ef6bSKonstantin Porotchkin }
384*fa61ef6bSKonstantin Porotchkin 
385*fa61ef6bSKonstantin Porotchkin static int is_usb_active(void)
386*fa61ef6bSKonstantin Porotchkin {
387*fa61ef6bSKonstantin Porotchkin 	return 1;
388*fa61ef6bSKonstantin Porotchkin }
389*fa61ef6bSKonstantin Porotchkin 
390*fa61ef6bSKonstantin Porotchkin #else /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */
391*fa61ef6bSKonstantin Porotchkin static size_t usb_read_file(const char *file_name)
392*fa61ef6bSKonstantin Porotchkin {
393*fa61ef6bSKonstantin Porotchkin 	return 0;
394*fa61ef6bSKonstantin Porotchkin }
395*fa61ef6bSKonstantin Porotchkin 
396*fa61ef6bSKonstantin Porotchkin static int is_usb_active(void)
397*fa61ef6bSKonstantin Porotchkin {
398*fa61ef6bSKonstantin Porotchkin 	return 0;
399*fa61ef6bSKonstantin Porotchkin }
400*fa61ef6bSKonstantin Porotchkin #endif /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */
401*fa61ef6bSKonstantin Porotchkin 
402*fa61ef6bSKonstantin Porotchkin /********************************************************************
403*fa61ef6bSKonstantin Porotchkin  *     Network services
404*fa61ef6bSKonstantin Porotchkin  ********************************************************************/
405*fa61ef6bSKonstantin Porotchkin #ifdef CONFIG_CMD_NET
406*fa61ef6bSKonstantin Porotchkin static size_t tftp_read_file(const char *file_name)
407*fa61ef6bSKonstantin Porotchkin {
408*fa61ef6bSKonstantin Porotchkin 	/* update global variable load_addr before tftp file from network */
409*fa61ef6bSKonstantin Porotchkin 	load_addr = get_load_addr();
410*fa61ef6bSKonstantin Porotchkin 	return net_loop(TFTPGET);
411*fa61ef6bSKonstantin Porotchkin }
412*fa61ef6bSKonstantin Porotchkin 
413*fa61ef6bSKonstantin Porotchkin static int is_tftp_active(void)
414*fa61ef6bSKonstantin Porotchkin {
415*fa61ef6bSKonstantin Porotchkin 	return 1;
416*fa61ef6bSKonstantin Porotchkin }
417*fa61ef6bSKonstantin Porotchkin 
418*fa61ef6bSKonstantin Porotchkin #else
419*fa61ef6bSKonstantin Porotchkin static size_t tftp_read_file(const char *file_name)
420*fa61ef6bSKonstantin Porotchkin {
421*fa61ef6bSKonstantin Porotchkin 	return 0;
422*fa61ef6bSKonstantin Porotchkin }
423*fa61ef6bSKonstantin Porotchkin 
424*fa61ef6bSKonstantin Porotchkin static int is_tftp_active(void)
425*fa61ef6bSKonstantin Porotchkin {
426*fa61ef6bSKonstantin Porotchkin 	return 0;
427*fa61ef6bSKonstantin Porotchkin }
428*fa61ef6bSKonstantin Porotchkin #endif /* CONFIG_CMD_NET */
429*fa61ef6bSKonstantin Porotchkin 
430*fa61ef6bSKonstantin Porotchkin enum bubt_devices {
431*fa61ef6bSKonstantin Porotchkin 	BUBT_DEV_NET = 0,
432*fa61ef6bSKonstantin Porotchkin 	BUBT_DEV_USB,
433*fa61ef6bSKonstantin Porotchkin 	BUBT_DEV_MMC,
434*fa61ef6bSKonstantin Porotchkin 	BUBT_DEV_SPI,
435*fa61ef6bSKonstantin Porotchkin 	BUBT_DEV_NAND,
436*fa61ef6bSKonstantin Porotchkin 
437*fa61ef6bSKonstantin Porotchkin 	BUBT_MAX_DEV
438*fa61ef6bSKonstantin Porotchkin };
439*fa61ef6bSKonstantin Porotchkin 
440*fa61ef6bSKonstantin Porotchkin struct bubt_dev bubt_devs[BUBT_MAX_DEV] = {
441*fa61ef6bSKonstantin Porotchkin 	{"tftp", tftp_read_file, NULL, is_tftp_active},
442*fa61ef6bSKonstantin Porotchkin 	{"usb",  usb_read_file,  NULL, is_usb_active},
443*fa61ef6bSKonstantin Porotchkin 	{"mmc",  mmc_read_file,  mmc_burn_image, is_mmc_active},
444*fa61ef6bSKonstantin Porotchkin 	{"spi",  NULL, spi_burn_image,  is_spi_active},
445*fa61ef6bSKonstantin Porotchkin 	{"nand", NULL, nand_burn_image, is_nand_active},
446*fa61ef6bSKonstantin Porotchkin };
447*fa61ef6bSKonstantin Porotchkin 
448*fa61ef6bSKonstantin Porotchkin static int bubt_write_file(struct bubt_dev *dst, size_t image_size)
449*fa61ef6bSKonstantin Porotchkin {
450*fa61ef6bSKonstantin Porotchkin 	if (!dst->write) {
451*fa61ef6bSKonstantin Porotchkin 		printf("Error: Write not supported on device %s\n", dst->name);
452*fa61ef6bSKonstantin Porotchkin 		return -ENOTSUPP;
453*fa61ef6bSKonstantin Porotchkin 	}
454*fa61ef6bSKonstantin Porotchkin 
455*fa61ef6bSKonstantin Porotchkin 	return dst->write(image_size);
456*fa61ef6bSKonstantin Porotchkin }
457*fa61ef6bSKonstantin Porotchkin 
458*fa61ef6bSKonstantin Porotchkin #if defined(CONFIG_ARMADA_8K)
459*fa61ef6bSKonstantin Porotchkin u32 do_checksum32(u32 *start, int32_t len)
460*fa61ef6bSKonstantin Porotchkin {
461*fa61ef6bSKonstantin Porotchkin 	u32 sum = 0;
462*fa61ef6bSKonstantin Porotchkin 	u32 *startp = start;
463*fa61ef6bSKonstantin Porotchkin 
464*fa61ef6bSKonstantin Porotchkin 	do {
465*fa61ef6bSKonstantin Porotchkin 		sum += *startp;
466*fa61ef6bSKonstantin Porotchkin 		startp++;
467*fa61ef6bSKonstantin Porotchkin 		len -= 4;
468*fa61ef6bSKonstantin Porotchkin 	} while (len > 0);
469*fa61ef6bSKonstantin Porotchkin 
470*fa61ef6bSKonstantin Porotchkin 	return sum;
471*fa61ef6bSKonstantin Porotchkin }
472*fa61ef6bSKonstantin Porotchkin 
473*fa61ef6bSKonstantin Porotchkin static int check_image_header(void)
474*fa61ef6bSKonstantin Porotchkin {
475*fa61ef6bSKonstantin Porotchkin 	struct mvebu_image_header *hdr =
476*fa61ef6bSKonstantin Porotchkin 			(struct mvebu_image_header *)get_load_addr();
477*fa61ef6bSKonstantin Porotchkin 	u32 header_len = hdr->prolog_size;
478*fa61ef6bSKonstantin Porotchkin 	u32 checksum;
479*fa61ef6bSKonstantin Porotchkin 	u32 checksum_ref = hdr->prolog_checksum;
480*fa61ef6bSKonstantin Porotchkin 
481*fa61ef6bSKonstantin Porotchkin 	/*
482*fa61ef6bSKonstantin Porotchkin 	 * For now compare checksum, and magic. Later we can
483*fa61ef6bSKonstantin Porotchkin 	 * verify more stuff on the header like interface type, etc
484*fa61ef6bSKonstantin Porotchkin 	 */
485*fa61ef6bSKonstantin Porotchkin 	if (hdr->magic != MAIN_HDR_MAGIC) {
486*fa61ef6bSKonstantin Porotchkin 		printf("ERROR: Bad MAGIC 0x%08x != 0x%08x\n",
487*fa61ef6bSKonstantin Porotchkin 		       hdr->magic, MAIN_HDR_MAGIC);
488*fa61ef6bSKonstantin Porotchkin 		return -ENOEXEC;
489*fa61ef6bSKonstantin Porotchkin 	}
490*fa61ef6bSKonstantin Porotchkin 
491*fa61ef6bSKonstantin Porotchkin 	/* The checksum value is discarded from checksum calculation */
492*fa61ef6bSKonstantin Porotchkin 	hdr->prolog_checksum = 0;
493*fa61ef6bSKonstantin Porotchkin 
494*fa61ef6bSKonstantin Porotchkin 	checksum = do_checksum32((u32 *)hdr, header_len);
495*fa61ef6bSKonstantin Porotchkin 	if (checksum != checksum_ref) {
496*fa61ef6bSKonstantin Porotchkin 		printf("Error: Bad Image checksum. 0x%x != 0x%x\n",
497*fa61ef6bSKonstantin Porotchkin 		       checksum, checksum_ref);
498*fa61ef6bSKonstantin Porotchkin 		return -ENOEXEC;
499*fa61ef6bSKonstantin Porotchkin 	}
500*fa61ef6bSKonstantin Porotchkin 
501*fa61ef6bSKonstantin Porotchkin 	/* Restore the checksum before writing */
502*fa61ef6bSKonstantin Porotchkin 	hdr->prolog_checksum = checksum_ref;
503*fa61ef6bSKonstantin Porotchkin 	printf("Image checksum...OK!\n");
504*fa61ef6bSKonstantin Porotchkin 
505*fa61ef6bSKonstantin Porotchkin 	return 0;
506*fa61ef6bSKonstantin Porotchkin }
507*fa61ef6bSKonstantin Porotchkin #elif defined(CONFIG_ARMADA_3700) /* Armada 3700 */
508*fa61ef6bSKonstantin Porotchkin static int check_image_header(void)
509*fa61ef6bSKonstantin Porotchkin {
510*fa61ef6bSKonstantin Porotchkin 	struct common_tim_data *hdr = (struct common_tim_data *)get_load_addr();
511*fa61ef6bSKonstantin Porotchkin 	int image_num;
512*fa61ef6bSKonstantin Porotchkin 	u8 hash_160_output[SHA1_SUM_LEN];
513*fa61ef6bSKonstantin Porotchkin 	u8 hash_256_output[SHA256_SUM_LEN];
514*fa61ef6bSKonstantin Porotchkin 	sha1_context hash1_text;
515*fa61ef6bSKonstantin Porotchkin 	sha256_context hash256_text;
516*fa61ef6bSKonstantin Porotchkin 	u8 *hash_output;
517*fa61ef6bSKonstantin Porotchkin 	u32 hash_algorithm_id;
518*fa61ef6bSKonstantin Porotchkin 	u32 image_size_to_hash;
519*fa61ef6bSKonstantin Porotchkin 	u32 flash_entry_addr;
520*fa61ef6bSKonstantin Porotchkin 	u32 *hash_value;
521*fa61ef6bSKonstantin Porotchkin 	u32 internal_hash[HASH_SUM_LEN];
522*fa61ef6bSKonstantin Porotchkin 	const u8 *buff;
523*fa61ef6bSKonstantin Porotchkin 	u32 num_of_image = hdr->num_images;
524*fa61ef6bSKonstantin Porotchkin 	u32 version = hdr->version;
525*fa61ef6bSKonstantin Porotchkin 	u32 trusted = hdr->trusted;
526*fa61ef6bSKonstantin Porotchkin 
527*fa61ef6bSKonstantin Porotchkin 	/* bubt checksum validation only supports nontrusted images */
528*fa61ef6bSKonstantin Porotchkin 	if (trusted == 1) {
529*fa61ef6bSKonstantin Porotchkin 		printf("bypass image validation, ");
530*fa61ef6bSKonstantin Porotchkin 		printf("only untrusted image is supported now\n");
531*fa61ef6bSKonstantin Porotchkin 		return 0;
532*fa61ef6bSKonstantin Porotchkin 	}
533*fa61ef6bSKonstantin Porotchkin 	/* only supports image version 3.5 and 3.6 */
534*fa61ef6bSKonstantin Porotchkin 	if (version != IMAGE_VERSION_3_5_0 && version != IMAGE_VERSION_3_6_0) {
535*fa61ef6bSKonstantin Porotchkin 		printf("Error: Unsupported Image version = 0x%08x\n", version);
536*fa61ef6bSKonstantin Porotchkin 		return -ENOEXEC;
537*fa61ef6bSKonstantin Porotchkin 	}
538*fa61ef6bSKonstantin Porotchkin 	/* validate images hash value */
539*fa61ef6bSKonstantin Porotchkin 	for (image_num = 0; image_num < num_of_image; image_num++) {
540*fa61ef6bSKonstantin Porotchkin 		struct mvebu_image_info *info =
541*fa61ef6bSKonstantin Porotchkin 				(struct mvebu_image_info *)(get_load_addr() +
542*fa61ef6bSKonstantin Porotchkin 				sizeof(struct common_tim_data) +
543*fa61ef6bSKonstantin Porotchkin 				image_num * sizeof(struct mvebu_image_info));
544*fa61ef6bSKonstantin Porotchkin 		hash_algorithm_id = info->hash_algorithm_id;
545*fa61ef6bSKonstantin Porotchkin 		image_size_to_hash = info->image_size_to_hash;
546*fa61ef6bSKonstantin Porotchkin 		flash_entry_addr = info->flash_entry_addr;
547*fa61ef6bSKonstantin Porotchkin 		hash_value = info->hash;
548*fa61ef6bSKonstantin Porotchkin 		buff = (const u8 *)(get_load_addr() + flash_entry_addr);
549*fa61ef6bSKonstantin Porotchkin 
550*fa61ef6bSKonstantin Porotchkin 		if (image_num == 0) {
551*fa61ef6bSKonstantin Porotchkin 			/*
552*fa61ef6bSKonstantin Porotchkin 			 * The first image includes hash values in its content.
553*fa61ef6bSKonstantin Porotchkin 			 * For hash calculation, we need to save the original
554*fa61ef6bSKonstantin Porotchkin 			 * hash values to a local variable that will be
555*fa61ef6bSKonstantin Porotchkin 			 * copied back for comparsion and set all zeros to
556*fa61ef6bSKonstantin Porotchkin 			 * the orignal hash values for calculating new value.
557*fa61ef6bSKonstantin Porotchkin 			 * First image original format :
558*fa61ef6bSKonstantin Porotchkin 			 * x...x (datum1) x...x(orig. hash values) x...x(datum2)
559*fa61ef6bSKonstantin Porotchkin 			 * Replaced first image format :
560*fa61ef6bSKonstantin Porotchkin 			 * x...x (datum1) 0...0(hash values) x...x(datum2)
561*fa61ef6bSKonstantin Porotchkin 			 */
562*fa61ef6bSKonstantin Porotchkin 			memcpy(internal_hash, hash_value,
563*fa61ef6bSKonstantin Porotchkin 			       sizeof(internal_hash));
564*fa61ef6bSKonstantin Porotchkin 			memset(hash_value, 0, sizeof(internal_hash));
565*fa61ef6bSKonstantin Porotchkin 		}
566*fa61ef6bSKonstantin Porotchkin 		if (image_size_to_hash == 0) {
567*fa61ef6bSKonstantin Porotchkin 			printf("Warning: Image_%d hash checksum is disabled, ",
568*fa61ef6bSKonstantin Porotchkin 			       image_num);
569*fa61ef6bSKonstantin Porotchkin 			printf("skip the image validation.\n");
570*fa61ef6bSKonstantin Porotchkin 			continue;
571*fa61ef6bSKonstantin Porotchkin 		}
572*fa61ef6bSKonstantin Porotchkin 		switch (hash_algorithm_id) {
573*fa61ef6bSKonstantin Porotchkin 		case SHA1_SUM_LEN:
574*fa61ef6bSKonstantin Porotchkin 			sha1_starts(&hash1_text);
575*fa61ef6bSKonstantin Porotchkin 			sha1_update(&hash1_text, buff, image_size_to_hash);
576*fa61ef6bSKonstantin Porotchkin 			sha1_finish(&hash1_text, hash_160_output);
577*fa61ef6bSKonstantin Porotchkin 			hash_output = hash_160_output;
578*fa61ef6bSKonstantin Porotchkin 			break;
579*fa61ef6bSKonstantin Porotchkin 		case SHA256_SUM_LEN:
580*fa61ef6bSKonstantin Porotchkin 			sha256_starts(&hash256_text);
581*fa61ef6bSKonstantin Porotchkin 			sha256_update(&hash256_text, buff, image_size_to_hash);
582*fa61ef6bSKonstantin Porotchkin 			sha256_finish(&hash256_text, hash_256_output);
583*fa61ef6bSKonstantin Porotchkin 			hash_output = hash_256_output;
584*fa61ef6bSKonstantin Porotchkin 			break;
585*fa61ef6bSKonstantin Porotchkin 		default:
586*fa61ef6bSKonstantin Porotchkin 			printf("Error: Unsupported hash_algorithm_id = %d\n",
587*fa61ef6bSKonstantin Porotchkin 			       hash_algorithm_id);
588*fa61ef6bSKonstantin Porotchkin 			return -ENOEXEC;
589*fa61ef6bSKonstantin Porotchkin 		}
590*fa61ef6bSKonstantin Porotchkin 		if (image_num == 0)
591*fa61ef6bSKonstantin Porotchkin 			memcpy(hash_value, internal_hash,
592*fa61ef6bSKonstantin Porotchkin 			       sizeof(internal_hash));
593*fa61ef6bSKonstantin Porotchkin 		if (memcmp(hash_value, hash_output, hash_algorithm_id) != 0) {
594*fa61ef6bSKonstantin Porotchkin 			printf("Error: Image_%d checksum is not correct\n",
595*fa61ef6bSKonstantin Porotchkin 			       image_num);
596*fa61ef6bSKonstantin Porotchkin 			return -ENOEXEC;
597*fa61ef6bSKonstantin Porotchkin 		}
598*fa61ef6bSKonstantin Porotchkin 	}
599*fa61ef6bSKonstantin Porotchkin 	printf("Image checksum...OK!\n");
600*fa61ef6bSKonstantin Porotchkin 
601*fa61ef6bSKonstantin Porotchkin 	return 0;
602*fa61ef6bSKonstantin Porotchkin }
603*fa61ef6bSKonstantin Porotchkin 
604*fa61ef6bSKonstantin Porotchkin #else /* Not ARMADA? */
605*fa61ef6bSKonstantin Porotchkin static int check_image_header(void)
606*fa61ef6bSKonstantin Porotchkin {
607*fa61ef6bSKonstantin Porotchkin 	printf("bubt cmd does not support this SoC device or family!\n");
608*fa61ef6bSKonstantin Porotchkin 	return -ENOEXEC;
609*fa61ef6bSKonstantin Porotchkin }
610*fa61ef6bSKonstantin Porotchkin #endif
611*fa61ef6bSKonstantin Porotchkin 
612*fa61ef6bSKonstantin Porotchkin static int bubt_verify(size_t image_size)
613*fa61ef6bSKonstantin Porotchkin {
614*fa61ef6bSKonstantin Porotchkin 	int err;
615*fa61ef6bSKonstantin Porotchkin 
616*fa61ef6bSKonstantin Porotchkin 	/* Check a correct image header exists */
617*fa61ef6bSKonstantin Porotchkin 	err = check_image_header();
618*fa61ef6bSKonstantin Porotchkin 	if (err) {
619*fa61ef6bSKonstantin Porotchkin 		printf("Error: Image header verification failed\n");
620*fa61ef6bSKonstantin Porotchkin 		return err;
621*fa61ef6bSKonstantin Porotchkin 	}
622*fa61ef6bSKonstantin Porotchkin 
623*fa61ef6bSKonstantin Porotchkin 	return 0;
624*fa61ef6bSKonstantin Porotchkin }
625*fa61ef6bSKonstantin Porotchkin 
626*fa61ef6bSKonstantin Porotchkin static int bubt_read_file(struct bubt_dev *src)
627*fa61ef6bSKonstantin Porotchkin {
628*fa61ef6bSKonstantin Porotchkin 	size_t image_size;
629*fa61ef6bSKonstantin Porotchkin 
630*fa61ef6bSKonstantin Porotchkin 	if (!src->read) {
631*fa61ef6bSKonstantin Porotchkin 		printf("Error: Read not supported on device \"%s\"\n",
632*fa61ef6bSKonstantin Porotchkin 		       src->name);
633*fa61ef6bSKonstantin Porotchkin 		return 0;
634*fa61ef6bSKonstantin Porotchkin 	}
635*fa61ef6bSKonstantin Porotchkin 
636*fa61ef6bSKonstantin Porotchkin 	image_size = src->read(net_boot_file_name);
637*fa61ef6bSKonstantin Porotchkin 	if (image_size <= 0) {
638*fa61ef6bSKonstantin Porotchkin 		printf("Error: Failed to read file %s from %s\n",
639*fa61ef6bSKonstantin Porotchkin 		       net_boot_file_name, src->name);
640*fa61ef6bSKonstantin Porotchkin 		return 0;
641*fa61ef6bSKonstantin Porotchkin 	}
642*fa61ef6bSKonstantin Porotchkin 
643*fa61ef6bSKonstantin Porotchkin 	return image_size;
644*fa61ef6bSKonstantin Porotchkin }
645*fa61ef6bSKonstantin Porotchkin 
646*fa61ef6bSKonstantin Porotchkin static int bubt_is_dev_active(struct bubt_dev *dev)
647*fa61ef6bSKonstantin Porotchkin {
648*fa61ef6bSKonstantin Porotchkin 	if (!dev->active) {
649*fa61ef6bSKonstantin Porotchkin 		printf("Device \"%s\" not supported by U-BOOT image\n",
650*fa61ef6bSKonstantin Porotchkin 		       dev->name);
651*fa61ef6bSKonstantin Porotchkin 		return 0;
652*fa61ef6bSKonstantin Porotchkin 	}
653*fa61ef6bSKonstantin Porotchkin 
654*fa61ef6bSKonstantin Porotchkin 	if (!dev->active()) {
655*fa61ef6bSKonstantin Porotchkin 		printf("Device \"%s\" is inactive\n", dev->name);
656*fa61ef6bSKonstantin Porotchkin 		return 0;
657*fa61ef6bSKonstantin Porotchkin 	}
658*fa61ef6bSKonstantin Porotchkin 
659*fa61ef6bSKonstantin Porotchkin 	return 1;
660*fa61ef6bSKonstantin Porotchkin }
661*fa61ef6bSKonstantin Porotchkin 
662*fa61ef6bSKonstantin Porotchkin struct bubt_dev *find_bubt_dev(char *dev_name)
663*fa61ef6bSKonstantin Porotchkin {
664*fa61ef6bSKonstantin Porotchkin 	int dev;
665*fa61ef6bSKonstantin Porotchkin 
666*fa61ef6bSKonstantin Porotchkin 	for (dev = 0; dev < BUBT_MAX_DEV; dev++) {
667*fa61ef6bSKonstantin Porotchkin 		if (strcmp(bubt_devs[dev].name, dev_name) == 0)
668*fa61ef6bSKonstantin Porotchkin 			return &bubt_devs[dev];
669*fa61ef6bSKonstantin Porotchkin 	}
670*fa61ef6bSKonstantin Porotchkin 
671*fa61ef6bSKonstantin Porotchkin 	return 0;
672*fa61ef6bSKonstantin Porotchkin }
673*fa61ef6bSKonstantin Porotchkin 
674*fa61ef6bSKonstantin Porotchkin #define DEFAULT_BUBT_SRC "tftp"
675*fa61ef6bSKonstantin Porotchkin 
676*fa61ef6bSKonstantin Porotchkin #ifndef DEFAULT_BUBT_DST
677*fa61ef6bSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SPI_BOOT
678*fa61ef6bSKonstantin Porotchkin #define DEFAULT_BUBT_DST "spi"
679*fa61ef6bSKonstantin Porotchkin #elif defined(CONFIG_MVEBU_NAND_BOOT)
680*fa61ef6bSKonstantin Porotchkin #define DEFAULT_BUBT_DST "nand"
681*fa61ef6bSKonstantin Porotchkin #elif defined(CONFIG_MVEBU_MMC_BOOT)
682*fa61ef6bSKonstantin Porotchkin #define DEFAULT_BUBT_DST "mmc"
683*fa61ef6bSKonstantin Porotchkin else
684*fa61ef6bSKonstantin Porotchkin #define DEFAULT_BUBT_DST "error"
685*fa61ef6bSKonstantin Porotchkin #endif
686*fa61ef6bSKonstantin Porotchkin #endif /* DEFAULT_BUBT_DST */
687*fa61ef6bSKonstantin Porotchkin 
688*fa61ef6bSKonstantin Porotchkin int do_bubt_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
689*fa61ef6bSKonstantin Porotchkin {
690*fa61ef6bSKonstantin Porotchkin 	struct bubt_dev *src, *dst;
691*fa61ef6bSKonstantin Porotchkin 	size_t image_size;
692*fa61ef6bSKonstantin Porotchkin 	char src_dev_name[8];
693*fa61ef6bSKonstantin Porotchkin 	char dst_dev_name[8];
694*fa61ef6bSKonstantin Porotchkin 	char *name;
695*fa61ef6bSKonstantin Porotchkin 	int  err;
696*fa61ef6bSKonstantin Porotchkin 
697*fa61ef6bSKonstantin Porotchkin 	if (argc < 2)
698*fa61ef6bSKonstantin Porotchkin 		copy_filename(net_boot_file_name,
699*fa61ef6bSKonstantin Porotchkin 			      CONFIG_MVEBU_UBOOT_DFLT_NAME,
700*fa61ef6bSKonstantin Porotchkin 			      sizeof(net_boot_file_name));
701*fa61ef6bSKonstantin Porotchkin 	else
702*fa61ef6bSKonstantin Porotchkin 		copy_filename(net_boot_file_name, argv[1],
703*fa61ef6bSKonstantin Porotchkin 			      sizeof(net_boot_file_name));
704*fa61ef6bSKonstantin Porotchkin 
705*fa61ef6bSKonstantin Porotchkin 	if (argc >= 3) {
706*fa61ef6bSKonstantin Porotchkin 		strncpy(dst_dev_name, argv[2], 8);
707*fa61ef6bSKonstantin Porotchkin 	} else {
708*fa61ef6bSKonstantin Porotchkin 		name = DEFAULT_BUBT_DST;
709*fa61ef6bSKonstantin Porotchkin 		strncpy(dst_dev_name, name, 8);
710*fa61ef6bSKonstantin Porotchkin 	}
711*fa61ef6bSKonstantin Porotchkin 
712*fa61ef6bSKonstantin Porotchkin 	if (argc >= 4)
713*fa61ef6bSKonstantin Porotchkin 		strncpy(src_dev_name, argv[3], 8);
714*fa61ef6bSKonstantin Porotchkin 	else
715*fa61ef6bSKonstantin Porotchkin 		strncpy(src_dev_name, DEFAULT_BUBT_SRC, 8);
716*fa61ef6bSKonstantin Porotchkin 
717*fa61ef6bSKonstantin Porotchkin 	/* Figure out the destination device */
718*fa61ef6bSKonstantin Porotchkin 	dst = find_bubt_dev(dst_dev_name);
719*fa61ef6bSKonstantin Porotchkin 	if (!dst) {
720*fa61ef6bSKonstantin Porotchkin 		printf("Error: Unknown destination \"%s\"\n", dst_dev_name);
721*fa61ef6bSKonstantin Porotchkin 		return -EINVAL;
722*fa61ef6bSKonstantin Porotchkin 	}
723*fa61ef6bSKonstantin Porotchkin 
724*fa61ef6bSKonstantin Porotchkin 	if (!bubt_is_dev_active(dst))
725*fa61ef6bSKonstantin Porotchkin 		return -ENODEV;
726*fa61ef6bSKonstantin Porotchkin 
727*fa61ef6bSKonstantin Porotchkin 	/* Figure out the source device */
728*fa61ef6bSKonstantin Porotchkin 	src = find_bubt_dev(src_dev_name);
729*fa61ef6bSKonstantin Porotchkin 	if (!src) {
730*fa61ef6bSKonstantin Porotchkin 		printf("Error: Unknown source \"%s\"\n", src_dev_name);
731*fa61ef6bSKonstantin Porotchkin 		return 1;
732*fa61ef6bSKonstantin Porotchkin 	}
733*fa61ef6bSKonstantin Porotchkin 
734*fa61ef6bSKonstantin Porotchkin 	if (!bubt_is_dev_active(src))
735*fa61ef6bSKonstantin Porotchkin 		return -ENODEV;
736*fa61ef6bSKonstantin Porotchkin 
737*fa61ef6bSKonstantin Porotchkin 	printf("Burning U-BOOT image \"%s\" from \"%s\" to \"%s\"\n",
738*fa61ef6bSKonstantin Porotchkin 	       net_boot_file_name, src->name, dst->name);
739*fa61ef6bSKonstantin Porotchkin 
740*fa61ef6bSKonstantin Porotchkin 	image_size = bubt_read_file(src);
741*fa61ef6bSKonstantin Porotchkin 	if (!image_size)
742*fa61ef6bSKonstantin Porotchkin 		return -EIO;
743*fa61ef6bSKonstantin Porotchkin 
744*fa61ef6bSKonstantin Porotchkin 	err = bubt_verify(image_size);
745*fa61ef6bSKonstantin Porotchkin 	if (err)
746*fa61ef6bSKonstantin Porotchkin 		return err;
747*fa61ef6bSKonstantin Porotchkin 
748*fa61ef6bSKonstantin Porotchkin 	err = bubt_write_file(dst, image_size);
749*fa61ef6bSKonstantin Porotchkin 	if (err)
750*fa61ef6bSKonstantin Porotchkin 		return err;
751*fa61ef6bSKonstantin Porotchkin 
752*fa61ef6bSKonstantin Porotchkin 	return 0;
753*fa61ef6bSKonstantin Porotchkin }
754*fa61ef6bSKonstantin Porotchkin 
755*fa61ef6bSKonstantin Porotchkin U_BOOT_CMD(
756*fa61ef6bSKonstantin Porotchkin 	bubt, 4, 0, do_bubt_cmd,
757*fa61ef6bSKonstantin Porotchkin 	"Burn a u-boot image to flash",
758*fa61ef6bSKonstantin Porotchkin 	"[file-name] [destination [source]]\n"
759*fa61ef6bSKonstantin Porotchkin 	"\t-file-name     The image file name to burn. Default = flash-image.bin\n"
760*fa61ef6bSKonstantin Porotchkin 	"\t-destination   Flash to burn to [spi, nand, mmc]. Default = active boot device\n"
761*fa61ef6bSKonstantin Porotchkin 	"\t-source        The source to load image from [tftp, usb, mmc]. Default = tftp\n"
762*fa61ef6bSKonstantin Porotchkin 	"Examples:\n"
763*fa61ef6bSKonstantin Porotchkin 	"\tbubt - Burn flash-image.bin from tftp to active boot device\n"
764*fa61ef6bSKonstantin Porotchkin 	"\tbubt flash-image-new.bin nand - Burn flash-image-new.bin from tftp to NAND flash\n"
765*fa61ef6bSKonstantin Porotchkin 	"\tbubt backup-flash-image.bin mmc usb - Burn backup-flash-image.bin from usb to MMC\n"
766*fa61ef6bSKonstantin Porotchkin 
767*fa61ef6bSKonstantin Porotchkin );
768