xref: /rk3399_rockchip-uboot/common/android_bootloader.c (revision ee9d343315efa249bd06969d542ad421784dece9)
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  */
6 
7 #include <android_bootloader.h>
8 #include <android_bootloader_message.h>
9 #include <android_avb/avb_slot_verify.h>
10 #include <android_avb/avb_ops_user.h>
11 #include <android_avb/rk_avb_ops_user.h>
12 #include <android_image.h>
13 #include <cli.h>
14 #include <common.h>
15 #include <dt_table.h>
16 #include <image-android-dt.h>
17 #include <malloc.h>
18 #include <fdt_support.h>
19 #include <fs.h>
20 #include <boot_rkimg.h>
21 #include <attestation_key.h>
22 #include <optee_include/OpteeClientInterface.h>
23 #include <linux/libfdt_env.h>
24 
25 #define ANDROID_PARTITION_BOOT "boot"
26 #define ANDROID_PARTITION_MISC "misc"
27 #define ANDROID_PARTITION_OEM  "oem"
28 #define ANDROID_PARTITION_RECOVERY  "recovery"
29 #define ANDROID_PARTITION_SYSTEM "system"
30 
31 #define ANDROID_ARG_SLOT_SUFFIX "androidboot.slot_suffix="
32 #define ANDROID_ARG_ROOT "root="
33 #define ANDROID_ARG_SERIALNO "androidboot.serialno="
34 #define ANDROID_VERIFY_STATE "androidboot.verifiedbootstate="
35 #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE
36 #define ANDROID_ARG_FDT_FILENAME "rk-kernel.dtb"
37 #define BOOTLOADER_MESSAGE_OFFSET_IN_MISC	(16 * 1024)
38 #define BOOTLOADER_MESSAGE_BLK_OFFSET	(BOOTLOADER_MESSAGE_OFFSET_IN_MISC >> 9)
39 #else
40 #define ANDROID_ARG_FDT_FILENAME "kernel.dtb"
41 #endif
42 #define OEM_UNLOCK_ARG_SIZE 30
43 #define UUID_SIZE 37
44 
45 #if defined(CONFIG_ANDROID_AB) && !defined(CONFIG_ANDROID_AVB)
46 static int get_partition_unique_uuid(char *partition,
47 				     char *guid_buf,
48 				     size_t guid_buf_size)
49 {
50 	struct blk_desc *dev_desc;
51 	disk_partition_t part_info;
52 
53 	dev_desc = rockchip_get_bootdev();
54 	if (!dev_desc) {
55 		printf("%s: Could not find device\n", __func__);
56 		return -1;
57 	}
58 
59 	if (part_get_info_by_name(dev_desc, partition, &part_info) < 0) {
60 		printf("Could not find \"%s\" partition\n", partition);
61 		return -1;
62 	}
63 
64 	if (guid_buf && guid_buf_size > 0)
65 		memcpy(guid_buf, part_info.uuid, guid_buf_size);
66 
67 	return 0;
68 }
69 #endif
70 
71 char *android_str_append(char *base_name, char *slot_suffix)
72 {
73 	char *part_name;
74 	size_t part_name_len;
75 
76 	part_name_len = strlen(base_name) + 1;
77 	if (slot_suffix)
78 		part_name_len += strlen(slot_suffix);
79 	part_name = malloc(part_name_len);
80 	if (!part_name)
81 		return NULL;
82 	strcpy(part_name, base_name);
83 	if (slot_suffix && (slot_suffix[0] != '\0'))
84 		strcat(part_name, slot_suffix);
85 
86 	return part_name;
87 }
88 
89 int android_bootloader_message_load(
90 	struct blk_desc *dev_desc,
91 	const disk_partition_t *part_info,
92 	struct android_bootloader_message *message)
93 {
94 	ulong message_blocks = sizeof(struct android_bootloader_message) /
95 	    part_info->blksz;
96 	if (message_blocks > part_info->size) {
97 		printf("misc partition too small.\n");
98 		return -1;
99 	}
100 
101 #ifdef CONFIG_RKIMG_BOOTLOADER
102 	if (blk_dread(dev_desc, part_info->start + BOOTLOADER_MESSAGE_BLK_OFFSET,
103 	     message_blocks, message) !=
104 #else
105 	if (blk_dread(dev_desc, part_info->start, message_blocks, message) !=
106 #endif
107 	    message_blocks) {
108 		printf("Could not read from misc partition\n");
109 		return -1;
110 	}
111 	debug("ANDROID: Loaded BCB, %lu blocks.\n", message_blocks);
112 	return 0;
113 }
114 
115 static int android_bootloader_message_write(
116 	struct blk_desc *dev_desc,
117 	const disk_partition_t *part_info,
118 	struct android_bootloader_message *message)
119 {
120 #ifdef CONFIG_RKIMG_BOOTLOADER
121 	ulong message_blocks = sizeof(struct android_bootloader_message) /
122 	    part_info->blksz + BOOTLOADER_MESSAGE_BLK_OFFSET;
123 #else
124 	ulong message_blocks = sizeof(struct android_bootloader_message) /
125 	    part_info->blksz;
126 #endif
127 	if (message_blocks > part_info->size) {
128 		printf("misc partition too small.\n");
129 		return -1;
130 	}
131 
132 	if (blk_dwrite(dev_desc, part_info->start, message_blocks, message) !=
133 	    message_blocks) {
134 		printf("Could not write to misc partition\n");
135 		return -1;
136 	}
137 	debug("ANDROID: Wrote new BCB, %lu blocks.\n", message_blocks);
138 	return 0;
139 }
140 
141 static enum android_boot_mode android_bootloader_load_and_clear_mode(
142 	struct blk_desc *dev_desc,
143 	const disk_partition_t *misc_part_info)
144 {
145 	struct android_bootloader_message bcb;
146 
147 #ifdef CONFIG_FASTBOOT
148 	char *bootloader_str;
149 
150 	/* Check for message from bootloader stored in RAM from a previous boot.
151 	 */
152 	bootloader_str = (char *)CONFIG_FASTBOOT_BUF_ADDR;
153 	if (!strcmp("reboot-bootloader", bootloader_str)) {
154 		bootloader_str[0] = '\0';
155 		return ANDROID_BOOT_MODE_BOOTLOADER;
156 	}
157 #endif
158 
159 	/* Check and update the BCB message if needed. */
160 	if (android_bootloader_message_load(dev_desc, misc_part_info, &bcb) <
161 	    0) {
162 		printf("WARNING: Unable to load the BCB.\n");
163 		return ANDROID_BOOT_MODE_NORMAL;
164 	}
165 
166 	if (!strcmp("bootonce-bootloader", bcb.command)) {
167 		/* Erase the message in the BCB since this value should be used
168 		 * only once.
169 		 */
170 		memset(bcb.command, 0, sizeof(bcb.command));
171 		android_bootloader_message_write(dev_desc, misc_part_info,
172 						 &bcb);
173 		return ANDROID_BOOT_MODE_BOOTLOADER;
174 	}
175 
176 	if (!strcmp("boot-recovery", bcb.command))
177 		return ANDROID_BOOT_MODE_RECOVERY;
178 
179 	return ANDROID_BOOT_MODE_NORMAL;
180 }
181 
182 /**
183  * Return the reboot reason string for the passed boot mode.
184  *
185  * @param mode	The Android Boot mode.
186  * @return a pointer to the reboot reason string for mode.
187  */
188 static const char *android_boot_mode_str(enum android_boot_mode mode)
189 {
190 	switch (mode) {
191 	case ANDROID_BOOT_MODE_NORMAL:
192 		return "(none)";
193 	case ANDROID_BOOT_MODE_RECOVERY:
194 		return "recovery";
195 	case ANDROID_BOOT_MODE_BOOTLOADER:
196 		return "bootloader";
197 	}
198 	return NULL;
199 }
200 
201 static int android_part_get_info_by_name_suffix(struct blk_desc *dev_desc,
202 						const char *base_name,
203 						const char *slot_suffix,
204 						disk_partition_t *part_info)
205 {
206 	char *part_name;
207 	int part_num;
208 	size_t part_name_len;
209 
210 	part_name_len = strlen(base_name) + 1;
211 	if (slot_suffix)
212 		part_name_len += strlen(slot_suffix);
213 	part_name = malloc(part_name_len);
214 	if (!part_name)
215 		return -1;
216 	strcpy(part_name, base_name);
217 	if (slot_suffix && (slot_suffix[0] != '\0'))
218 		strcat(part_name, slot_suffix);
219 
220 	part_num = part_get_info_by_name(dev_desc, part_name, part_info);
221 	if (part_num < 0) {
222 		debug("ANDROID: Could not find partition \"%s\"\n", part_name);
223 		part_num = -1;
224 	}
225 
226 	free(part_name);
227 	return part_num;
228 }
229 
230 static int android_bootloader_boot_bootloader(void)
231 {
232 	const char *fastboot_cmd = env_get("fastbootcmd");
233 
234 	if (fastboot_cmd == NULL) {
235 		printf("fastboot_cmd is null, run default fastboot_cmd!\n");
236 		fastboot_cmd = "fastboot usb 0";
237 	}
238 
239 	return run_command(fastboot_cmd, CMD_FLAG_ENV);
240 }
241 
242 #ifdef CONFIG_SUPPORT_OEM_DTB
243 static int android_bootloader_get_fdt(const char *part_name,
244 		const char *load_file_name)
245 {
246 	struct blk_desc *dev_desc;
247 	disk_partition_t boot_part_info;
248 	char *fdt_addr = NULL;
249 	char slot_suffix[5] = {0};
250 	char dev_part[3] = {0};
251 	loff_t bytes = 0;
252 	loff_t pos = 0;
253 	loff_t len_read;
254 	unsigned long addr = 0;
255 	int part_num = -1;
256 	int ret;
257 
258 	dev_desc = rockchip_get_bootdev();
259 	if (!dev_desc) {
260 		printf("%s: dev_desc is NULL!\n", __func__);
261 		return -1;
262 	}
263 
264 	memset(&boot_part_info, 0, sizeof(boot_part_info));
265 
266 #ifdef CONFIG_RK_AVB_LIBAVB_USER
267 	if (rk_avb_get_current_slot(slot_suffix)) {
268 		printf("ANDROID: Get Current Slot error.\n");
269 		return -1;
270 	}
271 
272 	part_num = android_part_get_info_by_name_suffix(dev_desc,
273 					     part_name,
274 					     slot_suffix, &boot_part_info);
275 #else
276 	part_num = part_get_info_by_name(dev_desc, part_name, &boot_part_info);
277 	if (part_num < 0) {
278 		printf("ANDROID: Could not find partition \"%s\"\n", part_name);
279 		return -1;
280 	}
281 #endif
282 
283 	snprintf(dev_part, ARRAY_SIZE(dev_part), ":%x", part_num);
284 	if (fs_set_blk_dev_with_part(dev_desc, part_num))
285 		return -1;
286 
287 	fdt_addr = env_get("fdt_addr_r");
288 	if (!fdt_addr) {
289 		printf("ANDROID: No Found FDT Load Address.\n");
290 		return -1;
291 	}
292 	addr = simple_strtoul(fdt_addr, NULL, 16);
293 
294 	ret = fs_read(load_file_name, addr, pos, bytes, &len_read);
295 	if (ret < 0)
296 		return -1;
297 
298 	return 0;
299 }
300 #endif
301 
302 int android_bootloader_boot_kernel(unsigned long kernel_address)
303 {
304 	ulong comp;
305 	char kernel_addr_str[12];
306 	char *fdt_addr = env_get("fdt_addr");
307 	char *kernel_addr_r = env_get("kernel_addr_r");
308 	char *kernel_addr_c = env_get("kernel_addr_c");
309 
310 	const char *comp_name[] = {
311 		[IH_COMP_NONE]  = "",
312 		[IH_COMP_GZIP]  = "GZIP",
313 		[IH_COMP_BZIP2] = "BZIP2",
314 		[IH_COMP_LZMA]  = "LZMA",
315 		[IH_COMP_LZO]   = "LZO",
316 		[IH_COMP_LZ4]   = "LZ4",
317 		[IH_COMP_ZIMAGE]= "ZIMAGE",
318 	};
319 	char *bootm_args[] = {
320 		"bootm", kernel_addr_str, kernel_addr_str, fdt_addr, NULL };
321 
322 	comp = android_image_get_comp((struct andr_img_hdr *)kernel_address);
323 	sprintf(kernel_addr_str, "0x%lx", kernel_address);
324 
325 	if (comp != IH_COMP_NONE)
326 		printf("Booting %s kernel at %s(Uncompress to %s) with fdt at %s...\n\n\n",
327 		       comp_name[comp], kernel_addr_c, kernel_addr_r, fdt_addr);
328 	else
329 		printf("Booting kernel at %s with fdt at %s...\n\n\n",
330 		       kernel_addr_r, fdt_addr);
331 
332 	do_bootm(NULL, 0, 4, bootm_args);
333 
334 	return -1;
335 }
336 
337 static char *strjoin(const char **chunks, char separator)
338 {
339 	int len, joined_len = 0;
340 	char *ret, *current;
341 	const char **p;
342 
343 	for (p = chunks; *p; p++)
344 		joined_len += strlen(*p) + 1;
345 
346 	if (!joined_len) {
347 		ret = malloc(1);
348 		if (ret)
349 			ret[0] = '\0';
350 		return ret;
351 	}
352 
353 	ret = malloc(joined_len);
354 	current = ret;
355 	if (!ret)
356 		return ret;
357 
358 	for (p = chunks; *p; p++) {
359 		len = strlen(*p);
360 		memcpy(current, *p, len);
361 		current += len;
362 		*current = separator;
363 		current++;
364 	}
365 	/* Replace the last separator by a \0. */
366 	current[-1] = '\0';
367 	return ret;
368 }
369 
370 /** android_assemble_cmdline - Assemble the command line to pass to the kernel
371  * @return a newly allocated string
372  */
373 char *android_assemble_cmdline(const char *slot_suffix,
374 				      const char *extra_args)
375 {
376 	const char *cmdline_chunks[16];
377 	const char **current_chunk = cmdline_chunks;
378 	char *env_cmdline, *cmdline, *rootdev_input, *serialno;
379 	char *allocated_suffix = NULL;
380 	char *allocated_serialno = NULL;
381 	char *allocated_rootdev = NULL;
382 	unsigned long rootdev_len;
383 
384 	env_cmdline = env_get("bootargs");
385 	if (env_cmdline)
386 		*(current_chunk++) = env_cmdline;
387 
388 	/* The |slot_suffix| needs to be passed to the kernel to know what
389 	 * slot to boot from.
390 	 */
391 	if (slot_suffix) {
392 		allocated_suffix = malloc(strlen(ANDROID_ARG_SLOT_SUFFIX) +
393 					  strlen(slot_suffix) + 1);
394 		memset(allocated_suffix, 0, strlen(ANDROID_ARG_SLOT_SUFFIX)
395 		       + strlen(slot_suffix) + 1);
396 		strcpy(allocated_suffix, ANDROID_ARG_SLOT_SUFFIX);
397 		strcat(allocated_suffix, slot_suffix);
398 		*(current_chunk++) = allocated_suffix;
399 	}
400 
401 	serialno = env_get("serial#");
402 	if (serialno) {
403 		allocated_serialno = malloc(strlen(ANDROID_ARG_SERIALNO) +
404 					  strlen(serialno) + 1);
405 		memset(allocated_serialno, 0, strlen(ANDROID_ARG_SERIALNO) +
406 				strlen(serialno) + 1);
407 		strcpy(allocated_serialno, ANDROID_ARG_SERIALNO);
408 		strcat(allocated_serialno, serialno);
409 		*(current_chunk++) = allocated_serialno;
410 	}
411 
412 	rootdev_input = env_get("android_rootdev");
413 	if (rootdev_input) {
414 		rootdev_len = strlen(ANDROID_ARG_ROOT) + CONFIG_SYS_CBSIZE + 1;
415 		allocated_rootdev = malloc(rootdev_len);
416 		strcpy(allocated_rootdev, ANDROID_ARG_ROOT);
417 		cli_simple_process_macros(rootdev_input,
418 					  allocated_rootdev +
419 					  strlen(ANDROID_ARG_ROOT));
420 		/* Make sure that the string is null-terminated since the
421 		 * previous could not copy to the end of the input string if it
422 		 * is too big.
423 		 */
424 		allocated_rootdev[rootdev_len - 1] = '\0';
425 		*(current_chunk++) = allocated_rootdev;
426 	}
427 
428 	if (extra_args)
429 		*(current_chunk++) = extra_args;
430 
431 	*(current_chunk++) = NULL;
432 	cmdline = strjoin(cmdline_chunks, ' ');
433 	free(allocated_suffix);
434 	free(allocated_rootdev);
435 	return cmdline;
436 }
437 
438 #ifdef CONFIG_ANDROID_AVB
439 static void slot_set_unbootable(AvbABSlotData* slot)
440 {
441 	slot->priority = 0;
442 	slot->tries_remaining = 0;
443 	slot->successful_boot = 0;
444 }
445 
446 static AvbSlotVerifyResult android_slot_verify(char *boot_partname,
447 			       unsigned long *android_load_address,
448 			       char *slot_suffix)
449 {
450 	const char *requested_partitions[1] = {NULL};
451 	uint8_t unlocked = true;
452 	AvbOps *ops;
453 	AvbSlotVerifyFlags flags;
454 	AvbSlotVerifyData *slot_data[1] = {NULL};
455 	AvbSlotVerifyResult verify_result;
456 	AvbABData ab_data, ab_data_orig;
457 	size_t slot_index_to_boot = 0;
458 	char verify_state[38] = {0};
459 	char can_boot = 1;
460 	unsigned long load_address = *android_load_address;
461 	struct andr_img_hdr *hdr;
462 
463 	requested_partitions[0] = boot_partname;
464 	ops = avb_ops_user_new();
465 	if (ops == NULL) {
466 		printf("avb_ops_user_new() failed!\n");
467 		return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
468 	}
469 
470 	if (ops->read_is_device_unlocked(ops, (bool *)&unlocked) != AVB_IO_RESULT_OK)
471 		printf("Error determining whether device is unlocked.\n");
472 
473 	printf("read_is_device_unlocked() ops returned that device is %s\n",
474 	       (unlocked & LOCK_MASK)? "UNLOCKED" : "LOCKED");
475 
476 	flags = AVB_SLOT_VERIFY_FLAGS_NONE;
477 	if (unlocked & LOCK_MASK)
478 		flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR;
479 
480 	if(load_metadata(ops->ab_ops, &ab_data, &ab_data_orig)) {
481 		printf("Can not load metadata\n");
482 		return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
483 	}
484 
485 	if (!strncmp(slot_suffix, "_a", 2))
486 		slot_index_to_boot = 0;
487 	else if (!strncmp(slot_suffix, "_b", 2))
488 		slot_index_to_boot = 1;
489 	else
490 		slot_index_to_boot = 0;
491 
492 	verify_result =
493 	avb_slot_verify(ops,
494 			requested_partitions,
495 			slot_suffix,
496 			flags,
497 			AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
498 			&slot_data[0]);
499 
500 	strcat(verify_state, ANDROID_VERIFY_STATE);
501 	switch (verify_result) {
502 	case AVB_SLOT_VERIFY_RESULT_OK:
503 		if (unlocked & LOCK_MASK)
504 			strcat(verify_state, "orange");
505 		else
506 			strcat(verify_state, "green");
507 		break;
508 	case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
509 		if (unlocked & LOCK_MASK)
510 			strcat(verify_state, "orange");
511 		else
512 			strcat(verify_state, "yellow");
513 		break;
514 	case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
515 	case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
516 	case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
517 	case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
518 	case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
519 	case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
520 	default:
521 		if (unlocked & LOCK_MASK)
522 			strcat(verify_state, "orange");
523 		else
524 			strcat(verify_state, "red");
525 		break;
526 	}
527 
528 	if (!slot_data[0]) {
529 		can_boot = 0;
530 		goto out;
531 	}
532 
533 	if (verify_result == AVB_SLOT_VERIFY_RESULT_OK ||
534 	    verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED ||
535 	    (unlocked & LOCK_MASK)) {
536 		int len = 0;
537 		char *bootargs, *newbootargs;
538 
539 		if (*slot_data[0]->cmdline) {
540 			debug("Kernel command line: %s\n", slot_data[0]->cmdline);
541 			len += strlen(slot_data[0]->cmdline);
542 		}
543 
544 		bootargs = env_get("bootargs");
545 		if (bootargs)
546 			len += strlen(bootargs);
547 
548 		newbootargs = malloc(len + 2);
549 
550 		if (!newbootargs) {
551 			puts("Error: malloc in android_slot_verify failed!\n");
552 			return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
553 		}
554 		*newbootargs = '\0';
555 
556 		if (bootargs) {
557 			strcpy(newbootargs, bootargs);
558 			strcat(newbootargs, " ");
559 		}
560 		if (*slot_data[0]->cmdline)
561 			strcat(newbootargs, slot_data[0]->cmdline);
562 		env_set("bootargs", newbootargs);
563 
564 		/* Reserve page_size */
565 		hdr = (void *)slot_data[0]->loaded_partitions->data;
566 		load_address -= hdr->page_size;
567 		*android_load_address = load_address;
568 
569 		memcpy((uint8_t *)load_address,
570 		       slot_data[0]->loaded_partitions->data,
571 		       slot_data[0]->loaded_partitions->data_size);
572 
573 		/* ... and decrement tries remaining, if applicable. */
574 		if (!ab_data.slots[slot_index_to_boot].successful_boot &&
575 		    ab_data.slots[slot_index_to_boot].tries_remaining > 0) {
576 			ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
577 		}
578 	} else {
579 		slot_set_unbootable(&ab_data.slots[slot_index_to_boot]);
580 	}
581 
582 out:
583 	env_update("bootargs", verify_state);
584 	if (save_metadata_if_changed(ops->ab_ops, &ab_data, &ab_data_orig)) {
585 		printf("Can not save metadata\n");
586 		verify_result = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
587 	}
588 
589 	if (slot_data[0] != NULL)
590 		avb_slot_verify_data_free(slot_data[0]);
591 
592 	if ((unlocked & LOCK_MASK) && can_boot)
593 		return 0;
594 	else
595 		return verify_result;
596 }
597 #endif
598 
599 #if defined(CONFIG_CMD_DTIMG) && defined(CONFIG_OF_LIBFDT_OVERLAY)
600 
601 /*
602  * Default return index 0.
603  */
604 __weak int board_select_fdt_index(ulong dt_table_hdr)
605 {
606 /*
607  * User can use "dt_for_each_entry(entry, hdr, idx)" to iterate
608  * over all dt entry of DT image and pick up which they want.
609  *
610  * Example:
611  *	struct dt_table_entry *entry;
612  *	int index;
613  *
614  *	dt_for_each_entry(entry, dt_table_hdr, index) {
615  *
616  *		.... (use entry)
617  *	}
618  *
619  *	return index;
620  */
621 	return 0;
622 }
623 
624 static int android_get_dtbo(ulong *fdt_dtbo,
625 			    const struct andr_img_hdr *hdr,
626 			    int *index)
627 {
628 	struct dt_table_header *dt_hdr = NULL;
629 	struct blk_desc *dev_desc;
630 	const char *part_name;
631 	disk_partition_t part_info;
632 	u32 blk_offset, blk_cnt;
633 	void *buf;
634 	ulong e_addr;
635 	u32 e_size;
636 	int e_idx;
637 	int ret;
638 
639 	/* Get partition according to boot mode */
640 	if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY)
641 		part_name = PART_RECOVERY;
642 	else
643 		part_name = PART_DTBO;
644 
645 	/* Get partition info */
646 	dev_desc = rockchip_get_bootdev();
647 	if (!dev_desc) {
648 		printf("%s: dev_desc is NULL!\n", __func__);
649 		return -ENODEV;
650 	}
651 
652 	ret = part_get_info_by_name(dev_desc, part_name, &part_info);
653 	if (ret < 0) {
654 		printf("%s: failed to get %s part info, ret=%d\n",
655 		       __func__, part_name, ret);
656 		return ret;
657 	}
658 
659 	/* Check dt table header */
660 	if (!strcmp(part_name, PART_RECOVERY))
661 		blk_offset = part_info.start +
662 			     (hdr->recovery_dtbo_offset / part_info.blksz);
663 	else
664 		blk_offset = part_info.start;
665 
666 	dt_hdr = memalign(ARCH_DMA_MINALIGN, part_info.blksz);
667 	if (!dt_hdr) {
668 		printf("%s: out of memory for dt header!\n", __func__);
669 		return -ENOMEM;
670 	}
671 
672 	ret = blk_dread(dev_desc, blk_offset, 1, dt_hdr);
673 	if (ret != 1) {
674 		printf("%s: failed to read dt table header\n",
675 		       __func__);
676 		goto out1;
677 	}
678 
679 	if (!android_dt_check_header((ulong)dt_hdr)) {
680 		printf("%s: Error: invalid dt table header: 0x%x\n",
681 		       __func__, dt_hdr->magic);
682 		ret = -EINVAL;
683 		goto out1;
684 	}
685 
686 #ifdef DEBUG
687 	android_dt_print_contents((ulong)dt_hdr);
688 #endif
689 
690 	blk_cnt = DIV_ROUND_UP(fdt32_to_cpu(dt_hdr->total_size),
691 			       part_info.blksz);
692 	/* Read all DT Image */
693 	buf = memalign(ARCH_DMA_MINALIGN, part_info.blksz * blk_cnt);
694 	if (!buf) {
695 		printf("%s: out of memory for %s part!\n", __func__, part_name);
696 		ret = -ENOMEM;
697 		goto out1;
698 	}
699 
700 	ret = blk_dread(dev_desc, blk_offset, blk_cnt, buf);
701 	if (ret != blk_cnt) {
702 		printf("%s: failed to read dtbo, blk_cnt=%d, ret=%d\n",
703 		       __func__, blk_cnt, ret);
704 		goto out2;
705 	}
706 
707 	e_idx = board_select_fdt_index((ulong)buf);
708 	if (e_idx < 0) {
709 		printf("%s: failed to select board fdt index\n", __func__);
710 		ret = -EINVAL;
711 		goto out2;
712 	}
713 
714 	ret = android_dt_get_fdt_by_index((ulong)buf, e_idx, &e_addr, &e_size);
715 	if (!ret) {
716 		printf("%s: failed to get fdt, index=%d\n", __func__, e_idx);
717 		ret = -EINVAL;
718 		goto out2;
719 	}
720 
721 	if (fdt_dtbo)
722 		*fdt_dtbo = e_addr;
723 	if (index)
724 		*index = e_idx;
725 
726 	free(dt_hdr);
727 	debug("ANDROID: Loading dt entry to 0x%lx size 0x%x idx %d from \"%s\" part\n",
728 	      e_addr, e_size, e_idx, part_name);
729 
730 	return 0;
731 
732 out2:
733 	free(buf);
734 out1:
735 	free(dt_hdr);
736 
737 	return ret;
738 }
739 
740 int android_fdt_overlay_apply(void *fdt_addr)
741 {
742 	struct andr_img_hdr *hdr;
743 	struct blk_desc *dev_desc;
744 	const char *part_name;
745 	disk_partition_t part_info;
746 	char buf[32] = {0};
747 	u32 blk_cnt;
748 	ulong fdt_dtbo = -1;
749 	int index = -1;
750 	int ret;
751 
752 	/* Get partition according to boot mode */
753 	if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY)
754 		part_name = PART_RECOVERY;
755 	else
756 		part_name = PART_BOOT;
757 
758 	/* Get partition info */
759 	dev_desc = rockchip_get_bootdev();
760 	if (!dev_desc) {
761 		printf("%s: dev_desc is NULL!\n", __func__);
762 		return -ENODEV;
763 	}
764 
765 	ret = part_get_info_by_name(dev_desc, part_name, &part_info);
766 	if (ret < 0) {
767 		printf("%s: failed to get %s part info, ret=%d\n",
768 		       __func__, part_name, ret);
769 		return ret;
770 	}
771 
772 	blk_cnt = DIV_ROUND_UP(sizeof(*hdr), part_info.blksz);
773 	hdr = memalign(ARCH_DMA_MINALIGN, part_info.blksz * blk_cnt);
774 	if (!hdr) {
775 		printf("%s: out of memory!\n", __func__);
776 		return -ENOMEM;
777 	}
778 
779 	ret = blk_dread(dev_desc, part_info.start, blk_cnt, hdr);
780 	if (ret != blk_cnt) {
781 		printf("%s: failed to read %s hdr!\n", __func__, part_name);
782 		goto out;
783 	}
784 
785 #ifdef DEBUG
786 	android_print_contents(hdr);
787 #endif
788 
789 	if (android_image_check_header(hdr)) {
790 		printf("%s: Invalid Android header %s\n", __func__, hdr->magic);
791 		return -EINVAL;
792 	}
793 
794 	/* Check header version */
795 	if (!hdr->header_version) {
796 		printf("Android header version 0\n");
797 		ret = -EINVAL;
798 		goto out;
799 	}
800 
801 	ret = android_get_dtbo(&fdt_dtbo, (void *)hdr, &index);
802 	if (!ret) {
803 		/* Must incease size before overlay */
804 		fdt_increase_size(fdt_addr, fdt_totalsize((void *)fdt_dtbo));
805 		ret = fdt_overlay_apply(fdt_addr, (void *)fdt_dtbo);
806 		if (!ret) {
807 			snprintf(buf, 32, "%s%d", "androidboot.dtbo_idx=", index);
808 			env_update("bootargs", buf);
809 			printf("ANDROID: fdt overlay OK\n");
810 		} else {
811 			printf("ANDROID: fdt overlay failed, ret=%d\n", ret);
812 		}
813 	}
814 
815 out:
816 	free(hdr);
817 
818 	return 0;
819 }
820 #endif
821 
822 static int load_android_image(struct blk_desc *dev_desc,
823 			      char *boot_partname,
824 			      char *slot_suffix,
825 			      unsigned long *load_address)
826 {
827 	disk_partition_t boot_part;
828 	int ret, part_num;
829 
830 	part_num = android_part_get_info_by_name_suffix(dev_desc,
831 							boot_partname,
832 							slot_suffix,
833 							&boot_part);
834 	if (part_num < 0) {
835 		printf("%s: Can't find part: %s\n", __func__, boot_partname);
836 		return -1;
837 	}
838 	debug("ANDROID: Loading kernel from \"%s\", partition %d.\n",
839 	      boot_part.name, part_num);
840 
841 	ret = android_image_load(dev_desc, &boot_part, *load_address, -1UL);
842 	if (ret < 0) {
843 		printf("%s: %s part load fail, ret=%d\n",
844 		       __func__, boot_part.name, ret);
845 		return ret;
846 	}
847 	*load_address = ret;
848 
849 	return 0;
850 }
851 
852 int android_bootloader_boot_flow(struct blk_desc *dev_desc,
853 				 unsigned long load_address)
854 {
855 	enum android_boot_mode mode;
856 	disk_partition_t misc_part_info;
857 	int part_num;
858 	int ret;
859 	char *command_line;
860 	char slot_suffix[3] = {0};
861 	const char *mode_cmdline = NULL;
862 	char *boot_partname = ANDROID_PARTITION_BOOT;
863 	ulong fdt_addr;
864 
865 	/*
866 	 * 1. Load MISC partition and determine the boot mode
867 	 *   clear its value for the next boot if needed.
868 	 */
869 	part_num = part_get_info_by_name(dev_desc, ANDROID_PARTITION_MISC,
870 					 &misc_part_info);
871 	if (part_num < 0)
872 		printf("%s Could not find misc partition\n", __func__);
873 
874 #ifdef CONFIG_OPTEE_CLIENT
875 	/* load attestation key from misc partition. */
876 	load_attestation_key(dev_desc, &misc_part_info);
877 #endif
878 
879 	mode = android_bootloader_load_and_clear_mode(dev_desc, &misc_part_info);
880 #ifdef CONFIG_RKIMG_BOOTLOADER
881 	if (mode == ANDROID_BOOT_MODE_NORMAL) {
882 		if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY)
883 			mode = ANDROID_BOOT_MODE_RECOVERY;
884 	}
885 #endif
886 	printf("ANDROID: reboot reason: \"%s\"\n", android_boot_mode_str(mode));
887 
888 #ifdef CONFIG_ANDROID_AB
889 	/*TODO: get from pre-loader or misc partition*/
890 	if (rk_avb_get_current_slot(slot_suffix))
891 		return -1;
892 
893 	if (slot_suffix[0] != '_') {
894 		printf("There is no bootable slot!\n");
895 		return -1;
896 	}
897 #endif
898 
899 	switch (mode) {
900 	case ANDROID_BOOT_MODE_NORMAL:
901 		/* In normal mode, we load the kernel from "boot" but append
902 		 * "skip_initramfs" to the cmdline to make it ignore the
903 		 * recovery initramfs in the boot partition.
904 		 */
905 #if defined(CONFIG_ANDROID_AB) && !defined(CONFIG_ANDROID_AVB)
906 		char root_partition[20] = {0};
907 		char guid_buf[UUID_SIZE] = {0};
908 		char root_partuuid[70] = "root=PARTUUID=";
909 
910 		strcat(root_partition, ANDROID_PARTITION_SYSTEM);
911 		strcat(root_partition, slot_suffix);
912 		get_partition_unique_uuid(root_partition, guid_buf, UUID_SIZE);
913 		strcat(root_partuuid, guid_buf);
914 		env_update("bootargs", root_partuuid);
915 #endif
916 
917 #ifdef CONFIG_ANDROID_AB
918 		mode_cmdline = "skip_initramfs";
919 #endif
920 		break;
921 	case ANDROID_BOOT_MODE_RECOVERY:
922 		/* In recovery mode we still boot the kernel from "boot" but
923 		 * don't skip the initramfs so it boots to recovery.
924 		 */
925 #ifndef CONFIG_ANDROID_AB
926 		boot_partname = ANDROID_PARTITION_RECOVERY;
927 #endif
928 		break;
929 	case ANDROID_BOOT_MODE_BOOTLOADER:
930 		/* Bootloader mode enters fastboot. If this operation fails we
931 		 * simply return since we can't recover from this situation by
932 		 * switching to another slot.
933 		 */
934 		return android_bootloader_boot_bootloader();
935 	}
936 
937 #ifdef CONFIG_ANDROID_AVB
938 	uint8_t vboot_flag = 0;
939 
940 	if (trusty_read_vbootkey_enable_flag(&vboot_flag))
941 		return -1;
942 
943 	if (vboot_flag) {
944 		printf("SecureBoot enabled, AVB verify\n");
945 		if (android_slot_verify(boot_partname, &load_address,
946 					slot_suffix))
947 			return -1;
948 	} else {
949 		printf("SecureBoot disabled, AVB skip\n");
950 		env_update("bootargs", "androidboot.verifiedbootstate=orange");
951 		if (load_android_image(dev_desc, boot_partname,
952 				       slot_suffix, &load_address))
953 			return -1;
954 	}
955 #else
956 	/*
957 	 * 2. Load the boot/recovery from the desired "boot" partition.
958 	 * Determine if this is an AOSP image.
959 	 */
960 	if (load_android_image(dev_desc, boot_partname,
961 			       slot_suffix, &load_address))
962 		return -1;
963 #endif
964 
965 	/* Set Android root variables. */
966 	env_set_ulong("android_root_devnum", dev_desc->devnum);
967 	env_set("android_slotsufix", slot_suffix);
968 
969 #ifdef CONFIG_FASTBOOT_OEM_UNLOCK
970 	/* read oem unlock status and attach to bootargs */
971 	uint8_t unlock = 0;
972 	TEEC_Result result;
973 	char oem_unlock[OEM_UNLOCK_ARG_SIZE] = {0};
974 	result = trusty_read_oem_unlock(&unlock);
975 	if (result) {
976 		printf("read oem unlock status with error : 0x%x\n", result);
977 	} else {
978 		snprintf(oem_unlock, OEM_UNLOCK_ARG_SIZE, "androidboot.oem_unlocked=%d", unlock);
979 		env_update("bootargs", oem_unlock);
980 	}
981 #endif
982 
983 	/* Assemble the command line */
984 	command_line = android_assemble_cmdline(slot_suffix, mode_cmdline);
985 	env_update("bootargs", command_line);
986 
987 	debug("ANDROID: bootargs: \"%s\"\n", command_line);
988 
989 #ifdef CONFIG_SUPPORT_OEM_DTB
990 	if (android_bootloader_get_fdt(ANDROID_PARTITION_OEM,
991 				       ANDROID_ARG_FDT_FILENAME)) {
992 		printf("Can not get the fdt data from oem!\n");
993 	}
994 #else
995 	ret = android_image_get_fdt((void *)load_address, &fdt_addr);
996 	if (!ret)
997 		env_set_hex("fdt_addr", fdt_addr);
998 #endif
999 	android_bootloader_boot_kernel(load_address);
1000 
1001 	/* TODO: If the kernel doesn't boot mark the selected slot as bad. */
1002 	return -1;
1003 }
1004 
1005 int android_avb_boot_flow(char *slot_suffix, unsigned long kernel_address)
1006 {
1007 	struct blk_desc *dev_desc;
1008 	disk_partition_t boot_part_info;
1009 	int ret;
1010 	dev_desc = rockchip_get_bootdev();
1011 	if (!dev_desc) {
1012 		printf("%s: dev_desc is NULL!\n", __func__);
1013 		return -1;
1014 	}
1015 	/* Load the kernel from the desired "boot" partition. */
1016 	android_part_get_info_by_name_suffix(dev_desc,
1017 					     ANDROID_PARTITION_BOOT,
1018 					     slot_suffix, &boot_part_info);
1019 	ret = android_image_load(dev_desc, &boot_part_info, kernel_address,
1020 				 -1UL);
1021 	if (ret < 0)
1022 		return ret;
1023 	android_bootloader_boot_kernel(kernel_address);
1024 
1025 	/* TODO: If the kernel doesn't boot mark the selected slot as bad. */
1026 	return -1;
1027 }
1028 
1029 int android_boot_flow(unsigned long kernel_address)
1030 {
1031 	struct blk_desc *dev_desc;
1032 	disk_partition_t boot_part_info;
1033 	int ret;
1034 	dev_desc = rockchip_get_bootdev();
1035 	if (!dev_desc) {
1036 		printf("%s: dev_desc is NULL!\n", __func__);
1037 		return -1;
1038 	}
1039 	/* Load the kernel from the desired "boot" partition. */
1040 	part_get_info_by_name(dev_desc, ANDROID_PARTITION_BOOT, &boot_part_info);
1041 	ret = android_image_load(dev_desc, &boot_part_info, kernel_address,
1042 				 -1UL);
1043 	if (ret < 0)
1044 		return ret;
1045 	android_bootloader_boot_kernel(kernel_address);
1046 
1047 	/* TODO: If the kernel doesn't boot mark the selected slot as bad. */
1048 	return -1;
1049 }
1050