From 60868c0f462162d8312ec71416174c9124c7ddec Mon Sep 17 00:00:00 2001 From: Luo Ji Date: Fri, 30 Mar 2018 10:28:32 +0800 Subject: [PATCH] MA-11626-1 [Android] Enable AVB only for legacy i.mx6/7 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 --- drivers/usb/gadget/f_fastboot.c | 50 +++++++++++------ include/fsl_fastboot.h | 5 +- lib/avb/fsl/fsl_avbkey.c | 6 +- lib/avb/libavb_ab/avb_ab_flow.c | 97 +++++++++++++++++++++++++++++++++ lib/avb/libavb_ab/avb_ab_flow.h | 7 +++ 5 files changed, 147 insertions(+), 18 deletions(-) diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index b4fec87c88..e4cdb8f509 100755 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -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 diff --git a/include/fsl_fastboot.h b/include/fsl_fastboot.h index 6d49813f43..a8edf54c2b 100644 --- a/include/fsl_fastboot.h +++ b/include/fsl_fastboot.h @@ -42,6 +42,10 @@ #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" diff --git a/lib/avb/fsl/fsl_avbkey.c b/lib/avb/fsl/fsl_avbkey.c index 0d99e8c684..9ad69c19c5 100644 --- a/lib/avb/fsl/fsl_avbkey.c +++ b/lib/avb/fsl/fsl_avbkey.c @@ -42,8 +42,12 @@ #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; } diff --git a/lib/avb/libavb_ab/avb_ab_flow.c b/lib/avb/libavb_ab/avb_ab_flow.c index b61d05c909..e3c412d818 100644 --- a/lib/avb/libavb_ab/avb_ab_flow.c +++ b/lib/avb/libavb_ab/avb_ab_flow.c @@ -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, diff --git a/lib/avb/libavb_ab/avb_ab_flow.h b/lib/avb/libavb_ab/avb_ab_flow.h index e6e06c8509..1974ca312e 100644 --- a/lib/avb/libavb_ab/avb_ab_flow.h +++ b/lib/avb/libavb_ab/avb_ab_flow.h @@ -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. -- 2.17.1