From 7660fb22e22a1ad6a408038a2f20f34392e5e708 Mon Sep 17 00:00:00 2001 From: Ji Luo Date: Thu, 28 May 2020 11:06:37 +0800 Subject: [PATCH] MA-17260 Add vendor boot and boot header v3 support GKI(Generic Kernel Image) would require the boot header v3 and vendor boot support, all device specific info are moved to vendor_boot partition ,the boot header v3 will not be compatible with earlier version(0/1/2). This commit adds support for boot header v3 and vendor boot, it would concatenate the generic ramdisk and vendor ramdisk to generate the final ramdisk passed to kernel. Test: boots with or without boot header v3 and vendor boot support. Signed-off-by: Ji Luo Change-Id: Ib3298ae46bfc728aa4a34909d372eff6cc86ca70 (cherry picked from commit c3854f270a19e7d57b996e6074d692ab9bc88c32) --- common/image-android.c | 262 +++++++++++++++++--------- drivers/fastboot/fb_fsl/fb_fsl_boot.c | 197 ++++++++++++------- include/android_image.h | 110 +++++++++++ include/image.h | 4 + lib/Kconfig | 3 + 5 files changed, 427 insertions(+), 149 deletions(-) diff --git a/common/image-android.c b/common/image-android.c index d7e3c936f6..892801d6cc 100644 --- a/common/image-android.c +++ b/common/image-android.c @@ -26,6 +26,7 @@ #include #define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR 0x10008000 +#define COMMANDLINE_LENGTH 2048 static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1]; @@ -55,80 +56,17 @@ static ulong android_image_get_kernel_addr(const struct andr_img_hdr *hdr) return hdr->kernel_addr; } -/** - * android_image_get_kernel() - processes kernel part of Android boot images - * @hdr: Pointer to image header, which is at the start - * of the image. - * @verify: Checksum verification flag. Currently unimplemented. - * @os_data: Pointer to a ulong variable, will hold os data start - * address. - * @os_len: Pointer to a ulong variable, will hold os data length. - * - * This function returns the os image's start address and length. Also, - * it appends the kernel command line to the bootargs env variable. - * - * Return: Zero, os start address and length on success, - * otherwise on failure. - */ -int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, - ulong *os_data, ulong *os_len) +static void append_kernel_cmdline(char *commandline) { - extern boot_metric metrics; - u32 kernel_addr = android_image_get_kernel_addr(hdr); - const struct image_header *ihdr = (const struct image_header *) - ((uintptr_t)hdr + hdr->page_size); - - /* - * Not all Android tools use the id field for signing the image with - * sha1 (or anything) so we don't check it. It is not obvious that the - * string is null terminated so we take care of this. - */ - strncpy(andr_tmp_str, hdr->name, ANDR_BOOT_NAME_SIZE); - andr_tmp_str[ANDR_BOOT_NAME_SIZE] = '\0'; - if (strlen(andr_tmp_str)) - printf("Android's image name: %s\n", andr_tmp_str); - - printf("Kernel load addr 0x%08x size %u KiB\n", - kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024)); - char newbootargs[512] = {0}; - char commandline[2048] = {0}; - int offset; - char *bootargs = env_get("bootargs"); - - if (bootargs) { - if (strlen(bootargs) + 1 > sizeof(commandline)) { - printf("bootargs is too long!\n"); - return -1; - } - else - strncpy(commandline, bootargs, sizeof(commandline) - 1); - } else { - offset = fdt_path_offset(gd->fdt_blob, "/chosen"); - if (offset > 0) { - bootargs = (char *)fdt_getprop(gd->fdt_blob, offset, - "bootargs", NULL); - if (bootargs) - sprintf(commandline, "%s ", bootargs); - } - - if (*hdr->cmdline) { - if (strlen(hdr->cmdline) + 1 > - sizeof(commandline) - strlen(commandline)) { - printf("cmdline in bootimg is too long!\n"); - return -1; - } - else - strncat(commandline, hdr->cmdline, sizeof(commandline) - strlen(commandline)); - } - } + extern boot_metric metrics; /* Add 'bootargs_ram_capacity' to hold the parameters based on different ram capacity */ char *bootargs_ram_capacity = env_get("bootargs_ram_capacity"); if (bootargs_ram_capacity) { - strncat(commandline, " ", sizeof(commandline) - strlen(commandline)); + strncat(commandline, " ", COMMANDLINE_LENGTH - strlen(commandline)); strncat(commandline, bootargs_ram_capacity, - sizeof(commandline) - strlen(commandline)); + COMMANDLINE_LENGTH - strlen(commandline)); } #ifdef CONFIG_SERIAL_TAG @@ -139,7 +77,7 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, " androidboot.serialno=%08x%08x", serialnr.high, serialnr.low); - strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline)); if (serialnr.high + serialnr.low != 0) { char bd_addr[16]={0}; @@ -151,7 +89,7 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, " androidboot.btmacaddr=%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", bd_addr[0],bd_addr[1],bd_addr[2],bd_addr[3],bd_addr[4],bd_addr[5], bd_addr[6],bd_addr[7],bd_addr[8],bd_addr[9],bd_addr[10],bd_addr[11]); - strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline)); } #endif @@ -161,12 +99,12 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, sprintf(newbootargs, " androidboot.soc_type=%s", soc_type); - strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline)); } sprintf(newbootargs, " androidboot.boot_device_root=mmcblk%d", mmc_map_to_kernel_blk(mmc_get_env_dev())); - strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline)); /* boot metric variables */ metrics.ble_1 = get_timer(0); @@ -174,7 +112,7 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, " androidboot.boottime=1BLL:%d,1BLE:%d,KL:%d,KD:%d,AVB:%d,ODT:%d,SW:%d", metrics.bll_1, metrics.ble_1, metrics.kl, metrics.kd, metrics.avb, metrics.odt, metrics.sw); - strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline)); #if defined(CONFIG_ARCH_MX6) || defined(CONFIG_ARCH_MX7) || \ defined(CONFIG_ARCH_MX7ULP) || defined(CONFIG_ARCH_IMX8M) @@ -191,14 +129,14 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, #else sprintf(newbootargs," androidboot.bootreason=reboot"); #endif - strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline)); #ifdef CONFIG_AVB_SUPPORT /* secondary cmdline added by avb */ char *bootargs_sec = env_get("bootargs_sec"); if (bootargs_sec) { - strncat(commandline, " ", sizeof(commandline) - strlen(commandline)); - strncat(commandline, bootargs_sec, sizeof(commandline) - strlen(commandline)); + strncat(commandline, " ", COMMANDLINE_LENGTH - strlen(commandline)); + strncat(commandline, bootargs_sec, COMMANDLINE_LENGTH - strlen(commandline)); } #endif #ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT @@ -209,8 +147,8 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, */ char *bootargs_3rd = env_get("bootargs_3rd"); if (bootargs_3rd) { - strncat(commandline, " ", sizeof(commandline) - strlen(commandline)); - strncat(commandline, bootargs_3rd, sizeof(commandline) - strlen(commandline)); + strncat(commandline, " ", COMMANDLINE_LENGTH - strlen(commandline)); + strncat(commandline, bootargs_3rd, COMMANDLINE_LENGTH - strlen(commandline)); } #endif @@ -220,18 +158,18 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, */ #if defined(CONFIG_ANDROID_SUPPORT) || defined(CONFIG_ANDROID_AUTO_SUPPORT) sprintf(newbootargs," androidboot.dtbo_idx=0"); - strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline)); + strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline)); #endif char *keystore = env_get("keystore"); if ((keystore == NULL) || strncmp(keystore, "trusty", sizeof("trusty"))) { char *bootargs_trusty = "androidboot.keystore=software"; - strncat(commandline, " ", sizeof(commandline) - strlen(commandline)); - strncat(commandline, bootargs_trusty, sizeof(commandline) - strlen(commandline)); + strncat(commandline, " ", COMMANDLINE_LENGTH - strlen(commandline)); + strncat(commandline, bootargs_trusty, COMMANDLINE_LENGTH - strlen(commandline)); } else { char *bootargs_trusty = "androidboot.keystore=trusty"; - strncat(commandline, " ", sizeof(commandline) - strlen(commandline)); - strncat(commandline, bootargs_trusty, sizeof(commandline) - strlen(commandline)); + strncat(commandline, " ", COMMANDLINE_LENGTH - strlen(commandline)); + strncat(commandline, bootargs_trusty, COMMANDLINE_LENGTH - strlen(commandline)); } #ifdef CONFIG_APPEND_BOOTARGS @@ -240,14 +178,83 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, char *append_bootargs = env_get("append_bootargs"); if (append_bootargs) { if (strlen(append_bootargs) + 2 > - (sizeof(commandline) - strlen(commandline))) { + (COMMANDLINE_LENGTH - strlen(commandline))) { printf("The 'append_bootargs' is too long to be appended to bootargs\n"); } else { - strncat(commandline, " ", sizeof(commandline) - strlen(commandline)); - strncat(commandline, append_bootargs, sizeof(commandline) - strlen(commandline)); + strncat(commandline, " ", COMMANDLINE_LENGTH - strlen(commandline)); + strncat(commandline, append_bootargs, COMMANDLINE_LENGTH - strlen(commandline)); } } #endif +} + +/** + * android_image_get_kernel() - processes kernel part of Android boot images + * @hdr: Pointer to image header, which is at the start + * of the image. + * @verify: Checksum verification flag. Currently unimplemented. + * @os_data: Pointer to a ulong variable, will hold os data start + * address. + * @os_len: Pointer to a ulong variable, will hold os data length. + * + * This function returns the os image's start address and length. Also, + * it appends the kernel command line to the bootargs env variable. + * + * Return: Zero, os start address and length on success, + * otherwise on failure. + */ +int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, + ulong *os_data, ulong *os_len) +{ + u32 kernel_addr = android_image_get_kernel_addr(hdr); + const struct image_header *ihdr = (const struct image_header *) + ((uintptr_t)hdr + hdr->page_size); + + /* + * Not all Android tools use the id field for signing the image with + * sha1 (or anything) so we don't check it. It is not obvious that the + * string is null terminated so we take care of this. + */ + strncpy(andr_tmp_str, hdr->name, ANDR_BOOT_NAME_SIZE); + andr_tmp_str[ANDR_BOOT_NAME_SIZE] = '\0'; + if (strlen(andr_tmp_str)) + printf("Android's image name: %s\n", andr_tmp_str); + + printf("Kernel load addr 0x%08x size %u KiB\n", + kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024)); + + char commandline[COMMANDLINE_LENGTH] = {0}; + int offset; + char *bootargs = env_get("bootargs"); + + if (bootargs) { + if (strlen(bootargs) + 1 > sizeof(commandline)) { + printf("bootargs is too long!\n"); + return -1; + } + else + strncpy(commandline, bootargs, sizeof(commandline) - 1); + } else { + offset = fdt_path_offset(gd->fdt_blob, "/chosen"); + if (offset > 0) { + bootargs = (char *)fdt_getprop(gd->fdt_blob, offset, + "bootargs", NULL); + if (bootargs) + sprintf(commandline, "%s ", bootargs); + } + + if (*hdr->cmdline) { + if (strlen(hdr->cmdline) + 1 > + COMMANDLINE_LENGTH - strlen(commandline)) { + printf("cmdline in bootimg is too long!\n"); + return -1; + } + else + strncat(commandline, hdr->cmdline, COMMANDLINE_LENGTH - strlen(commandline)); + } + } + + append_kernel_cmdline(commandline); debug("Kernel command line: %s\n", commandline); env_set("bootargs", commandline); @@ -266,6 +273,84 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, else *os_len = hdr->kernel_size; } + + return 0; +} + +/** + * android_image_get_kernel() - processes kernel part of Android boot images + * @hdr: Pointer to boot image header, which is at the start + * of the image. + * @vendor_hdr: Pointer to vendor_boot image header, which is at the start + * of the image. + * This function appends the kernel command line to the bootargs env variable. + * + * Return: Zero on success, otherwise on failure. + */ +int android_image_get_kernel_v3(const struct boot_img_hdr_v3 *hdr, + const struct vendor_boot_img_hdr_v3 *vendor_hdr) +{ + u32 kernel_addr = vendor_hdr->kernel_addr; + + /* + * Not all Android tools use the id field for signing the image with + * sha1 (or anything) so we don't check it. It is not obvious that the + * string is null terminated so we take care of this. + */ + strncpy(andr_tmp_str, (char *)(vendor_hdr->name), ANDR_VENDOR_BOOT_NAME_SIZE); + andr_tmp_str[ANDR_VENDOR_BOOT_NAME_SIZE] = '\0'; + if (strlen(andr_tmp_str)) + printf("Android's image name: %s\n", andr_tmp_str); + + printf("Kernel load addr 0x%08x size %u KiB\n", + kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024)); + + char commandline[COMMANDLINE_LENGTH] = {0}; + int offset; + char *bootargs = env_get("bootargs"); + + if (bootargs) { + if (strlen(bootargs) + 1 > sizeof(commandline)) { + printf("bootargs is too long!\n"); + return -1; + } + else + strncpy(commandline, bootargs, sizeof(commandline) - 1); + } else { + offset = fdt_path_offset(gd->fdt_blob, "/chosen"); + if (offset > 0) { + bootargs = (char *)fdt_getprop(gd->fdt_blob, offset, + "bootargs", NULL); + if (bootargs) + sprintf(commandline, "%s ", bootargs); + } + + if (*vendor_hdr->cmdline) { + if (strlen((char *)vendor_hdr->cmdline) + 1 > + COMMANDLINE_LENGTH - strlen(commandline)) { + printf("cmdline in bootimg is too long!\n"); + return -1; + } + else + strncat(commandline, (char *)(vendor_hdr->cmdline), COMMANDLINE_LENGTH - strlen(commandline)); + } + + if (*hdr->cmdline) { + if (strlen((char *)hdr->cmdline) + 1 > + COMMANDLINE_LENGTH - strlen(commandline)) { + printf("cmdline in bootimg is too long!\n"); + return -1; + } + else + strncat(commandline, (char *)hdr->cmdline, COMMANDLINE_LENGTH - strlen(commandline)); + } + } + + append_kernel_cmdline(commandline); + + debug("Kernel command line: %s\n", commandline); + env_set("bootargs", commandline); + return 0; } @@ -274,6 +359,13 @@ int android_image_check_header(const struct andr_img_hdr *hdr) return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE); } +int android_image_check_header_v3(const struct boot_img_hdr_v3 *hdr, + const struct vendor_boot_img_hdr_v3 *vendor_hdr) +{ + return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE) || + memcmp(ANDR_VENDOR_BOOT_MAGIC, vendor_hdr->magic, ANDR_VENDOR_BOOT_MAGIC_SIZE); +} + ulong android_image_get_end(const struct andr_img_hdr *hdr) { ulong end; diff --git a/drivers/fastboot/fb_fsl/fb_fsl_boot.c b/drivers/fastboot/fb_fsl/fb_fsl_boot.c index 8e7acd54d9..ca2c421177 100644 --- a/drivers/fastboot/fb_fsl/fb_fsl_boot.c +++ b/drivers/fastboot/fb_fsl/fb_fsl_boot.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "../lib/avb/fsl/utils.h" #ifdef CONFIG_AVB_SUPPORT @@ -498,7 +499,11 @@ fail: #if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC) /* we can use avb to verify Trusty if we want */ +#ifdef CONFIG_VENDOR_BOOT_SUPPORT +const char *requested_partitions_boot[] = {"boot", "vendor_boot", FDT_PART_NAME, NULL}; +#else const char *requested_partitions_boot[] = {"boot", FDT_PART_NAME, NULL}; +#endif const char *requested_partitions_recovery[] = {"recovery", FDT_PART_NAME, NULL}; static bool is_load_fdt_from_part(void) @@ -547,8 +552,13 @@ static int find_partition_data_by_name(char* part_name, int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong addr = 0; + /* 'hdr' should point to boot.img */ +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + struct boot_img_hdr_v3 *hdr = NULL; + struct vendor_boot_img_hdr_v3 *vendor_hdr = NULL; +#else struct andr_img_hdr *hdr = NULL; - ulong image_size; +#endif u32 avb_metric; bool check_image_arm64 = false; bool is_recovery_mode = false; @@ -556,6 +566,9 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { AvbABFlowResult avb_result; AvbSlotVerifyData *avb_out_data = NULL; AvbPartitionData *avb_loadpart = NULL; +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + AvbPartitionData *avb_vendorboot = NULL; +#endif /* get bootmode, default to boot "boot" */ if (argc > 1) { @@ -581,7 +594,11 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { avb_metric = get_timer(0); /* we don't need to verify fdt partition if we don't have it. */ if (!is_load_fdt_from_part()) { +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + requested_partitions_boot[2] = NULL; +#else requested_partitions_boot[1] = NULL; +#endif requested_partitions_recovery[1] = NULL; } #ifndef CONFIG_SYSTEM_RAMDISK_SUPPORT @@ -590,7 +607,7 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { } #endif - /* if in lock state, do avb verify */ + /* do avb verify */ #ifndef CONFIG_DUAL_BOOTLOADER /* For imx6 on Android, we don't have a/b slot and we want to verify * boot/recovery with AVB. For imx8 and Android Things we don't have @@ -637,6 +654,10 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { #ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT if (find_partition_data_by_name("boot", avb_out_data, &avb_loadpart)) goto fail; +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + if (find_partition_data_by_name("vendor_boot", avb_out_data, &avb_vendorboot)) + goto fail; +#endif #else if (!is_recovery_mode) { if (find_partition_data_by_name("boot", avb_out_data, &avb_loadpart)) @@ -647,10 +668,19 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { } #endif assert(avb_loadpart != NULL); +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + assert(avb_vendorboot != NULL); +#endif /* we should use avb_part_data->data as boot image */ /* boot image is already read by avb */ +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + hdr = (struct boot_img_hdr_v3 *)avb_loadpart->data; + vendor_hdr = (struct vendor_boot_img_hdr_v3 *)avb_vendorboot->data; + if (android_image_check_header_v3(hdr, vendor_hdr)) { +#else hdr = (struct andr_img_hdr *)avb_loadpart->data; if (android_image_check_header(hdr)) { +#endif printf("boota: bad boot image magic\n"); goto fail; } @@ -689,32 +719,47 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { fastboot_setup_system_boot_args(avb_out_data->ab_suffix, true); } #endif /* CONFIG_SYSTEM_RAMDISK_SUPPORT */ - image_size = avb_loadpart->data_size; -#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M) + /* If we are using uncompressed kernel image, copy it directly to - * hdr->kernel_addr, if we are using compressed lz4 kernel image, + * physical dram address. If we are using compressed lz4 kernel image, * we need to decompress the kernel image first. */ +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + if (image_arm64((void *)((ulong)hdr + 4096))) { + memcpy((void *)(long)vendor_hdr->kernel_addr, + (void *)((ulong)hdr + 4096), hdr->kernel_size); + } else if (IS_ENABLED(CONFIG_LZ4)) { + size_t lz4_len = MAX_KERNEL_LEN; + if (ulz4fn((void *)((ulong)hdr + 4096), + hdr->kernel_size, (void *)(ulong)vendor_hdr->kernel_addr, &lz4_len) != 0) { + printf("Decompress kernel fail!\n"); + goto fail; + } + } else { + printf("Wrong kernel image! Please check if you need to enable 'CONFIG_LZ4'\n"); + goto fail; + } +#else /* CONFIG_VENDOR_BOOT_SUPPORT */ +#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M) if (image_arm64((void *)((ulong)hdr + hdr->page_size))) { memcpy((void *)(long)hdr->kernel_addr, (void *)((ulong)hdr + hdr->page_size), hdr->kernel_size); - } else { -#ifdef CONFIG_LZ4 + } else if (IS_ENABLED(CONFIG_LZ4)) { size_t lz4_len = MAX_KERNEL_LEN; if (ulz4fn((void *)((ulong)hdr + hdr->page_size), hdr->kernel_size, (void *)(ulong)hdr->kernel_addr, &lz4_len) != 0) { printf("Decompress kernel fail!\n"); goto fail; } -#else /* CONFIG_LZ4 */ - printf("please enable CONFIG_LZ4 if we're using compressed lz4 kernel image!\n"); + } else { + printf("Wrong kernel image! Please check if you need to enable 'CONFIG_LZ4'\n"); goto fail; -#endif /* CONFIG_LZ4 */ } #else /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */ /* copy kernel image and boot header to hdr->kernel_addr - hdr->page_size */ memcpy((void *)(ulong)(hdr->kernel_addr - hdr->page_size), (void *)hdr, hdr->page_size + ALIGN(hdr->kernel_size, hdr->page_size)); #endif /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */ +#endif /* CONFIG_VENDOR_BOOT_SUPPORT */ } else { /* Fall into fastboot mode if get unacceptable error from avb * or verify fail in lock state. @@ -725,8 +770,22 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { goto fail; } - flush_cache((ulong)image_load_addr, image_size); +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + check_image_arm64 = image_arm64((void *)(ulong)vendor_hdr->kernel_addr); +#else check_image_arm64 = image_arm64((void *)(ulong)hdr->kernel_addr); +#endif + +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + /* Need to concatenate vendor_boot ramdisk and boot ramdisk, check + * "include/android_image.h" for boot/vendor_boot image overlay. + */ + memcpy((void *)(ulong)vendor_hdr->ramdisk_addr, + (void *)(ulong)vendor_hdr + ALIGN(sizeof(struct vendor_boot_img_hdr_v3), vendor_hdr->page_size), + vendor_hdr->vendor_ramdisk_size); + memcpy((void *)(ulong)vendor_hdr->ramdisk_addr + vendor_hdr->vendor_ramdisk_size, + (void *)(ulong)hdr + 4096 + ALIGN(hdr->kernel_size, 4096), hdr->ramdisk_size); +#else /* CONFIG_VENDOR_BOOT_SUPPORT */ #if !defined(CONFIG_SYSTEM_RAMDISK_SUPPORT) || !defined(CONFIG_ANDROID_AUTO_SUPPORT) memcpy((void *)(ulong)hdr->ramdisk_addr, (void *)(ulong)hdr + hdr->page_size + ALIGN(hdr->kernel_size, hdr->page_size), hdr->ramdisk_size); @@ -735,82 +794,87 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { memcpy((void *)(ulong)hdr->ramdisk_addr, (void *)(ulong)hdr + hdr->page_size + ALIGN(hdr->kernel_size, hdr->page_size), hdr->ramdisk_size); #endif +#endif /* CONFIG_VENDOR_BOOT_SUPPORT */ -#ifdef CONFIG_OF_LIBFDT /* load the dtb file */ +#ifdef CONFIG_OF_LIBFDT u32 fdt_addr = 0; u32 fdt_size = 0; struct dt_table_header *dt_img = NULL; - if (is_load_fdt_from_part()) { - fdt_addr = (ulong)((ulong)(hdr->kernel_addr) + MAX_KERNEL_LEN); +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + fdt_addr = (ulong)((ulong)(vendor_hdr->kernel_addr) + MAX_KERNEL_LEN); +#else + fdt_addr = (ulong)((ulong)(hdr->kernel_addr) + MAX_KERNEL_LEN); +#endif #ifdef CONFIG_ANDROID_THINGS_SUPPORT - if (find_partition_data_by_name("oem_bootloader", - avb_out_data, &avb_loadpart)) { - goto fail; - } else - dt_img = (struct dt_table_header *)avb_loadpart->data; + if (find_partition_data_by_name("oem_bootloader", + avb_out_data, &avb_loadpart)) { + goto fail; + } else + dt_img = (struct dt_table_header *)avb_loadpart->data; #elif defined(CONFIG_SYSTEM_RAMDISK_SUPPORT) /* It means boot.img(recovery) do not include dtb, it need load dtb from partition */ - if (find_partition_data_by_name("dtbo", - avb_out_data, &avb_loadpart)) { - goto fail; - } else - dt_img = (struct dt_table_header *)avb_loadpart->data; + if (find_partition_data_by_name("dtbo", + avb_out_data, &avb_loadpart)) { + goto fail; + } else + dt_img = (struct dt_table_header *)avb_loadpart->data; #else /* recovery.img include dts while boot.img use dtbo */ - if (is_recovery_mode) { - if (hdr->header_version != 1) { - printf("boota: boot image header version error!\n"); - goto fail; - } - - dt_img = (struct dt_table_header *)((void *)(ulong)hdr + - hdr->page_size + - ALIGN(hdr->kernel_size, hdr->page_size) + - ALIGN(hdr->ramdisk_size, hdr->page_size) + - ALIGN(hdr->second_size, hdr->page_size)); - } else if (find_partition_data_by_name("dtbo", - avb_out_data, &avb_loadpart)) { - goto fail; - } else - dt_img = (struct dt_table_header *)avb_loadpart->data; -#endif - - if (be32_to_cpu(dt_img->magic) != DT_TABLE_MAGIC) { - printf("boota: bad dt table magic %08x\n", - be32_to_cpu(dt_img->magic)); - goto fail; - } else if (!be32_to_cpu(dt_img->dt_entry_count)) { - printf("boota: no dt entries\n"); + if (is_recovery_mode) { + if (hdr->header_version != 1) { + printf("boota: boot image header version error!\n"); goto fail; } - struct dt_table_entry *dt_entry; - dt_entry = (struct dt_table_entry *)((ulong)dt_img + - be32_to_cpu(dt_img->dt_entries_offset)); - fdt_size = be32_to_cpu(dt_entry->dt_size); - memcpy((void *)fdt_addr, (void *)((ulong)dt_img + - be32_to_cpu(dt_entry->dt_offset)), fdt_size); - } else { - fdt_addr = (ulong)(hdr->second_addr); - fdt_size = (ulong)(hdr->second_size); - if (fdt_size && fdt_addr) { - memcpy((void *)(ulong)fdt_addr, - (void *)(ulong)hdr + hdr->page_size - + ALIGN(hdr->kernel_size, hdr->page_size) - + ALIGN(hdr->ramdisk_size, hdr->page_size), - fdt_size); - } + dt_img = (struct dt_table_header *)((void *)(ulong)hdr + + hdr->page_size + + ALIGN(hdr->kernel_size, hdr->page_size) + + ALIGN(hdr->ramdisk_size, hdr->page_size) + + ALIGN(hdr->second_size, hdr->page_size)); + } else if (find_partition_data_by_name("dtbo", + avb_out_data, &avb_loadpart)) { + goto fail; + } else + dt_img = (struct dt_table_header *)avb_loadpart->data; +#endif + + if (be32_to_cpu(dt_img->magic) != DT_TABLE_MAGIC) { + printf("boota: bad dt table magic %08x\n", + be32_to_cpu(dt_img->magic)); + goto fail; + } else if (!be32_to_cpu(dt_img->dt_entry_count)) { + printf("boota: no dt entries\n"); + goto fail; } + + struct dt_table_entry *dt_entry; + dt_entry = (struct dt_table_entry *)((ulong)dt_img + + be32_to_cpu(dt_img->dt_entries_offset)); + fdt_size = be32_to_cpu(dt_entry->dt_size); + memcpy((void *)fdt_addr, (void *)((ulong)dt_img + + be32_to_cpu(dt_entry->dt_offset)), fdt_size); #endif /*CONFIG_OF_LIBFDT*/ +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + android_image_get_kernel_v3(hdr, vendor_hdr); + addr = vendor_hdr->kernel_addr; +#else if (check_image_arm64) { android_image_get_kernel(hdr, 0, NULL, NULL); addr = hdr->kernel_addr; } else { addr = (ulong)(hdr->kernel_addr - hdr->page_size); } +#endif + +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + printf("kernel @ %08x (%d)\n", vendor_hdr->kernel_addr, hdr->kernel_size); + printf("ramdisk @ %08x (%d)\n", vendor_hdr->ramdisk_addr, + vendor_hdr->vendor_ramdisk_size + hdr->ramdisk_size); +#else printf("kernel @ %08x (%d)\n", hdr->kernel_addr, hdr->kernel_size); printf("ramdisk @ %08x (%d)\n", hdr->ramdisk_addr, hdr->ramdisk_size); +#endif #ifdef CONFIG_OF_LIBFDT if (fdt_size) printf("fdt @ %08x (%d)\n", fdt_addr, fdt_size); @@ -827,7 +891,12 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { boot_args[0] = "bootm"; sprintf(boot_addr_start, "0x%lx", addr); +#ifdef CONFIG_VENDOR_BOOT_SUPPORT + sprintf(ramdisk_addr, "0x%x:0x%x", vendor_hdr->ramdisk_addr, + vendor_hdr->vendor_ramdisk_size + hdr->ramdisk_size); +#else sprintf(ramdisk_addr, "0x%x:0x%x", hdr->ramdisk_addr, hdr->ramdisk_size); +#endif sprintf(fdt_addr_start, "0x%x", fdt_addr); /* when CONFIG_SYSTEM_RAMDISK_SUPPORT is enabled and it's for Android Auto, if it's not recovery mode diff --git a/include/android_image.h b/include/android_image.h index ef6ecc2e78..fb435035d6 100644 --- a/include/android_image.h +++ b/include/android_image.h @@ -20,6 +20,11 @@ #define ANDR_BOOT_ARGS_SIZE 512 #define ANDR_BOOT_EXTRA_ARGS_SIZE 1024 +#define ANDR_VENDOR_BOOT_MAGIC "VNDRBOOT" +#define ANDR_VENDOR_BOOT_MAGIC_SIZE 8 +#define ANDR_VENDOR_BOOT_ARGS_SIZE 2048 +#define ANDR_VENDOR_BOOT_NAME_SIZE 16 + /* The bootloader expects the structure of andr_img_hdr with header * version 0 to be as follows: */ /* Boot metric variables (in millisecond) */ @@ -80,6 +85,66 @@ struct andr_img_hdr { u64 dtb_addr; /* physical load address for DTB image */ } __attribute__((packed)); +struct boot_img_hdr_v3 { + // Must be BOOT_MAGIC. + uint8_t magic[ANDR_BOOT_MAGIC_SIZE]; + + uint32_t kernel_size; /* size in bytes */ + uint32_t ramdisk_size; /* size in bytes */ + + // Operating system version and security patch level. + // For version "A.B.C" and patch level "Y-M-D": + // (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M) + // os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0] + uint32_t os_version; + +#if __cplusplus + void SetOsVersion(unsigned major, unsigned minor, unsigned patch) { + os_version &= ((1 << 11) - 1); + os_version |= (((major & 0x7f) << 25) | ((minor & 0x7f) << 18) | ((patch & 0x7f) << 11)); + } + + void SetOsPatchLevel(unsigned year, unsigned month) { + os_version &= ~((1 << 11) - 1); + os_version |= (((year - 2000) & 0x7f) << 4) | ((month & 0xf) << 0); + } +#endif + + uint32_t header_size; + + uint32_t reserved[4]; + + // Version of the boot image header. + uint32_t header_version; + + uint8_t cmdline[ANDR_BOOT_ARGS_SIZE + ANDR_BOOT_EXTRA_ARGS_SIZE]; +} __attribute__((packed)); + +struct vendor_boot_img_hdr_v3 { + // Must be ANDR_VENDOR_BOOT_MAGIC. + uint8_t magic[ANDR_VENDOR_BOOT_MAGIC_SIZE]; + + // Version of the vendor boot image header. + uint32_t header_version; + + uint32_t page_size; /* flash page size we assume */ + + uint32_t kernel_addr; /* physical load addr */ + uint32_t ramdisk_addr; /* physical load addr */ + + uint32_t vendor_ramdisk_size; /* size in bytes */ + + uint8_t cmdline[ANDR_VENDOR_BOOT_ARGS_SIZE]; + + uint32_t tags_addr; /* physical addr for kernel tags (if required) */ + uint8_t name[ANDR_VENDOR_BOOT_NAME_SIZE]; /* asciiz product name */ + + uint32_t header_size; + + uint32_t dtb_size; /* size in bytes for DTB image */ + uint64_t dtb_addr; /* physical load address for DTB image */ +} __attribute__((packed)); + /* When a boot header is of version 0, the structure of boot image is as * follows: * @@ -152,6 +217,51 @@ struct andr_img_hdr { * else: jump to kernel_addr */ +/* When the boot image header has a version of 3, the structure of the boot + * image is as follows: + * + * +---------------------+ + * | boot header | 4096 bytes + * +---------------------+ + * | kernel | m pages + * +---------------------+ + * | ramdisk | n pages + * +---------------------+ + * + * m = (kernel_size + 4096 - 1) / 4096 + * n = (ramdisk_size + 4096 - 1) / 4096 + * + * Note that in version 3 of the boot image header, page size is fixed at 4096 bytes. + * + * The structure of the vendor boot image (introduced with version 3 and + * required to be present when a v3 boot image is used) is as follows: + * + * +---------------------+ + * | vendor boot header | o pages + * +---------------------+ + * | vendor ramdisk | p pages + * +---------------------+ + * | dtb | q pages + * +---------------------+ + + * o = (2112 + page_size - 1) / page_size + * p = (vendor_ramdisk_size + page_size - 1) / page_size + * q = (dtb_size + page_size - 1) / page_size + * + * 0. all entities in the boot image are 4096-byte aligned in flash, all + * entities in the vendor boot image are page_size (determined by the vendor + * and specified in the vendor boot image header) aligned in flash + * 1. kernel, ramdisk, vendor ramdisk, and DTB are required (size != 0) + * 2. load the kernel and DTB at the specified physical address (kernel_addr, + * dtb_addr) + * 3. load the vendor ramdisk at ramdisk_addr + * 4. load the generic ramdisk immediately following the vendor ramdisk in + * memory + * 5. set up registers for kernel entry as required by your architecture + * 6. if the platform has a second stage bootloader jump to it (must be + * contained outside boot and vendor boot partitions), otherwise + * jump to kernel_addr + */ struct header_image { uint32_t code0; /* Executable code */ uint32_t code1; /* Executable code */ diff --git a/include/image.h b/include/image.h index 05266b4cf2..3b0d896a0e 100644 --- a/include/image.h +++ b/include/image.h @@ -1522,9 +1522,13 @@ struct cipher_algo *image_get_cipher_algo(const char *full_name); #if !defined(USE_HOSTCC) #if defined(CONFIG_ANDROID_BOOT_IMAGE) struct andr_img_hdr; +struct boot_img_hdr_v3; +struct vendor_boot_img_hdr_v3; int android_image_check_header(const struct andr_img_hdr *hdr); +int android_image_check_header_v3(const struct boot_img_hdr_v3 *hdr, const struct vendor_boot_img_hdr_v3 *vendor_hdr); int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, ulong *os_data, ulong *os_len); +int android_image_get_kernel_v3(const struct boot_img_hdr_v3 *hdr, const struct vendor_boot_img_hdr_v3 *vendor_hdr); int android_image_get_ramdisk(const struct andr_img_hdr *hdr, ulong *rd_data, ulong *rd_len); int android_image_get_second(const struct andr_img_hdr *hdr, diff --git a/lib/Kconfig b/lib/Kconfig index e16db5e49e..c34fa5c587 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -371,6 +371,9 @@ config TRUSTY_UNLOCK_PERMISSION bool "Support unlock permission protection in trusty" depends on IMX_TRUSTY_OS +config VENDOR_BOOT_SUPPORT + bool "Support vendor boot load" + endmenu menu "Hashing Support" -- 2.17.1