xref: /rk3399_rockchip-uboot/common/spl/spl_boot_image.c (revision 36c449fe1f667af7b034680940bb8694b94b7e89)
1*36c449feSJoseph Chen /*
2*36c449feSJoseph Chen  * (C) Copyright 2023 Rockchip Electronics Co., Ltd
3*36c449feSJoseph Chen  *
4*36c449feSJoseph Chen  * SPDX-License-Identifier:     GPL-2.0+
5*36c449feSJoseph Chen  */
6*36c449feSJoseph Chen 
7*36c449feSJoseph Chen #include <common.h>
8*36c449feSJoseph Chen #include <android_image.h>
9*36c449feSJoseph Chen #include <crypto.h>
10*36c449feSJoseph Chen #include <image.h>
11*36c449feSJoseph Chen #include <mp_boot.h>
12*36c449feSJoseph Chen #include <part.h>
13*36c449feSJoseph Chen #include <spl.h>
14*36c449feSJoseph Chen #include <asm/io.h>
15*36c449feSJoseph Chen 
16*36c449feSJoseph Chen #define BLK_CNT(_num_bytes, _block_size) \
17*36c449feSJoseph Chen 		((_num_bytes + _block_size - 1) / _block_size)
18*36c449feSJoseph Chen 
19*36c449feSJoseph Chen #ifdef CONFIG_ANDROID_BOOT_IMAGE
android_check_header(const struct andr_img_hdr * hdr)20*36c449feSJoseph Chen static int android_check_header(const struct andr_img_hdr *hdr)
21*36c449feSJoseph Chen {
22*36c449feSJoseph Chen 	return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE);
23*36c449feSJoseph Chen }
24*36c449feSJoseph Chen 
print_hash(const char * label,u8 * hash,int len)25*36c449feSJoseph Chen static void print_hash(const char *label, u8 *hash, int len)
26*36c449feSJoseph Chen {
27*36c449feSJoseph Chen 	int i;
28*36c449feSJoseph Chen 
29*36c449feSJoseph Chen 	printf("%s:\n    0x", label ? : "Hash");
30*36c449feSJoseph Chen 	for (i = 0; i < len; i++)
31*36c449feSJoseph Chen 		printf("%02x", hash[i]);
32*36c449feSJoseph Chen 	printf("\n");
33*36c449feSJoseph Chen }
34*36c449feSJoseph Chen 
35*36c449feSJoseph Chen #if 0
36*36c449feSJoseph Chen static void spl_android_print_contents(const struct andr_img_hdr *hdr)
37*36c449feSJoseph Chen {
38*36c449feSJoseph Chen 	const char * const p = IMAGE_INDENT_STRING;
39*36c449feSJoseph Chen 	/* os_version = ver << 11 | lvl */
40*36c449feSJoseph Chen 	u32 os_ver = hdr->os_version >> 11;
41*36c449feSJoseph Chen 	u32 os_lvl = hdr->os_version & ((1U << 11) - 1);
42*36c449feSJoseph Chen 	u32 header_version = hdr->header_version;
43*36c449feSJoseph Chen 
44*36c449feSJoseph Chen 	printf("%skernel size:      %x\n", p, hdr->kernel_size);
45*36c449feSJoseph Chen 	printf("%skernel address:   %x\n", p, hdr->kernel_addr);
46*36c449feSJoseph Chen 	printf("%sramdisk size:     %x\n", p, hdr->ramdisk_size);
47*36c449feSJoseph Chen 	printf("%sramdisk address: %x\n", p, hdr->ramdisk_addr);
48*36c449feSJoseph Chen 	printf("%ssecond size:      %x\n", p, hdr->second_size);
49*36c449feSJoseph Chen 	printf("%ssecond address:   %x\n", p, hdr->second_addr);
50*36c449feSJoseph Chen 	printf("%stags address:     %x\n", p, hdr->tags_addr);
51*36c449feSJoseph Chen 	printf("%spage size:        %x\n", p, hdr->page_size);
52*36c449feSJoseph Chen 	printf("%sheader_version:   %x\n", p, header_version);
53*36c449feSJoseph Chen 	/* ver = A << 14 | B << 7 | C         (7 bits for each of A, B, C)
54*36c449feSJoseph Chen 	 * lvl = ((Y - 2000) & 127) << 4 | M  (7 bits for Y, 4 bits for M) */
55*36c449feSJoseph Chen 	printf("%sos_version:       %x (ver: %u.%u.%u, level: %u.%u)\n",
56*36c449feSJoseph Chen 	       p, hdr->os_version,
57*36c449feSJoseph Chen 	       (os_ver >> 7) & 0x7F, (os_ver >> 14) & 0x7F, os_ver & 0x7F,
58*36c449feSJoseph Chen 	       (os_lvl >> 4) + 2000, os_lvl & 0x0F);
59*36c449feSJoseph Chen 	printf("%sname:             %s\n", p, hdr->name);
60*36c449feSJoseph Chen 	printf("%scmdline:          %s\n", p, hdr->cmdline);
61*36c449feSJoseph Chen 
62*36c449feSJoseph Chen 	if (header_version == 1 || header_version == 2) {
63*36c449feSJoseph Chen 		printf("%srecovery dtbo size:    %x\n", p, hdr->recovery_dtbo_size);
64*36c449feSJoseph Chen 		printf("%srecovery dtbo offset:  %llx\n", p, hdr->recovery_dtbo_offset);
65*36c449feSJoseph Chen 		printf("%sheader size:           %x\n", p, hdr->header_size);
66*36c449feSJoseph Chen 	}
67*36c449feSJoseph Chen 
68*36c449feSJoseph Chen 	if (header_version == 2 || header_version == 3) {
69*36c449feSJoseph Chen 		printf("%sdtb size:              %x\n", p, hdr->dtb_size);
70*36c449feSJoseph Chen 		printf("%sdtb addr:              %llx\n", p, hdr->dtb_addr);
71*36c449feSJoseph Chen 	}
72*36c449feSJoseph Chen 
73*36c449feSJoseph Chen 	if (header_version >= 3) {
74*36c449feSJoseph Chen 		printf("%scmdline:               %s\n", p, hdr->total_cmdline);
75*36c449feSJoseph Chen 		printf("%svendor ramdisk size:   %x\n", p, hdr->vendor_ramdisk_size);
76*36c449feSJoseph Chen 		printf("%svendor page size:      %x\n", p, hdr->vendor_page_size);
77*36c449feSJoseph Chen 		printf("%svendor header version: %d\n", p, hdr->vendor_header_version);
78*36c449feSJoseph Chen 		printf("%svendor header size:    %x\n", p, hdr->vendor_header_size);
79*36c449feSJoseph Chen 	}
80*36c449feSJoseph Chen 
81*36c449feSJoseph Chen 	if (header_version >= 4) {
82*36c449feSJoseph Chen 		printf("%svendor ramdisk table size:        %x\n",
83*36c449feSJoseph Chen 		       p, hdr->vendor_ramdisk_table_size);
84*36c449feSJoseph Chen 		printf("%svendor ramdisk table entry num:   %x\n",
85*36c449feSJoseph Chen 		       p, hdr->vendor_ramdisk_table_entry_num);
86*36c449feSJoseph Chen 		printf("%svendor ramdisk table entry size:  %x\n",
87*36c449feSJoseph Chen 		       p, hdr->vendor_ramdisk_table_entry_size);
88*36c449feSJoseph Chen 		printf("%svendor bootconfig size:           %d\n",
89*36c449feSJoseph Chen 		       p, hdr->vendor_bootconfig_size);
90*36c449feSJoseph Chen 	}
91*36c449feSJoseph Chen }
92*36c449feSJoseph Chen #endif
93*36c449feSJoseph Chen 
android_size(struct andr_img_hdr * hdr)94*36c449feSJoseph Chen static ulong android_size(struct andr_img_hdr *hdr)
95*36c449feSJoseph Chen {
96*36c449feSJoseph Chen 	ulong len;
97*36c449feSJoseph Chen 
98*36c449feSJoseph Chen 	len = hdr->page_size +
99*36c449feSJoseph Chen 		ALIGN(hdr->kernel_size, hdr->page_size) +
100*36c449feSJoseph Chen 		ALIGN(hdr->ramdisk_size, hdr->page_size) +
101*36c449feSJoseph Chen 		ALIGN(hdr->second_size, hdr->page_size);
102*36c449feSJoseph Chen 	if (hdr->header_version > 0)
103*36c449feSJoseph Chen 		len += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
104*36c449feSJoseph Chen 	if (hdr->header_version > 1)
105*36c449feSJoseph Chen 		len += ALIGN(hdr->dtb_size, hdr->page_size);
106*36c449feSJoseph Chen #if 0
107*36c449feSJoseph Chen 	spl_android_print_contents(hdr);
108*36c449feSJoseph Chen #endif
109*36c449feSJoseph Chen 
110*36c449feSJoseph Chen 	return len;
111*36c449feSJoseph Chen }
112*36c449feSJoseph Chen 
spl_load_android(struct task_data * data)113*36c449feSJoseph Chen int spl_load_android(struct task_data *data)
114*36c449feSJoseph Chen {
115*36c449feSJoseph Chen 	struct spl_load_info *info = &data->info;
116*36c449feSJoseph Chen 	void *buf = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
117*36c449feSJoseph Chen 	disk_partition_t part;
118*36c449feSJoseph Chen 	ulong blkcnt;
119*36c449feSJoseph Chen 
120*36c449feSJoseph Chen 	debug("== Android: load start\n");
121*36c449feSJoseph Chen 
122*36c449feSJoseph Chen 	if (part_get_info_by_name(info->dev, "boot", &part) < 0) {
123*36c449feSJoseph Chen 		printf("No boot partition\n");
124*36c449feSJoseph Chen 		return -ENOENT;
125*36c449feSJoseph Chen 	}
126*36c449feSJoseph Chen 
127*36c449feSJoseph Chen 	blkcnt = BLK_CNT(sizeof(struct andr_img_hdr), info->bl_len);
128*36c449feSJoseph Chen 	if (info->read(info, part.start, blkcnt, buf) != blkcnt)
129*36c449feSJoseph Chen 		return -EIO;
130*36c449feSJoseph Chen 
131*36c449feSJoseph Chen 	if (android_check_header(buf))
132*36c449feSJoseph Chen 		return -EINVAL;
133*36c449feSJoseph Chen 
134*36c449feSJoseph Chen 	blkcnt = BLK_CNT(android_size(buf), info->bl_len);
135*36c449feSJoseph Chen 	if (info->read(info, part.start, blkcnt, buf) != blkcnt)
136*36c449feSJoseph Chen 		return -EIO;
137*36c449feSJoseph Chen 
138*36c449feSJoseph Chen 	data->boot_addr = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
139*36c449feSJoseph Chen 	data->boot_size = blkcnt * info->bl_len;
140*36c449feSJoseph Chen 
141*36c449feSJoseph Chen 	flush_dcache_range((ulong)data, (ulong)data + sizeof(*data));
142*36c449feSJoseph Chen 	flush_dcache_range((ulong)buf, (ulong)buf + blkcnt);
143*36c449feSJoseph Chen 
144*36c449feSJoseph Chen 	debug("== Android: load 0x%08lx size OK\n", blkcnt * info->bl_len);
145*36c449feSJoseph Chen 
146*36c449feSJoseph Chen 	return 0;
147*36c449feSJoseph Chen }
148*36c449feSJoseph Chen 
149*36c449feSJoseph Chen #ifdef CONFIG_ARMV8_CE_SHA1
spl_hash_android(struct task_data * data)150*36c449feSJoseph Chen int spl_hash_android(struct task_data *data)
151*36c449feSJoseph Chen {
152*36c449feSJoseph Chen 	struct andr_img_hdr *hdr = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
153*36c449feSJoseph Chen 	sha1_context ctx;
154*36c449feSJoseph Chen 	uchar hash[32];
155*36c449feSJoseph Chen 	void *buf;
156*36c449feSJoseph Chen 
157*36c449feSJoseph Chen 	printf("== Android: hash start\n");
158*36c449feSJoseph Chen 
159*36c449feSJoseph Chen 	if (hdr->header_version >= 3)
160*36c449feSJoseph Chen 		return -EINVAL;
161*36c449feSJoseph Chen 
162*36c449feSJoseph Chen 	sha1_starts(&ctx);
163*36c449feSJoseph Chen 
164*36c449feSJoseph Chen 	buf = (void *)hdr + hdr->page_size;
165*36c449feSJoseph Chen 	sha1_update(&ctx, (const uchar *)buf, hdr->kernel_size);
166*36c449feSJoseph Chen 	sha1_update(&ctx, (const uchar *)&hdr->kernel_size, sizeof(hdr->kernel_size));
167*36c449feSJoseph Chen 
168*36c449feSJoseph Chen 	buf += ALIGN(hdr->kernel_size, hdr->page_size);
169*36c449feSJoseph Chen 	sha1_update(&ctx, (const uchar *)buf, hdr->ramdisk_size);
170*36c449feSJoseph Chen 	sha1_update(&ctx, (const uchar *)&hdr->ramdisk_size, sizeof(hdr->ramdisk_size));
171*36c449feSJoseph Chen 
172*36c449feSJoseph Chen 	buf += ALIGN(hdr->ramdisk_size, hdr->page_size);
173*36c449feSJoseph Chen 	sha1_update(&ctx, (const uchar *)buf, hdr->second_size);
174*36c449feSJoseph Chen 	sha1_update(&ctx, (const uchar *)&hdr->second_size, sizeof(hdr->second_size));
175*36c449feSJoseph Chen 
176*36c449feSJoseph Chen 	if (hdr->header_version > 0) {
177*36c449feSJoseph Chen 		buf += ALIGN(hdr->second_size, hdr->page_size);
178*36c449feSJoseph Chen 		sha1_update(&ctx, (const uchar *)buf, hdr->recovery_dtbo_size);
179*36c449feSJoseph Chen 		sha1_update(&ctx, (const uchar *)&hdr->recovery_dtbo_size, sizeof(hdr->recovery_dtbo_size));
180*36c449feSJoseph Chen 	}
181*36c449feSJoseph Chen 	if (hdr->header_version > 1) {
182*36c449feSJoseph Chen 		buf += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
183*36c449feSJoseph Chen 		sha1_update(&ctx, (const uchar *)buf, hdr->dtb_size);
184*36c449feSJoseph Chen 		sha1_update(&ctx, (const uchar *)&hdr->dtb_size, sizeof(hdr->dtb_size));
185*36c449feSJoseph Chen 	}
186*36c449feSJoseph Chen 
187*36c449feSJoseph Chen 	sha1_finish(&ctx, hash);
188*36c449feSJoseph Chen 
189*36c449feSJoseph Chen 	if (memcmp(hash, hdr->id, 20)) {
190*36c449feSJoseph Chen 		print_hash("Hash from header", (u8 *)hdr->id, 20);
191*36c449feSJoseph Chen 		print_hash("Hash real", (u8 *)hash, 20);
192*36c449feSJoseph Chen 		return -EBADFD;
193*36c449feSJoseph Chen 	}
194*36c449feSJoseph Chen 
195*36c449feSJoseph Chen 	printf("== Android: hash OK, 0x%08lx\n", (ulong)data->boot_addr);
196*36c449feSJoseph Chen 
197*36c449feSJoseph Chen 	return 0;
198*36c449feSJoseph Chen }
199*36c449feSJoseph Chen 
200*36c449feSJoseph Chen #else
spl_hash_android(struct task_data * data)201*36c449feSJoseph Chen int spl_hash_android(struct task_data *data)
202*36c449feSJoseph Chen {
203*36c449feSJoseph Chen 	struct andr_img_hdr *hdr = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
204*36c449feSJoseph Chen 	struct udevice *dev;
205*36c449feSJoseph Chen 	sha_context ctx;
206*36c449feSJoseph Chen 	uchar hash[32];
207*36c449feSJoseph Chen 	void *buf;
208*36c449feSJoseph Chen 
209*36c449feSJoseph Chen 	debug("== Android: hash start\n");
210*36c449feSJoseph Chen 
211*36c449feSJoseph Chen 	if (hdr->header_version >= 3)
212*36c449feSJoseph Chen 		return -EINVAL;
213*36c449feSJoseph Chen 
214*36c449feSJoseph Chen 	ctx.algo = CRYPTO_SHA1;
215*36c449feSJoseph Chen 	dev = crypto_get_device(ctx.algo);
216*36c449feSJoseph Chen 	if (!dev) {
217*36c449feSJoseph Chen 		printf("No crypto device for sha1\n");
218*36c449feSJoseph Chen 		return -ENODEV;
219*36c449feSJoseph Chen 	}
220*36c449feSJoseph Chen 
221*36c449feSJoseph Chen 	ctx.length = hdr->kernel_size + sizeof(hdr->kernel_size) +
222*36c449feSJoseph Chen 	      hdr->ramdisk_size + sizeof(hdr->ramdisk_size) +
223*36c449feSJoseph Chen 	      hdr->second_size + sizeof(hdr->second_size);
224*36c449feSJoseph Chen 	if (hdr->header_version > 0)
225*36c449feSJoseph Chen 		ctx.length += hdr->recovery_dtbo_size + sizeof(hdr->recovery_dtbo_size);
226*36c449feSJoseph Chen 	if (hdr->header_version > 1)
227*36c449feSJoseph Chen 		ctx.length += hdr->dtb_size + sizeof(hdr->dtb_size);
228*36c449feSJoseph Chen 
229*36c449feSJoseph Chen 	crypto_sha_init(dev, &ctx);
230*36c449feSJoseph Chen 
231*36c449feSJoseph Chen 	buf = (void *)hdr + hdr->page_size;
232*36c449feSJoseph Chen 	crypto_sha_update(dev, buf, hdr->kernel_size);
233*36c449feSJoseph Chen 	crypto_sha_update(dev, &hdr->kernel_size, sizeof(hdr->kernel_size));
234*36c449feSJoseph Chen 
235*36c449feSJoseph Chen 	buf += ALIGN(hdr->kernel_size, hdr->page_size);
236*36c449feSJoseph Chen 	crypto_sha_update(dev, buf, hdr->ramdisk_size);
237*36c449feSJoseph Chen 	crypto_sha_update(dev, &hdr->ramdisk_size, sizeof(hdr->ramdisk_size));
238*36c449feSJoseph Chen 
239*36c449feSJoseph Chen 	buf += ALIGN(hdr->ramdisk_size, hdr->page_size);
240*36c449feSJoseph Chen 	crypto_sha_update(dev, buf, hdr->second_size);
241*36c449feSJoseph Chen 	crypto_sha_update(dev, &hdr->second_size, sizeof(hdr->second_size));
242*36c449feSJoseph Chen 
243*36c449feSJoseph Chen 	if (hdr->header_version > 0) {
244*36c449feSJoseph Chen 		buf += ALIGN(hdr->second_size, hdr->page_size);
245*36c449feSJoseph Chen 		crypto_sha_update(dev, buf, hdr->recovery_dtbo_size);
246*36c449feSJoseph Chen 		crypto_sha_update(dev, &hdr->recovery_dtbo_size, sizeof(hdr->recovery_dtbo_size));
247*36c449feSJoseph Chen 	}
248*36c449feSJoseph Chen 	if (hdr->header_version > 1) {
249*36c449feSJoseph Chen 		buf += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
250*36c449feSJoseph Chen 		crypto_sha_update(dev, buf, hdr->dtb_size);
251*36c449feSJoseph Chen 		crypto_sha_update(dev, &hdr->dtb_size, sizeof(hdr->dtb_size));
252*36c449feSJoseph Chen 	}
253*36c449feSJoseph Chen 
254*36c449feSJoseph Chen 	crypto_sha_final(dev, &ctx, hash);
255*36c449feSJoseph Chen 
256*36c449feSJoseph Chen 	if (memcmp(hash, hdr->id, 20)) {
257*36c449feSJoseph Chen 		print_hash("Hash from header", (u8 *)hdr->id, 20);
258*36c449feSJoseph Chen 		print_hash("Hash real", (u8 *)hash, 20);
259*36c449feSJoseph Chen 		return -EBADFD;
260*36c449feSJoseph Chen 	}
261*36c449feSJoseph Chen 
262*36c449feSJoseph Chen 	debug("== Android: hash OK, 0x%08lx\n", (ulong)data->boot_addr);
263*36c449feSJoseph Chen 
264*36c449feSJoseph Chen 	return 0;
265*36c449feSJoseph Chen }
266*36c449feSJoseph Chen 
267*36c449feSJoseph Chen #endif
268*36c449feSJoseph Chen #endif
269*36c449feSJoseph Chen 
270*36c449feSJoseph Chen #ifdef CONFIG_ROCKCHIP_FIT_IMAGE
spl_load_fit(struct task_data * data)271*36c449feSJoseph Chen int spl_load_fit(struct task_data *data)
272*36c449feSJoseph Chen {
273*36c449feSJoseph Chen 	struct spl_load_info *info = &data->info;
274*36c449feSJoseph Chen 	void *buf = (void *)CONFIG_SPL_BOOT_IMAGE_BUF;
275*36c449feSJoseph Chen 	disk_partition_t part;
276*36c449feSJoseph Chen 	ulong blkcnt;
277*36c449feSJoseph Chen 	int size;
278*36c449feSJoseph Chen 
279*36c449feSJoseph Chen 	debug("== FIT: load start\n");
280*36c449feSJoseph Chen 
281*36c449feSJoseph Chen 	if (part_get_info_by_name(info->dev, "boot", &part) < 0) {
282*36c449feSJoseph Chen 	        printf("No boot partition\n");
283*36c449feSJoseph Chen 		return -ENOENT;
284*36c449feSJoseph Chen 	}
285*36c449feSJoseph Chen 
286*36c449feSJoseph Chen 	blkcnt = BLK_CNT(sizeof(struct fdt_header), info->bl_len);
287*36c449feSJoseph Chen 	if (info->read(info, part.start, blkcnt, buf) != blkcnt)
288*36c449feSJoseph Chen 		return -EIO;
289*36c449feSJoseph Chen 
290*36c449feSJoseph Chen 	if (fdt_check_header(buf))
291*36c449feSJoseph Chen 		return -EINVAL;
292*36c449feSJoseph Chen 
293*36c449feSJoseph Chen 	size = fit_get_totalsize(buf, &size);
294*36c449feSJoseph Chen 	blkcnt = BLK_CNT(size, info->bl_len);
295*36c449feSJoseph Chen 	if (info->read(info, part.start, blkcnt, buf) != blkcnt)
296*36c449feSJoseph Chen 		return -EIO;
297*36c449feSJoseph Chen 
298*36c449feSJoseph Chen 	flush_dcache_range((ulong)buf, (ulong)buf + blkcnt);
299*36c449feSJoseph Chen 
300*36c449feSJoseph Chen 	debug("== FIT: load 0x%08x size OK\n", size);
301*36c449feSJoseph Chen 
302*36c449feSJoseph Chen 	return 0;
303*36c449feSJoseph Chen }
304*36c449feSJoseph Chen #endif
305*36c449feSJoseph Chen 
306