diff options
Diffstat (limited to 'boot')
-rw-r--r-- | boot/Kconfig | 1 | ||||
-rw-r--r-- | boot/bootmeth_android.c | 104 | ||||
-rw-r--r-- | boot/bootmeth_extlinux.c | 3 | ||||
-rw-r--r-- | boot/image-android.c | 45 | ||||
-rw-r--r-- | boot/image-board.c | 16 | ||||
-rw-r--r-- | boot/upl_read.c | 2 |
6 files changed, 137 insertions, 34 deletions
diff --git a/boot/Kconfig b/boot/Kconfig index 7dd30a030e3..661e89ca05b 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -500,7 +500,6 @@ config BOOTMETH_ANDROID bool "Bootdev support for Android" depends on X86 || ARM || SANDBOX depends on CMDLINE - select ANDROID_AB select ANDROID_BOOT_IMAGE select CMD_BCB imply CMD_FASTBOOT diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c index 19b1f2c377b..3a5144aaa3b 100644 --- a/boot/bootmeth_android.c +++ b/boot/bootmeth_android.c @@ -29,6 +29,7 @@ #define BCB_PART_NAME "misc" #define BOOT_PART_NAME "boot" #define VENDOR_BOOT_PART_NAME "vendor_boot" +#define SLOT_LEN 2 /** * struct android_priv - Private data @@ -42,8 +43,10 @@ */ struct android_priv { enum android_boot_mode boot_mode; - char slot[2]; + char *slot; u32 header_version; + u32 boot_img_size; + u32 vendor_boot_img_size; }; static int android_check(struct udevice *dev, struct bootflow_iter *iter) @@ -71,7 +74,11 @@ static int scan_boot_part(struct udevice *blk, struct android_priv *priv) char *buf; int ret; - sprintf(partname, BOOT_PART_NAME "_%s", priv->slot); + if (priv->slot) + sprintf(partname, BOOT_PART_NAME "_%s", priv->slot); + else + sprintf(partname, BOOT_PART_NAME); + ret = part_get_info_by_name(desc, partname, &partition); if (ret < 0) return log_msg_ret("part info", ret); @@ -93,7 +100,13 @@ static int scan_boot_part(struct udevice *blk, struct android_priv *priv) return log_msg_ret("header", -ENOENT); } + if (!android_image_get_bootimg_size(buf, &priv->boot_img_size)) { + free(buf); + return log_msg_ret("get bootimg size", -EINVAL); + } + priv->header_version = ((struct andr_boot_img_hdr_v0 *)buf)->header_version; + free(buf); return 0; @@ -108,7 +121,11 @@ static int scan_vendor_boot_part(struct udevice *blk, struct android_priv *priv) char *buf; int ret; - sprintf(partname, VENDOR_BOOT_PART_NAME "_%s", priv->slot); + if (priv->slot) + sprintf(partname, VENDOR_BOOT_PART_NAME "_%s", priv->slot); + else + sprintf(partname, VENDOR_BOOT_PART_NAME); + ret = part_get_info_by_name(desc, partname, &partition); if (ret < 0) return log_msg_ret("part info", ret); @@ -129,6 +146,12 @@ static int scan_vendor_boot_part(struct udevice *blk, struct android_priv *priv) free(buf); return log_msg_ret("header", -ENOENT); } + + if (!android_image_get_vendor_bootimg_size(buf, &priv->vendor_boot_img_size)) { + free(buf); + return log_msg_ret("get vendor bootimg size", -EINVAL); + } + free(buf); return 0; @@ -142,6 +165,11 @@ static int android_read_slot_from_bcb(struct bootflow *bflow, bool decrement) char slot_suffix[3]; int ret; + if (!CONFIG_IS_ENABLED(ANDROID_AB)) { + priv->slot = NULL; + return 0; + } + ret = part_get_info_by_name(desc, BCB_PART_NAME, &misc); if (ret < 0) return log_msg_ret("part", ret); @@ -150,6 +178,7 @@ static int android_read_slot_from_bcb(struct bootflow *bflow, bool decrement) if (ret < 0) return log_msg_ret("slot", ret); + priv->slot = malloc(SLOT_LEN); priv->slot[0] = BOOT_SLOT_NAME(ret); priv->slot[1] = '\0'; @@ -259,16 +288,12 @@ static int android_read_bootflow(struct udevice *dev, struct bootflow *bflow) goto free_priv; } - if (priv->header_version != 4) { - log_debug("only boot.img v4 is supported %u\n", priv->header_version); - ret = -EINVAL; - goto free_priv; - } - - ret = scan_vendor_boot_part(bflow->blk, priv); - if (ret < 0) { - log_debug("scan vendor_boot failed: err=%d\n", ret); - goto free_priv; + if (priv->header_version >= 3) { + ret = scan_vendor_boot_part(bflow->blk, priv); + if (ret < 0) { + log_debug("scan vendor_boot failed: err=%d\n", ret); + goto free_priv; + } } /* @@ -278,7 +303,7 @@ static int android_read_bootflow(struct udevice *dev, struct bootflow *bflow) configure_serialno(bflow); configure_bootloader_version(bflow); - if (priv->boot_mode == ANDROID_BOOT_MODE_NORMAL) { + if (priv->boot_mode == ANDROID_BOOT_MODE_NORMAL && priv->slot) { ret = bootflow_cmdline_set_arg(bflow, "androidboot.force_normal_boot", "1", false); if (ret < 0) { @@ -319,28 +344,44 @@ static int android_read_file(struct udevice *dev, struct bootflow *bflow, * @blk: Block device to read * @name: Partition name to read * @slot: Nul-terminated slot suffixed to partition name ("a\0" or "b\0") + * @image_size: Image size in bytes used when reading the partition * @addr: Address where the partition content is loaded into * Return: 0 if OK, negative errno on failure. */ static int read_slotted_partition(struct blk_desc *desc, const char *const name, - const char slot[2], ulong addr) + const char slot[2], ulong image_size, ulong addr) { struct disk_partition partition; char partname[PART_NAME_LEN]; + size_t partname_len; + ulong num_blks = DIV_ROUND_UP(image_size, desc->blksz); int ret; u32 n; - /* Ensure name fits in partname it should be: <name>_<slot>\0 */ - if (strlen(name) > (PART_NAME_LEN - 2 - 1)) + /* + * Ensure name fits in partname. + * For A/B, it should be <name>_<slot>\0 + * For non A/B, it should be <name>\0 + */ + if (CONFIG_IS_ENABLED(ANDROID_AB)) + partname_len = PART_NAME_LEN - 2 - 1; + else + partname_len = PART_NAME_LEN - 1; + + if (strlen(name) > partname_len) return log_msg_ret("name too long", -EINVAL); - sprintf(partname, "%s_%s", name, slot); + if (slot) + sprintf(partname, "%s_%s", name, slot); + else + sprintf(partname, "%s", name); + ret = part_get_info_by_name(desc, partname, &partition); if (ret < 0) return log_msg_ret("part", ret); - n = blk_dread(desc, partition.start, partition.size, map_sysmem(addr, 0)); - if (n < partition.size) + n = blk_dread(desc, partition.start, num_blks, map_sysmem(addr, 0)); + if (n < num_blks) return log_msg_ret("part read", -EIO); return 0; @@ -386,7 +427,7 @@ static int run_avb_verification(struct bootflow *bflow) AvbSlotVerifyData *out_data; enum avb_boot_state boot_state; char *extra_args; - char slot_suffix[3]; + char slot_suffix[3] = ""; bool unlocked = false; int ret; @@ -394,7 +435,8 @@ static int run_avb_verification(struct bootflow *bflow) if (!avb_ops) return log_msg_ret("avb ops", -ENOMEM); - sprintf(slot_suffix, "_%s", priv->slot); + if (priv->slot) + sprintf(slot_suffix, "_%s", priv->slot); ret = avb_ops->read_is_device_unlocked(avb_ops, &unlocked); if (ret != AVB_IO_RESULT_OK) @@ -472,16 +514,22 @@ static int boot_android_normal(struct bootflow *bflow) if (ret < 0) return log_msg_ret("read slot", ret); - ret = read_slotted_partition(desc, "boot", priv->slot, loadaddr); + ret = read_slotted_partition(desc, "boot", priv->slot, priv->boot_img_size, + loadaddr); if (ret < 0) return log_msg_ret("read boot", ret); - ret = read_slotted_partition(desc, "vendor_boot", priv->slot, vloadaddr); - if (ret < 0) - return log_msg_ret("read vendor_boot", ret); - + if (priv->header_version >= 3) { + ret = read_slotted_partition(desc, "vendor_boot", priv->slot, + priv->vendor_boot_img_size, vloadaddr); + if (ret < 0) + return log_msg_ret("read vendor_boot", ret); + set_avendor_bootimg_addr(vloadaddr); + } set_abootimg_addr(loadaddr); - set_avendor_bootimg_addr(vloadaddr); + + if (priv->slot) + free(priv->slot); ret = bootm_boot_start(loadaddr, bflow->cmdline); diff --git a/boot/bootmeth_extlinux.c b/boot/bootmeth_extlinux.c index be8fbf4df63..c6ae6dffcb7 100644 --- a/boot/bootmeth_extlinux.c +++ b/boot/bootmeth_extlinux.c @@ -8,6 +8,7 @@ #define LOG_CATEGORY UCLASS_BOOTSTD +#include <asm/cache.h> #include <bootdev.h> #include <bootflow.h> #include <bootmeth.h> @@ -159,7 +160,7 @@ static int extlinux_read_bootflow(struct udevice *dev, struct bootflow *bflow) return log_msg_ret("try", ret); size = bflow->size; - ret = bootmeth_alloc_file(bflow, 0x10000, 1); + ret = bootmeth_alloc_file(bflow, 0x10000, ARCH_DMA_MINALIGN); if (ret) return log_msg_ret("read", ret); diff --git a/boot/image-android.c b/boot/image-android.c index cd01278f211..93b54bf8d79 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -178,6 +178,51 @@ 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_bootimg_size(const void *hdr, u32 *boot_img_size) +{ + struct andr_image_data data; + + if (!hdr || !boot_img_size) { + printf("hdr or boot_img_size can't be NULL\n"); + return false; + } + + if (!is_android_boot_image_header(hdr)) { + printf("Incorrect boot image header\n"); + return false; + } + + if (((struct andr_boot_img_hdr_v0 *)hdr)->header_version <= 2) + android_boot_image_v0_v1_v2_parse_hdr(hdr, &data); + else + android_boot_image_v3_v4_parse_hdr(hdr, &data); + + *boot_img_size = data.boot_img_total_size; + + return true; +} + +bool android_image_get_vendor_bootimg_size(const void *hdr, u32 *vendor_boot_img_size) +{ + struct andr_image_data data; + + if (!hdr || !vendor_boot_img_size) { + printf("hdr or vendor_boot_img_size can't be NULL\n"); + return false; + } + + if (!is_android_vendor_boot_image_header(hdr)) { + printf("Incorrect vendor boot image header\n"); + return false; + } + + android_vendor_boot_image_v3_v4_parse_hdr(hdr, &data); + + *vendor_boot_img_size = data.vendor_boot_img_total_size; + + return true; +} + bool android_image_get_data(const void *boot_hdr, const void *vendor_boot_hdr, struct andr_image_data *data) { diff --git a/boot/image-board.c b/boot/image-board.c index 1757e5816d8..b726bd6b303 100644 --- a/boot/image-board.c +++ b/boot/image-board.c @@ -624,9 +624,10 @@ int boot_get_fpga(struct bootm_headers *images) void *buf; int conf_noffset; int fit_img_result; - const char *uname, *name; + const char *uname, *name, *compatible; int err; int devnum = 0; /* TODO support multi fpga platforms */ + int flags = 0; if (!IS_ENABLED(CONFIG_FPGA)) return -ENOSYS; @@ -674,20 +675,29 @@ int boot_get_fpga(struct bootm_headers *images) return fit_img_result; } + conf_noffset = fit_image_get_node(buf, uname); + compatible = fdt_getprop(buf, conf_noffset, "compatible", NULL); + if (!compatible) { + printf("'fpga' image without 'compatible' property\n"); + } else { + if (CONFIG_IS_ENABLED(FPGA_LOAD_SECURE)) + flags = fpga_compatible2flag(devnum, compatible); + } + if (!fpga_is_partial_data(devnum, img_len)) { name = "full"; err = fpga_loadbitstream(devnum, (char *)img_data, img_len, BIT_FULL); if (err) err = fpga_load(devnum, (const void *)img_data, - img_len, BIT_FULL, 0); + img_len, BIT_FULL, flags); } else { name = "partial"; err = fpga_loadbitstream(devnum, (char *)img_data, img_len, BIT_PARTIAL); if (err) err = fpga_load(devnum, (const void *)img_data, - img_len, BIT_PARTIAL, 0); + img_len, BIT_PARTIAL, flags); } if (err) diff --git a/boot/upl_read.c b/boot/upl_read.c index 5063897a132..be3e1d116e1 100644 --- a/boot/upl_read.c +++ b/boot/upl_read.c @@ -520,7 +520,7 @@ static int decode_upl_graphics(struct upl *upl, ofnode node) return log_msg_ret("reg", -EINVAL); } - len = decode_addr_size(upl, buf, sizeof(buf), &gra->reg); + len = decode_addr_size(upl, buf, size, &gra->reg); if (len < 0) return log_msg_ret("buf", len); |