MA-11626-1 [Android] Enable AVB only for legacy i.mx6/7
authorLuo Ji <ji.luo@nxp.com>
Fri, 30 Mar 2018 02:28:32 +0000 (10:28 +0800)
committerLuo Ji <ji.luo@nxp.com>
Wed, 4 Apr 2018 10:23:09 +0000 (18:23 +0800)
Enable AVB verify of boot/recovery for legacy(imx6/7)
on normal Android. A/B slot is not enabled on legacy
due to the limitation of storage capacity.

Change-Id: I7f636df6c82172d8a8d8588d45b385f32332a9cc
Signed-off-by: Luo Ji <ji.luo@nxp.com>
drivers/usb/gadget/f_fastboot.c
include/fsl_fastboot.h
lib/avb/fsl/fsl_avbkey.c
lib/avb/libavb_ab/avb_ab_flow.c
lib/avb/libavb_ab/avb_ab_flow.h

index b4fec87..e4cdb8f 100755 (executable)
@@ -93,8 +93,8 @@ extern void trusty_os_init(void);
  */
 static unsigned int download_size;
 static unsigned int download_bytes;
-#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
-static bool is_recovery_mode;
+#if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC)
+static bool is_recovery_mode = false;
 #endif
 
 /* common variables of fastboot getvar command */
@@ -1474,9 +1474,6 @@ void fastboot_run_bootmode(void)
        case BOOTMODE_FASTBOOT_BCB_CMD:
                /* Make the boot into fastboot mode*/
                puts("Fastboot: Got bootloader commands!\n");
-#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
-               is_recovery_mode = false;
-#endif
                run_command("fastboot 0", 0);
                break;
 #ifdef CONFIG_ANDROID_RECOVERY
@@ -1484,7 +1481,7 @@ void fastboot_run_bootmode(void)
        case BOOTMODE_RECOVERY_KEY_PRESSED:
                /* Make the boot into recovery mode */
                puts("Fastboot: Got Recovery key pressing or recovery commands!\n");
-#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
+#if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC)
                is_recovery_mode = true;
 #else
                board_recovery_setup();
@@ -1493,9 +1490,6 @@ void fastboot_run_bootmode(void)
 #endif
        default:
                /* skip special mode boot*/
-#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
-               is_recovery_mode = false;
-#endif
                puts("Fastboot: Normal\n");
                break;
        }
@@ -1538,8 +1532,6 @@ bootimg_print_image_hdr(struct andr_img_hdr *hdr)
 static struct andr_img_hdr boothdr __aligned(ARCH_DMA_MINALIGN);
 
 #if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC)
-/* we can use avb to verify Trusty if we want */
-const char *requested_partitions[] = {"boot", 0};
 
 int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
 
@@ -1568,9 +1560,25 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
        }
        bool allow_fail = (lock_status == FASTBOOT_UNLOCK ? true : false);
        avb_metric = get_timer(0);
-       /* if in lock state, do avb verify */
+       /* For imx6 on Android, we don't have a/b slot and we want to verify
+        * boot/recovery with AVB. For imx8 and Android Things we don't have
+        * recovery and support a/b slot for boot */
+#ifdef CONFIG_ANDROID_AB_SUPPORT
+       /* we can use avb to verify Trusty if we want */
+       const char *requested_partitions[] = {"boot", 0};
        avb_result = avb_ab_flow_fast(&fsl_avb_ab_ops, requested_partitions, allow_fail,
                        AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &avb_out_data);
+#else /* CONFIG_ANDROID_AB_SUPPORT */
+       if (!is_recovery_mode) {
+               const char *requested_partitions[] = {"boot", 0};
+               avb_result = avb_single_flow(&fsl_avb_ab_ops, requested_partitions, allow_fail,
+                               AVB_HASHTREE_ERROR_MODE_RESTART, &avb_out_data);
+       } else {
+               const char *requested_partitions[] = {"recovery", 0};
+               avb_result = avb_single_flow(&fsl_avb_ab_ops, requested_partitions, allow_fail,
+                               AVB_HASHTREE_ERROR_MODE_RESTART, &avb_out_data);
+       }
+#endif /* CONFIG_ANDROID_AB_SUPPORT */
        /* get the duration of avb */
        metrics.avb = get_timer(avb_metric);
 
@@ -1613,7 +1621,7 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
                        else
                                fastboot_setup_system_boot_args(avb_out_data->ab_suffix, true);
                }
-#endif
+#endif /* CONFIG_SYSTEM_RAMDISK_SUPPORT */
                image_size = avb_loadpart->data_size;
 #if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
                /* If we are using uncompressed kernel image, copy it directly to
@@ -1652,7 +1660,17 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
                size_t num_read;
                hdr = &boothdr;
 
-               char bootimg[8];
+               char bootimg[10];
+               /* we don't have a/b slot for imx6 on normal Android*/
+#ifndef CONFIG_ANDROID_AB_SUPPORT
+               char *slot = "";
+               if (!is_recovery_mode) {
+                       sprintf(bootimg, "boot");
+               } else {
+                       sprintf(bootimg, "recovery");
+               }
+               printf("boot '%s' still\n", bootimg);
+#else
                char *slot = select_slot(&fsl_avb_ab_ops);
                if (slot == NULL) {
                        printf("boota: no bootable slot\n");
@@ -1660,6 +1678,7 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
                }
                sprintf(bootimg, "boot%s", slot);
                printf(" boot '%s' still\n", bootimg);
+#endif
                /* maybe we should use bootctl to select a/b
                 * but libavb doesn't export a/b select */
                if (fsl_avb_ops.read_from_partition(&fsl_avb_ops, bootimg,
@@ -1710,7 +1729,6 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
                }
                hdr = (struct andr_img_hdr *)(ulong)(hdr->kernel_addr - hdr->page_size);
 #endif /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */
-
                char bootargs_sec[ANDR_BOOT_ARGS_SIZE];
                sprintf(bootargs_sec,
                                "androidboot.verifiedbootstate=orange androidboot.slot_suffix=%s", slot);
@@ -1718,7 +1736,7 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
 #ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
                if(!is_recovery_mode)
                        fastboot_setup_system_boot_args(slot, true);
-#endif
+#endif /* CONFIG_SYSTEM_RAMDISK_SUPPORT */
 #ifdef CONFIG_FASTBOOT_LOCK
        }
 #endif
index 6d49813..a8edf54 100644 (file)
 #define FASTBOOT_PARTITION_TEE "tos"
 #define FASTBOOT_PARTITION_PRDATA "presistdata"
 
+#ifdef CONFIG_AVB_SUPPORT
+#define FASTBOOT_PARTITION_AVBKEY "avbkey"
+#endif
+
 #ifdef CONFIG_ANDROID_AB_SUPPORT
 #define FASTBOOT_PARTITION_BOOT_A "boot_a"
 #define FASTBOOT_PARTITION_RECOVERY "recovery"
@@ -53,7 +57,6 @@
 #ifdef CONFIG_AVB_SUPPORT
 #define FASTBOOT_PARTITION_VBMETA_A "vbmeta_a"
 #define FASTBOOT_PARTITION_VBMETA_B "vbmeta_b"
-#define FASTBOOT_PARTITION_AVBKEY "avbkey"
 #endif
 #define FASTBOOT_PARTITION_MISC "misc"
 #define FASTBOOT_PARTITION_GPT "gpt"
index 0d99e8c..9ad69c1 100644 (file)
 #define RESULT_ERROR -1
 #define RESULT_OK     0
 
-#ifndef CONFIG_FSL_CAAM_KB
+#if !defined(CONFIG_FSL_CAAM_KB) || !defined(ANDROID_AB_SUPPORT)
 /* ARM64 won't avbkey and rollback index in this stage directly. */
+/* For legacy imx6/7, we won't enable A/B due to the limitation of
+ * storage capacity, but we still want to verify the boot/recovery
+ * with AVB. In this case, we won't check and store the rollback
+ * index. */
 int avbkey_init(uint8_t *plainkey, uint32_t keylen) {
        return 0;
 }
index b61d05c..e3c412d 100644 (file)
@@ -406,6 +406,103 @@ out:
   return ret;
 }
 
+/* For legacy i.mx6/7, we won't enable A/B due to the limitation of
+ * storage capacity, but we still want to verify boot/recovery with
+ * AVB. */
+AvbABFlowResult avb_single_flow(AvbABOps* ab_ops,
+                            const char* const* requested_partitions,
+                            AvbSlotVerifyFlags flags,
+                            AvbHashtreeErrorMode hashtree_error_mode,
+                            AvbSlotVerifyData** out_data) {
+  AvbOps* ops = ab_ops->ops;
+  AvbSlotVerifyData* slot_data = NULL;
+  AvbSlotVerifyData* data = NULL;
+  AvbABFlowResult ret;
+  bool saw_and_allowed_verification_error = false;
+
+  /* Validate boot/recovery. */
+  AvbSlotVerifyResult verify_result;
+
+  verify_result = avb_slot_verify(ops,
+                    requested_partitions,
+                    "",
+                    flags,
+                    hashtree_error_mode,
+                    &slot_data);
+  switch (verify_result) {
+      case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
+        ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+        goto out;
+
+      case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
+        ret = AVB_AB_FLOW_RESULT_ERROR_IO;
+        goto out;
+
+      case AVB_SLOT_VERIFY_RESULT_OK:
+        break;
+
+      case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+      case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
+          /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
+           * these mean game over.
+           */
+        ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
+        goto out;
+
+      /* explicit fallthrough. */
+      case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+      case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
+      case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
+        if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) {
+          /* Do nothing since we allow this. */
+          avb_debugv("Allowing slot ",
+                     slot_suffixes[n],
+                     " which verified "
+                     "with result ",
+                     avb_slot_verify_result_to_string(verify_result),
+                     " because "
+                     "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
+                     "is set.\n",
+                     NULL);
+          saw_and_allowed_verification_error = true;
+        } else {
+            ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
+            goto out;
+        }
+        break;
+
+      case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
+        ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
+        goto out;
+        /* Do not add a 'default:' case here because of -Wswitch. */
+      }
+
+  avb_assert(slot_data != NULL);
+  data = slot_data;
+  slot_data = NULL;
+  if (saw_and_allowed_verification_error) {
+    avb_assert(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
+    ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
+  } else {
+    ret = AVB_AB_FLOW_RESULT_OK;
+  }
+
+out:
+  if (slot_data != NULL) {
+    avb_slot_verify_data_free(slot_data);
+  }
+
+  if (out_data != NULL) {
+    *out_data = data;
+  } else {
+    if (data != NULL) {
+      avb_slot_verify_data_free(data);
+    }
+  }
+
+  return ret;
+}
+
 AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
                             const char* const* requested_partitions,
                             AvbSlotVerifyFlags flags,
index e6e06c8..1974ca3 100644 (file)
@@ -228,6 +228,13 @@ AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
                             AvbSlotVerifyFlags flags,
                             AvbHashtreeErrorMode hashtree_error_mode,
                             AvbSlotVerifyData** out_data);
+/* This is for legacy i.mx6/7 which don't enable A/B but want to
+ * verify boot/recovery with AVB */
+AvbABFlowResult avb_single_flow(AvbABOps* ab_ops,
+                            const char* const* requested_partitions,
+                            AvbSlotVerifyFlags flags,
+                            AvbHashtreeErrorMode hashtree_error_mode,
+                            AvbSlotVerifyData** out_data);
 
 /* Marks the slot with the given slot number as active. Returns
  * AVB_IO_RESULT_OK on success, error code otherwise.