xref: /rk3399_rockchip-uboot/common/image-android.c (revision 2a3fb7bb049d69d96f3bc7dae8caa756fdc8a613)
1 /*
2  * Copyright (c) 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de>
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <image.h>
9 #include <android_image.h>
10 #include <android_bootloader.h>
11 #include <malloc.h>
12 #include <mapmem.h>
13 #include <errno.h>
14 #include <boot_rkimg.h>
15 #include <crypto.h>
16 #include <sysmem.h>
17 #include <u-boot/sha1.h>
18 #ifdef CONFIG_RKIMG_BOOTLOADER
19 #include <asm/arch/resource_img.h>
20 #endif
21 #ifdef CONFIG_RK_AVB_LIBAVB_USER
22 #include <android_avb/avb_slot_verify.h>
23 #include <android_avb/avb_ops_user.h>
24 #include <android_avb/rk_avb_ops_user.h>
25 #endif
26 #include <optee_include/OpteeClientInterface.h>
27 
28 DECLARE_GLOBAL_DATA_PTR;
29 
30 #define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR	0x10008000
31 #define ANDROID_ARG_FDT_FILENAME		"rk-kernel.dtb"
32 #define ANDROID_Q_VER				10
33 #define ANDROID_PARTITION_VENDOR_BOOT		"vendor_boot"
34 
35 #define BLK_CNT(_num_bytes, _block_size)	\
36 		((_num_bytes + _block_size - 1) / _block_size)
37 
38 static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1];
39 static u32 android_kernel_comp_type = IH_COMP_NONE;
40 
41 u32 android_image_major_version(void)
42 {
43 	/* MSB 7-bits */
44 	return gd->bd->bi_andr_version >> 25;
45 }
46 
47 u32 android_bcb_msg_sector_offset(void)
48 {
49 	/*
50 	 * Rockchip platforms defines BCB message at the 16KB offset of
51 	 * misc partition while the Google defines it at 0x00 offset.
52 	 *
53 	 * From Android-Q, the 0x00 offset is mandary on Google VTS, so that
54 	 * this is a compatibility according to android image 'os_version'.
55 	 */
56 #ifdef CONFIG_RKIMG_BOOTLOADER
57 	return (android_image_major_version() >= ANDROID_Q_VER) ? 0x00 : 0x20;
58 #else
59 	return 0x00;
60 #endif
61 }
62 
63 static ulong android_image_get_kernel_addr(const struct andr_img_hdr *hdr)
64 {
65 	/*
66 	 * All the Android tools that generate a boot.img use this
67 	 * address as the default.
68 	 *
69 	 * Even though it doesn't really make a lot of sense, and it
70 	 * might be valid on some platforms, we treat that address as
71 	 * the default value for this field, and try to execute the
72 	 * kernel in place in such a case.
73 	 *
74 	 * Otherwise, we will return the actual value set by the user.
75 	 */
76 	if (hdr->kernel_addr == ANDROID_IMAGE_DEFAULT_KERNEL_ADDR)
77 		return (ulong)hdr + hdr->page_size;
78 
79 #ifdef CONFIG_ARCH_ROCKCHIP
80 	/*
81 	 * If kernel is compressed, kernel_addr is set as decompressed address
82 	 * after compressed being loaded to ram, so let's use it.
83 	 */
84 	if (android_kernel_comp_type != IH_COMP_NONE &&
85 	    android_kernel_comp_type != IH_COMP_ZIMAGE)
86 		return hdr->kernel_addr;
87 
88 	/*
89 	 * Compatble with rockchip legacy packing with kernel/ramdisk/second
90 	 * address base from 0x60000000(SDK versiont < 8.1), these are invalid
91 	 * address, so we calc it by real size.
92 	 */
93 	return (ulong)hdr + hdr->page_size;
94 #else
95 	return hdr->kernel_addr;
96 #endif
97 
98 }
99 
100 void android_image_set_comp(struct andr_img_hdr *hdr, u32 comp)
101 {
102 	android_kernel_comp_type = comp;
103 }
104 
105 u32 android_image_get_comp(const struct andr_img_hdr *hdr)
106 {
107 	return android_kernel_comp_type;
108 }
109 
110 int android_image_parse_kernel_comp(const struct andr_img_hdr *hdr)
111 {
112 	ulong kaddr = android_image_get_kernel_addr(hdr);
113 	return bootm_parse_comp((const unsigned char *)kaddr);
114 }
115 
116 /**
117  * android_image_get_kernel() - processes kernel part of Android boot images
118  * @hdr:	Pointer to image header, which is at the start
119  *			of the image.
120  * @verify:	Checksum verification flag. Currently unimplemented.
121  * @os_data:	Pointer to a ulong variable, will hold os data start
122  *			address.
123  * @os_len:	Pointer to a ulong variable, will hold os data length.
124  *
125  * This function returns the os image's start address and length. Also,
126  * it appends the kernel command line to the bootargs env variable.
127  *
128  * Return: Zero, os start address and length on success,
129  *		otherwise on failure.
130  */
131 int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
132 			     ulong *os_data, ulong *os_len)
133 {
134 	u32 kernel_addr = android_image_get_kernel_addr(hdr);
135 	const char *cmdline = hdr->header_version < 3 ?
136 			      hdr->cmdline : hdr->total_cmdline;
137 	/*
138 	 * Not all Android tools use the id field for signing the image with
139 	 * sha1 (or anything) so we don't check it. It is not obvious that the
140 	 * string is null terminated so we take care of this.
141 	 */
142 	strncpy(andr_tmp_str, hdr->name, ANDR_BOOT_NAME_SIZE);
143 	andr_tmp_str[ANDR_BOOT_NAME_SIZE] = '\0';
144 	if (strlen(andr_tmp_str))
145 		printf("Android's image name: %s\n", andr_tmp_str);
146 
147 	printf("Kernel load addr 0x%08x size %u KiB\n",
148 	       kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024));
149 
150 	int len = 0;
151 	if (cmdline) {
152 		debug("Kernel command line: %s\n", cmdline);
153 		len += strlen(cmdline);
154 	}
155 
156 	char *bootargs = env_get("bootargs");
157 	if (bootargs)
158 		len += strlen(bootargs);
159 
160 	char *newbootargs = malloc(len + 2);
161 	if (!newbootargs) {
162 		puts("Error: malloc in android_image_get_kernel failed!\n");
163 		return -ENOMEM;
164 	}
165 	*newbootargs = '\0';
166 
167 	if (bootargs) {
168 		strcpy(newbootargs, bootargs);
169 		strcat(newbootargs, " ");
170 	}
171 	if (cmdline)
172 		strcat(newbootargs, cmdline);
173 
174 	env_set("bootargs", newbootargs);
175 
176 	if (os_data) {
177 		*os_data = (ulong)hdr;
178 		*os_data += hdr->page_size;
179 	}
180 	if (os_len)
181 		*os_len = hdr->kernel_size;
182 	return 0;
183 }
184 
185 int android_image_check_header(const struct andr_img_hdr *hdr)
186 {
187 	return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE);
188 }
189 
190 ulong android_image_get_end(const struct andr_img_hdr *hdr)
191 {
192 	ulong end;
193 	/*
194 	 * The header takes a full page, the remaining components are aligned
195 	 * on page boundary
196 	 */
197 	end = (ulong)hdr;
198 	if (hdr->header_version < 3) {
199 		end += hdr->page_size;
200 		end += ALIGN(hdr->kernel_size, hdr->page_size);
201 		end += ALIGN(hdr->ramdisk_size, hdr->page_size);
202 		end += ALIGN(hdr->second_size, hdr->page_size);
203 		if (hdr->header_version == 1) {
204 			end += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
205 		} else if (hdr->header_version == 2) {
206 			end += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
207 			end += ALIGN(hdr->dtb_size, hdr->page_size);
208 		}
209 	} else {
210 		/* boot_img_hdr_v3 */
211 		end += hdr->page_size;
212 		end += ALIGN(hdr->kernel_size, hdr->page_size);
213 		end += ALIGN(hdr->ramdisk_size, hdr->page_size);
214 	}
215 
216 	return end;
217 }
218 
219 u32 android_image_get_ksize(const struct andr_img_hdr *hdr)
220 {
221 	return hdr->kernel_size;
222 }
223 
224 void android_image_set_kload(struct andr_img_hdr *hdr, u32 load_address)
225 {
226 	hdr->kernel_addr = load_address;
227 }
228 
229 ulong android_image_get_kload(const struct andr_img_hdr *hdr)
230 {
231 	return android_image_get_kernel_addr(hdr);
232 }
233 
234 int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
235 			      ulong *rd_data, ulong *rd_len)
236 {
237 	ulong ramdisk_addr_r;
238 
239 	if (!hdr->ramdisk_size) {
240 		*rd_data = *rd_len = 0;
241 		return -1;
242 	}
243 
244 	/* Have been loaded by android_image_load_separate() on ramdisk_addr_r */
245 	ramdisk_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0);
246 	if (!ramdisk_addr_r) {
247 		printf("No Found Ramdisk Load Address.\n");
248 		return -1;
249 	}
250 
251 	*rd_data = ramdisk_addr_r;
252 	*rd_len = hdr->ramdisk_size;
253 
254 	printf("RAM disk load addr 0x%08lx size %u KiB\n",
255 	       *rd_data, DIV_ROUND_UP(hdr->ramdisk_size, 1024));
256 
257 	return 0;
258 }
259 
260 int android_image_get_fdt(const struct andr_img_hdr *hdr,
261 			      ulong *rd_data)
262 {
263 	ulong fdt_addr_r;
264 
265 	if (!hdr->second_size) {
266 		*rd_data = 0;
267 		return -1;
268 	}
269 
270 	/* Have been loaded by android_image_load_separate() on fdt_addr_r */
271 	fdt_addr_r = env_get_ulong("fdt_addr_r", 16, 0);
272 	if (!fdt_addr_r) {
273 		printf("No Found FDT Load Address.\n");
274 		return -1;
275 	}
276 
277 	*rd_data = fdt_addr_r;
278 
279 	debug("FDT load addr 0x%08x size %u KiB\n",
280 	      hdr->second_addr, DIV_ROUND_UP(hdr->second_size, 1024));
281 
282 	return 0;
283 }
284 
285 #if defined(CONFIG_DM_CRYPTO) && defined(CONFIG_ANDROID_BOOT_IMAGE_HASH)
286 static void print_hash(const char *label, u8 *hash, int len)
287 {
288 	int i;
289 
290 	printf("%s:\n    0x", label ? : "Hash");
291 	for (i = 0; i < len; i++)
292 		printf("%02x", hash[i]);
293 	printf("\n");
294 }
295 #endif
296 
297 typedef enum {
298 	IMG_KERNEL,
299 	IMG_RAMDISK,
300 	IMG_SECOND,
301 	IMG_RECOVERY_DTBO,
302 	IMG_RK_DTB,	/* within resource.img in second position */
303 	IMG_DTB,
304 	IMG_VENDOR_RAMDISK,
305 	IMG_MAX,
306 } img_t;
307 
308 static int image_load(img_t img, struct andr_img_hdr *hdr,
309 		      ulong blkstart, void *ram_base,
310 		      struct udevice *crypto)
311 {
312 	struct blk_desc *desc = rockchip_get_bootdev();
313 	disk_partition_t part_vendor_boot;
314 	__maybe_unused u32 sizesz;
315 	ulong pgsz = hdr->page_size;
316 	ulong blksz = desc->blksz;
317 	ulong blkcnt, blkoff;
318 	ulong orgdst = 0;
319 	ulong offset = 0;
320 	ulong extra = 0;
321 	ulong datasz;
322 	void *ramdst;
323 	int ret = 0;
324 
325 	switch (img) {
326 	case IMG_KERNEL:
327 		offset = 0; /* include a page_size(image header) */
328 		blkcnt = DIV_ROUND_UP(hdr->kernel_size + pgsz, blksz);
329 		ramdst = (void *)env_get_ulong("android_addr_r", 16, 0);
330 		datasz = hdr->kernel_size + pgsz;
331 		sizesz = sizeof(hdr->kernel_size);
332 		if (!sysmem_alloc_base(MEM_KERNEL,
333 				(phys_addr_t)ramdst, blkcnt * blksz))
334 			return -ENOMEM;
335 		break;
336 	case IMG_VENDOR_RAMDISK:
337 		if (part_get_info_by_name(desc,
338 					  ANDROID_PARTITION_VENDOR_BOOT,
339 					  &part_vendor_boot) < 0) {
340 			printf("No vendor boot partition\n");
341 			return -ENOENT;
342 		}
343 		/* Always load vendor boot from storage: avb full load boot/recovery */
344 		blkstart = part_vendor_boot.start;
345 		ram_base = 0;
346 
347 		pgsz = hdr->vendor_page_size;
348 		offset = ALIGN(VENDOR_BOOT_HDR_SIZE, pgsz);
349 		blkcnt = DIV_ROUND_UP(hdr->vendor_ramdisk_size, blksz);
350 		ramdst = (void *)env_get_ulong("ramdisk_addr_r", 16, 0);
351 		datasz = hdr->vendor_ramdisk_size;
352 		sizesz = sizeof(hdr->vendor_ramdisk_size);
353 		/*
354 		 * Add extra memory for generic ramdisk space.
355 		 *
356 		 * In case of unaligned vendor ramdisk size, reserve
357 		 * 1 more blksz.
358 		 */
359 		if (hdr->header_version == 3)
360 			extra = ALIGN(hdr->ramdisk_size, blksz) + blksz;
361 		if (datasz && !sysmem_alloc_base(MEM_RAMDISK,
362 			(phys_addr_t)ramdst, blkcnt * blksz + extra))
363 			return -ENOMEM;
364 		break;
365 	case IMG_RAMDISK:
366 		offset = pgsz + ALIGN(hdr->kernel_size, pgsz);
367 		blkcnt = DIV_ROUND_UP(hdr->ramdisk_size, blksz);
368 		ramdst = (void *)env_get_ulong("ramdisk_addr_r", 16, 0);
369 		/*
370 		 * ramdisk_addr_r:
371 		 *	|----------------|---------|
372 		 *	| vendor-ramdisk | ramdisk |
373 		 *	|----------------|---------|
374 		 */
375 		if (hdr->header_version >= 3) {
376 			ramdst += hdr->vendor_ramdisk_size;
377 			if (!IS_ALIGNED((ulong)ramdst, blksz)) {
378 				orgdst = (ulong)ramdst;
379 				ramdst = (void *)ALIGN(orgdst, blksz);
380 			}
381 		}
382 		datasz = hdr->ramdisk_size;
383 		sizesz = sizeof(hdr->ramdisk_size);
384 		/*
385 		 * skip v3: sysmem has been alloced by vendor ramdisk.
386 		 */
387 		if (hdr->header_version < 3) {
388 			if (datasz && !sysmem_alloc_base(MEM_RAMDISK,
389 				(phys_addr_t)ramdst, blkcnt * blksz))
390 				return -ENOMEM;
391 		}
392 		break;
393 	case IMG_SECOND:
394 		offset = pgsz +
395 			 ALIGN(hdr->kernel_size, pgsz) +
396 			 ALIGN(hdr->ramdisk_size, pgsz);
397 		blkcnt = DIV_ROUND_UP(hdr->second_size, blksz);
398 		datasz = hdr->second_size;
399 		sizesz = sizeof(hdr->second_size);
400 		ramdst = malloc(blkcnt * blksz);
401 		break;
402 	case IMG_RECOVERY_DTBO:
403 		offset = pgsz +
404 			 ALIGN(hdr->kernel_size, pgsz) +
405 			 ALIGN(hdr->ramdisk_size, pgsz) +
406 			 ALIGN(hdr->second_size, pgsz);
407 		blkcnt = DIV_ROUND_UP(hdr->recovery_dtbo_size, blksz);
408 		datasz = hdr->recovery_dtbo_size;
409 		sizesz = sizeof(hdr->recovery_dtbo_size);
410 		ramdst = malloc(blkcnt * blksz);
411 		break;
412 	case IMG_DTB:
413 		offset = pgsz +
414 			 ALIGN(hdr->kernel_size, pgsz) +
415 			 ALIGN(hdr->ramdisk_size, pgsz) +
416 			 ALIGN(hdr->second_size, pgsz) +
417 			 ALIGN(hdr->recovery_dtbo_size, pgsz);
418 		blkcnt = DIV_ROUND_UP(hdr->dtb_size, blksz);
419 		datasz = hdr->dtb_size;
420 		sizesz = sizeof(hdr->dtb_size);
421 		ramdst = malloc(blkcnt * blksz);
422 		break;
423 	case IMG_RK_DTB:
424 #ifdef CONFIG_RKIMG_BOOTLOADER
425 		/* No going further, it handles DTBO, HW-ID, etc */
426 		ramdst = (void *)env_get_ulong("fdt_addr_r", 16, 0);
427 		if (gd->fdt_blob != (void *)ramdst)
428 			ret = rockchip_read_dtb_file(ramdst);
429 #endif
430 		return ret < 0 ? ret : 0;
431 	default:
432 		return -EINVAL;
433 	}
434 
435 	if (!ramdst) {
436 		printf("No memory for image(%d)\n", img);
437 		return -ENOMEM;
438 	}
439 
440 	if (!blksz || !datasz)
441 		goto crypto_calc;
442 
443 	/* load */
444 	if (ram_base) {
445 		memcpy(ramdst, (char *)((ulong)ram_base + offset), datasz);
446 	} else {
447 		blkoff = DIV_ROUND_UP(offset, blksz);
448 		ret = blk_dread(desc, blkstart + blkoff, blkcnt, ramdst);
449 		if (ret != blkcnt) {
450 			printf("Failed to read img(%d), ret=%d\n", img, ret);
451 			return -EIO;
452 		}
453 	}
454 
455 	if (orgdst)
456 		memmove((char *)orgdst, ramdst, datasz);
457 
458 crypto_calc:
459 	/* sha1 */
460 #ifdef CONFIG_DM_CRYPTO
461 	if (crypto) {
462 		if (img == IMG_KERNEL) {
463 			ramdst += pgsz;
464 			datasz -= pgsz;
465 		}
466 
467 		crypto_sha_update(crypto, (u32 *)ramdst, datasz);
468 		crypto_sha_update(crypto, (u32 *)&datasz, sizesz);
469 	}
470 #endif
471 
472 	return 0;
473 }
474 
475 /*
476  * @ram_base: !NULL means require memcpy for an exist full android image.
477  */
478 static int android_image_separate(struct andr_img_hdr *hdr,
479 				  const disk_partition_t *part,
480 				  void *load_address,
481 				  void *ram_base)
482 {
483 	ulong bstart;
484 
485 	if (android_image_check_header(hdr)) {
486 		printf("Bad android image header\n");
487 		return -EINVAL;
488 	}
489 
490 	/* set for image_load(IMG_KERNEL, ...) */
491 	env_set_hex("android_addr_r", (ulong)load_address);
492 	bstart = part ? part->start : 0;
493 
494 	/*
495 	 * 1. Load images to their individual target ram position
496 	 *    in order to disable fdt/ramdisk relocation.
497 	 */
498 #if defined(CONFIG_DM_CRYPTO) && defined(CONFIG_ANDROID_BOOT_IMAGE_HASH)
499 	struct udevice *dev;
500 	sha_context ctx;
501 	uchar hash[20];
502 
503 	ctx.length = 0;
504 	ctx.algo = CRYPTO_SHA1;
505 	dev = crypto_get_device(ctx.algo);
506 	if (!dev) {
507 		printf("Can't find crypto device for SHA1 capability\n");
508 		return -ENODEV;
509 	}
510 
511   #ifdef CONFIG_ROCKCHIP_CRYPTO_V1
512 	/* v1: requires total length before sha init */
513 	ctx.length += hdr->kernel_size + sizeof(hdr->kernel_size) +
514 		      hdr->ramdisk_size + sizeof(hdr->ramdisk_size) +
515 		      hdr->second_size + sizeof(hdr->second_size);
516 	if (hdr->header_version > 0)
517 		ctx.length += hdr->recovery_dtbo_size +
518 					sizeof(hdr->recovery_dtbo_size);
519 	if (hdr->header_version > 1)
520 		ctx.length += hdr->dtb_size + sizeof(hdr->dtb_size);
521   #endif
522 	crypto_sha_init(dev, &ctx);
523 
524 	/* load, never change order ! */
525 	if (image_load(IMG_RK_DTB,  hdr, bstart, ram_base, NULL))
526 		return -1;
527 	if (image_load(IMG_KERNEL,  hdr, bstart, ram_base, dev))
528 		return -1;
529 	if (image_load(IMG_RAMDISK, hdr, bstart, ram_base, dev))
530 		return -1;
531 	if (image_load(IMG_SECOND,  hdr, bstart, ram_base, dev))
532 		return -1;
533 	if (hdr->header_version > 0) {
534 		if (image_load(IMG_RECOVERY_DTBO, hdr, bstart, ram_base, dev))
535 			return -1;
536 	}
537 	if (hdr->header_version > 1) {
538 		if (image_load(IMG_DTB, hdr, bstart, ram_base, dev))
539 			return -1;
540 	}
541 
542 	crypto_sha_final(dev, &ctx, hash);
543 	if (memcmp(hash, hdr->id, 20)) {
544 		print_hash("Hash from header", (u8 *)hdr->id, 20);
545 		print_hash("Hash real", (u8 *)hash, 20);
546 		return -EBADFD;
547 	} else {
548 		printf("Image hash OK\n");
549 	}
550 
551 #else /* !(CONFIG_DM_CRYPTO && CONFIG_ANDROID_BOOT_IMAGE_HASH) */
552 	if (image_load(IMG_RK_DTB,  hdr, bstart, ram_base, NULL))
553 		return -1;
554 	if (image_load(IMG_KERNEL,  hdr, bstart, ram_base, NULL))
555 		return -1;
556 	if (image_load(IMG_RAMDISK, hdr, bstart, ram_base, NULL))
557 		return -1;
558 	if (image_load(IMG_SECOND,  hdr, bstart, ram_base, NULL))
559 		return -1;
560 	if (hdr->header_version > 0) {
561 		if (image_load(IMG_RECOVERY_DTBO, hdr, bstart, ram_base, NULL))
562 			return -1;
563 	}
564 	if (hdr->header_version > 1) {
565 		if (image_load(IMG_DTB, hdr, bstart, ram_base, NULL))
566 			return -1;
567 	}
568 #endif
569 
570 	/* 2. Disable fdt/ramdisk relocation, it saves boot time */
571 	env_set("bootm-no-reloc", "y");
572 
573 	return 0;
574 }
575 
576 static int android_image_separate_v3(struct andr_img_hdr *hdr,
577 				     const disk_partition_t *part,
578 				     void *load_address, void *ram_base)
579 {
580 	ulong bstart;
581 
582 	if (android_image_check_header(hdr)) {
583 		printf("Bad android image header\n");
584 		return -EINVAL;
585 	}
586 
587 	/* set for image_load(IMG_KERNEL, ...) */
588 	env_set_hex("android_addr_r", (ulong)load_address);
589 	bstart = part ? part->start : 0;
590 
591 	/*
592 	 * 1. Load images to their individual target ram position
593 	 *    in order to disable fdt/ramdisk relocation.
594 	 */
595 	if (image_load(IMG_RK_DTB,  hdr, bstart, ram_base, NULL))
596 		return -1;
597 	if (image_load(IMG_KERNEL,  hdr, bstart, ram_base, NULL))
598 		return -1;
599 	if (image_load(IMG_VENDOR_RAMDISK, hdr, bstart, ram_base, NULL))
600 		return -1;
601 	if (image_load(IMG_RAMDISK, hdr, bstart, ram_base, NULL))
602 		return -1;
603 
604 	/*
605 	 * Copy the populated hdr to load address after image_load(IMG_KERNEL)
606 	 *
607 	 * The image_load(IMG_KERNEL) only reads boot_img_hdr_v3 while
608 	 * vendor_boot_img_hdr_v3 is not included, so fix it here.
609 	 */
610 	memcpy((char *)load_address, hdr, hdr->page_size);
611 
612 	/* 2. Disable fdt/ramdisk relocation, it saves boot time */
613 	env_set("bootm-no-reloc", "y");
614 
615 	return 0;
616 }
617 
618 static ulong android_image_get_comp_addr(struct andr_img_hdr *hdr, int comp)
619 {
620 	ulong kernel_addr_c;
621 	ulong load_addr = 0;
622 
623 	kernel_addr_c = env_get_ulong("kernel_addr_c", 16, 0);
624 
625 #ifdef CONFIG_ARM64
626 	/*
627 	 * On 64-bit kernel, assuming use IMAGE by default.
628 	 *
629 	 * kernel_addr_c is for LZ4-IMAGE but maybe not defined.
630 	 * kernel_addr_r is for IMAGE.
631 	 */
632 	if (comp != IH_COMP_NONE) {
633 		ulong comp_addr;
634 
635 		if (kernel_addr_c) {
636 			comp_addr = kernel_addr_c;
637 		} else {
638 			printf("Warn: No \"kernel_addr_c\"\n");
639 			comp_addr = CONFIG_SYS_SDRAM_BASE + 0x2000000;/* 32M */
640 			env_set_hex("kernel_addr_c", comp_addr);
641 		}
642 
643 		load_addr = comp_addr - hdr->page_size;
644 	}
645 #else
646 	/*
647 	 * On 32-bit kernel:
648 	 *
649 	 * The input load_addr is from env value: "kernel_addr_r", it has
650 	 * different role depends on whether kernel_addr_c is defined:
651 	 *
652 	 * - kernel_addr_r is for lz4/zImage if kernel_addr_c if [not] defined.
653 	 * - kernel_addr_r is for IMAGE if kernel_addr_c is defined.
654 	 */
655 	if (comp == IH_COMP_NONE) {
656 		if (kernel_addr_c) {
657 			/* input load_addr is for Image, nothing to do */
658 		} else {
659 			/* input load_addr is for lz4/zImage, set default addr for Image */
660 			load_addr = CONFIG_SYS_SDRAM_BASE + 0x8000;
661 			env_set_hex("kernel_addr_r", load_addr);
662 
663 			load_addr -= hdr->page_size;
664 		}
665 	} else {
666 		if (kernel_addr_c) {
667 			/* input load_addr is for Image, so use another for lz4/zImage */
668 			load_addr = kernel_addr_c - hdr->page_size;
669 		} else {
670 			/* input load_addr is for lz4/zImage, nothing to do */
671 		}
672 	}
673 #endif
674 
675 	return load_addr;
676 }
677 
678 /*
679  * 'boot_android' cmd use "kernel_addr_r" as default load address !
680  * We update it according to compress type and "kernel_addr_c/r".
681  */
682 int android_image_parse_comp(struct andr_img_hdr *hdr, ulong *load_addr)
683 {
684 	ulong new_load_addr;
685 	int comp;
686 
687 	comp = android_image_parse_kernel_comp(hdr);
688 	env_set_ulong("os_comp", comp);
689 
690 	new_load_addr = android_image_get_comp_addr(hdr, comp);
691 	if (new_load_addr != 0)
692 		*load_addr = new_load_addr;
693 
694 	return comp;
695 }
696 
697 void android_image_set_decomp(struct andr_img_hdr *hdr, int comp)
698 {
699 	ulong kernel_addr_r;
700 
701 	/* zImage handles decompress itself */
702 	if (comp != IH_COMP_NONE && comp != IH_COMP_ZIMAGE) {
703 		kernel_addr_r = env_get_ulong("kernel_addr_r", 16, 0x02080000);
704 		android_image_set_kload(hdr, kernel_addr_r);
705 		android_image_set_comp(hdr, comp);
706 	} else {
707 		android_image_set_comp(hdr, IH_COMP_NONE);
708 	}
709 }
710 
711 static int android_image_load_separate(struct andr_img_hdr *hdr,
712 				       const disk_partition_t *part,
713 				       void *load_addr)
714 {
715 	if (hdr->header_version < 3)
716 		return android_image_separate(hdr, part, load_addr, NULL);
717 	else
718 		return android_image_separate_v3(hdr, part, load_addr, NULL);
719 }
720 
721 int android_image_memcpy_separate(struct andr_img_hdr *hdr, ulong *load_addr)
722 {
723 	ulong comp_addr = *load_addr;
724 	int comp;
725 
726 	comp = android_image_parse_comp(hdr, &comp_addr);
727 	if (comp_addr == (ulong)hdr)
728 		return 0;
729 
730 	if (hdr->header_version < 3) {
731 		if (android_image_separate(hdr, NULL, (void *)comp_addr, hdr))
732 			return -1;
733 	} else {
734 		if (android_image_separate_v3(hdr, NULL, (void *)comp_addr, hdr))
735 			return -1;
736 	}
737 
738 	*load_addr = comp_addr;
739 	android_image_set_decomp((void *)comp_addr, comp);
740 
741 	return 0;
742 }
743 
744 long android_image_load(struct blk_desc *dev_desc,
745 			const disk_partition_t *part_info,
746 			unsigned long load_address,
747 			unsigned long max_size) {
748 	struct andr_img_hdr *hdr;
749 	int comp, ret;
750 	int blk_off;
751 
752 	if (max_size < part_info->blksz)
753 		return -1;
754 
755 	hdr = populate_andr_img_hdr(dev_desc, (disk_partition_t *)part_info);
756 	if (!hdr) {
757 		printf("No valid android hdr\n");
758 		return -1;
759 	}
760 
761 	/*
762 	 * create the layout:
763 	 *
764 	 * |<- page_size ->|1-blk |
765 	 * |-----|---------|------|-----|
766 	 * | hdr |   ...   |   kernel   |
767 	 * |-----|----- ---|------------|
768 	 *
769 	 * Alloc page_size and 1 more blk for reading kernel image to
770 	 * get it's compression type, then fill the android hdr what
771 	 * we have populated before.
772 	 *
773 	 * Why? see: android_image_get_kernel_addr().
774 	 */
775 	blk_off = BLK_CNT(hdr->page_size, dev_desc->blksz);
776 	hdr = (struct andr_img_hdr *)
777 			realloc(hdr, (blk_off + 1) * dev_desc->blksz);
778 	if (!hdr)
779 		return -1;
780 
781 	if (blk_dread(dev_desc, part_info->start + blk_off, 1,
782 		      (char *)hdr + hdr->page_size) != 1) {
783 		free(hdr);
784 		return -1;
785 	}
786 
787 	/* Make kernel start address at load_address */
788 	load_address -= hdr->page_size;
789 
790 	/* Let's load kernel now ! */
791 	comp = android_image_parse_comp(hdr, &load_address);
792 	ret = android_image_load_separate(hdr, part_info, (void *)load_address);
793 	if (ret) {
794 		printf("Failed to load android image\n");
795 		goto fail;
796 	}
797 	android_image_set_decomp((void *)load_address, comp);
798 
799 	debug("Loading Android Image to 0x%08lx\n", load_address);
800 
801 	free(hdr);
802 	return load_address;
803 
804 fail:
805 	free(hdr);
806 	return -1;
807 }
808 
809 static struct andr_img_hdr *
810 extract_boot_image_v012_header(struct blk_desc *dev_desc,
811 			       const disk_partition_t *boot_img)
812 {
813 	struct andr_img_hdr *hdr;
814 	long blk_cnt, blks_read;
815 
816 	blk_cnt = BLK_CNT(sizeof(struct andr_img_hdr), dev_desc->blksz);
817 	hdr = (struct andr_img_hdr *)malloc(blk_cnt * dev_desc->blksz);
818 
819 	if (!blk_cnt || !hdr)
820 		return NULL;
821 
822 	blks_read = blk_dread(dev_desc, boot_img->start, blk_cnt, hdr);
823 	if (blks_read != blk_cnt) {
824 		debug("boot img header blk cnt is %ld and blks read is %ld\n",
825 		      blk_cnt, blks_read);
826 		return NULL;
827 	}
828 
829 	if (android_image_check_header((void *)hdr)) {
830 		printf("boot header magic is invalid.\n");
831 		return NULL;
832 	}
833 
834 	if (hdr->page_size < sizeof(*hdr)) {
835 		printf("android hdr is over size\n");
836 		return NULL;
837 	}
838 
839 	return hdr;
840 }
841 
842 static struct boot_img_hdr_v3 *
843 extract_boot_image_v3_header(struct blk_desc *dev_desc,
844 			     const disk_partition_t *boot_img)
845 {
846 	struct boot_img_hdr_v3 *boot_hdr;
847 	long blk_cnt, blks_read;
848 
849 	blk_cnt = BLK_CNT(sizeof(struct boot_img_hdr_v3), dev_desc->blksz);
850 	boot_hdr = (struct boot_img_hdr_v3 *)malloc(blk_cnt * dev_desc->blksz);
851 
852 	if (!blk_cnt || !boot_hdr)
853 		return NULL;
854 
855 	blks_read = blk_dread(dev_desc, boot_img->start, blk_cnt, boot_hdr);
856 	if (blks_read != blk_cnt) {
857 		debug("boot img header blk cnt is %ld and blks read is %ld\n",
858 		      blk_cnt, blks_read);
859 		return NULL;
860 	}
861 
862 	if (android_image_check_header((void *)boot_hdr)) {
863 		printf("boot header magic is invalid.\n");
864 		return NULL;
865 	}
866 
867 	if (boot_hdr->header_version != 3) {
868 		printf("boot header is not v3.\n");
869 		return NULL;
870 	}
871 
872 	return boot_hdr;
873 }
874 
875 static struct vendor_boot_img_hdr_v3 *
876 extract_vendor_boot_image_v3_header(struct blk_desc *dev_desc,
877 				    const disk_partition_t *part_vendor_boot)
878 {
879 	struct vendor_boot_img_hdr_v3 *vboot_hdr;
880 	long blk_cnt, blks_read;
881 
882 	blk_cnt = BLK_CNT(sizeof(struct vendor_boot_img_hdr_v3),
883 				part_vendor_boot->blksz);
884 	vboot_hdr = (struct vendor_boot_img_hdr_v3 *)
885 				malloc(blk_cnt * part_vendor_boot->blksz);
886 
887 	if (!blk_cnt || !vboot_hdr)
888 		return NULL;
889 
890 	blks_read = blk_dread(dev_desc, part_vendor_boot->start,
891 			      blk_cnt, vboot_hdr);
892 	if (blks_read != blk_cnt) {
893 		debug("vboot img header blk cnt is %ld and blks read is %ld\n",
894 		      blk_cnt, blks_read);
895 		return NULL;
896 	}
897 
898 	if (strncmp(VENDOR_BOOT_MAGIC, (void *)vboot_hdr->magic,
899 		    VENDOR_BOOT_MAGIC_SIZE)) {
900 		printf("vendor boot header is invalid.\n");
901 		return NULL;
902 	}
903 
904 	if (vboot_hdr->header_version != 3) {
905 		printf("vendor boot header is not v3.\n");
906 		return NULL;
907 	}
908 
909 	return vboot_hdr;
910 }
911 
912 static int populate_boot_info(const struct boot_img_hdr_v3 *boot_hdr,
913 			      const struct vendor_boot_img_hdr_v3 *vendor_hdr,
914 			      struct andr_img_hdr *hdr)
915 {
916 	memset(hdr->magic, 0, ANDR_BOOT_MAGIC_SIZE);
917 	memcpy(hdr->magic, boot_hdr->magic, ANDR_BOOT_MAGIC_SIZE);
918 
919 	hdr->kernel_size = boot_hdr->kernel_size;
920 	/* don't use vendor_hdr->kernel_addr, we prefer "hdr + hdr->page_size" */
921 	hdr->kernel_addr = ANDROID_IMAGE_DEFAULT_KERNEL_ADDR;
922 	/* generic ramdisk: immediately following the vendor ramdisk */
923 	hdr->ramdisk_size = boot_hdr->ramdisk_size +
924 				vendor_hdr->vendor_ramdisk_size;
925 	/* actually, useless */
926 	hdr->ramdisk_addr = vendor_hdr->ramdisk_addr +
927 				vendor_hdr->vendor_ramdisk_size;
928 	/* removed in v3 */
929 	hdr->second_size = 0;
930 	hdr->second_addr = 0;
931 
932 	hdr->tags_addr = vendor_hdr->tags_addr;
933 
934 	/* fixed in v3 */
935 	hdr->page_size = 4096;
936 	hdr->header_version = boot_hdr->header_version;
937 	hdr->os_version = boot_hdr->os_version;
938 
939 	memset(hdr->name, 0, ANDR_BOOT_NAME_SIZE);
940 	strncpy(hdr->name, (const char *)vendor_hdr->name, ANDR_BOOT_NAME_SIZE);
941 
942 	/* removed in v3 */
943 	memset(hdr->cmdline, 0, ANDR_BOOT_ARGS_SIZE);
944 	memset(hdr->id, 0, 32);
945 	memset(hdr->extra_cmdline, 0, ANDR_BOOT_EXTRA_ARGS_SIZE);
946 	hdr->recovery_dtbo_size = 0;
947 	hdr->recovery_dtbo_offset = 0;
948 
949 	hdr->header_size = boot_hdr->header_size;
950 	hdr->dtb_size = vendor_hdr->dtb_size;
951 	hdr->dtb_addr = vendor_hdr->dtb_addr;
952 
953 	/* boot_img_hdr_v3 fields */
954 	hdr->vendor_ramdisk_size = vendor_hdr->vendor_ramdisk_size;
955 	hdr->vendor_page_size = vendor_hdr->page_size;
956 	hdr->vendor_header_version = vendor_hdr->header_version;
957 	hdr->vendor_header_size = vendor_hdr->header_size;
958 
959 	hdr->total_cmdline = calloc(1, TOTAL_BOOT_ARGS_SIZE);
960 	if (!hdr->total_cmdline)
961 		return -ENOMEM;
962 	strncpy(hdr->total_cmdline, (const char *)boot_hdr->cmdline,
963 		sizeof(boot_hdr->cmdline));
964 	strncat(hdr->total_cmdline, " ", 1);
965 	strncat(hdr->total_cmdline, (const char *)vendor_hdr->cmdline,
966 		sizeof(vendor_hdr->cmdline));
967 
968 	if (hdr->page_size < sizeof(*hdr)) {
969 		printf("android hdr is over size\n");
970 		return -EINVAL;
971 	}
972 
973 	return 0;
974 }
975 
976 /*
977  * The possible cases of boot.img + recovery.img:
978  *
979  * [N]: 0, 1, 2
980  * [M]: 0, 1, 2, 3
981  *
982  * |--------------------|---------------------|
983  * |   boot.img         |    recovery.img     |
984  * |--------------------|---------------------|
985  * | boot_img_hdr_v[N]  |  boot_img_hdr_v[N]  | <= if A/B is not required
986  * |--------------------|---------------------|
987  * | boot_img_hdr_v3    |  boot_img_hdr_v2    | <= if A/B is not required
988  * |------------------------------------------|
989  * | boot_img_hdr_v[M], no recovery.img       | <= if A/B is required
990  * |------------------------------------------|
991  */
992 struct andr_img_hdr *populate_andr_img_hdr(struct blk_desc *dev_desc,
993 					   disk_partition_t *part_boot)
994 {
995 	disk_partition_t part_vendor_boot;
996 	struct vendor_boot_img_hdr_v3 *vboot_hdr;
997 	struct boot_img_hdr_v3 *boot_hdr;
998 	struct andr_img_hdr *andr_hdr;
999 	int header_version;
1000 
1001 	if (!dev_desc || !part_boot)
1002 		return NULL;
1003 
1004 	andr_hdr = (struct andr_img_hdr *)malloc(1 * dev_desc->blksz);
1005 	if (!andr_hdr)
1006 		return NULL;
1007 
1008 	if (blk_dread(dev_desc, part_boot->start, 1, andr_hdr) != 1) {
1009 		free(andr_hdr);
1010 		return NULL;
1011 	}
1012 
1013 	if (android_image_check_header(andr_hdr)) {
1014 		free(andr_hdr);
1015 		return NULL;
1016 	}
1017 
1018 	header_version = andr_hdr->header_version;
1019 	free(andr_hdr);
1020 
1021 	if (header_version < 3) {
1022 		return extract_boot_image_v012_header(dev_desc, part_boot);
1023 	} else {
1024 		if (part_get_info_by_name(dev_desc,
1025 					  ANDROID_PARTITION_VENDOR_BOOT,
1026 					  &part_vendor_boot) < 0) {
1027 			printf("No vendor boot partition\n");
1028 			return NULL;
1029 		}
1030 		boot_hdr = extract_boot_image_v3_header(dev_desc, part_boot);
1031 		vboot_hdr = extract_vendor_boot_image_v3_header(dev_desc,
1032 							&part_vendor_boot);
1033 		if (!boot_hdr || !vboot_hdr)
1034 			goto image_load_exit;
1035 
1036 		andr_hdr = (struct andr_img_hdr *)
1037 				malloc(sizeof(struct andr_img_hdr));
1038 		if (!andr_hdr) {
1039 			printf("No memory for andr hdr\n");
1040 			goto image_load_exit;
1041 		}
1042 
1043 		if (populate_boot_info(boot_hdr, vboot_hdr, andr_hdr)) {
1044 			printf("populate boot info failed\n");
1045 			goto image_load_exit;
1046 		}
1047 
1048 		free(boot_hdr);
1049 		free(vboot_hdr);
1050 
1051 		return andr_hdr;
1052 
1053 image_load_exit:
1054 		free(boot_hdr);
1055 		free(vboot_hdr);
1056 
1057 		return NULL;
1058 	}
1059 
1060 	return NULL;
1061 }
1062 
1063 #if !defined(CONFIG_SPL_BUILD)
1064 /**
1065  * android_print_contents - prints out the contents of the Android format image
1066  * @hdr: pointer to the Android format image header
1067  *
1068  * android_print_contents() formats a multi line Android image contents
1069  * description.
1070  * The routine prints out Android image properties
1071  *
1072  * returns:
1073  *     no returned results
1074  */
1075 void android_print_contents(const struct andr_img_hdr *hdr)
1076 {
1077 	const char * const p = IMAGE_INDENT_STRING;
1078 	/* os_version = ver << 11 | lvl */
1079 	u32 os_ver = hdr->os_version >> 11;
1080 	u32 os_lvl = hdr->os_version & ((1U << 11) - 1);
1081 	u32 header_version = hdr->header_version;
1082 
1083 	printf("%skernel size:      %x\n", p, hdr->kernel_size);
1084 	printf("%skernel address:   %x\n", p, hdr->kernel_addr);
1085 	printf("%sramdisk size:     %x\n", p, hdr->ramdisk_size);
1086 	printf("%sramdisk address: %x\n", p, hdr->ramdisk_addr);
1087 	printf("%ssecond size:      %x\n", p, hdr->second_size);
1088 	printf("%ssecond address:   %x\n", p, hdr->second_addr);
1089 	printf("%stags address:     %x\n", p, hdr->tags_addr);
1090 	printf("%spage size:        %x\n", p, hdr->page_size);
1091 	printf("%sheader_version:   %x\n", p, header_version);
1092 	/* ver = A << 14 | B << 7 | C         (7 bits for each of A, B, C)
1093 	 * lvl = ((Y - 2000) & 127) << 4 | M  (7 bits for Y, 4 bits for M) */
1094 	printf("%sos_version:       %x (ver: %u.%u.%u, level: %u.%u)\n",
1095 	       p, hdr->os_version,
1096 	       (os_ver >> 7) & 0x7F, (os_ver >> 14) & 0x7F, os_ver & 0x7F,
1097 	       (os_lvl >> 4) + 2000, os_lvl & 0x0F);
1098 	printf("%sname:             %s\n", p, hdr->name);
1099 	printf("%scmdline:          %s\n", p, hdr->cmdline);
1100 
1101 	if (header_version == 1 || header_version == 2) {
1102 		printf("%srecovery dtbo size:    %x\n", p, hdr->recovery_dtbo_size);
1103 		printf("%srecovery dtbo offset:  %llx\n", p, hdr->recovery_dtbo_offset);
1104 		printf("%sheader size:           %x\n", p, hdr->header_size);
1105 	}
1106 
1107 	if (header_version == 2 || header_version == 3) {
1108 		printf("%sdtb size:              %x\n", p, hdr->dtb_size);
1109 		printf("%sdtb addr:              %llx\n", p, hdr->dtb_addr);
1110 	}
1111 
1112 	if (header_version == 3) {
1113 		printf("%scmdline:               %s\n", p, hdr->total_cmdline);
1114 		printf("%svendor ramdisk size:   %x\n", p, hdr->vendor_ramdisk_size);
1115 		printf("%svendor page size:      %x\n", p, hdr->vendor_page_size);
1116 		printf("%svendor header version: %d\n", p, hdr->vendor_header_version);
1117 		printf("%svendor header size:    %x\n", p, hdr->vendor_header_size);
1118 	}
1119 }
1120 #endif
1121