xref: /rk3399_rockchip-uboot/common/android_bootloader.c (revision 22f2eaa842ce4767e480a1a10cbb4cad9dea4707)
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 int android_bootloader_boot_flow(struct blk_desc *dev_desc,
823 				 unsigned long load_address)
824 {
825 	enum android_boot_mode mode;
826 	disk_partition_t misc_part_info;
827 	int part_num;
828 	int ret;
829 	char *command_line;
830 	char slot_suffix[3] = {0};
831 	const char *mode_cmdline = NULL;
832 	char *boot_partname = ANDROID_PARTITION_BOOT;
833 	ulong fdt_addr;
834 
835 	/*
836 	 * 1. Load MISC partition and determine the boot mode
837 	 *   clear its value for the next boot if needed.
838 	 */
839 	part_num = part_get_info_by_name(dev_desc, ANDROID_PARTITION_MISC,
840 					 &misc_part_info);
841 	if (part_num < 0)
842 		printf("%s Could not find misc partition\n", __func__);
843 
844 #ifdef CONFIG_OPTEE_CLIENT
845 	/* load attestation key from misc partition. */
846 	load_attestation_key(dev_desc, &misc_part_info);
847 #endif
848 
849 	mode = android_bootloader_load_and_clear_mode(dev_desc, &misc_part_info);
850 #ifdef CONFIG_RKIMG_BOOTLOADER
851 	if (mode == ANDROID_BOOT_MODE_NORMAL) {
852 		if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY)
853 			mode = ANDROID_BOOT_MODE_RECOVERY;
854 	}
855 #endif
856 	printf("ANDROID: reboot reason: \"%s\"\n", android_boot_mode_str(mode));
857 
858 #ifdef CONFIG_ANDROID_AB
859 	/*TODO: get from pre-loader or misc partition*/
860 	if (rk_avb_get_current_slot(slot_suffix))
861 		return -1;
862 
863 	if (slot_suffix[0] != '_') {
864 		printf("There is no bootable slot!\n");
865 		return -1;
866 	}
867 #endif
868 
869 	switch (mode) {
870 	case ANDROID_BOOT_MODE_NORMAL:
871 		/* In normal mode, we load the kernel from "boot" but append
872 		 * "skip_initramfs" to the cmdline to make it ignore the
873 		 * recovery initramfs in the boot partition.
874 		 */
875 #if defined(CONFIG_ANDROID_AB) && !defined(CONFIG_ANDROID_AVB)
876 		char root_partition[20] = {0};
877 		char guid_buf[UUID_SIZE] = {0};
878 		char root_partuuid[70] = "root=PARTUUID=";
879 
880 		strcat(root_partition, ANDROID_PARTITION_SYSTEM);
881 		strcat(root_partition, slot_suffix);
882 		get_partition_unique_uuid(root_partition, guid_buf, UUID_SIZE);
883 		strcat(root_partuuid, guid_buf);
884 		env_update("bootargs", root_partuuid);
885 #endif
886 
887 #ifdef CONFIG_ANDROID_AB
888 		mode_cmdline = "skip_initramfs";
889 #endif
890 		break;
891 	case ANDROID_BOOT_MODE_RECOVERY:
892 		/* In recovery mode we still boot the kernel from "boot" but
893 		 * don't skip the initramfs so it boots to recovery.
894 		 */
895 #ifndef CONFIG_ANDROID_AB
896 		boot_partname = ANDROID_PARTITION_RECOVERY;
897 #endif
898 		break;
899 	case ANDROID_BOOT_MODE_BOOTLOADER:
900 		/* Bootloader mode enters fastboot. If this operation fails we
901 		 * simply return since we can't recover from this situation by
902 		 * switching to another slot.
903 		 */
904 		return android_bootloader_boot_bootloader();
905 	}
906 
907 #ifdef CONFIG_ANDROID_AVB
908 	if (android_slot_verify(boot_partname, &load_address, slot_suffix))
909 		return -1;
910 #else
911 	/*
912 	 * 2. Load the boot/recovery from the desired "boot" partition.
913 	 * Determine if this is an AOSP image.
914 	 */
915 	disk_partition_t boot_part_info;
916 	part_num =
917 	    android_part_get_info_by_name_suffix(dev_desc,
918 						 boot_partname,
919 						 slot_suffix, &boot_part_info);
920 	if (part_num < 0) {
921 		printf("%s Could not found bootable partition %s\n", __func__,
922 		       boot_partname);
923 		return -1;
924 	}
925 	debug("ANDROID: Loading kernel from \"%s\", partition %d.\n",
926 	      boot_part_info.name, part_num);
927 
928 	ret = android_image_load(dev_desc, &boot_part_info, load_address,
929 				 -1UL);
930 	if (ret < 0) {
931 		printf("%s %s part load fail\n", __func__, boot_part_info.name);
932 		return ret;
933 	}
934 	load_address = ret;
935 #endif
936 
937 	/* Set Android root variables. */
938 	env_set_ulong("android_root_devnum", dev_desc->devnum);
939 	env_set("android_slotsufix", slot_suffix);
940 
941 #ifdef CONFIG_FASTBOOT_OEM_UNLOCK
942 	/* read oem unlock status and attach to bootargs */
943 	uint8_t unlock = 0;
944 	TEEC_Result result;
945 	char oem_unlock[OEM_UNLOCK_ARG_SIZE] = {0};
946 	result = trusty_read_oem_unlock(&unlock);
947 	if (result) {
948 		printf("read oem unlock status with error : 0x%x\n", result);
949 	} else {
950 		snprintf(oem_unlock, OEM_UNLOCK_ARG_SIZE, "androidboot.oem_unlocked=%d", unlock);
951 		env_update("bootargs", oem_unlock);
952 	}
953 #endif
954 
955 	/* Assemble the command line */
956 	command_line = android_assemble_cmdline(slot_suffix, mode_cmdline);
957 	env_update("bootargs", command_line);
958 
959 	debug("ANDROID: bootargs: \"%s\"\n", command_line);
960 
961 #ifdef CONFIG_SUPPORT_OEM_DTB
962 	if (android_bootloader_get_fdt(ANDROID_PARTITION_OEM,
963 				       ANDROID_ARG_FDT_FILENAME)) {
964 		printf("Can not get the fdt data from oem!\n");
965 	}
966 #else
967 	ret = android_image_get_fdt((void *)load_address, &fdt_addr);
968 	if (!ret)
969 		env_set_hex("fdt_addr", fdt_addr);
970 #endif
971 	android_bootloader_boot_kernel(load_address);
972 
973 	/* TODO: If the kernel doesn't boot mark the selected slot as bad. */
974 	return -1;
975 }
976 
977 int android_avb_boot_flow(char *slot_suffix, unsigned long kernel_address)
978 {
979 	struct blk_desc *dev_desc;
980 	disk_partition_t boot_part_info;
981 	int ret;
982 	dev_desc = rockchip_get_bootdev();
983 	if (!dev_desc) {
984 		printf("%s: dev_desc is NULL!\n", __func__);
985 		return -1;
986 	}
987 	/* Load the kernel from the desired "boot" partition. */
988 	android_part_get_info_by_name_suffix(dev_desc,
989 					     ANDROID_PARTITION_BOOT,
990 					     slot_suffix, &boot_part_info);
991 	ret = android_image_load(dev_desc, &boot_part_info, kernel_address,
992 				 -1UL);
993 	if (ret < 0)
994 		return ret;
995 	android_bootloader_boot_kernel(kernel_address);
996 
997 	/* TODO: If the kernel doesn't boot mark the selected slot as bad. */
998 	return -1;
999 }
1000 
1001 int android_boot_flow(unsigned long kernel_address)
1002 {
1003 	struct blk_desc *dev_desc;
1004 	disk_partition_t boot_part_info;
1005 	int ret;
1006 	dev_desc = rockchip_get_bootdev();
1007 	if (!dev_desc) {
1008 		printf("%s: dev_desc is NULL!\n", __func__);
1009 		return -1;
1010 	}
1011 	/* Load the kernel from the desired "boot" partition. */
1012 	part_get_info_by_name(dev_desc, ANDROID_PARTITION_BOOT, &boot_part_info);
1013 	ret = android_image_load(dev_desc, &boot_part_info, kernel_address,
1014 				 -1UL);
1015 	if (ret < 0)
1016 		return ret;
1017 	android_bootloader_boot_kernel(kernel_address);
1018 
1019 	/* TODO: If the kernel doesn't boot mark the selected slot as bad. */
1020 	return -1;
1021 }
1022