MA-11327 [Android] Load Image in do_boota process once to reduce boot time
authorLuo Ji <ji.luo@nxp.com>
Wed, 7 Feb 2018 08:56:29 +0000 (16:56 +0800)
committerLuo Ji <ji.luo@nxp.com>
Fri, 9 Feb 2018 01:50:28 +0000 (09:50 +0800)
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 <ji.luo@nxp.com>
drivers/usb/gadget/f_fastboot.c
lib/avb/libavb/avb_slot_verify.c
lib/avb/libavb/avb_slot_verify.h
lib/avb/libavb_ab/avb_ab_flow.c

index 0795e57..7fdabf3 100755 (executable)
@@ -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 */
index d00b9b9..add57c7 100644 (file)
@@ -32,6 +32,7 @@
 #include "avb_vbmeta_image.h"
 #include "avb_version.h"
 #include <common.h>
+#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;
index 08b11fc..0293304 100644 (file)
@@ -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
index ccd8e27..cba82f8 100644 (file)
@@ -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);
     }
   }