From d71a732af45e2d3acef92649f4f7986a83175cf4 Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:03 +0100 Subject: android: boot: rename andr_img_hdr -> andr_boot_img_hdr_v0 Android introduced boot header version 3 or 4. The header structure change with version 3 and 4 to support the new updates such as: - Introducing Vendor boot image: with a vendor ramdisk - Bootconfig feature (v4) Change andr_img_hdr struct name to maintain support for version v0, v1 and v2 while introducing version 3 and 4. Signed-off-by: Safae Ouajih Reviewed-by: Simon Glass Reviewed-by: Mattijs Korpershoek Tested-by: Mattijs Korpershoek --- boot/image-android.c | 37 +++++++++++++++++++++++-------------- boot/image-fdt.c | 2 +- 2 files changed, 24 insertions(+), 15 deletions(-) (limited to 'boot') diff --git a/boot/image-android.c b/boot/image-android.c index 2628db37412..b070974791a 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -18,7 +18,7 @@ static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1]; -static ulong android_image_get_kernel_addr(const struct andr_img_hdr *hdr) +static ulong android_image_get_kernel_addr(const struct andr_boot_img_hdr_v0 *hdr) { /* * All the Android tools that generate a boot.img use this @@ -59,7 +59,7 @@ static ulong android_image_get_kernel_addr(const struct andr_img_hdr *hdr) * 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, +int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, int verify, ulong *os_data, ulong *os_len) { u32 kernel_addr = android_image_get_kernel_addr(hdr); @@ -122,12 +122,21 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, return 0; } -int android_image_check_header(const struct andr_img_hdr *hdr) +/** + * android_image_check_header() - Check the magic of boot image + * + * This checks the header of Android boot image and verifies the + * magic is "ANDROID!" + * + * @hdr: Pointer to boot image + * Return: 0 if the magic is correct, non-zero if there is a magic mismatch + */ +int android_image_check_header(const struct andr_boot_img_hdr_v0 *hdr) { return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE); } -ulong android_image_get_end(const struct andr_img_hdr *hdr) +ulong android_image_get_end(const struct andr_boot_img_hdr_v0 *hdr) { ulong end; @@ -150,12 +159,12 @@ ulong android_image_get_end(const struct andr_img_hdr *hdr) return end; } -ulong android_image_get_kload(const struct andr_img_hdr *hdr) +ulong android_image_get_kload(const struct andr_boot_img_hdr_v0 *hdr) { return android_image_get_kernel_addr(hdr); } -ulong android_image_get_kcomp(const struct andr_img_hdr *hdr) +ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr) { const void *p = (void *)((uintptr_t)hdr + hdr->page_size); @@ -167,7 +176,7 @@ ulong android_image_get_kcomp(const struct andr_img_hdr *hdr) return image_decomp_type(p, sizeof(u32)); } -int android_image_get_ramdisk(const struct andr_img_hdr *hdr, +int android_image_get_ramdisk(const struct andr_boot_img_hdr_v0 *hdr, ulong *rd_data, ulong *rd_len) { if (!hdr->ramdisk_size) { @@ -186,8 +195,8 @@ int android_image_get_ramdisk(const struct andr_img_hdr *hdr, return 0; } -int android_image_get_second(const struct andr_img_hdr *hdr, - ulong *second_data, ulong *second_len) +int android_image_get_second(const struct andr_boot_img_hdr_v0 *hdr, + ulong *second_data, ulong *second_len) { if (!hdr->second_size) { *second_data = *second_len = 0; @@ -226,7 +235,7 @@ int android_image_get_second(const struct andr_img_hdr *hdr, */ bool android_image_get_dtbo(ulong hdr_addr, ulong *addr, u32 *size) { - const struct andr_img_hdr *hdr; + const struct andr_boot_img_hdr_v0 *hdr; ulong dtbo_img_addr; bool ret = true; @@ -275,7 +284,7 @@ exit: */ static bool android_image_get_dtb_img_addr(ulong hdr_addr, ulong *addr) { - const struct andr_img_hdr *hdr; + const struct andr_boot_img_hdr_v0 *hdr; ulong dtb_img_addr; bool ret = true; @@ -328,7 +337,7 @@ exit: bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr, u32 *size) { - const struct andr_img_hdr *hdr; + const struct andr_boot_img_hdr_v0 *hdr; bool res; ulong dtb_img_addr; /* address of DTB part in boot image */ u32 dtb_img_size; /* size of DTB payload in boot image */ @@ -393,7 +402,7 @@ bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr, * returns: * no returned results */ -void android_print_contents(const struct andr_img_hdr *hdr) +void android_print_contents(const struct andr_boot_img_hdr_v0 *hdr) { const char * const p = IMAGE_INDENT_STRING; /* os_version = ver << 11 | lvl */ @@ -485,7 +494,7 @@ static bool android_image_print_dtb_info(const struct fdt_header *fdt, */ bool android_image_print_dtb_contents(ulong hdr_addr) { - const struct andr_img_hdr *hdr; + const struct andr_boot_img_hdr_v0 *hdr; bool res; ulong dtb_img_addr; /* address of DTB part in boot image */ u32 dtb_img_size; /* size of DTB payload in boot image */ diff --git a/boot/image-fdt.c b/boot/image-fdt.c index 714d05d1a53..ba44ecf8ef3 100644 --- a/boot/image-fdt.c +++ b/boot/image-fdt.c @@ -529,7 +529,7 @@ int boot_get_fdt(int flag, int argc, char *const argv[], uint8_t arch, } #ifdef CONFIG_ANDROID_BOOT_IMAGE } else if (genimg_get_format(buf) == IMAGE_FORMAT_ANDROID) { - struct andr_img_hdr *hdr = buf; + struct andr_boot_img_hdr_v0 *hdr = buf; ulong fdt_data, fdt_len; u32 fdt_size, dtb_idx; /* -- cgit v1.3.1 From 734cb47d6de16d2e3b52a03bce5daab40e5bb29d Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:05 +0100 Subject: android: boot: replace android_image_check_header With the new vendor boot image introduced in versions 3 and 4 of boot image header, the header check must be done for both boot image and vendor boot image. Thus, replace android_image_check_header() by is_android_boot_image_header() to only refer to boot image header check. Signed-off-by: Safae Ouajih Reviewed-by: Simon Glass Reviewed-by: Mattijs Korpershoek Tested-by: Mattijs Korpershoek --- boot/image-android.c | 17 ++++------------- boot/image-board.c | 2 +- cmd/abootimg.c | 4 ++-- drivers/fastboot/fb_mmc.c | 3 +-- include/image.h | 22 +++++++++++----------- 5 files changed, 19 insertions(+), 29 deletions(-) (limited to 'boot') diff --git a/boot/image-android.c b/boot/image-android.c index b070974791a..ac7cb479c15 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -122,18 +122,9 @@ int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, int verify, return 0; } -/** - * android_image_check_header() - Check the magic of boot image - * - * This checks the header of Android boot image and verifies the - * magic is "ANDROID!" - * - * @hdr: Pointer to boot image - * Return: 0 if the magic is correct, non-zero if there is a magic mismatch - */ -int android_image_check_header(const struct andr_boot_img_hdr_v0 *hdr) +bool is_android_boot_image_header(const struct andr_boot_img_hdr_v0 *hdr) { - return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE); + return !memcmp(ANDR_BOOT_MAGIC, hdr, ANDR_BOOT_MAGIC_SIZE); } ulong android_image_get_end(const struct andr_boot_img_hdr_v0 *hdr) @@ -240,7 +231,7 @@ bool android_image_get_dtbo(ulong hdr_addr, ulong *addr, u32 *size) bool ret = true; hdr = map_sysmem(hdr_addr, sizeof(*hdr)); - if (android_image_check_header(hdr)) { + if (!is_android_boot_image_header(hdr)) { printf("Error: Boot Image header is incorrect\n"); ret = false; goto exit; @@ -289,7 +280,7 @@ static bool android_image_get_dtb_img_addr(ulong hdr_addr, ulong *addr) bool ret = true; hdr = map_sysmem(hdr_addr, sizeof(*hdr)); - if (android_image_check_header(hdr)) { + if (!is_android_boot_image_header(hdr)) { printf("Error: Boot Image header is incorrect\n"); ret = false; goto exit; diff --git a/boot/image-board.c b/boot/image-board.c index 9bf70824cb7..e086103258f 100644 --- a/boot/image-board.c +++ b/boot/image-board.c @@ -284,7 +284,7 @@ int genimg_get_format(const void *img_addr) return IMAGE_FORMAT_FIT; } if (IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE) && - !android_image_check_header(img_addr)) + is_android_boot_image_header(img_addr)) return IMAGE_FORMAT_ANDROID; return IMAGE_FORMAT_INVALID; diff --git a/cmd/abootimg.c b/cmd/abootimg.c index 026c03f91c7..b5cfb141ef7 100644 --- a/cmd/abootimg.c +++ b/cmd/abootimg.c @@ -26,7 +26,7 @@ static int abootimg_get_ver(int argc, char *const argv[]) return CMD_RET_USAGE; hdr = map_sysmem(abootimg_addr(), sizeof(*hdr)); - if (android_image_check_header(hdr)) { + if (!is_android_boot_image_header(hdr)) { printf("Error: Boot Image header is incorrect\n"); res = CMD_RET_FAILURE; goto exit; @@ -73,7 +73,7 @@ static int abootimg_get_dtb_load_addr(int argc, char *const argv[]) return CMD_RET_USAGE; hdr = map_sysmem(abootimg_addr(), sizeof(*hdr)); - if (android_image_check_header(hdr)) { + if (!is_android_boot_image_header(hdr)) { printf("Error: Boot Image header is incorrect\n"); res = CMD_RET_FAILURE; goto exit; diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c index 68677c55ce1..29c18cb82a4 100644 --- a/drivers/fastboot/fb_mmc.c +++ b/drivers/fastboot/fb_mmc.c @@ -313,8 +313,7 @@ static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc, } /* Check boot header magic string */ - res = android_image_check_header(hdr); - if (res != 0) { + if (!is_android_boot_image_header(hdr)) { pr_err("bad boot image magic\n"); fastboot_fail("boot partition not initialized", response); return 0; diff --git a/include/image.h b/include/image.h index 735484117d7..6e67cf4817a 100644 --- a/include/image.h +++ b/include/image.h @@ -1736,17 +1736,6 @@ struct cipher_algo *image_get_cipher_algo(const char *full_name); struct andr_boot_img_hdr_v0; -/** - * android_image_check_header() - Check the magic of boot image - * - * This checks the header of Android boot image and verifies the - * magic is "ANDROID!" - * - * @hdr: Pointer to image header - * Return: 0 if the magic is correct, non-zero if there is a magic mismatch - */ -int android_image_check_header(const struct andr_boot_img_hdr_v0 *hdr); - /** * android_image_get_kernel() - Processes kernel part of Android boot images * @@ -1838,6 +1827,17 @@ ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr); void android_print_contents(const struct andr_boot_img_hdr_v0 *hdr); bool android_image_print_dtb_contents(ulong hdr_addr); +/** + * is_android_boot_image_header() - Check the magic of boot image + * + * This checks the header of Android boot image and verifies the + * magic is "ANDROID!" + * + * @hdr: Pointer to boot image + * Return: non-zero if the magic is correct, zero otherwise + */ +bool is_android_boot_image_header(const struct andr_boot_img_hdr_v0 *hdr); + /** * board_fit_config_name_match() - Check for a matching board name * -- cgit v1.3.1 From f48efa0edb6f65b2c382209871df7c9b61a905e2 Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:07 +0100 Subject: android: boot: kcomp: support andr_image_data andr_image_data structure is used as a global representation of boot image header structure. Introduce this new structure to support all boot header versions : v0,v1.v2.v3.v4 and to support v3 and v4 while maitaining support for v0,v1,v2. The need of using andr_image_data comes from the change of header structure in both version 3 and 4. Rework android_image_get_kcomp() to support this new struct. Signed-off-by: Safae Ouajih Reviewed-by: Simon Glass Reviewed-by: Mattijs Korpershoek Tested-by: Mattijs Korpershoek --- boot/image-android.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++- include/android_image.h | 27 ++++++++++++++++++ include/image.h | 12 ++++++++ 3 files changed, 113 insertions(+), 1 deletion(-) (limited to 'boot') diff --git a/boot/image-android.c b/boot/image-android.c index ac7cb479c15..ea05c1814f0 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -18,6 +18,74 @@ static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1]; +static void android_boot_image_v0_v1_v2_parse_hdr(const struct andr_boot_img_hdr_v0 *hdr, + struct andr_image_data *data) +{ + ulong end; + + data->image_name = hdr->name; + data->kcmdline = hdr->cmdline; + data->kernel_addr = hdr->kernel_addr; + data->ramdisk_addr = hdr->ramdisk_addr; + data->header_version = hdr->header_version; + data->dtb_load_addr = hdr->dtb_addr; + + end = (ulong)hdr; + + /* + * The header takes a full page, the remaining components are aligned + * on page boundary + */ + + end += hdr->page_size; + + data->kernel_ptr = end; + data->kernel_size = hdr->kernel_size; + end += ALIGN(hdr->kernel_size, hdr->page_size); + + data->ramdisk_ptr = end; + data->ramdisk_size = hdr->ramdisk_size; + end += ALIGN(hdr->ramdisk_size, hdr->page_size); + + data->second_ptr = end; + data->second_size = hdr->second_size; + end += ALIGN(hdr->second_size, hdr->page_size); + + if (hdr->header_version >= 1) { + data->recovery_dtbo_ptr = end; + data->recovery_dtbo_size = hdr->recovery_dtbo_size; + end += ALIGN(hdr->recovery_dtbo_size, hdr->page_size); + } + + if (hdr->header_version >= 2) { + data->dtb_ptr = end; + data->dtb_size = hdr->dtb_size; + end += ALIGN(hdr->dtb_size, hdr->page_size); + } + + data->boot_img_total_size = end - (ulong)hdr; +} + +bool android_image_get_data(const void *boot_hdr, struct andr_image_data *data) +{ + if (!boot_hdr || !data) { + printf("boot_hdr or data params can't be NULL\n"); + return false; + } + + if (!is_android_boot_image_header(boot_hdr)) { + printf("Incorrect boot image header\n"); + return false; + } + + if (((struct andr_boot_img_hdr_v0 *)boot_hdr)->header_version > 2) + printf("Only boot image header version 2 and below are supported\n"); + else + android_boot_image_v0_v1_v2_parse_hdr(boot_hdr, data); + + return true; +} + static ulong android_image_get_kernel_addr(const struct andr_boot_img_hdr_v0 *hdr) { /* @@ -157,8 +225,13 @@ ulong android_image_get_kload(const struct andr_boot_img_hdr_v0 *hdr) ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr) { - const void *p = (void *)((uintptr_t)hdr + hdr->page_size); + struct andr_image_data img_data; + const void *p; + + if (!android_image_get_data(hdr, &img_data)) + return -EINVAL; + p = (const void *)img_data.kernel_ptr; if (image_get_magic((struct legacy_img_hdr *)p) == IH_MAGIC) return image_get_comp((struct legacy_img_hdr *)p); else if (get_unaligned_le32(p) == LZ4F_MAGIC) diff --git a/include/android_image.h b/include/android_image.h index f0543630019..fb3a9d9858b 100644 --- a/include/android_image.h +++ b/include/android_image.h @@ -317,4 +317,31 @@ struct andr_boot_img_hdr_v0 { * contained outside boot and vendor boot partitions), otherwise * jump to kernel_addr */ + +/* Private struct */ +struct andr_image_data { + ulong kernel_ptr; /* kernel address */ + u32 kernel_size; /* size in bytes */ + u32 ramdisk_size; /* size in bytes */ + u32 boot_ramdisk_size; /* size in bytes */ + ulong second_ptr; /* secondary bootloader address */ + u32 second_size; /* secondary bootloader size */ + ulong dtb_ptr; /* address of dtb image */ + u32 dtb_size; /* size of dtb image */ + ulong recovery_dtbo_ptr; /* size in bytes for recovery DTBO/ACPIO image */ + u32 recovery_dtbo_size; /* offset to recovery dtbo/acpio in boot image */ + + const char *kcmdline; /* boot kernel cmdline */ + const char *kcmdline_extra; /* vendor-boot extra kernel cmdline */ + const char *image_name; /* asciiz product name */ + + u32 kernel_addr; /* physical load addr */ + ulong ramdisk_addr; /* physical load addr */ + ulong ramdisk_ptr; /* ramdisk address */ + ulong dtb_load_addr; /* physical load address for DTB image */ + ulong tags_addr; /* physical addr for kernel tags */ + u32 header_version; /* version of the boot image header */ + u32 boot_img_total_size; /* boot image size */ +}; + #endif diff --git a/include/image.h b/include/image.h index 6e67cf4817a..4bf6c98ced7 100644 --- a/include/image.h +++ b/include/image.h @@ -1733,7 +1733,19 @@ struct cipher_algo { int fit_image_cipher_get_algo(const void *fit, int noffset, char **algo); struct cipher_algo *image_get_cipher_algo(const char *full_name); +struct andr_image_data; +/** + * android_image_get_data() - Parse Android boot image + * + * This is used to parse boot image header into andr_image_data + * generic structure. + * + * @boot_hdr: Pointer to boot image header + * @data: Pointer to generic boot format structure + * Return: true if succeeded, false otherwise + */ +bool android_image_get_data(const void *boot_hdr, struct andr_image_data *data); struct andr_boot_img_hdr_v0; /** -- cgit v1.3.1 From 607b07554e23ff58d245f16765d831253a4210de Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:08 +0100 Subject: android: boot: move to andr_image_data structure Move from andr_boot_img_hdr_v0 to andr_image_data structure to prepare for boot image header version 3 and 4. Signed-off-by: Safae Ouajih Tested-by: Mattijs Korpershoek --- boot/image-android.c | 121 +++++++++++++++++++++++++++------------------------ cmd/abootimg.c | 31 ++++++------- 2 files changed, 81 insertions(+), 71 deletions(-) (limited to 'boot') diff --git a/boot/image-android.c b/boot/image-android.c index ea05c1814f0..15a735e2303 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -86,7 +86,7 @@ bool android_image_get_data(const void *boot_hdr, struct andr_image_data *data) return true; } -static ulong android_image_get_kernel_addr(const struct andr_boot_img_hdr_v0 *hdr) +static ulong android_image_get_kernel_addr(struct andr_image_data *img_data) { /* * All the Android tools that generate a boot.img use this @@ -99,17 +99,17 @@ static ulong android_image_get_kernel_addr(const struct andr_boot_img_hdr_v0 *hd * * Otherwise, we will return the actual value set by the user. */ - if (hdr->kernel_addr == ANDROID_IMAGE_DEFAULT_KERNEL_ADDR) - return (ulong)hdr + hdr->page_size; + if (img_data->kernel_addr == ANDROID_IMAGE_DEFAULT_KERNEL_ADDR) + return img_data->kernel_ptr; /* * abootimg creates images where all load addresses are 0 * and we need to fix them. */ - if (hdr->kernel_addr == 0 && hdr->ramdisk_addr == 0) + if (img_data->kernel_addr == 0 && img_data->ramdisk_addr == 0) return env_get_ulong("kernel_addr_r", 16, 0); - return hdr->kernel_addr; + return img_data->kernel_addr; } /** @@ -130,27 +130,33 @@ static ulong android_image_get_kernel_addr(const struct andr_boot_img_hdr_v0 *hd int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, int verify, ulong *os_data, ulong *os_len) { - u32 kernel_addr = android_image_get_kernel_addr(hdr); - const struct legacy_img_hdr *ihdr = (const struct legacy_img_hdr *) - ((uintptr_t)hdr + hdr->page_size); + struct andr_image_data img_data = {0}; + u32 kernel_addr; + const struct legacy_img_hdr *ihdr; + + if (!android_image_get_data(hdr, &img_data)) + return -EINVAL; + + kernel_addr = android_image_get_kernel_addr(&img_data); + ihdr = (const struct legacy_img_hdr *)img_data.kernel_ptr; /* * 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); + strlcpy(andr_tmp_str, img_data.image_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)); + kernel_addr, DIV_ROUND_UP(img_data.kernel_size, 1024)); int len = 0; - if (*hdr->cmdline) { - printf("Kernel command line: %s\n", hdr->cmdline); - len += strlen(hdr->cmdline); + if (*img_data.kcmdline) { + printf("Kernel command line: %s\n", img_data.kcmdline); + len += strlen(img_data.kcmdline); } char *bootargs = env_get("bootargs"); @@ -168,8 +174,9 @@ int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, int verify, strcpy(newbootargs, bootargs); strcat(newbootargs, " "); } - if (*hdr->cmdline) - strcat(newbootargs, hdr->cmdline); + + if (*img_data.kcmdline) + strcat(newbootargs, img_data.kcmdline); env_set("bootargs", newbootargs); @@ -177,15 +184,14 @@ int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, int verify, if (image_get_magic(ihdr) == IH_MAGIC) { *os_data = image_get_data(ihdr); } else { - *os_data = (ulong)hdr; - *os_data += hdr->page_size; + *os_data = img_data.kernel_ptr; } } if (os_len) { if (image_get_magic(ihdr) == IH_MAGIC) *os_len = image_get_data_size(ihdr); else - *os_len = hdr->kernel_size; + *os_len = img_data.kernel_size; } return 0; } @@ -197,30 +203,25 @@ bool is_android_boot_image_header(const struct andr_boot_img_hdr_v0 *hdr) ulong android_image_get_end(const struct andr_boot_img_hdr_v0 *hdr) { - ulong end; - - /* - * The header takes a full page, the remaining components are aligned - * on page boundary - */ - end = (ulong)hdr; - end += hdr->page_size; - end += ALIGN(hdr->kernel_size, hdr->page_size); - end += ALIGN(hdr->ramdisk_size, hdr->page_size); - end += ALIGN(hdr->second_size, hdr->page_size); + struct andr_image_data img_data; - if (hdr->header_version >= 1) - end += ALIGN(hdr->recovery_dtbo_size, hdr->page_size); + if (!android_image_get_data(hdr, &img_data)) + return -EINVAL; - if (hdr->header_version >= 2) - end += ALIGN(hdr->dtb_size, hdr->page_size); + if (img_data.header_version > 2) + return 0; - return end; + return img_data.boot_img_total_size; } ulong android_image_get_kload(const struct andr_boot_img_hdr_v0 *hdr) { - return android_image_get_kernel_addr(hdr); + struct andr_image_data img_data; + + if (!android_image_get_data(hdr, &img_data)) + return -EINVAL; + + return android_image_get_kernel_addr(&img_data); } ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr) @@ -243,38 +244,43 @@ ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr) int android_image_get_ramdisk(const struct andr_boot_img_hdr_v0 *hdr, ulong *rd_data, ulong *rd_len) { - if (!hdr->ramdisk_size) { + struct andr_image_data img_data = {0}; + + if (!android_image_get_data(hdr, &img_data)) + return -EINVAL; + + if (!img_data.ramdisk_size) { *rd_data = *rd_len = 0; return -1; } - printf("RAM disk load addr 0x%08x size %u KiB\n", - hdr->ramdisk_addr, DIV_ROUND_UP(hdr->ramdisk_size, 1024)); + printf("RAM disk load addr 0x%08lx size %u KiB\n", + img_data.ramdisk_ptr, DIV_ROUND_UP(img_data.ramdisk_size, 1024)); - *rd_data = (unsigned long)hdr; - *rd_data += hdr->page_size; - *rd_data += ALIGN(hdr->kernel_size, hdr->page_size); + *rd_data = img_data.ramdisk_ptr; - *rd_len = hdr->ramdisk_size; + *rd_len = img_data.ramdisk_size; return 0; } int android_image_get_second(const struct andr_boot_img_hdr_v0 *hdr, ulong *second_data, ulong *second_len) { - if (!hdr->second_size) { + struct andr_image_data img_data; + + if (!android_image_get_data(hdr, &img_data)) + return -EINVAL; + + if (!img_data.second_size) { *second_data = *second_len = 0; return -1; } - *second_data = (unsigned long)hdr; - *second_data += hdr->page_size; - *second_data += ALIGN(hdr->kernel_size, hdr->page_size); - *second_data += ALIGN(hdr->ramdisk_size, hdr->page_size); + *second_data = img_data.second_ptr; printf("second address is 0x%lx\n",*second_data); - *second_len = hdr->second_size; + *second_len = img_data.second_size; return 0; } @@ -401,17 +407,22 @@ exit: bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr, u32 *size) { + struct andr_image_data img_data; const struct andr_boot_img_hdr_v0 *hdr; - bool res; + + hdr = map_sysmem(hdr_addr, sizeof(*hdr)); + if (!android_image_get_data(hdr, &img_data)) { + unmap_sysmem(hdr); + return false; + } + unmap_sysmem(hdr); + ulong dtb_img_addr; /* address of DTB part in boot image */ u32 dtb_img_size; /* size of DTB payload in boot image */ ulong dtb_addr; /* address of DTB blob with specified index */ u32 i; /* index iterator */ - res = android_image_get_dtb_img_addr(hdr_addr, &dtb_img_addr); - if (!res) - return false; - + android_image_get_dtb_img_addr(hdr_addr, &dtb_img_addr); /* Check if DTB area of boot image is in DTBO format */ if (android_dt_check_header(dtb_img_addr)) { return android_dt_get_fdt_by_index(dtb_img_addr, index, addr, @@ -419,9 +430,7 @@ bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr, } /* Find out the address of DTB with specified index in concat blobs */ - hdr = map_sysmem(hdr_addr, sizeof(*hdr)); - dtb_img_size = hdr->dtb_size; - unmap_sysmem(hdr); + dtb_img_size = img_data.dtb_size; i = 0; dtb_addr = dtb_img_addr; while (dtb_addr < dtb_img_addr + dtb_img_size) { diff --git a/cmd/abootimg.c b/cmd/abootimg.c index b5cfb141ef7..f04a7c7c8e6 100644 --- a/cmd/abootimg.c +++ b/cmd/abootimg.c @@ -66,33 +66,34 @@ static int abootimg_get_recovery_dtbo(int argc, char *const argv[]) static int abootimg_get_dtb_load_addr(int argc, char *const argv[]) { - const struct andr_boot_img_hdr_v0 *hdr; - int res = CMD_RET_SUCCESS; - if (argc > 1) return CMD_RET_USAGE; + struct andr_image_data img_data = {0}; + const struct andr_boot_img_hdr_v0 *hdr; hdr = map_sysmem(abootimg_addr(), sizeof(*hdr)); - if (!is_android_boot_image_header(hdr)) { - printf("Error: Boot Image header is incorrect\n"); - res = CMD_RET_FAILURE; - goto exit; + if (!android_image_get_data(hdr, &img_data)) { + unmap_sysmem(hdr); + return CMD_RET_FAILURE; } + unmap_sysmem(hdr); - if (hdr->header_version < 2) { + if (img_data.header_version < 2) { printf("Error: header_version must be >= 2 for this\n"); - res = CMD_RET_FAILURE; - goto exit; + return CMD_RET_FAILURE; + } + + if (!img_data.dtb_load_addr) { + printf("Error: failed to read dtb_load_addr\n"); + return CMD_RET_FAILURE; } if (argc == 0) - printf("%lx\n", (ulong)hdr->dtb_addr); + printf("%lx\n", (ulong)img_data.dtb_load_addr); else - env_set_hex(argv[0], (ulong)hdr->dtb_addr); + env_set_hex(argv[0], (ulong)img_data.dtb_load_addr); -exit: - unmap_sysmem(hdr); - return res; + return CMD_RET_SUCCESS; } static int abootimg_get_dtb_by_index(int argc, char *const argv[]) -- cgit v1.3.1 From bb5d692732ca02511f2f491af1e680c87373fd35 Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:09 +0100 Subject: android: boot: content print is not supported for v3, v4 header version Content print is not supported for version 3 and 4 of boot image header. Thus, only print that content when v2 is used. Update android_print_contents() to print an error message when trying to print boot image header version 3 or 4 content. Signed-off-by: Safae Ouajih Reviewed-by: Simon Glass Reviewed-by: Mattijs Korpershoek Tested-by: Mattijs Korpershoek --- boot/image-android.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'boot') diff --git a/boot/image-android.c b/boot/image-android.c index 15a735e2303..31a5d30162e 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -477,6 +477,10 @@ bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr, */ void android_print_contents(const struct andr_boot_img_hdr_v0 *hdr) { + if (hdr->header_version >= 3) { + printf("Content print is not supported for boot image header version > 2"); + return; + } const char * const p = IMAGE_INDENT_STRING; /* os_version = ver << 11 | lvl */ u32 os_ver = hdr->os_version >> 11; @@ -509,7 +513,7 @@ void android_print_contents(const struct andr_boot_img_hdr_v0 *hdr) hdr->header_size); } - if (hdr->header_version >= 2) { + if (hdr->header_version == 2) { printf("%sdtb size: %x\n", p, hdr->dtb_size); printf("%sdtb addr: %llx\n", p, hdr->dtb_addr); } -- cgit v1.3.1 From 447240e27b892ab2ccc1ada03a260abbb562484e Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:10 +0100 Subject: android: boot: boot image header v3, v4 do not support recovery DTBO android_image_get_dtbo() is used to get recovery DTBO via abootimg cmd. This is not supported in boot image header v3 and v4. Thus, print an error message when v1,v2 header version are not used. Signed-off-by: Safae Ouajih Reviewed-by: Simon Glass Reviewed-by: Mattijs Korpershoek Tested-by: Mattijs Korpershoek --- boot/image-android.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'boot') diff --git a/boot/image-android.c b/boot/image-android.c index 31a5d30162e..748fd212ae6 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -316,8 +316,8 @@ bool android_image_get_dtbo(ulong hdr_addr, ulong *addr, u32 *size) goto exit; } - if (hdr->header_version < 1) { - printf("Error: header_version must be >= 1 to get dtbo\n"); + if (hdr->header_version != 1 && hdr->header_version != 2) { + printf("Error: header version must be >= 1 and <= 2 to get dtbo\n"); ret = false; goto exit; } -- cgit v1.3.1 From e058176be32b09ca4f787442fd99d29e44079519 Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:11 +0100 Subject: android: boot: add vendor boot image to prepare for v3, v4 support Introduce vendor boot image for version 3 and 4 of boot image header. The vendor boot image will hold extra information about kernel, dtb and ramdisk. This is done to prepare for boot image version 3 and 4 support. Signed-off-by: Safae Ouajih Reviewed-by: Simon Glass Reviewed-by: Mattijs Korpershoek Tested-by: Mattijs Korpershoek --- boot/bootm.c | 8 ++++---- boot/image-android.c | 54 ++++++++++++++++++++++++++++++++++------------------ boot/image-board.c | 3 +-- boot/image-fdt.c | 3 ++- cmd/abootimg.c | 4 ++-- include/image.h | 48 +++++++++++++++++++++++++++++++++++----------- 6 files changed, 81 insertions(+), 39 deletions(-) (limited to 'boot') diff --git a/boot/bootm.c b/boot/bootm.c index 2eec60ec7b5..28a8fc32612 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -182,11 +182,11 @@ static int bootm_find_os(struct cmd_tbl *cmdtp, int flag, int argc, #ifdef CONFIG_ANDROID_BOOT_IMAGE case IMAGE_FORMAT_ANDROID: images.os.type = IH_TYPE_KERNEL; - images.os.comp = android_image_get_kcomp(os_hdr); + images.os.comp = android_image_get_kcomp(os_hdr, NULL); images.os.os = IH_OS_LINUX; - images.os.end = android_image_get_end(os_hdr); - images.os.load = android_image_get_kload(os_hdr); + images.os.end = android_image_get_end(os_hdr, NULL); + images.os.load = android_image_get_kload(os_hdr, NULL); images.ep = images.os.load; ep_found = true; break; @@ -965,7 +965,7 @@ static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc, #ifdef CONFIG_ANDROID_BOOT_IMAGE case IMAGE_FORMAT_ANDROID: printf("## Booting Android Image at 0x%08lx ...\n", img_addr); - if (android_image_get_kernel(buf, images->verify, + if (android_image_get_kernel(buf, NULL, images->verify, os_data, os_len)) return NULL; break; diff --git a/boot/image-android.c b/boot/image-android.c index 748fd212ae6..f16eebff49e 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -66,7 +66,8 @@ static void android_boot_image_v0_v1_v2_parse_hdr(const struct andr_boot_img_hdr data->boot_img_total_size = end - (ulong)hdr; } -bool android_image_get_data(const void *boot_hdr, struct andr_image_data *data) +bool android_image_get_data(const void *boot_hdr, const void *vendor_boot_hdr, + struct andr_image_data *data) { if (!boot_hdr || !data) { printf("boot_hdr or data params can't be NULL\n"); @@ -114,8 +115,10 @@ static ulong android_image_get_kernel_addr(struct andr_image_data *img_data) /** * android_image_get_kernel() - processes kernel part of Android boot images - * @hdr: Pointer to image header, which is at the start + * @hdr: Pointer to boot image header, which is at the start * of the image. + * @vendor_boot_img: Pointer to vendor boot 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. @@ -127,14 +130,15 @@ static ulong android_image_get_kernel_addr(struct andr_image_data *img_data) * Return: Zero, os start address and length on success, * otherwise on failure. */ -int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, int verify, +int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, + const void *vendor_boot_img, int verify, ulong *os_data, ulong *os_len) { struct andr_image_data img_data = {0}; u32 kernel_addr; const struct legacy_img_hdr *ihdr; - if (!android_image_get_data(hdr, &img_data)) + if (!android_image_get_data(hdr, vendor_boot_img, &img_data)) return -EINVAL; kernel_addr = android_image_get_kernel_addr(&img_data); @@ -201,11 +205,12 @@ bool is_android_boot_image_header(const struct andr_boot_img_hdr_v0 *hdr) return !memcmp(ANDR_BOOT_MAGIC, hdr, ANDR_BOOT_MAGIC_SIZE); } -ulong android_image_get_end(const struct andr_boot_img_hdr_v0 *hdr) +ulong android_image_get_end(const struct andr_boot_img_hdr_v0 *hdr, + const void *vendor_boot_img) { struct andr_image_data img_data; - if (!android_image_get_data(hdr, &img_data)) + if (!android_image_get_data(hdr, vendor_boot_img, &img_data)) return -EINVAL; if (img_data.header_version > 2) @@ -214,22 +219,24 @@ ulong android_image_get_end(const struct andr_boot_img_hdr_v0 *hdr) return img_data.boot_img_total_size; } -ulong android_image_get_kload(const struct andr_boot_img_hdr_v0 *hdr) +ulong android_image_get_kload(const struct andr_boot_img_hdr_v0 *hdr, + const void *vendor_boot_img) { struct andr_image_data img_data; - if (!android_image_get_data(hdr, &img_data)) + if (!android_image_get_data(hdr, vendor_boot_img, &img_data)) return -EINVAL; return android_image_get_kernel_addr(&img_data); } -ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr) +ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr, + const void *vendor_boot_img) { struct andr_image_data img_data; const void *p; - if (!android_image_get_data(hdr, &img_data)) + if (!android_image_get_data(hdr, vendor_boot_img, &img_data)) return -EINVAL; p = (const void *)img_data.kernel_ptr; @@ -242,11 +249,11 @@ ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr) } int android_image_get_ramdisk(const struct andr_boot_img_hdr_v0 *hdr, - ulong *rd_data, ulong *rd_len) + const void *vendor_boot_img, ulong *rd_data, ulong *rd_len) { struct andr_image_data img_data = {0}; - if (!android_image_get_data(hdr, &img_data)) + if (!android_image_get_data(hdr, vendor_boot_img, &img_data)) return -EINVAL; if (!img_data.ramdisk_size) { @@ -268,7 +275,7 @@ int android_image_get_second(const struct andr_boot_img_hdr_v0 *hdr, { struct andr_image_data img_data; - if (!android_image_get_data(hdr, &img_data)) + if (!android_image_get_data(hdr, NULL, &img_data)) return -EINVAL; if (!img_data.second_size) { @@ -348,11 +355,12 @@ exit: /** * android_image_get_dtb_img_addr() - Get the address of DTB area in boot image. * @hdr_addr: Boot image header address + * @vhdr_addr: Vendor Boot image header address * @addr: Will contain the address of DTB area in boot image * * Return: true on success or false on fail. */ -static bool android_image_get_dtb_img_addr(ulong hdr_addr, ulong *addr) +static bool android_image_get_dtb_img_addr(ulong hdr_addr, ulong vhdr_addr, ulong *addr) { const struct andr_boot_img_hdr_v0 *hdr; ulong dtb_img_addr; @@ -395,6 +403,7 @@ exit: /** * android_image_get_dtb_by_index() - Get address and size of blob in DTB area. * @hdr_addr: Boot image header address + * @vendor_boot_img: Pointer to vendor boot image header, which is at the start of the image. * @index: Index of desired DTB in DTB area (starting from 0) * @addr: If not NULL, will contain address to specified DTB * @size: If not NULL, will contain size of specified DTB @@ -404,17 +413,24 @@ exit: * * Return: true on success or false on error. */ -bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr, - u32 *size) +bool android_image_get_dtb_by_index(ulong hdr_addr, ulong vendor_boot_img, + u32 index, ulong *addr, u32 *size) { struct andr_image_data img_data; const struct andr_boot_img_hdr_v0 *hdr; + const struct andr_vnd_boot_img_hdr *vhdr; hdr = map_sysmem(hdr_addr, sizeof(*hdr)); - if (!android_image_get_data(hdr, &img_data)) { + if (vendor_boot_img != -1) + vhdr = map_sysmem(vendor_boot_img, sizeof(*vhdr)); + if (!android_image_get_data(hdr, vhdr, &img_data)) { + if (vendor_boot_img != -1) + unmap_sysmem(vhdr); unmap_sysmem(hdr); return false; } + if (vendor_boot_img != -1) + unmap_sysmem(vhdr); unmap_sysmem(hdr); ulong dtb_img_addr; /* address of DTB part in boot image */ @@ -422,7 +438,7 @@ bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr, ulong dtb_addr; /* address of DTB blob with specified index */ u32 i; /* index iterator */ - android_image_get_dtb_img_addr(hdr_addr, &dtb_img_addr); + android_image_get_dtb_img_addr(hdr_addr, vendor_boot_img, &dtb_img_addr); /* Check if DTB area of boot image is in DTBO format */ if (android_dt_check_header(dtb_img_addr)) { return android_dt_get_fdt_by_index(dtb_img_addr, index, addr, @@ -578,7 +594,7 @@ bool android_image_print_dtb_contents(ulong hdr_addr) ulong dtb_addr; /* address of DTB blob with specified index */ u32 i; /* index iterator */ - res = android_image_get_dtb_img_addr(hdr_addr, &dtb_img_addr); + res = android_image_get_dtb_img_addr(hdr_addr, 0, &dtb_img_addr); if (!res) return false; diff --git a/boot/image-board.c b/boot/image-board.c index e086103258f..2d73c76a4af 100644 --- a/boot/image-board.c +++ b/boot/image-board.c @@ -428,8 +428,7 @@ static int select_ramdisk(struct bootm_headers *images, const char *select, u8 a if (IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE)) { void *ptr = map_sysmem(images->os.start, 0); int ret; - - ret = android_image_get_ramdisk(ptr, rd_datap, rd_lenp); + ret = android_image_get_ramdisk(ptr, NULL, rd_datap, rd_lenp); unmap_sysmem(ptr); if (ret) return ret; diff --git a/boot/image-fdt.c b/boot/image-fdt.c index ba44ecf8ef3..d639f37896a 100644 --- a/boot/image-fdt.c +++ b/boot/image-fdt.c @@ -536,7 +536,8 @@ int boot_get_fdt(int flag, int argc, char *const argv[], uint8_t arch, * Firstly check if this android boot image has dtb field. */ dtb_idx = (u32)env_get_ulong("adtb_idx", 10, 0); - if (android_image_get_dtb_by_index((ulong)hdr, dtb_idx, &fdt_addr, &fdt_size)) { + if (android_image_get_dtb_by_index((ulong)hdr, 0, + dtb_idx, &fdt_addr, &fdt_size)) { fdt_blob = (char *)map_sysmem(fdt_addr, 0); if (fdt_check_header(fdt_blob)) goto no_fdt; diff --git a/cmd/abootimg.c b/cmd/abootimg.c index f04a7c7c8e6..4d6cf0fa3eb 100644 --- a/cmd/abootimg.c +++ b/cmd/abootimg.c @@ -72,7 +72,7 @@ static int abootimg_get_dtb_load_addr(int argc, char *const argv[]) const struct andr_boot_img_hdr_v0 *hdr; hdr = map_sysmem(abootimg_addr(), sizeof(*hdr)); - if (!android_image_get_data(hdr, &img_data)) { + if (!android_image_get_data(hdr, NULL, &img_data)) { unmap_sysmem(hdr); return CMD_RET_FAILURE; } @@ -119,7 +119,7 @@ static int abootimg_get_dtb_by_index(int argc, char *const argv[]) return CMD_RET_FAILURE; } - if (!android_image_get_dtb_by_index(abootimg_addr(), num, + if (!android_image_get_dtb_by_index(abootimg_addr(), 0, num, &addr, &size)) { return CMD_RET_FAILURE; } diff --git a/include/image.h b/include/image.h index 4bf6c98ced7..f84c03f08fb 100644 --- a/include/image.h +++ b/include/image.h @@ -1736,16 +1736,19 @@ struct cipher_algo *image_get_cipher_algo(const char *full_name); struct andr_image_data; /** - * android_image_get_data() - Parse Android boot image + * android_image_get_data() - Parse Android boot images * - * This is used to parse boot image header into andr_image_data - * generic structure. + * This is used to parse boot and vendor-boot header into + * andr_image_data generic structure. * * @boot_hdr: Pointer to boot image header + * @vendor_boot_hdr: Pointer to vendor boot image header * @data: Pointer to generic boot format structure * Return: true if succeeded, false otherwise */ -bool android_image_get_data(const void *boot_hdr, struct andr_image_data *data); +bool android_image_get_data(const void *boot_hdr, const void *vendor_boot_hdr, + struct andr_image_data *data); + struct andr_boot_img_hdr_v0; /** @@ -1756,6 +1759,7 @@ struct andr_boot_img_hdr_v0; * * @hdr: Pointer to image header, which is at the start * of the image. + * @vendor_boot_img : Pointer to vendor boot image header * @verify: Checksum verification flag. Currently unimplemented. * @os_data: Pointer to a ulong variable, will hold os data start * address. @@ -1763,7 +1767,8 @@ struct andr_boot_img_hdr_v0; * Return: Zero, os start address and length on success, * otherwise on failure. */ -int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, int verify, +int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, + const void *vendor_boot_img, int verify, ulong *os_data, ulong *os_len); /** @@ -1772,12 +1777,13 @@ int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, int verify, * This extracts the load address of the ramdisk and its size * * @hdr: Pointer to image header + * @vendor_boot_img : Pointer to vendor boot image header * @rd_data: Pointer to a ulong variable, will hold ramdisk address * @rd_len: Pointer to a ulong variable, will hold ramdisk length * Return: 0 if succeeded, -1 if ramdisk size is 0 */ int android_image_get_ramdisk(const struct andr_boot_img_hdr_v0 *hdr, - ulong *rd_data, ulong *rd_len); + const void *vendor_boot_img, ulong *rd_data, ulong *rd_len); /** * android_image_get_second() - Extracts the secondary bootloader address @@ -1793,8 +1799,22 @@ int android_image_get_ramdisk(const struct andr_boot_img_hdr_v0 *hdr, int android_image_get_second(const struct andr_boot_img_hdr_v0 *hdr, ulong *second_data, ulong *second_len); bool android_image_get_dtbo(ulong hdr_addr, ulong *addr, u32 *size); -bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr, - u32 *size); + +/** + * android_image_get_dtb_by_index() - Get address and size of blob in DTB area. + * @hdr_addr: Boot image header address + * @vendor_boot_img: Pointer to vendor boot image header, which is at the start of the image. + * @index: Index of desired DTB in DTB area (starting from 0) + * @addr: If not NULL, will contain address to specified DTB + * @size: If not NULL, will contain size of specified DTB + * + * Get the address and size of DTB blob by its index in DTB area of Android + * Boot Image in RAM. + * + * Return: true on success or false on error. + */ +bool android_image_get_dtb_by_index(ulong hdr_addr, ulong vendor_boot_img, + u32 index, ulong *addr, u32 *size); /** * android_image_get_end() - Get the end of Android boot image @@ -1802,9 +1822,11 @@ bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr, * This returns the end address of Android boot image address * * @hdr: Pointer to image header + * @vendor_boot_img : Pointer to vendor boot image header * Return: The end address of Android boot image */ -ulong android_image_get_end(const struct andr_boot_img_hdr_v0 *hdr); +ulong android_image_get_end(const struct andr_boot_img_hdr_v0 *hdr, + const void *vendor_boot_img); /** * android_image_get_kload() - Get the kernel load address @@ -1813,9 +1835,11 @@ ulong android_image_get_end(const struct andr_boot_img_hdr_v0 *hdr); * from the boot image header or the "kernel_addr_r" environment variable * * @hdr: Pointer to image header + * @vendor_boot_img : Pointer to vendor boot image header * Return: The kernel load address */ -ulong android_image_get_kload(const struct andr_boot_img_hdr_v0 *hdr); +ulong android_image_get_kload(const struct andr_boot_img_hdr_v0 *hdr, + const void *vendor_boot_img); /** * android_image_get_kcomp() - Get kernel compression type @@ -1823,9 +1847,11 @@ ulong android_image_get_kload(const struct andr_boot_img_hdr_v0 *hdr); * This gets the kernel compression type from the boot image header * * @hdr: Pointer to image header + * @vendor_boot_img : Pointer to vendor boot image header * Return: Kernel compression type */ -ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr); +ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr, + const void *vendor_boot_img); /** * android_print_contents() - Prints out the contents of the Android format image -- cgit v1.3.1 From 1115027d2f75ade805f0d4d44a6a2c21e74ea6b2 Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:12 +0100 Subject: android: boot: update android_image_get_data to support v3, v4 Since boot image header version 3 and 4 introduced vendor boot image, use the following functions to fill the generic android structure : andr_image_data: - android_boot_image_v3_v4_parse_hdr() - android_vendor_boot_image_v3_v4_parse_hdr() Update android_image_get_data() to support v3 and v4 Signed-off-by: Safae Ouajih Reviewed-by: Simon Glass Reviewed-by: Mattijs Korpershoek Tested-by: Mattijs Korpershoek --- boot/image-android.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++-- include/android_image.h | 3 ++ include/image.h | 11 +++++++ 3 files changed, 91 insertions(+), 3 deletions(-) (limited to 'boot') diff --git a/boot/image-android.c b/boot/image-android.c index f16eebff49e..712d437766b 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -18,6 +18,65 @@ static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1]; +static void android_boot_image_v3_v4_parse_hdr(const struct andr_boot_img_hdr_v3 *hdr, + struct andr_image_data *data) +{ + ulong end; + + data->kcmdline = hdr->cmdline; + data->header_version = hdr->header_version; + + /* + * The header takes a full page, the remaining components are aligned + * on page boundary. + */ + end = (ulong)hdr; + end += ANDR_GKI_PAGE_SIZE; + data->kernel_ptr = end; + data->kernel_size = hdr->kernel_size; + end += ALIGN(hdr->kernel_size, ANDR_GKI_PAGE_SIZE); + data->ramdisk_size = hdr->ramdisk_size; + data->boot_ramdisk_size = hdr->ramdisk_size; + end += ALIGN(hdr->ramdisk_size, ANDR_GKI_PAGE_SIZE); + + if (hdr->header_version > 3) + end += ALIGN(hdr->signature_size, ANDR_GKI_PAGE_SIZE); + + data->boot_img_total_size = end - (ulong)hdr; +} + +static void android_vendor_boot_image_v3_v4_parse_hdr(const struct andr_vnd_boot_img_hdr + *hdr, struct andr_image_data *data) +{ + ulong end; + + /* + * The header takes a full page, the remaining components are aligned + * on page boundary. + */ + data->tags_addr = hdr->tags_addr; + data->image_name = hdr->name; + data->kernel_addr = hdr->kernel_addr; + data->ramdisk_addr = hdr->ramdisk_addr; + data->dtb_load_addr = hdr->dtb_addr; + end = (ulong)hdr; + end += hdr->page_size; + if (hdr->vendor_ramdisk_size) { + data->vendor_ramdisk_ptr = end; + data->vendor_ramdisk_size = hdr->vendor_ramdisk_size; + data->ramdisk_size += hdr->vendor_ramdisk_size; + end += ALIGN(hdr->vendor_ramdisk_size, hdr->page_size); + } + + data->dtb_ptr = end; + data->dtb_size = hdr->dtb_size; + + end += ALIGN(hdr->dtb_size, hdr->page_size); + end += ALIGN(hdr->vendor_ramdisk_table_size, hdr->page_size); + end += ALIGN(hdr->bootconfig_size, hdr->page_size); + data->vendor_boot_img_total_size = end - (ulong)hdr; +} + static void android_boot_image_v0_v1_v2_parse_hdr(const struct andr_boot_img_hdr_v0 *hdr, struct andr_image_data *data) { @@ -79,10 +138,20 @@ bool android_image_get_data(const void *boot_hdr, const void *vendor_boot_hdr, return false; } - if (((struct andr_boot_img_hdr_v0 *)boot_hdr)->header_version > 2) - printf("Only boot image header version 2 and below are supported\n"); - else + if (((struct andr_boot_img_hdr_v0 *)boot_hdr)->header_version > 2) { + if (!vendor_boot_hdr) { + printf("For boot header v3+ vendor boot image has to be provided\n"); + return false; + } + if (!is_android_vendor_boot_image_header(vendor_boot_hdr)) { + printf("Incorrect vendor boot image header\n"); + return false; + } + android_boot_image_v3_v4_parse_hdr(boot_hdr, data); + android_vendor_boot_image_v3_v4_parse_hdr(vendor_boot_hdr, data); + } else { android_boot_image_v0_v1_v2_parse_hdr(boot_hdr, data); + } return true; } @@ -200,6 +269,11 @@ int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, return 0; } +bool is_android_vendor_boot_image_header(const void *vendor_boot_img) +{ + return !memcmp(VENDOR_BOOT_MAGIC, vendor_boot_img, ANDR_VENDOR_BOOT_MAGIC_SIZE); +} + bool is_android_boot_image_header(const struct andr_boot_img_hdr_v0 *hdr) { return !memcmp(ANDR_BOOT_MAGIC, hdr, ANDR_BOOT_MAGIC_SIZE); diff --git a/include/android_image.h b/include/android_image.h index fb3a9d9858b..99e78035082 100644 --- a/include/android_image.h +++ b/include/android_image.h @@ -323,6 +323,8 @@ struct andr_image_data { ulong kernel_ptr; /* kernel address */ u32 kernel_size; /* size in bytes */ u32 ramdisk_size; /* size in bytes */ + ulong vendor_ramdisk_ptr; /* vendor ramdisk address */ + u32 vendor_ramdisk_size; /* vendor ramdisk size*/ u32 boot_ramdisk_size; /* size in bytes */ ulong second_ptr; /* secondary bootloader address */ u32 second_size; /* secondary bootloader size */ @@ -342,6 +344,7 @@ struct andr_image_data { ulong tags_addr; /* physical addr for kernel tags */ u32 header_version; /* version of the boot image header */ u32 boot_img_total_size; /* boot image size */ + u32 vendor_boot_img_total_size; /* vendor boot image size */ }; #endif diff --git a/include/image.h b/include/image.h index f84c03f08fb..c2e751c1364 100644 --- a/include/image.h +++ b/include/image.h @@ -1876,6 +1876,17 @@ bool android_image_print_dtb_contents(ulong hdr_addr); */ bool is_android_boot_image_header(const struct andr_boot_img_hdr_v0 *hdr); +/** + * is_android_vendor_boot_image_header() - Check the magic of vendor boot image + * + * This checks the header of Android vendor boot image and verifies the magic + * is "VNDRBOOT" + * + * @vendor_boot_img: Pointer to boot image + * Return: non-zero if the magic is correct, zero otherwise + */ +bool is_android_vendor_boot_image_header(const void *vendor_boot_img); + /** * board_fit_config_name_match() - Check for a matching board name * -- cgit v1.3.1 From c79a2e6823d5a3a2813f66d03023c0a192c27e7e Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:13 +0100 Subject: android: boot: ramdisk: support vendor ramdisk Version 3 and 4 of boot image header introduced vendor boot ramdisk: Please check include/android_image.h for details. The ramdisk is now split into a generic ramdisk in boot image and a vendor ramdisk in vendor boot image. Support the new vendor ramdisk. Signed-off-by: Safae Ouajih Reviewed-by: Simon Glass Reviewed-by: Mattijs Korpershoek Tested-by: Mattijs Korpershoek --- boot/image-android.c | 13 +++++++++++-- include/image.h | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'boot') diff --git a/boot/image-android.c b/boot/image-android.c index 712d437766b..35243fd5b16 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -25,6 +25,7 @@ static void android_boot_image_v3_v4_parse_hdr(const struct andr_boot_img_hdr_v3 data->kcmdline = hdr->cmdline; data->header_version = hdr->header_version; + data->ramdisk_ptr = env_get_ulong("ramdisk_addr_r", 16, 0); /* * The header takes a full page, the remaining components are aligned @@ -322,10 +323,11 @@ ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr, return image_decomp_type(p, sizeof(u32)); } -int android_image_get_ramdisk(const struct andr_boot_img_hdr_v0 *hdr, - const void *vendor_boot_img, ulong *rd_data, ulong *rd_len) +int android_image_get_ramdisk(const void *hdr, const void *vendor_boot_img, + ulong *rd_data, ulong *rd_len) { struct andr_image_data img_data = {0}; + ulong ramdisk_ptr; if (!android_image_get_data(hdr, vendor_boot_img, &img_data)) return -EINVAL; @@ -334,6 +336,13 @@ int android_image_get_ramdisk(const struct andr_boot_img_hdr_v0 *hdr, *rd_data = *rd_len = 0; return -1; } + if (img_data.header_version > 2) { + ramdisk_ptr = img_data.ramdisk_ptr; + memcpy((void *)(ramdisk_ptr), (void *)img_data.vendor_ramdisk_ptr, + img_data.vendor_ramdisk_size); + memcpy((void *)(ramdisk_ptr + img_data.vendor_ramdisk_size), + (void *)img_data.ramdisk_ptr, img_data.boot_ramdisk_size); + } printf("RAM disk load addr 0x%08lx size %u KiB\n", img_data.ramdisk_ptr, DIV_ROUND_UP(img_data.ramdisk_size, 1024)); diff --git a/include/image.h b/include/image.h index c2e751c1364..c4d9b1c5754 100644 --- a/include/image.h +++ b/include/image.h @@ -1782,8 +1782,8 @@ int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, * @rd_len: Pointer to a ulong variable, will hold ramdisk length * Return: 0 if succeeded, -1 if ramdisk size is 0 */ -int android_image_get_ramdisk(const struct andr_boot_img_hdr_v0 *hdr, - const void *vendor_boot_img, ulong *rd_data, ulong *rd_len); +int android_image_get_ramdisk(const void *hdr, const void *vendor_boot_img, + ulong *rd_data, ulong *rd_len); /** * android_image_get_second() - Extracts the secondary bootloader address -- cgit v1.3.1 From b36b227b6a37695ab39306341c3a977cf9b081b6 Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:14 +0100 Subject: android: boot: support extra command line In version 3 and 4 of boot image header, the vendor specific command line are located in vendor boot image. Thus, use extra command line to add those cmd to bootargs. Signed-off-by: Safae Ouajih Reviewed-by: Simon Glass Reviewed-by: Mattijs Korpershoek Tested-by: Mattijs Korpershoek --- boot/image-android.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'boot') diff --git a/boot/image-android.c b/boot/image-android.c index 35243fd5b16..a944f0a31aa 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -55,6 +55,7 @@ static void android_vendor_boot_image_v3_v4_parse_hdr(const struct andr_vnd_boot * The header takes a full page, the remaining components are aligned * on page boundary. */ + data->kcmdline_extra = hdr->cmdline; data->tags_addr = hdr->tags_addr; data->image_name = hdr->name; data->kernel_addr = hdr->kernel_addr; @@ -233,6 +234,11 @@ int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, len += strlen(img_data.kcmdline); } + if (img_data.kcmdline_extra) { + printf("Kernel extra command line: %s\n", img_data.kcmdline_extra); + len += strlen(img_data.kcmdline_extra); + } + char *bootargs = env_get("bootargs"); if (bootargs) len += strlen(bootargs); @@ -252,6 +258,11 @@ int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, if (*img_data.kcmdline) strcat(newbootargs, img_data.kcmdline); + if (img_data.kcmdline_extra) { + strcat(newbootargs, " "); + strcat(newbootargs, img_data.kcmdline_extra); + } + env_set("bootargs", newbootargs); if (os_data) { -- cgit v1.3.1 From 2d0da1972ded075ba783f3ea705662349e77fa61 Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:15 +0100 Subject: android: boot: update android_image_get_dtb_img_addr to support v3, v4 Add support for boot image version 3 and 4 in android_image_get_dtb_img_addr(). Since the dtb is now included in vendor_boot image instead of boot image, extract the dtb address from vendor_boot image when a v3 or v4 is used. Signed-off-by: Safae Ouajih Reviewed-by: Simon Glass Reviewed-by: Mattijs Korpershoek Tested-by: Mattijs Korpershoek --- boot/image-android.c | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) (limited to 'boot') diff --git a/boot/image-android.c b/boot/image-android.c index a944f0a31aa..6be439ed12b 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -457,6 +457,7 @@ exit: static bool android_image_get_dtb_img_addr(ulong hdr_addr, ulong vhdr_addr, ulong *addr) { const struct andr_boot_img_hdr_v0 *hdr; + const struct andr_vnd_boot_img_hdr *v_hdr; ulong dtb_img_addr; bool ret = true; @@ -473,22 +474,40 @@ static bool android_image_get_dtb_img_addr(ulong hdr_addr, ulong vhdr_addr, ulon goto exit; } - if (hdr->dtb_size == 0) { - printf("Error: dtb_size is 0\n"); - ret = false; - goto exit; + if (hdr->header_version == 2) { + if (!hdr->dtb_size) { + printf("Error: dtb_size is 0\n"); + ret = false; + goto exit; + } + /* Calculate the address of DTB area in boot image */ + dtb_img_addr = hdr_addr; + dtb_img_addr += hdr->page_size; + dtb_img_addr += ALIGN(hdr->kernel_size, hdr->page_size); + dtb_img_addr += ALIGN(hdr->ramdisk_size, hdr->page_size); + dtb_img_addr += ALIGN(hdr->second_size, hdr->page_size); + dtb_img_addr += ALIGN(hdr->recovery_dtbo_size, hdr->page_size); + + *addr = dtb_img_addr; } - /* Calculate the address of DTB area in boot image */ - dtb_img_addr = hdr_addr; - dtb_img_addr += hdr->page_size; - dtb_img_addr += ALIGN(hdr->kernel_size, hdr->page_size); - dtb_img_addr += ALIGN(hdr->ramdisk_size, hdr->page_size); - dtb_img_addr += ALIGN(hdr->second_size, hdr->page_size); - dtb_img_addr += ALIGN(hdr->recovery_dtbo_size, hdr->page_size); - - *addr = dtb_img_addr; - + if (hdr->header_version > 2) { + v_hdr = map_sysmem(vhdr_addr, sizeof(*v_hdr)); + if (!v_hdr->dtb_size) { + printf("Error: dtb_size is 0\n"); + ret = false; + unmap_sysmem(v_hdr); + goto exit; + } + /* Calculate the address of DTB area in boot image */ + dtb_img_addr = vhdr_addr; + dtb_img_addr += v_hdr->page_size; + if (v_hdr->vendor_ramdisk_size) + dtb_img_addr += ALIGN(v_hdr->vendor_ramdisk_size, v_hdr->page_size); + *addr = dtb_img_addr; + unmap_sysmem(v_hdr); + goto exit; + } exit: unmap_sysmem(hdr); return ret; -- cgit v1.3.1 From 636da2039aea4ea3a638b14da0a9ec258897a10c Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:17 +0100 Subject: android: boot: support boot image header version 3 and 4 Enable the support for boot image header version 3 and 4 using abootimg command. In order to use version 3 or 4: 1- Vendor boot image address should be given to abootimg cmd. abootimg addr $1 $vendor_boot_load_addr 2- "ramdisk_addr_r" env variable (ramdisk address) should be set to host the ramdisk : generic ramdisk + vendor ramdisk Replace "struct andr_boot_img_hdr_v0*" by "void *" in some functions since v3 and v4 are now supported as well. Signed-off-by: Safae Ouajih Reviewed-by: Mattijs Korpershoek Tested-by: Mattijs Korpershoek --- boot/bootm.c | 37 ++++++++++++++++++++++++++++++++----- boot/image-android.c | 16 ++++++++++------ boot/image-board.c | 18 +++++++++++++++--- boot/image-fdt.c | 2 +- cmd/abootimg.c | 24 ++++++++++++++++++++++-- include/image.h | 25 +++++++++++++++++++------ 6 files changed, 99 insertions(+), 23 deletions(-) (limited to 'boot') diff --git a/boot/bootm.c b/boot/bootm.c index 28a8fc32612..4144ff3b031 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -113,6 +113,10 @@ static int bootm_find_os(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { const void *os_hdr; +#ifdef CONFIG_ANDROID_BOOT_IMAGE + const void *vendor_boot_img; + const void *boot_img; +#endif bool ep_found = false; int ret; @@ -181,14 +185,23 @@ static int bootm_find_os(struct cmd_tbl *cmdtp, int flag, int argc, #endif #ifdef CONFIG_ANDROID_BOOT_IMAGE case IMAGE_FORMAT_ANDROID: + boot_img = os_hdr; + vendor_boot_img = NULL; + if (IS_ENABLED(CONFIG_CMD_ABOOTIMG)) { + boot_img = map_sysmem(get_abootimg_addr(), 0); + vendor_boot_img = map_sysmem(get_avendor_bootimg_addr(), 0); + } images.os.type = IH_TYPE_KERNEL; - images.os.comp = android_image_get_kcomp(os_hdr, NULL); + images.os.comp = android_image_get_kcomp(boot_img, vendor_boot_img); images.os.os = IH_OS_LINUX; - - images.os.end = android_image_get_end(os_hdr, NULL); - images.os.load = android_image_get_kload(os_hdr, NULL); + images.os.end = android_image_get_end(boot_img, vendor_boot_img); + images.os.load = android_image_get_kload(boot_img, vendor_boot_img); images.ep = images.os.load; ep_found = true; + if (IS_ENABLED(CONFIG_CMD_ABOOTIMG)) { + unmap_sysmem(vendor_boot_img); + unmap_sysmem(boot_img); + } break; #endif default: @@ -889,6 +902,10 @@ static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc, int os_noffset; #endif +#ifdef CONFIG_ANDROID_BOOT_IMAGE + const void *boot_img; + const void *vendor_boot_img; +#endif img_addr = genimg_get_kernel_addr_fit(argc < 1 ? NULL : argv[0], &fit_uname_config, &fit_uname_kernel); @@ -964,10 +981,20 @@ static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc, #endif #ifdef CONFIG_ANDROID_BOOT_IMAGE case IMAGE_FORMAT_ANDROID: + boot_img = buf; + vendor_boot_img = NULL; + if (IS_ENABLED(CONFIG_CMD_ABOOTIMG)) { + boot_img = map_sysmem(get_abootimg_addr(), 0); + vendor_boot_img = map_sysmem(get_avendor_bootimg_addr(), 0); + } printf("## Booting Android Image at 0x%08lx ...\n", img_addr); - if (android_image_get_kernel(buf, NULL, images->verify, + if (android_image_get_kernel(boot_img, vendor_boot_img, images->verify, os_data, os_len)) return NULL; + if (IS_ENABLED(CONFIG_CMD_ABOOTIMG)) { + unmap_sysmem(vendor_boot_img); + unmap_sysmem(boot_img); + } break; #endif default: diff --git a/boot/image-android.c b/boot/image-android.c index 6be439ed12b..fb29ff403f9 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -201,7 +201,7 @@ static ulong android_image_get_kernel_addr(struct andr_image_data *img_data) * Return: Zero, os start address and length on success, * otherwise on failure. */ -int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, +int android_image_get_kernel(const void *hdr, const void *vendor_boot_img, int verify, ulong *os_data, ulong *os_len) { @@ -286,7 +286,7 @@ bool is_android_vendor_boot_image_header(const void *vendor_boot_img) return !memcmp(VENDOR_BOOT_MAGIC, vendor_boot_img, ANDR_VENDOR_BOOT_MAGIC_SIZE); } -bool is_android_boot_image_header(const struct andr_boot_img_hdr_v0 *hdr) +bool is_android_boot_image_header(const void *hdr) { return !memcmp(ANDR_BOOT_MAGIC, hdr, ANDR_BOOT_MAGIC_SIZE); } @@ -305,7 +305,7 @@ ulong android_image_get_end(const struct andr_boot_img_hdr_v0 *hdr, return img_data.boot_img_total_size; } -ulong android_image_get_kload(const struct andr_boot_img_hdr_v0 *hdr, +ulong android_image_get_kload(const void *hdr, const void *vendor_boot_img) { struct andr_image_data img_data; @@ -316,7 +316,7 @@ ulong android_image_get_kload(const struct andr_boot_img_hdr_v0 *hdr, return android_image_get_kernel_addr(&img_data); } -ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr, +ulong android_image_get_kcomp(const void *hdr, const void *vendor_boot_img) { struct andr_image_data img_data; @@ -364,14 +364,18 @@ int android_image_get_ramdisk(const void *hdr, const void *vendor_boot_img, return 0; } -int android_image_get_second(const struct andr_boot_img_hdr_v0 *hdr, - ulong *second_data, ulong *second_len) +int android_image_get_second(const void *hdr, ulong *second_data, ulong *second_len) { struct andr_image_data img_data; if (!android_image_get_data(hdr, NULL, &img_data)) return -EINVAL; + if (img_data.header_version > 2) { + printf("Second stage bootloader is only supported for boot image version <= 2\n"); + return -EOPNOTSUPP; + } + if (!img_data.second_size) { *second_data = *second_len = 0; return -1; diff --git a/boot/image-board.c b/boot/image-board.c index 2d73c76a4af..7dd0c32e6e1 100644 --- a/boot/image-board.c +++ b/boot/image-board.c @@ -426,10 +426,22 @@ static int select_ramdisk(struct bootm_headers *images, const char *select, u8 a break; case IMAGE_FORMAT_ANDROID: if (IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE)) { - void *ptr = map_sysmem(images->os.start, 0); int ret; - ret = android_image_get_ramdisk(ptr, NULL, rd_datap, rd_lenp); - unmap_sysmem(ptr); + if (IS_ENABLED(CONFIG_CMD_ABOOTIMG)) { + void *boot_img = map_sysmem(get_abootimg_addr(), 0); + void *vendor_boot_img = map_sysmem(get_avendor_bootimg_addr(), 0); + + ret = android_image_get_ramdisk(boot_img, vendor_boot_img, + rd_datap, rd_lenp); + unmap_sysmem(vendor_boot_img); + unmap_sysmem(boot_img); + } else { + void *ptr = map_sysmem(images->os.start, 0); + + ret = android_image_get_ramdisk(ptr, NULL, rd_datap, rd_lenp); + unmap_sysmem(ptr); + } + if (ret) return ret; done = true; diff --git a/boot/image-fdt.c b/boot/image-fdt.c index d639f37896a..f10200f6474 100644 --- a/boot/image-fdt.c +++ b/boot/image-fdt.c @@ -529,7 +529,7 @@ int boot_get_fdt(int flag, int argc, char *const argv[], uint8_t arch, } #ifdef CONFIG_ANDROID_BOOT_IMAGE } else if (genimg_get_format(buf) == IMAGE_FORMAT_ANDROID) { - struct andr_boot_img_hdr_v0 *hdr = buf; + void *hdr = buf; ulong fdt_data, fdt_len; u32 fdt_size, dtb_idx; /* diff --git a/cmd/abootimg.c b/cmd/abootimg.c index 4d6cf0fa3eb..2653b555b10 100644 --- a/cmd/abootimg.c +++ b/cmd/abootimg.c @@ -17,6 +17,16 @@ static ulong _abootimg_addr = -1; static ulong _avendor_bootimg_addr = -1; +ulong get_abootimg_addr(void) +{ + return (_abootimg_addr == -1 ? image_load_addr : _abootimg_addr); +} + +ulong get_avendor_bootimg_addr(void) +{ + return _avendor_bootimg_addr; +} + static int abootimg_get_ver(int argc, char *const argv[]) { const struct andr_boot_img_hdr_v0 *hdr; @@ -70,12 +80,21 @@ static int abootimg_get_dtb_load_addr(int argc, char *const argv[]) return CMD_RET_USAGE; struct andr_image_data img_data = {0}; const struct andr_boot_img_hdr_v0 *hdr; + const struct andr_vnd_boot_img_hdr *vhdr; hdr = map_sysmem(abootimg_addr(), sizeof(*hdr)); - if (!android_image_get_data(hdr, NULL, &img_data)) { + if (get_avendor_bootimg_addr() != -1) + vhdr = map_sysmem(get_avendor_bootimg_addr(), sizeof(*vhdr)); + + if (!android_image_get_data(hdr, vhdr, &img_data)) { + if (get_avendor_bootimg_addr() != -1) + unmap_sysmem(vhdr); unmap_sysmem(hdr); return CMD_RET_FAILURE; } + + if (get_avendor_bootimg_addr() != -1) + unmap_sysmem(vhdr); unmap_sysmem(hdr); if (img_data.header_version < 2) { @@ -119,7 +138,8 @@ static int abootimg_get_dtb_by_index(int argc, char *const argv[]) return CMD_RET_FAILURE; } - if (!android_image_get_dtb_by_index(abootimg_addr(), 0, num, + if (!android_image_get_dtb_by_index(abootimg_addr(), + get_avendor_bootimg_addr(), num, &addr, &size)) { return CMD_RET_FAILURE; } diff --git a/include/image.h b/include/image.h index c4d9b1c5754..456197d6fda 100644 --- a/include/image.h +++ b/include/image.h @@ -1767,7 +1767,7 @@ struct andr_boot_img_hdr_v0; * Return: Zero, os start address and length on success, * otherwise on failure. */ -int android_image_get_kernel(const struct andr_boot_img_hdr_v0 *hdr, +int android_image_get_kernel(const void *hdr, const void *vendor_boot_img, int verify, ulong *os_data, ulong *os_len); @@ -1796,8 +1796,7 @@ int android_image_get_ramdisk(const void *hdr, const void *vendor_boot_img, * @second_len : Pointer to a ulong variable, will hold secondary bootloader length * Return: 0 if succeeded, -1 if secondary bootloader size is 0 */ -int android_image_get_second(const struct andr_boot_img_hdr_v0 *hdr, - ulong *second_data, ulong *second_len); +int android_image_get_second(const void *hdr, ulong *second_data, ulong *second_len); bool android_image_get_dtbo(ulong hdr_addr, ulong *addr, u32 *size); /** @@ -1838,7 +1837,7 @@ ulong android_image_get_end(const struct andr_boot_img_hdr_v0 *hdr, * @vendor_boot_img : Pointer to vendor boot image header * Return: The kernel load address */ -ulong android_image_get_kload(const struct andr_boot_img_hdr_v0 *hdr, +ulong android_image_get_kload(const void *hdr, const void *vendor_boot_img); /** @@ -1850,7 +1849,7 @@ ulong android_image_get_kload(const struct andr_boot_img_hdr_v0 *hdr, * @vendor_boot_img : Pointer to vendor boot image header * Return: Kernel compression type */ -ulong android_image_get_kcomp(const struct andr_boot_img_hdr_v0 *hdr, +ulong android_image_get_kcomp(const void *hdr, const void *vendor_boot_img); /** @@ -1874,7 +1873,7 @@ bool android_image_print_dtb_contents(ulong hdr_addr); * @hdr: Pointer to boot image * Return: non-zero if the magic is correct, zero otherwise */ -bool is_android_boot_image_header(const struct andr_boot_img_hdr_v0 *hdr); +bool is_android_boot_image_header(const void *hdr); /** * is_android_vendor_boot_image_header() - Check the magic of vendor boot image @@ -1887,6 +1886,20 @@ bool is_android_boot_image_header(const struct andr_boot_img_hdr_v0 *hdr); */ bool is_android_vendor_boot_image_header(const void *vendor_boot_img); +/** + * get_abootimg_addr() - Get Android boot image address + * + * Return: Android boot image address + */ +ulong get_abootimg_addr(void); + +/** + * get_avendor_bootimg_addr() - Get Android vendor boot image address + * + * Return: Android vendor boot image address + */ +ulong get_avendor_bootimg_addr(void); + /** * board_fit_config_name_match() - Check for a matching board name * -- cgit v1.3.1 From 57e405e1f4745cdca49a4a6b260afe68592b1d5c Mon Sep 17 00:00:00 2001 From: Safae Ouajih Date: Mon, 6 Feb 2023 00:50:18 +0100 Subject: android: boot: support bootconfig Support Bootconfig feature. - The bootconfig feature replaces the androidboot.* kernel cmdline options. This was adapted from downstream [1] commit : 7af0a0506d4d ("cuttlefish: support bootconfig parameters"). Link:[1] https://android.googlesource.com/platform/external/u-boot/ Signed-off-by: Safae Ouajih Reviewed-by: Simon Glass Reviewed-by: Mattijs Korpershoek Tested-by: Mattijs Korpershoek --- boot/image-android.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++-- include/android_image.h | 11 ++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) (limited to 'boot') diff --git a/boot/image-android.c b/boot/image-android.c index fb29ff403f9..88e40bc7ec6 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -18,6 +18,45 @@ static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1]; +static ulong checksum(const unsigned char *buffer, ulong size) +{ + ulong sum = 0; + + for (ulong i = 0; i < size; i++) + sum += buffer[i]; + return sum; +} + +static bool is_trailer_present(ulong bootconfig_end_addr) +{ + return !strncmp((char *)(bootconfig_end_addr - BOOTCONFIG_MAGIC_SIZE), + BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_SIZE); +} + +static ulong add_trailer(ulong bootconfig_start_addr, ulong bootconfig_size) +{ + ulong end; + ulong sum; + + if (!bootconfig_start_addr) + return -1; + if (!bootconfig_size) + return 0; + + end = bootconfig_start_addr + bootconfig_size; + if (is_trailer_present(end)) + return 0; + + memcpy((void *)(end), &bootconfig_size, BOOTCONFIG_SIZE_SIZE); + sum = checksum((unsigned char *)bootconfig_start_addr, bootconfig_size); + memcpy((void *)(end + BOOTCONFIG_SIZE_SIZE), &sum, + BOOTCONFIG_CHECKSUM_SIZE); + memcpy((void *)(end + BOOTCONFIG_SIZE_SIZE + BOOTCONFIG_CHECKSUM_SIZE), + BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_SIZE); + + return BOOTCONFIG_TRAILER_SIZE; +} + static void android_boot_image_v3_v4_parse_hdr(const struct andr_boot_img_hdr_v3 *hdr, struct andr_image_data *data) { @@ -61,6 +100,7 @@ static void android_vendor_boot_image_v3_v4_parse_hdr(const struct andr_vnd_boot data->kernel_addr = hdr->kernel_addr; data->ramdisk_addr = hdr->ramdisk_addr; data->dtb_load_addr = hdr->dtb_addr; + data->bootconfig_size = hdr->bootconfig_size; end = (ulong)hdr; end += hdr->page_size; if (hdr->vendor_ramdisk_size) { @@ -75,7 +115,13 @@ static void android_vendor_boot_image_v3_v4_parse_hdr(const struct andr_vnd_boot end += ALIGN(hdr->dtb_size, hdr->page_size); end += ALIGN(hdr->vendor_ramdisk_table_size, hdr->page_size); - end += ALIGN(hdr->bootconfig_size, hdr->page_size); + data->bootconfig_addr = end; + if (hdr->bootconfig_size) { + data->bootconfig_size += add_trailer(data->bootconfig_addr, + data->bootconfig_size); + data->ramdisk_size += data->bootconfig_size; + } + end += ALIGN(data->bootconfig_size, hdr->page_size); data->vendor_boot_img_total_size = end - (ulong)hdr; } @@ -352,7 +398,15 @@ int android_image_get_ramdisk(const void *hdr, const void *vendor_boot_img, memcpy((void *)(ramdisk_ptr), (void *)img_data.vendor_ramdisk_ptr, img_data.vendor_ramdisk_size); memcpy((void *)(ramdisk_ptr + img_data.vendor_ramdisk_size), - (void *)img_data.ramdisk_ptr, img_data.boot_ramdisk_size); + (void *)img_data.ramdisk_ptr, + img_data.boot_ramdisk_size); + if (img_data.bootconfig_size) { + memcpy((void *) + (ramdisk_ptr + img_data.vendor_ramdisk_size + + img_data.boot_ramdisk_size), + (void *)img_data.bootconfig_addr, + img_data.bootconfig_size); + } } printf("RAM disk load addr 0x%08lx size %u KiB\n", diff --git a/include/android_image.h b/include/android_image.h index 99e78035082..d503c980b23 100644 --- a/include/android_image.h +++ b/include/android_image.h @@ -25,6 +25,14 @@ #define ANDR_VENDOR_BOOT_ARGS_SIZE 2048 #define ANDR_VENDOR_BOOT_NAME_SIZE 16 +#define BOOTCONFIG_MAGIC "#BOOTCONFIG\n" +#define BOOTCONFIG_MAGIC_SIZE 12 +#define BOOTCONFIG_SIZE_SIZE 4 +#define BOOTCONFIG_CHECKSUM_SIZE 4 +#define BOOTCONFIG_TRAILER_SIZE BOOTCONFIG_MAGIC_SIZE + \ + BOOTCONFIG_SIZE_SIZE + \ + BOOTCONFIG_CHECKSUM_SIZE + struct andr_boot_img_hdr_v3 { u8 magic[ANDR_BOOT_MAGIC_SIZE]; @@ -337,6 +345,9 @@ struct andr_image_data { const char *kcmdline_extra; /* vendor-boot extra kernel cmdline */ const char *image_name; /* asciiz product name */ + ulong bootconfig_addr; /* bootconfig image address */ + ulong bootconfig_size; /* bootconfig image size */ + u32 kernel_addr; /* physical load addr */ ulong ramdisk_addr; /* physical load addr */ ulong ramdisk_ptr; /* ramdisk address */ -- cgit v1.3.1