From 9df731a176aab8e03b984b681b1bea01ccff6644 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 06 Nov 2023 07:23:06 +0000
Subject: [PATCH] rk3568 rt uboot init

---
 u-boot/common/android_bootloader.c |  415 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 355 insertions(+), 60 deletions(-)

diff --git a/u-boot/common/android_bootloader.c b/u-boot/common/android_bootloader.c
index 772e6bf..ab080b8 100644
--- a/u-boot/common/android_bootloader.c
+++ b/u-boot/common/android_bootloader.c
@@ -18,6 +18,7 @@
 #include <dt_table.h>
 #include <image-android-dt.h>
 #include <malloc.h>
+#include <mp_boot.h>
 #include <fdt_support.h>
 #include <fs.h>
 #include <boot_rkimg.h>
@@ -462,15 +463,305 @@
 	slot->successful_boot = 0;
 }
 
+static char *join_str(const char *a, const char *b)
+{
+	size_t len = strlen(a) + strlen(b) + 1 /* null term */;
+	char *ret = (char *)malloc(len);
+
+	if (!ret) {
+		debug("failed to alloc %zu\n", len);
+		return NULL;
+	}
+	strcpy(ret, a);
+	strcat(ret, b);
+
+	return ret;
+}
+
+static size_t get_partition_size(AvbOps *ops, char *name,
+				 const char *slot_suffix)
+{
+	char *partition_name = join_str(name, slot_suffix);
+	uint64_t size = 0;
+	AvbIOResult res;
+
+	if (partition_name == NULL)
+		goto bail;
+
+	res = ops->get_size_of_partition(ops, partition_name, &size);
+	if (res != AVB_IO_RESULT_OK && res != AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION)
+		size = 0;
+bail:
+	if (partition_name)
+		free(partition_name);
+
+	return size;
+}
+
+static struct AvbOpsData preload_user_data;
+
+static int avb_image_distribute_prepare(AvbSlotVerifyData *slot_data,
+					AvbOps *ops, char *slot_suffix)
+{
+	struct AvbOpsData *data = (struct AvbOpsData *)(ops->user_data);
+	size_t vendor_boot_size;
+	size_t init_boot_size;
+	size_t resource_size;
+	size_t boot_size;
+	void *image_buf;
+
+	boot_size = max(get_partition_size(ops, ANDROID_PARTITION_BOOT, slot_suffix),
+		get_partition_size(ops, ANDROID_PARTITION_RECOVERY, slot_suffix));
+	init_boot_size = get_partition_size(ops,
+				ANDROID_PARTITION_INIT_BOOT, slot_suffix);
+	vendor_boot_size = get_partition_size(ops,
+				ANDROID_PARTITION_VENDOR_BOOT, slot_suffix);
+	resource_size = get_partition_size(ops,
+				ANDROID_PARTITION_RESOURCE, slot_suffix);
+	image_buf = sysmem_alloc(MEM_AVB_ANDROID,
+				 boot_size + init_boot_size +
+				 vendor_boot_size + resource_size);
+	if (!image_buf) {
+		printf("avb: sysmem alloc failed\n");
+		return -ENOMEM;
+	}
+
+	/* layout: | boot/recovery | vendor_boot | init_boot | resource | */
+	data->slot_suffix = slot_suffix;
+	data->boot.addr = image_buf;
+	data->boot.size = 0;
+	data->vendor_boot.addr = data->boot.addr + boot_size;
+	data->vendor_boot.size = 0;
+	data->init_boot.addr = data->vendor_boot.addr + vendor_boot_size;
+	data->init_boot.size = 0;
+	data->resource.addr = data->init_boot.addr + init_boot_size;
+	data->resource.size = 0;
+
+	return 0;
+}
+
+static int avb_image_distribute_finish(AvbSlotVerifyData *slot_data,
+				       AvbSlotVerifyFlags flags,
+				       ulong *load_address)
+{
+	struct andr_img_hdr *hdr;
+	ulong load_addr = *load_address;
+	void *vendor_boot_hdr = NULL;
+	void *init_boot_hdr = NULL;
+	void *boot_hdr = NULL;
+	char *part_name;
+	int i, ret;
+
+	for (i = 0; i < slot_data->num_loaded_partitions; i++) {
+		part_name = slot_data->loaded_partitions[i].partition_name;
+		if (!strncmp(ANDROID_PARTITION_BOOT, part_name, 4) ||
+		    !strncmp(ANDROID_PARTITION_RECOVERY, part_name, 8)) {
+			boot_hdr = slot_data->loaded_partitions[i].data;
+		} else if (!strncmp(ANDROID_PARTITION_INIT_BOOT, part_name, 9)) {
+			init_boot_hdr = slot_data->loaded_partitions[i].data;
+		} else if (!strncmp(ANDROID_PARTITION_VENDOR_BOOT, part_name, 11)) {
+			vendor_boot_hdr = slot_data->loaded_partitions[i].data;
+		}
+	}
+
+	/*
+	 *		populate boot_img_hdr_v34
+	 *
+	 * If allow verification error: the images are loaded by
+	 * ops->get_preloaded_partition() which auto populates
+	 * boot_img_hdr_v34.
+	 *
+	 * If not allow verification error: the images are full loaded
+	 * by ops->read_from_partition() which doesn't populate
+	 * boot_img_hdr_v34, we need to fix it here for bootm and
+	 */
+
+	hdr = boot_hdr;
+	if (hdr->header_version >= 3 &&
+	    !(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR)) {
+		hdr = malloc(sizeof(struct andr_img_hdr));
+		if (!hdr)
+			return -ENOMEM;
+
+		ret = populate_boot_info(boot_hdr, vendor_boot_hdr,
+					 init_boot_hdr, hdr, true);
+		if (ret < 0) {
+			printf("avb: populate boot info failed, ret=%d\n", ret);
+			return ret;
+		}
+		memcpy(boot_hdr, hdr, sizeof(*hdr));
+	}
+
+	/* distribute ! */
+	load_addr -= hdr->page_size;
+	if (android_image_memcpy_separate(boot_hdr, &load_addr)) {
+		printf("Failed to separate copy android image\n");
+		return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+	}
+
+	*load_address = load_addr;
+
+	return 0;
+}
+
+int android_image_verify_resource(const char *boot_part, ulong *resc_buf)
+{
+	const char *requested_partitions[] = {
+		NULL,
+		NULL,
+	};
+	struct AvbOpsData *data;
+	uint8_t unlocked = true;
+	AvbOps *ops;
+	AvbSlotVerifyFlags flags;
+	AvbSlotVerifyData *slot_data = {NULL};
+	AvbSlotVerifyResult verify_result;
+	char slot_suffix[3] = {0};
+	char *part_name;
+	void *image_buf = NULL;
+	int retry_no_vbmeta_partition = 1;
+	int i, ret;
+
+	ops = avb_ops_user_new();
+	if (ops == NULL) {
+		printf("avb_ops_user_new() failed!\n");
+		return -AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+	}
+
+	if (ops->read_is_device_unlocked(ops, (bool *)&unlocked) != AVB_IO_RESULT_OK)
+		printf("Error determining whether device is unlocked.\n");
+
+	printf("Device is: %s\n", (unlocked & LOCK_MASK)? "UNLOCKED" : "LOCKED");
+
+	if (unlocked & LOCK_MASK) {
+		*resc_buf = 0;
+		return 0;
+	}
+
+	flags = AVB_SLOT_VERIFY_FLAGS_NONE;
+	if (strcmp(boot_part, ANDROID_PARTITION_RECOVERY) == 0)
+		flags |= AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION;
+
+#ifdef CONFIG_ANDROID_AB
+	part_name = strdup(boot_part);
+	*(part_name + strlen(boot_part) - 2) = '\0';
+	requested_partitions[0] = part_name;
+
+	ret = rk_avb_get_current_slot(slot_suffix);
+	if (ret) {
+		printf("Failed to get slot suffix, ret=%d\n", ret);
+		return ret;
+	}
+#else
+	requested_partitions[0] = boot_part;
+#endif
+	data = (struct AvbOpsData *)(ops->user_data);
+	ret = avb_image_distribute_prepare(slot_data, ops, slot_suffix);
+	if (ret) {
+		printf("avb image distribute prepare failed %d\n", ret);
+		return ret;
+	}
+
+retry_verify:
+	verify_result =
+	avb_slot_verify(ops,
+			requested_partitions,
+			slot_suffix,
+			flags,
+			AVB_HASHTREE_ERROR_MODE_RESTART,
+			&slot_data);
+	if (verify_result != AVB_SLOT_VERIFY_RESULT_OK &&
+	    verify_result != AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED) {
+		if (retry_no_vbmeta_partition && strcmp(boot_part, ANDROID_PARTITION_RECOVERY) == 0) {
+			printf("Verify recovery with vbmeta.\n");
+			flags &= ~AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION;
+			retry_no_vbmeta_partition = 0;
+			goto retry_verify;
+		}
+	}
+
+	if (verify_result != AVB_SLOT_VERIFY_RESULT_OK || !slot_data) {
+		sysmem_free((ulong)data->boot.addr);
+		return verify_result;
+	}
+
+	for (i = 0; i < slot_data->num_loaded_partitions; i++) {
+		part_name = slot_data->loaded_partitions[i].partition_name;
+		if (!strncmp(ANDROID_PARTITION_RESOURCE, part_name, 8)) {
+			image_buf = slot_data->loaded_partitions[i].data;
+			break;
+		} else if (!strncmp(ANDROID_PARTITION_BOOT, part_name, 4) ||
+			   !strncmp(ANDROID_PARTITION_RECOVERY, part_name, 8)) {
+			struct andr_img_hdr *hdr;
+
+			hdr = (void *)slot_data->loaded_partitions[i].data;
+			if (android_image_check_header(hdr))
+				continue;
+
+			if (hdr->header_version <= 2) {
+				image_buf = (void *)hdr + hdr->page_size +
+					ALIGN(hdr->kernel_size, hdr->page_size) +
+					ALIGN(hdr->ramdisk_size, hdr->page_size);
+				break;
+			}
+		}
+	}
+
+	if (image_buf) {
+		memcpy((char *)&preload_user_data, (char *)data, sizeof(*data));
+		*resc_buf = (ulong)image_buf;
+	}
+
+	return 0;
+}
+
+/*
+ *		AVB Policy.
+ *
+ * == avb with unlock:
+ * Don't process hash verify.
+ * Go pre-loaded path: Loading vendor_boot and init_boot
+ * directly to where they should be, while loading the
+ * boot/recovery. The boot message tells like:
+ * ···
+ * preloaded: distribute image from 'boot_a'
+ * preloaded: distribute image from 'init_boot_a'
+ * preloaded: distribute image from 'vendor_boot_a'
+ * ···
+ *
+ * == avb with lock:
+ * Process hash verify.
+ * Go pre-loaded path: Loading full vendor_boot, init_boot and
+ * boot/recovery one by one to verify, and distributing them to
+ * where they should be by memcpy at last.
+ *
+ * The three images share a large memory buffer that allocated
+ * by sysmem_alloc(), it locate at high memory address that
+ * just lower than SP bottom. The boot message tells like:
+ * ···
+ * preloaded: full image from 'boot_a' at 0xe47f90c0 - 0xe7a4b0c0
+ * preloaded: full image from 'init_boot_a' at 0xeaff90c0 - 0xeb2950c0
+ * preloaded: full image from 'vendor_boot_a' at 0xe87f90c0 - 0xe9f6e0c0
+ * ···
+ */
 static AvbSlotVerifyResult android_slot_verify(char *boot_partname,
 			       unsigned long *android_load_address,
 			       char *slot_suffix)
 {
-	const char *requested_partitions[1] = {NULL};
+	const char *requested_partitions[] = {
+		boot_partname,
+		NULL,
+		NULL,
+		NULL,
+	};
+	struct AvbOpsData *data;
+	struct blk_desc *dev_desc;
+	struct andr_img_hdr *hdr;
+	disk_partition_t part_info;
 	uint8_t unlocked = true;
 	AvbOps *ops;
 	AvbSlotVerifyFlags flags;
-	AvbSlotVerifyData *slot_data[1] = {NULL};
+	AvbSlotVerifyData *slot_data = {NULL};
 	AvbSlotVerifyResult verify_result;
 	AvbABData ab_data, ab_data_orig;
 	size_t slot_index_to_boot = 0;
@@ -478,9 +769,29 @@
 	char can_boot = 1;
 	char retry_no_vbmeta_partition = 1;
 	unsigned long load_address = *android_load_address;
-	struct andr_img_hdr *hdr;
+	int ret;
 
-	requested_partitions[0] = boot_partname;
+	dev_desc = rockchip_get_bootdev();
+	if (!dev_desc)
+		return AVB_IO_RESULT_ERROR_IO;
+
+	if (part_get_info_by_name(dev_desc, boot_partname, &part_info) < 0) {
+		printf("Could not find \"%s\" partition\n", boot_partname);
+		return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+	}
+
+	hdr = populate_andr_img_hdr(dev_desc, &part_info);
+	if (!hdr) {
+		printf("No valid android hdr\n");
+		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
+	}
+
+	if (hdr->header_version >= 4) {
+		requested_partitions[1] = ANDROID_PARTITION_VENDOR_BOOT;
+		if (((hdr->os_version >> 25) & 0x7f) >= 13)
+			requested_partitions[2] = ANDROID_PARTITION_INIT_BOOT;
+	}
+
 	ops = avb_ops_user_new();
 	if (ops == NULL) {
 		printf("avb_ops_user_new() failed!\n");
@@ -497,7 +808,7 @@
 	if (unlocked & LOCK_MASK)
 		flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR;
 
-	if(load_metadata(ops->ab_ops, &ab_data, &ab_data_orig)) {
+	if (load_metadata(ops->ab_ops, &ab_data, &ab_data_orig)) {
 		printf("Can not load metadata\n");
 		return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 	}
@@ -509,8 +820,30 @@
 	else
 		slot_index_to_boot = 0;
 
-	if (strcmp(boot_partname, "recovery") == 0)
+	if (strcmp(boot_partname, ANDROID_PARTITION_RECOVERY) == 0)
 		flags |= AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION;
+
+#ifdef CONFIG_MP_BOOT
+	preload_user_data.boot.addr = (void *)mpb_post(1);
+	preload_user_data.boot.size = (size_t)mpb_post(2);
+#endif
+
+	/* use preload one if available */
+	if (preload_user_data.boot.addr) {
+		data = (struct AvbOpsData *)(ops->user_data);
+
+		data->slot_suffix = slot_suffix;
+		data->boot = preload_user_data.boot;
+		data->vendor_boot = preload_user_data.vendor_boot;
+		data->init_boot = preload_user_data.init_boot;
+		data->resource = preload_user_data.resource;
+	} else {
+		ret = avb_image_distribute_prepare(slot_data, ops, slot_suffix);
+		if (ret < 0) {
+			printf("avb image distribute prepare failed %d\n", ret);
+			return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+		}
+	}
 
 retry_verify:
 	verify_result =
@@ -519,10 +852,10 @@
 			slot_suffix,
 			flags,
 			AVB_HASHTREE_ERROR_MODE_RESTART,
-			&slot_data[0]);
+			&slot_data);
 	if (verify_result != AVB_SLOT_VERIFY_RESULT_OK &&
 	    verify_result != AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED) {
-		if (retry_no_vbmeta_partition && strcmp(boot_partname, "recovery") == 0) {
+		if (retry_no_vbmeta_partition && strcmp(boot_partname, ANDROID_PARTITION_RECOVERY) == 0) {
 			printf("Verify recovery with vbmeta.\n");
 			flags &= ~AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION;
 			retry_no_vbmeta_partition = 0;
@@ -558,7 +891,7 @@
 		break;
 	}
 
-	if (!slot_data[0]) {
+	if (!slot_data) {
 		can_boot = 0;
 		goto out;
 	}
@@ -569,12 +902,12 @@
 		int len = 0;
 		char *bootargs, *newbootargs;
 #ifdef CONFIG_ANDROID_AVB_ROLLBACK_INDEX
-		if (rk_avb_update_stored_rollback_indexes_for_slot(ops, slot_data[0]))
+		if (rk_avb_update_stored_rollback_indexes_for_slot(ops, slot_data))
 			printf("Fail to update the rollback indexes.\n");
 #endif
-		if (*slot_data[0]->cmdline) {
-			debug("Kernel command line: %s\n", slot_data[0]->cmdline);
-			len += strlen(slot_data[0]->cmdline);
+		if (slot_data->cmdline) {
+			debug("Kernel command line: %s\n", slot_data->cmdline);
+			len += strlen(slot_data->cmdline);
 		}
 
 		bootargs = env_get("bootargs");
@@ -593,49 +926,15 @@
 			strcpy(newbootargs, bootargs);
 			strcat(newbootargs, " ");
 		}
-		if (*slot_data[0]->cmdline)
-			strcat(newbootargs, slot_data[0]->cmdline);
+		if (slot_data->cmdline)
+			strcat(newbootargs, slot_data->cmdline);
 		env_set("bootargs", newbootargs);
 
-		hdr = (void *)slot_data[0]->loaded_partitions->data;
-
-		/*
-		 *		populate boot_img_hdr_v34
-		 *
-		 * If allow verification error: the image is loaded by
-		 * ops->get_preloaded_partition() which auto populates
-		 * boot_img_hdr_v34.
-		 *
-		 * If not allow verification error: the image is full loaded
-		 * by ops->read_from_partition() which doesn't populate
-		 * boot_img_hdr_v34, we need to fix it here.
-		 */
-		if (hdr->header_version >= 3 &&
-		    !(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR)) {
-			struct andr_img_hdr *v3hdr;
-			struct blk_desc *dev_desc;
-			disk_partition_t part;
-
-			dev_desc = rockchip_get_bootdev();
-			if (!dev_desc)
-				return -1;
-
-			if (part_get_info_by_name(dev_desc,
-						  boot_partname, &part) < 0)
-				return -1;
-
-			v3hdr = populate_andr_img_hdr(dev_desc, &part);
-			if (v3hdr) {
-				memcpy(hdr, v3hdr, sizeof(*v3hdr));
-				free(v3hdr);
-			}
-		}
-
-		/* Reserve page_size */
-		load_address -= hdr->page_size;
-		if (android_image_memcpy_separate(hdr, &load_address)) {
-			printf("Failed to separate copy android image\n");
-			return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+		/* if need, distribute full image to where they should be */
+		ret = avb_image_distribute_finish(slot_data, flags, &load_address);
+		if (ret) {
+			printf("avb image distribute finish failed %d\n", ret);
+			return ret;
 		}
 		*android_load_address = load_address;
 	} else {
@@ -649,8 +948,8 @@
 		verify_result = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 	}
 
-	if (slot_data[0] != NULL)
-		avb_slot_verify_data_free(slot_data[0]);
+	if (slot_data != NULL)
+		avb_slot_verify_data_free(slot_data);
 
 	if ((unlocked & LOCK_MASK) && can_boot)
 		return 0;
@@ -1047,10 +1346,6 @@
 		printf("Android image load failed\n");
 		return -1;
 	}
-#endif
-
-#ifdef CONFIG_ANDROID_AB
-	ab_update_root_uuid();
 #endif
 
 	/* Set Android root variables. */

--
Gitblit v1.6.2