From 760b3ac1a4073a05e0ecde5282eff96ad62db46b Mon Sep 17 00:00:00 2001 From: Luo Ji Date: Wed, 7 Feb 2018 16:56:29 +0800 Subject: [PATCH] MA-11327 [Android] Load Image in do_boota process once to reduce boot time Load bootimage to the address defined in boot header so we don't need to copy it again, this will save some boot time. Change-Id: I87979decb5cae58648f8afec4a0ee3503aea841f Signed-off-by: Luo Ji --- drivers/usb/gadget/f_fastboot.c | 21 +++++---- lib/avb/libavb/avb_slot_verify.c | 73 +++++++++++++++++++++++++++++++- lib/avb/libavb/avb_slot_verify.h | 2 +- lib/avb/libavb_ab/avb_ab_flow.c | 4 +- 4 files changed, 87 insertions(+), 13 deletions(-) diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 0795e57a8c..7fdabf3f24 100755 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -1559,7 +1559,8 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { /* get the duration of avb */ metrics.avb = get_timer(avb_metric); - if (avb_result == AVB_AB_FLOW_RESULT_OK) { + if ((avb_result == AVB_AB_FLOW_RESULT_OK) || + (avb_result == AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR)) { assert(avb_out_data != NULL); /* load the first partition */ avb_loadpart = avb_out_data->loaded_partitions; @@ -1567,11 +1568,14 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { /* we should use avb_part_data->data as boot image */ /* boot image is already read by avb */ hdr = (struct andr_img_hdr *)avb_loadpart->data; - if (android_image_check_header(hdr)) { - printf("boota: bad boot image magic\n"); - goto fail; + if (avb_result == AVB_AB_FLOW_RESULT_OK) + printf(" verify OK, boot '%s%s'\n", + avb_loadpart->partition_name, avb_out_data->ab_suffix); + else { + printf(" verify FAIL, state: UNLOCK\n"); + printf(" boot '%s%s' still\n", + avb_loadpart->partition_name, avb_out_data->ab_suffix); } - printf(" verify OK, boot '%s%s'\n", avb_loadpart->partition_name, avb_out_data->ab_suffix); /* The dm-verity commandline has conflicts with system bootargs and we can't * determine whether dm-verity is opened by the commandline for now. */ char bootargs_sec[ANDR_BOOT_ARGS_SIZE]; @@ -1590,12 +1594,11 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { fastboot_setup_system_boot_args(avb_out_data->ab_suffix); #endif image_size = avb_loadpart->data_size; - memcpy((void *)(ulong)(hdr->kernel_addr - hdr->page_size), (void *)hdr, image_size); } else if (lock_status == FASTBOOT_LOCK) { /* && verify fail */ /* if in lock state, verify enforce fail */ printf(" verify FAIL, state: LOCK\n"); goto fail; - } else { /* lock_status == FASTBOOT_UNLOCK && verify fail */ + } else { /* lock_status == FASTBOOT_UNLOCK && get unacceptable verify fail */ /* if in unlock state, log the verify state */ printf(" verify FAIL, state: UNLOCK\n"); #endif @@ -1696,9 +1699,9 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { if (!is_recovery_mode) boot_args[2] = NULL; #endif - + /* we should free the avb_out_data but should not free the bootimage */ if (avb_out_data != NULL) - avb_slot_verify_data_free(avb_out_data); + avb_slot_verify_data_free_fast(avb_out_data); #ifdef CONFIG_IMX_TRUSTY_OS /* put ql-tipc to release resource for Linux */ diff --git a/lib/avb/libavb/avb_slot_verify.c b/lib/avb/libavb/avb_slot_verify.c index d00b9b9404..add57c79b8 100644 --- a/lib/avb/libavb/avb_slot_verify.c +++ b/lib/avb/libavb/avb_slot_verify.c @@ -32,6 +32,7 @@ #include "avb_vbmeta_image.h" #include "avb_version.h" #include +#include "android_image.h" /* Maximum allow length (in bytes) of a partition name, including * ab_suffix. @@ -69,6 +70,8 @@ static inline bool result_should_continue(AvbSlotVerifyResult result) { return false; } +static struct andr_img_hdr boothdr __aligned(ARCH_DMA_MINALIGN); + static AvbSlotVerifyResult load_and_verify_hash_partition( AvbOps* ops, const char* const* requested_partitions, @@ -117,10 +120,36 @@ static AvbSlotVerifyResult load_and_verify_hash_partition( goto out; } - image_buf = avb_malloc(hash_desc.image_size); - if (image_buf == NULL) { + /* If we are going to load bootimage, load it to + * hdr->kernel_addr - hdr->page_size address directly, + * so we don't need to copy it again!*/ + if (strstr(part_name, "boot") != NULL) { + struct andr_img_hdr *hdr = &boothdr; + /* read boot header first so we can get the address */ + if (ops->read_from_partition(ops, part_name, + 0, sizeof(boothdr), hdr, &part_num_read) != AVB_IO_RESULT_OK && + part_num_read != sizeof(boothdr)) { + printf("Error! read bootimage head error\n"); + ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO; + goto out; + } + /* check bootimg header to make sure we have a vaild bootimage */ + if (android_image_check_header(hdr)) { + printf("Error! bad boot image magic\n"); + /* bad boot image magic is critical so we will return + * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA here, + * it will make this slot be marked as unbootable.*/ + ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA; + goto out; + } + + image_buf = (uint8_t*)(unsigned long)(hdr->kernel_addr - hdr->page_size); + } else { + image_buf = avb_malloc(hash_desc.image_size); + if (image_buf == NULL) { ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM; goto out; + } } io_ret = ops->read_from_partition(ops, @@ -1147,6 +1176,46 @@ void avb_slot_verify_data_free(AvbSlotVerifyData* data) { } avb_free(data); } +void avb_slot_verify_data_free_fast(AvbSlotVerifyData* data) { + if (data->ab_suffix != NULL) { + avb_free(data->ab_suffix); + } + if (data->cmdline != NULL) { + avb_free(data->cmdline); + } + if (data->vbmeta_images != NULL) { + size_t n; + for (n = 0; n < data->num_vbmeta_images; n++) { + AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n]; + if (vbmeta_image->partition_name != NULL) { + avb_free(vbmeta_image->partition_name); + } + if (vbmeta_image->vbmeta_data != NULL) { + avb_free(vbmeta_image->vbmeta_data); + } + } + avb_free(data->vbmeta_images); + } + if (data->loaded_partitions != NULL) { + size_t n; + for (n = 0; n < data->num_loaded_partitions; n++) { + AvbPartitionData* loaded_partition = &data->loaded_partitions[n]; + if (loaded_partition->partition_name != NULL) { + /* the address of bootimage isn't alloced by malloc, we don't + * need to free it. */ + if (strstr(loaded_partition->partition_name, "boot") != NULL) + continue; + else + avb_free(loaded_partition->partition_name); + } + if (loaded_partition->data != NULL) { + avb_free(loaded_partition->data); + } + } + avb_free(data->loaded_partitions); + } + avb_free(data); +} const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) { const char* ret = NULL; diff --git a/lib/avb/libavb/avb_slot_verify.h b/lib/avb/libavb/avb_slot_verify.h index 08b11fcf1a..029330458d 100644 --- a/lib/avb/libavb/avb_slot_verify.h +++ b/lib/avb/libavb/avb_slot_verify.h @@ -176,7 +176,7 @@ typedef struct { /* Frees a |AvbSlotVerifyData| including all data it points to. */ void avb_slot_verify_data_free(AvbSlotVerifyData* data); - +void avb_slot_verify_data_free_fast(AvbSlotVerifyData* data); /* Performs a full verification of the slot identified by |ab_suffix| * and load the contents of the partitions whose name is in the * NULL-terminated string array |requested_partitions| (each partition diff --git a/lib/avb/libavb_ab/avb_ab_flow.c b/lib/avb/libavb_ab/avb_ab_flow.c index ccd8e27958..cba82f8a12 100644 --- a/lib/avb/libavb_ab/avb_ab_flow.c +++ b/lib/avb/libavb_ab/avb_ab_flow.c @@ -388,7 +388,9 @@ out: *out_data = data; } else { if (data != NULL) { - avb_slot_verify_data_free(data); + /* the address of bootimage isn't alloced by malloc, + * we should not free it. */ + avb_slot_verify_data_free_fast(data); } } -- 2.17.1