xref: /rk3399_rockchip-uboot/cmd/bootrkp.c (revision c01d4489240b61c7bd45952c3d9c4e02b10bec0f)
1a0e58cf2SKever Yang /*
2a0e58cf2SKever Yang  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3a0e58cf2SKever Yang  *
4a0e58cf2SKever Yang  * SPDX-License-Identifier:     GPL-2.0+
5a0e58cf2SKever Yang  */
6a0e58cf2SKever Yang 
7a0e58cf2SKever Yang #include <common.h>
8e72b9125SJoseph Chen #include <attestation_key.h>
9e72b9125SJoseph Chen #include <bootm.h>
1014768307SJoseph Chen #include <boot_rkimg.h>
1114768307SJoseph Chen #include <keymaster.h>
12e72b9125SJoseph Chen #include <console.h>
13e72b9125SJoseph Chen #include <image.h>
146caa0333SKever Yang #include <malloc.h>
15e72b9125SJoseph Chen #include <sysmem.h>
16e72b9125SJoseph Chen #include <linux/libfdt.h>
17e72b9125SJoseph Chen #include <asm/arch/hotkey.h>
18e72b9125SJoseph Chen #include <asm/arch/resource_img.h>
19e72b9125SJoseph Chen #include <asm/arch/boot_mode.h>
20a0e58cf2SKever Yang 
21e72b9125SJoseph Chen DECLARE_GLOBAL_DATA_PTR;
22e72b9125SJoseph Chen 
23e72b9125SJoseph Chen #ifdef CONFIG_ROCKCHIP_CRC
24e72b9125SJoseph Chen #define tole(x) cpu_to_le32(x)
25e72b9125SJoseph Chen 
26e72b9125SJoseph Chen /* Table of CRC-32's of all single-byte values (made by make_crc_table) */
27e72b9125SJoseph Chen static const uint32_t crc_table[256] = {
28e72b9125SJoseph Chen 	tole(0x00000000L), tole(0x04c10db7L), tole(0x09821b6eL), tole(0x0d4316d9L),
29e72b9125SJoseph Chen 	tole(0x130436dcL), tole(0x17c53b6bL), tole(0x1a862db2L), tole(0x1e472005L),
30e72b9125SJoseph Chen 	tole(0x26086db8L), tole(0x22c9600fL), tole(0x2f8a76d6L), tole(0x2b4b7b61L),
31e72b9125SJoseph Chen 	tole(0x350c5b64L), tole(0x31cd56d3L), tole(0x3c8e400aL), tole(0x384f4dbdL),
32e72b9125SJoseph Chen 	tole(0x4c10db70L), tole(0x48d1d6c7L), tole(0x4592c01eL), tole(0x4153cda9L),
33e72b9125SJoseph Chen 	tole(0x5f14edacL), tole(0x5bd5e01bL), tole(0x5696f6c2L), tole(0x5257fb75L),
34e72b9125SJoseph Chen 	tole(0x6a18b6c8L), tole(0x6ed9bb7fL), tole(0x639aada6L), tole(0x675ba011L),
35e72b9125SJoseph Chen 	tole(0x791c8014L), tole(0x7ddd8da3L), tole(0x709e9b7aL), tole(0x745f96cdL),
36e72b9125SJoseph Chen 	tole(0x9821b6e0L), tole(0x9ce0bb57L), tole(0x91a3ad8eL), tole(0x9562a039L),
37e72b9125SJoseph Chen 	tole(0x8b25803cL), tole(0x8fe48d8bL), tole(0x82a79b52L), tole(0x866696e5L),
38e72b9125SJoseph Chen 	tole(0xbe29db58L), tole(0xbae8d6efL), tole(0xb7abc036L), tole(0xb36acd81L),
39e72b9125SJoseph Chen 	tole(0xad2ded84L), tole(0xa9ece033L), tole(0xa4aff6eaL), tole(0xa06efb5dL),
40e72b9125SJoseph Chen 	tole(0xd4316d90L), tole(0xd0f06027L), tole(0xddb376feL), tole(0xd9727b49L),
41e72b9125SJoseph Chen 	tole(0xc7355b4cL), tole(0xc3f456fbL), tole(0xceb74022L), tole(0xca764d95L),
42e72b9125SJoseph Chen 	tole(0xf2390028L), tole(0xf6f80d9fL), tole(0xfbbb1b46L), tole(0xff7a16f1L),
43e72b9125SJoseph Chen 	tole(0xe13d36f4L), tole(0xe5fc3b43L), tole(0xe8bf2d9aL), tole(0xec7e202dL),
44e72b9125SJoseph Chen 	tole(0x34826077L), tole(0x30436dc0L), tole(0x3d007b19L), tole(0x39c176aeL),
45e72b9125SJoseph Chen 	tole(0x278656abL), tole(0x23475b1cL), tole(0x2e044dc5L), tole(0x2ac54072L),
46e72b9125SJoseph Chen 	tole(0x128a0dcfL), tole(0x164b0078L), tole(0x1b0816a1L), tole(0x1fc91b16L),
47e72b9125SJoseph Chen 	tole(0x018e3b13L), tole(0x054f36a4L), tole(0x080c207dL), tole(0x0ccd2dcaL),
48e72b9125SJoseph Chen 	tole(0x7892bb07L), tole(0x7c53b6b0L), tole(0x7110a069L), tole(0x75d1addeL),
49e72b9125SJoseph Chen 	tole(0x6b968ddbL), tole(0x6f57806cL), tole(0x621496b5L), tole(0x66d59b02L),
50e72b9125SJoseph Chen 	tole(0x5e9ad6bfL), tole(0x5a5bdb08L), tole(0x5718cdd1L), tole(0x53d9c066L),
51e72b9125SJoseph Chen 	tole(0x4d9ee063L), tole(0x495fedd4L), tole(0x441cfb0dL), tole(0x40ddf6baL),
52e72b9125SJoseph Chen 	tole(0xaca3d697L), tole(0xa862db20L), tole(0xa521cdf9L), tole(0xa1e0c04eL),
53e72b9125SJoseph Chen 	tole(0xbfa7e04bL), tole(0xbb66edfcL), tole(0xb625fb25L), tole(0xb2e4f692L),
54e72b9125SJoseph Chen 	tole(0x8aabbb2fL), tole(0x8e6ab698L), tole(0x8329a041L), tole(0x87e8adf6L),
55e72b9125SJoseph Chen 	tole(0x99af8df3L), tole(0x9d6e8044L), tole(0x902d969dL), tole(0x94ec9b2aL),
56e72b9125SJoseph Chen 	tole(0xe0b30de7L), tole(0xe4720050L), tole(0xe9311689L), tole(0xedf01b3eL),
57e72b9125SJoseph Chen 	tole(0xf3b73b3bL), tole(0xf776368cL), tole(0xfa352055L), tole(0xfef42de2L),
58e72b9125SJoseph Chen 	tole(0xc6bb605fL), tole(0xc27a6de8L), tole(0xcf397b31L), tole(0xcbf87686L),
59e72b9125SJoseph Chen 	tole(0xd5bf5683L), tole(0xd17e5b34L), tole(0xdc3d4dedL), tole(0xd8fc405aL),
60e72b9125SJoseph Chen 	tole(0x6904c0eeL), tole(0x6dc5cd59L), tole(0x6086db80L), tole(0x6447d637L),
61e72b9125SJoseph Chen 	tole(0x7a00f632L), tole(0x7ec1fb85L), tole(0x7382ed5cL), tole(0x7743e0ebL),
62e72b9125SJoseph Chen 	tole(0x4f0cad56L), tole(0x4bcda0e1L), tole(0x468eb638L), tole(0x424fbb8fL),
63e72b9125SJoseph Chen 	tole(0x5c089b8aL), tole(0x58c9963dL), tole(0x558a80e4L), tole(0x514b8d53L),
64e72b9125SJoseph Chen 	tole(0x25141b9eL), tole(0x21d51629L), tole(0x2c9600f0L), tole(0x28570d47L),
65e72b9125SJoseph Chen 	tole(0x36102d42L), tole(0x32d120f5L), tole(0x3f92362cL), tole(0x3b533b9bL),
66e72b9125SJoseph Chen 	tole(0x031c7626L), tole(0x07dd7b91L), tole(0x0a9e6d48L), tole(0x0e5f60ffL),
67e72b9125SJoseph Chen 	tole(0x101840faL), tole(0x14d94d4dL), tole(0x199a5b94L), tole(0x1d5b5623L),
68e72b9125SJoseph Chen 	tole(0xf125760eL), tole(0xf5e47bb9L), tole(0xf8a76d60L), tole(0xfc6660d7L),
69e72b9125SJoseph Chen 	tole(0xe22140d2L), tole(0xe6e04d65L), tole(0xeba35bbcL), tole(0xef62560bL),
70e72b9125SJoseph Chen 	tole(0xd72d1bb6L), tole(0xd3ec1601L), tole(0xdeaf00d8L), tole(0xda6e0d6fL),
71e72b9125SJoseph Chen 	tole(0xc4292d6aL), tole(0xc0e820ddL), tole(0xcdab3604L), tole(0xc96a3bb3L),
72e72b9125SJoseph Chen 	tole(0xbd35ad7eL), tole(0xb9f4a0c9L), tole(0xb4b7b610L), tole(0xb076bba7L),
73e72b9125SJoseph Chen 	tole(0xae319ba2L), tole(0xaaf09615L), tole(0xa7b380ccL), tole(0xa3728d7bL),
74e72b9125SJoseph Chen 	tole(0x9b3dc0c6L), tole(0x9ffccd71L), tole(0x92bfdba8L), tole(0x967ed61fL),
75e72b9125SJoseph Chen 	tole(0x8839f61aL), tole(0x8cf8fbadL), tole(0x81bbed74L), tole(0x857ae0c3L),
76e72b9125SJoseph Chen 	tole(0x5d86a099L), tole(0x5947ad2eL), tole(0x5404bbf7L), tole(0x50c5b640L),
77e72b9125SJoseph Chen 	tole(0x4e829645L), tole(0x4a439bf2L), tole(0x47008d2bL), tole(0x43c1809cL),
78e72b9125SJoseph Chen 	tole(0x7b8ecd21L), tole(0x7f4fc096L), tole(0x720cd64fL), tole(0x76cddbf8L),
79e72b9125SJoseph Chen 	tole(0x688afbfdL), tole(0x6c4bf64aL), tole(0x6108e093L), tole(0x65c9ed24L),
80e72b9125SJoseph Chen 	tole(0x11967be9L), tole(0x1557765eL), tole(0x18146087L), tole(0x1cd56d30L),
81e72b9125SJoseph Chen 	tole(0x02924d35L), tole(0x06534082L), tole(0x0b10565bL), tole(0x0fd15becL),
82e72b9125SJoseph Chen 	tole(0x379e1651L), tole(0x335f1be6L), tole(0x3e1c0d3fL), tole(0x3add0088L),
83e72b9125SJoseph Chen 	tole(0x249a208dL), tole(0x205b2d3aL), tole(0x2d183be3L), tole(0x29d93654L),
84e72b9125SJoseph Chen 	tole(0xc5a71679L), tole(0xc1661bceL), tole(0xcc250d17L), tole(0xc8e400a0L),
85e72b9125SJoseph Chen 	tole(0xd6a320a5L), tole(0xd2622d12L), tole(0xdf213bcbL), tole(0xdbe0367cL),
86e72b9125SJoseph Chen 	tole(0xe3af7bc1L), tole(0xe76e7676L), tole(0xea2d60afL), tole(0xeeec6d18L),
87e72b9125SJoseph Chen 	tole(0xf0ab4d1dL), tole(0xf46a40aaL), tole(0xf9295673L), tole(0xfde85bc4L),
88e72b9125SJoseph Chen 	tole(0x89b7cd09L), tole(0x8d76c0beL), tole(0x8035d667L), tole(0x84f4dbd0L),
89e72b9125SJoseph Chen 	tole(0x9ab3fbd5L), tole(0x9e72f662L), tole(0x9331e0bbL), tole(0x97f0ed0cL),
90e72b9125SJoseph Chen 	tole(0xafbfa0b1L), tole(0xab7ead06L), tole(0xa63dbbdfL), tole(0xa2fcb668L),
91e72b9125SJoseph Chen 	tole(0xbcbb966dL), tole(0xb87a9bdaL), tole(0xb5398d03L), tole(0xb1f880b4L)
92e72b9125SJoseph Chen };
93e72b9125SJoseph Chen 
94e72b9125SJoseph Chen #define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
95e72b9125SJoseph Chen 
96e72b9125SJoseph Chen static uint32_t crc32_rk(uint32_t crc, const unsigned char *s, uint32_t len)
97a0e58cf2SKever Yang {
98e72b9125SJoseph Chen 	const uint32_t *tab;
99e72b9125SJoseph Chen 
100e72b9125SJoseph Chen 	tab = crc_table;
101e72b9125SJoseph Chen 	crc = cpu_to_le32(crc);
102e72b9125SJoseph Chen 
103e72b9125SJoseph Chen 	do {
104e72b9125SJoseph Chen 		DO_CRC(*s++);
105e72b9125SJoseph Chen 	} while (--len);
106e72b9125SJoseph Chen 
107e72b9125SJoseph Chen 	return le32_to_cpu(crc);
108e72b9125SJoseph Chen }
109e72b9125SJoseph Chen 
110e72b9125SJoseph Chen #undef DO_CRC
111e72b9125SJoseph Chen 
112e72b9125SJoseph Chen static u32 crc32_verify(unsigned char *data, u32 size)
113e72b9125SJoseph Chen {
114e72b9125SJoseph Chen 	u32 crc_check = 0, crc_calc = 0;
115e72b9125SJoseph Chen 	int i = 0;
116e72b9125SJoseph Chen 
117e72b9125SJoseph Chen 	if (size <= 4)
118e72b9125SJoseph Chen 		return 0;
119e72b9125SJoseph Chen 
120e72b9125SJoseph Chen 	size -= 4;
121e72b9125SJoseph Chen 	for (i = 3; i >= 0; i--)
122e72b9125SJoseph Chen 		crc_check = (crc_check << 8) + (*(data + size + i));
123e72b9125SJoseph Chen 
124e72b9125SJoseph Chen 	crc_calc = crc32_rk(0, data, size);
125e72b9125SJoseph Chen 
126e72b9125SJoseph Chen 	return (crc_calc == crc_check) ? crc_check : 0;
127e72b9125SJoseph Chen }
128e72b9125SJoseph Chen #endif
129e72b9125SJoseph Chen 
130e72b9125SJoseph Chen #if !defined(CONFIG_ARM64)
131e72b9125SJoseph Chen #ifdef CONFIG_LMB
132e72b9125SJoseph Chen static void boot_start_lmb(bootm_headers_t *images)
133e72b9125SJoseph Chen {
134e72b9125SJoseph Chen 	lmb_init(&images->lmb);
135e72b9125SJoseph Chen #ifdef CONFIG_NR_DRAM_BANKS
136e72b9125SJoseph Chen 	int i;
137e72b9125SJoseph Chen 
138e72b9125SJoseph Chen 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
139e72b9125SJoseph Chen 		lmb_add(&images->lmb, gd->bd->bi_dram[i].start,
140e72b9125SJoseph Chen 			gd->bd->bi_dram[i].size);
141e72b9125SJoseph Chen 	}
142e72b9125SJoseph Chen #else
143e72b9125SJoseph Chen 	ulong		mem_start;
144e72b9125SJoseph Chen 	phys_size_t	mem_size;
145e72b9125SJoseph Chen 
146e72b9125SJoseph Chen 	mem_start = env_get_bootm_low();
147e72b9125SJoseph Chen 	mem_size = env_get_bootm_size();
148e72b9125SJoseph Chen 	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
149e72b9125SJoseph Chen #endif
150e72b9125SJoseph Chen 	arch_lmb_reserve(&images->lmb);
151e72b9125SJoseph Chen 	board_lmb_reserve(&images->lmb);
152e72b9125SJoseph Chen }
153e72b9125SJoseph Chen #else
154e72b9125SJoseph Chen static inline void boot_start_lmb(bootm_headers_t *images) { }
155e72b9125SJoseph Chen #endif
156e72b9125SJoseph Chen 
157e72b9125SJoseph Chen static void boot_lmb_init(bootm_headers_t *images)
158e72b9125SJoseph Chen {
159e72b9125SJoseph Chen 	boot_start_lmb(images);
160e72b9125SJoseph Chen 	images->state = BOOTM_STATE_OS_GO;
161e72b9125SJoseph Chen }
162e72b9125SJoseph Chen #endif
163e72b9125SJoseph Chen 
164e72b9125SJoseph Chen static void fdt_ramdisk_skip_relocation(void)
165e72b9125SJoseph Chen {
166e72b9125SJoseph Chen 	char *ramdisk_high = env_get("initrd_high");
167e72b9125SJoseph Chen 	char *fdt_high = env_get("fdt_high");
168e72b9125SJoseph Chen 
169e72b9125SJoseph Chen 	if (!fdt_high) {
170e72b9125SJoseph Chen 		env_set_hex("fdt_high", -1UL);
171e72b9125SJoseph Chen 		printf("Fdt ");
172e72b9125SJoseph Chen 	}
173e72b9125SJoseph Chen 
174e72b9125SJoseph Chen 	if (!ramdisk_high) {
175e72b9125SJoseph Chen 		env_set_hex("initrd_high", -1UL);
176e72b9125SJoseph Chen 		printf("Ramdisk ");
177e72b9125SJoseph Chen 	}
178e72b9125SJoseph Chen 
179e72b9125SJoseph Chen 	if (!fdt_high || !ramdisk_high)
180e72b9125SJoseph Chen 		printf("skip relocation\n");
181e72b9125SJoseph Chen }
182e72b9125SJoseph Chen 
183e72b9125SJoseph Chen /*
184e72b9125SJoseph Chen  * non-OTA packaged kernel.img & boot.img return the image size on success,
185e72b9125SJoseph Chen  * and a negative value on error.
186e72b9125SJoseph Chen  */
187e72b9125SJoseph Chen static int read_rockchip_image(struct blk_desc *dev_desc,
188e72b9125SJoseph Chen 			       disk_partition_t *part, void *dst)
189e72b9125SJoseph Chen {
190e72b9125SJoseph Chen 	struct rockchip_image *img;
191e72b9125SJoseph Chen 	int header_len = 8;
192e72b9125SJoseph Chen 	int cnt, ret;
193e72b9125SJoseph Chen #ifdef CONFIG_ROCKCHIP_CRC
194e72b9125SJoseph Chen 	u32 crc32;
195e72b9125SJoseph Chen #endif
196e72b9125SJoseph Chen 
197e72b9125SJoseph Chen 	img = memalign(ARCH_DMA_MINALIGN, RK_BLK_SIZE);
198e72b9125SJoseph Chen 	if (!img)
199e72b9125SJoseph Chen 		return -ENOMEM;
200e72b9125SJoseph Chen 
201e72b9125SJoseph Chen 	/* read first block with header imformation */
202e72b9125SJoseph Chen 	ret = blk_dread(dev_desc, part->start, 1, img);
203e72b9125SJoseph Chen 	if (ret != 1) {
204e72b9125SJoseph Chen 		ret = -EIO;
205e72b9125SJoseph Chen 		goto err;
206e72b9125SJoseph Chen 	}
207e72b9125SJoseph Chen 
208e72b9125SJoseph Chen 	if (img->tag != TAG_KERNEL) {
209e72b9125SJoseph Chen 		printf("Invalid %s image tag(0x%x)\n", part->name, img->tag);
210e72b9125SJoseph Chen 		ret = -EINVAL;
211e72b9125SJoseph Chen 		goto err;
212e72b9125SJoseph Chen 	}
213e72b9125SJoseph Chen 
214e72b9125SJoseph Chen 	/*
215e72b9125SJoseph Chen 	 * read the rest blks
216e72b9125SJoseph Chen 	 * total size = image size + 8 bytes header + 4 bytes crc32
217e72b9125SJoseph Chen 	 */
218e72b9125SJoseph Chen 	cnt = DIV_ROUND_UP(img->size + 8 + 4, RK_BLK_SIZE);
219e72b9125SJoseph Chen 	if (!sysmem_alloc_base_by_name((const char *)part->name,
220e72b9125SJoseph Chen 				       (phys_addr_t)dst,
221e72b9125SJoseph Chen 				       cnt * dev_desc->blksz)) {
222e72b9125SJoseph Chen 		ret = -ENXIO;
223e72b9125SJoseph Chen 		goto err;
224e72b9125SJoseph Chen 	}
225e72b9125SJoseph Chen 
226e72b9125SJoseph Chen 	memcpy(dst, img->image, RK_BLK_SIZE - header_len);
227e72b9125SJoseph Chen 	ret = blk_dread(dev_desc, part->start + 1, cnt - 1,
228e72b9125SJoseph Chen 			dst + RK_BLK_SIZE - header_len);
229e72b9125SJoseph Chen 	if (ret != (cnt - 1)) {
230e72b9125SJoseph Chen 		printf("Failed to read %s part, ret=%d\n", part->name, ret);
231e72b9125SJoseph Chen 		ret = -EIO;
232e72b9125SJoseph Chen 	} else {
233e72b9125SJoseph Chen 		ret = img->size;
234e72b9125SJoseph Chen 	}
235e72b9125SJoseph Chen 
236e72b9125SJoseph Chen #ifdef CONFIG_ROCKCHIP_CRC
237e72b9125SJoseph Chen 	printf("%s image rk crc32 verify... ", part->name);
238e72b9125SJoseph Chen 	crc32 = crc32_verify((uchar *)(ulong)dst, img->size + 4);
239e72b9125SJoseph Chen 	if (!crc32) {
240e72b9125SJoseph Chen 		printf("fail!\n");
241e72b9125SJoseph Chen 		ret = -EINVAL;
242e72b9125SJoseph Chen 	} else {
243e72b9125SJoseph Chen 		printf("okay.\n");
244e72b9125SJoseph Chen 	}
245e72b9125SJoseph Chen #endif
246e72b9125SJoseph Chen 
247e72b9125SJoseph Chen err:
248e72b9125SJoseph Chen 	free(img);
249e72b9125SJoseph Chen 	return ret;
250e72b9125SJoseph Chen }
251e72b9125SJoseph Chen 
252e72b9125SJoseph Chen static int boot_rockchip_image(struct blk_desc *dev_desc,
253e72b9125SJoseph Chen 			       disk_partition_t *boot_part)
254e72b9125SJoseph Chen {
255e72b9125SJoseph Chen 	disk_partition_t kernel_part;
256e72b9125SJoseph Chen 	ulong ramdisk_addr_r;
257e72b9125SJoseph Chen 	ulong kernel_addr_r;
258e72b9125SJoseph Chen 	ulong fdt_addr_r;
259e72b9125SJoseph Chen 	int ramdisk_size;
260e72b9125SJoseph Chen 	int kernel_size;
261e72b9125SJoseph Chen 	int fdt_size;
262e72b9125SJoseph Chen 	int ret;
263e72b9125SJoseph Chen 
264e72b9125SJoseph Chen 	printf("\n## Booting Rockchip Format Image\n");
265e72b9125SJoseph Chen 
266e72b9125SJoseph Chen 	ramdisk_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0);
267e72b9125SJoseph Chen 	kernel_addr_r = env_get_ulong("kernel_addr_r", 16, 0);
268e72b9125SJoseph Chen 	fdt_addr_r = env_get_ulong("fdt_addr_r", 16, 0);
269e72b9125SJoseph Chen 
270e72b9125SJoseph Chen 	ret = part_get_info_by_name(dev_desc, PART_KERNEL, &kernel_part);
271e72b9125SJoseph Chen 	if (ret < 0) {
272e72b9125SJoseph Chen 		printf("Could not find kernel partition, ret=%d\n", ret);
273e72b9125SJoseph Chen 		return -EINVAL;
274e72b9125SJoseph Chen 	}
275e72b9125SJoseph Chen 
276e72b9125SJoseph Chen 	kernel_size = read_rockchip_image(dev_desc, &kernel_part,
277e72b9125SJoseph Chen 					  (void *)kernel_addr_r);
278e72b9125SJoseph Chen 	if (kernel_size < 0) {
279e72b9125SJoseph Chen 		printf("Failed to read kernel image, ret=%d\n", ret);
280e72b9125SJoseph Chen 		return -EINVAL;
281e72b9125SJoseph Chen 	}
282e72b9125SJoseph Chen 
283e72b9125SJoseph Chen 	ramdisk_size = read_rockchip_image(dev_desc, boot_part,
284e72b9125SJoseph Chen 					   (void *)ramdisk_addr_r);
285e72b9125SJoseph Chen 	if (ramdisk_size < 0)
286e72b9125SJoseph Chen 		ramdisk_size = 0;
287e72b9125SJoseph Chen 
288e72b9125SJoseph Chen 	if (gd->fdt_blob != (void *)fdt_addr_r) {
289e72b9125SJoseph Chen 		fdt_size = rockchip_read_dtb_file((void *)fdt_addr_r);
290e72b9125SJoseph Chen 		if (fdt_size < 0) {
291e72b9125SJoseph Chen 			printf("Failed to read fdt, ret=%d\n", fdt_size);
292e72b9125SJoseph Chen 			return -EINVAL;
293e72b9125SJoseph Chen 		}
294e72b9125SJoseph Chen 	}
295e72b9125SJoseph Chen 
296e72b9125SJoseph Chen 	printf("fdt	 @ 0x%08lx (0x%08x)\n", fdt_addr_r, fdt_totalsize(fdt_addr_r));
297e72b9125SJoseph Chen 	printf("kernel   @ 0x%08lx (0x%08x)\n", kernel_addr_r, kernel_size);
298e72b9125SJoseph Chen 	printf("ramdisk  @ 0x%08lx (0x%08x)\n", ramdisk_addr_r, ramdisk_size);
299e72b9125SJoseph Chen 
300e72b9125SJoseph Chen 	fdt_ramdisk_skip_relocation();
301e72b9125SJoseph Chen 	hotkey_run(HK_SYSMEM);
302e72b9125SJoseph Chen 	sysmem_overflow_check();
303e72b9125SJoseph Chen 
304e72b9125SJoseph Chen #if defined(CONFIG_ARM64)
305e72b9125SJoseph Chen 	char cmdbuf[64];
306e72b9125SJoseph Chen 
307e72b9125SJoseph Chen 	snprintf(cmdbuf, 64, "booti 0x%lx 0x%lx:0x%x 0x%lx",
308e72b9125SJoseph Chen 		 kernel_addr_r, ramdisk_addr_r, ramdisk_size, fdt_addr_r);
309e72b9125SJoseph Chen 	run_command(cmdbuf, 0);
310e72b9125SJoseph Chen #else
311e72b9125SJoseph Chen 	/* We asume it's always zImage on 32-bit platform */
312e72b9125SJoseph Chen 	ulong kaddr_c = env_get_ulong("kernel_addr_c", 16, 0);
313e72b9125SJoseph Chen 	ulong kaddr_r, kaddr, ksize;
314e72b9125SJoseph Chen 
315e72b9125SJoseph Chen 	if (kernel_addr_r && !kaddr_c) {
316e72b9125SJoseph Chen 		kaddr_c = kernel_addr_r;
317e72b9125SJoseph Chen 		kaddr_r = CONFIG_SYS_SDRAM_BASE;
318e72b9125SJoseph Chen 	}
319e72b9125SJoseph Chen 
320e72b9125SJoseph Chen 	if (!sysmem_free((phys_addr_t)kaddr_c)) {
321e72b9125SJoseph Chen 		kaddr = kaddr_r;
322e72b9125SJoseph Chen 		ksize = kernel_size * 100 / 45 ; /* Ratio: 45% */
323e72b9125SJoseph Chen 		ksize = ALIGN(ksize, dev_desc->blksz);
324*c01d4489SJoseph Chen 		if (!sysmem_alloc_base(MEM_UNCOMP_KERNEL,
325e72b9125SJoseph Chen 				       (phys_addr_t)kaddr, ksize))
326e72b9125SJoseph Chen 			return -ENOMEM;
327e72b9125SJoseph Chen 	}
328e72b9125SJoseph Chen 
329e72b9125SJoseph Chen 	hotkey_run(HK_SYSMEM);
330e72b9125SJoseph Chen 	sysmem_overflow_check();
331e72b9125SJoseph Chen 
332e72b9125SJoseph Chen 	boot_lmb_init(&images);
333e72b9125SJoseph Chen 	images.ep = kernel_addr_r;
334e72b9125SJoseph Chen 	images.initrd_start = ramdisk_addr_r;
335e72b9125SJoseph Chen 	images.initrd_end = ramdisk_addr_r + ramdisk_size;
336e72b9125SJoseph Chen 	images.ft_addr = (void *)fdt_addr_r;
337e72b9125SJoseph Chen 	images.ft_len = fdt_totalsize(fdt_addr_r);
338e72b9125SJoseph Chen 	do_bootm_linux(0, 0, NULL, &images);
339e72b9125SJoseph Chen #endif
340e72b9125SJoseph Chen 
341e72b9125SJoseph Chen 	return 0;
342e72b9125SJoseph Chen }
343e72b9125SJoseph Chen 
344e72b9125SJoseph Chen static int do_boot_rockchip(cmd_tbl_t *cmdtp, int flag,
345e72b9125SJoseph Chen 			    int argc, char *const argv[])
346e72b9125SJoseph Chen {
347e72b9125SJoseph Chen 	char *part_name = PART_BOOT;
348a0e58cf2SKever Yang 	struct blk_desc *dev_desc;
349e72b9125SJoseph Chen 	disk_partition_t part;
350e72b9125SJoseph Chen 	int ret;
351a0e58cf2SKever Yang 
352a0e58cf2SKever Yang 	dev_desc = rockchip_get_bootdev();
3536651d4c0SJason Zhu 	if (!dev_desc) {
354e72b9125SJoseph Chen 		printf("dev_desc is NULL!\n");
3554701d790SAndy Yan 		return CMD_RET_FAILURE;
3566651d4c0SJason Zhu 	}
35791c73fb4Sqiujian 
358c2ba77d9SJian Qiu #ifdef CONFIG_ANDROID_KEYMASTER_CA
35991c73fb4Sqiujian 	/* load attestation key from misc partition. */
360e72b9125SJoseph Chen 	ret = part_get_info_by_name(dev_desc, PART_MISC, &part);
36191c73fb4Sqiujian 	if (ret < 0)
362e72b9125SJoseph Chen 		printf("Could not find misc partition\n");
36391c73fb4Sqiujian 	else
364e72b9125SJoseph Chen 		load_attestation_key(dev_desc, &part);
36591c73fb4Sqiujian #endif
36691c73fb4Sqiujian 
36765413a00SJian Qiu #ifdef CONFIG_FASTBOOT_OEM_UNLOCK
3689e68721bSqiujian 	/* read oem unlock status and attach to bootargs */
36914768307SJoseph Chen 	char oem_unlock[30] = {0};
3709e68721bSqiujian 	TEEC_Result result;
37114768307SJoseph Chen 	uint8_t unlock = 0;
37214768307SJoseph Chen 
3739e68721bSqiujian 	result = trusty_read_oem_unlock(&unlock);
3749e68721bSqiujian 	if (result) {
375e72b9125SJoseph Chen 		printf("Failed to read oem unlock status, ret=%d\n", result);
3769e68721bSqiujian 	} else {
37714768307SJoseph Chen 		snprintf(oem_unlock, sizeof(oem_unlock),
37814768307SJoseph Chen 			 "androidboot.oem_unlocked=%d", unlock);
3799e68721bSqiujian 		env_update("bootargs", oem_unlock);
3809e68721bSqiujian 	}
3819e68721bSqiujian #endif
382e72b9125SJoseph Chen 	if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY)
383e72b9125SJoseph Chen 		part_name = PART_RECOVERY;
3849e68721bSqiujian 
385e72b9125SJoseph Chen 	ret = part_get_info_by_name(dev_desc, part_name, &part);
38614768307SJoseph Chen 	if (ret < 0) {
387e72b9125SJoseph Chen 		printf("Could not find %s part\n", part.name);
38814768307SJoseph Chen 		return CMD_RET_FAILURE;
38914768307SJoseph Chen 	}
390a0e58cf2SKever Yang 
391e72b9125SJoseph Chen 	return boot_rockchip_image(dev_desc, &part) ? CMD_RET_FAILURE : 0;
392a0e58cf2SKever Yang }
393a0e58cf2SKever Yang 
394a0e58cf2SKever Yang U_BOOT_CMD(
395e72b9125SJoseph Chen 	bootrkp,  1,     1,      do_boot_rockchip,
39632af749aSKever Yang 	"Boot Linux Image from rockchip image type",
39732af749aSKever Yang 	"kernel.img: zImage/Image\n"
39832af749aSKever Yang 	"boot.img: ramdisk\n"
39932af749aSKever Yang 	"resource.img: dtb, u-boot logo, kernel logo"
400a0e58cf2SKever Yang );
401