From 97495e9189afc4a26e6e03fd8ac7389f445c590e Mon Sep 17 00:00:00 2001 From: Ji Luo Date: Wed, 22 Jul 2020 19:03:32 +0800 Subject: [PATCH] MA-17541-1 Support virtual A/B update A 'misc_virtual_ab_message' struct will be stored at the 32kB offset in misc partition, which will be used to record the virtual A/B update status. Bootloader should take care of this status, some operations must be restricted. This commit will: 1. Restrict erase/flash operations to "misc", "userdata" or "metadata" partitions if the merge status are "SNAPSHOTTED" or "MERGING". 2. Restrict slot switch if the merge status is "MERGING". 3. Output a warning in slot switch if the merge status is "SNAPSHOTTED". 4. Set the merge status as "CANCELLED" if image flash happen. Test: 1. fastboot erase/flash "userdata", "misc", "metadata" after virtual A/B update 2. slot switch after virtual A/B update Signed-off-by: Ji Luo Change-Id: I33f0041c5e76913d3970d943cad52353e0ac5f2d (cherry picked from commit 30df087bfc5e31413473f85dfefaa7176bc394a8) (cherry picked from commit 7fd03bcc8f1fc094362c11d71cf740ac9b5724c1) --- drivers/fastboot/fb_fsl/Makefile | 1 + drivers/fastboot/fb_fsl/fb_fsl_command.c | 53 ++++++++++++ drivers/fastboot/fb_fsl/fb_fsl_virtual_ab.c | 95 +++++++++++++++++++++ drivers/fastboot/fb_fsl/fb_fsl_virtual_ab.h | 17 ++++ include/android_bootloader_message.h | 13 +++ lib/Kconfig | 3 + 6 files changed, 182 insertions(+) create mode 100644 drivers/fastboot/fb_fsl/fb_fsl_virtual_ab.c create mode 100644 drivers/fastboot/fb_fsl/fb_fsl_virtual_ab.h diff --git a/drivers/fastboot/fb_fsl/Makefile b/drivers/fastboot/fb_fsl/Makefile index 61db7ed52c..6a88aee180 100644 --- a/drivers/fastboot/fb_fsl/Makefile +++ b/drivers/fastboot/fb_fsl/Makefile @@ -10,4 +10,5 @@ ifndef CONFIG_SPL_BUILD obj-y += fb_fsl_dev.o fb_fsl_boot.o fb_fsl_command.o fb_fsl_common.o fb_fsl_getvar.o fb_fsl_partitions.o obj-$(CONFIG_FASTBOOT_LOCK) += fastboot_lock_unlock.o obj-$(CONFIG_BCB_SUPPORT) += command.o bcb.o +obj-$(CONFIG_VIRTUAL_AB_SUPPORT) += fb_fsl_virtual_ab.o endif diff --git a/drivers/fastboot/fb_fsl/fb_fsl_command.c b/drivers/fastboot/fb_fsl/fb_fsl_command.c index c5f6b9f88c..6580e6e26b 100644 --- a/drivers/fastboot/fb_fsl/fb_fsl_command.c +++ b/drivers/fastboot/fb_fsl/fb_fsl_command.c @@ -49,6 +49,7 @@ #endif #include "fb_fsl_common.h" +#include "fb_fsl_virtual_ab.h" #define EP_BUFFER_SIZE 4096 @@ -409,6 +410,14 @@ static FbLockState do_fastboot_unlock(bool force) } } #endif + +#ifdef CONFIG_VIRTUAL_AB_SUPPORT + if (virtual_ab_update_is_merging() || virtual_ab_update_is_snapshoted()) { + printf("Can not erase userdata while a snapshot update is in progress!\n"); + return FASTBOOT_LOCK_ERROR; + } +#endif + wipe_all_userdata(); status = fastboot_set_lock_stat(FASTBOOT_UNLOCK); if (status < 0) @@ -430,6 +439,13 @@ static FbLockState do_fastboot_lock(void) return FASTBOOT_LOCK; } +#ifdef CONFIG_VIRTUAL_AB_SUPPORT + if (virtual_ab_update_is_merging() || virtual_ab_update_is_snapshoted()) { + printf("Can not erase userdata while a snapshot update is in progress!\n"); + return FASTBOOT_LOCK_ERROR; + } +#endif + wipe_all_userdata(); status = fastboot_set_lock_stat(FASTBOOT_LOCK); if (status < 0) @@ -734,6 +750,20 @@ static void set_active_avb(char *cmd, char *response) return; } +#ifdef CONFIG_VIRTUAL_AB_SUPPORT + if (virtual_ab_update_is_merging()) { + printf("Can not switch slot while snapshot merge is in progress!\n"); + fastboot_fail("Snapshot merge is in progress!", response); + return; + } + + /* Only output a warning when the image is snapshoted. */ + if (virtual_ab_update_is_snapshoted()) + printf("Warning: changing the active slot with a snapshot applied may cancel the update!\n"); + else + printf("Warning: Virtual A/B is enabled, switch slot may make the system fail to boot. \n"); +#endif + slot = slotidx_from_suffix(cmd); if (slot < 0) { @@ -778,9 +808,23 @@ static void flash(char *cmd, char *response) } #endif +#ifdef CONFIG_VIRTUAL_AB_SUPPORT + if (partition_is_protected_during_merge(cmd)) { + printf("Can not flash partition %s while a snapshot update is in progress!\n", cmd); + fastboot_fail("Snapshot update is in progress", response); + return; + } +#endif + fastboot_process_flash(cmd, fastboot_buf_addr, fastboot_bytes_received, response); +#ifdef CONFIG_VIRTUAL_AB_SUPPORT + /* Cancel virtual AB update after image flash */ + if (virtual_ab_update_is_merging() || virtual_ab_update_is_snapshoted()) + virtual_ab_cancel_update(); +#endif + #if defined(CONFIG_FASTBOOT_LOCK) if (strncmp(cmd, "gpt", 3) == 0) { int gpt_valid = 0; @@ -820,6 +864,15 @@ static void erase(char *cmd, char *response) return; } #endif + +#ifdef CONFIG_VIRTUAL_AB_SUPPORT + if (partition_is_protected_during_merge(cmd)) { + printf("Can not erase partition %s while a snapshot update is in progress!", cmd); + fastboot_fail("Snapshot update is in progress", response); + return; + } +#endif + fastboot_process_erase(cmd, response); } #endif diff --git a/drivers/fastboot/fb_fsl/fb_fsl_virtual_ab.c b/drivers/fastboot/fb_fsl/fb_fsl_virtual_ab.c new file mode 100644 index 0000000000..09e54f51ee --- /dev/null +++ b/drivers/fastboot/fb_fsl/fb_fsl_virtual_ab.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 NXP + */ + +#include +#include "android_bootloader_message.h" +#include "../lib/avb/fsl/utils.h" +#include "fb_fsl_virtual_ab.h" +#include "fsl_avb.h" +#include "fb_fsl.h" + +static int read_virtual_ab_message(misc_virtual_ab_message *message) +{ + size_t num_bytes; + + if (fsl_read_from_partition_multi(NULL, FASTBOOT_PARTITION_MISC, + SYSTEM_SPACE_SIZE_IN_MISC, + sizeof(misc_virtual_ab_message), + (void *)message, &num_bytes) || (num_bytes != sizeof(misc_virtual_ab_message))) { + printf("Error reading virtual AB message from misc!\n"); + return -1; + } + + if ((message->magic != MISC_VIRTUAL_AB_MAGIC_HEADER) || + (message->version != MISC_VIRTUAL_AB_MESSAGE_VERSION)) { + printf("Invalid virtual AB status, resetting..."); + message->version = MISC_VIRTUAL_AB_MESSAGE_VERSION; + message->magic = MISC_VIRTUAL_AB_MAGIC_HEADER; + message->merge_status = VIRTUAL_AB_NONE; + message->source_slot = 0; + if (fsl_write_to_partition(NULL, FASTBOOT_PARTITION_MISC, + SYSTEM_SPACE_SIZE_IN_MISC, + sizeof(misc_virtual_ab_message), + (void *)message)) { + printf("Error writing virtual AB message to misc!\n"); + return -1; + } + } + + return 0; +} + +/* Flash or erase shall be prohibited to "misc", "userdata" and "metadata" partitions + * when the virtual AB status is VIRTUAL_AB_MERGING or VIRTUAL_AB_SNAPSHOTTED. + * */ +bool partition_is_protected_during_merge(char *part) +{ + if ((!strncmp(part, "misc", sizeof("misc")) || + !strncmp(part, "userdata", sizeof("userdata")) || + !strncmp(part, "metadata", sizeof("metadata"))) && + (virtual_ab_update_is_merging() || virtual_ab_update_is_snapshoted())) + return true; + else + return false; +} + +bool virtual_ab_update_is_merging(void) +{ + misc_virtual_ab_message message; + read_virtual_ab_message(&message); + if (message.merge_status == VIRTUAL_AB_MERGING) + return true; + else + return false; +} + +bool virtual_ab_update_is_snapshoted(void) +{ + misc_virtual_ab_message message; + + read_virtual_ab_message(&message); + if (message.merge_status == VIRTUAL_AB_SNAPSHOTTED) + return true; + else + return false; +} + +int virtual_ab_cancel_update(void) +{ + misc_virtual_ab_message message; + + read_virtual_ab_message(&message); + message.merge_status = VIRTUAL_AB_CANCELLED; + + if (fsl_write_to_partition(NULL, FASTBOOT_PARTITION_MISC, + SYSTEM_SPACE_SIZE_IN_MISC, + sizeof(misc_virtual_ab_message), + (void *)&message)) { + printf("Error writing virtual AB message to misc!\n"); + return -1; + } + + return 0; +} diff --git a/drivers/fastboot/fb_fsl/fb_fsl_virtual_ab.h b/drivers/fastboot/fb_fsl/fb_fsl_virtual_ab.h new file mode 100644 index 0000000000..75ceb55092 --- /dev/null +++ b/drivers/fastboot/fb_fsl/fb_fsl_virtual_ab.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 NXP + */ + +typedef enum { + VIRTUAL_AB_NONE = 0, + VIRTUAL_AB_UNKNOWN, + VIRTUAL_AB_SNAPSHOTTED, + VIRTUAL_AB_MERGING, + VIRTUAL_AB_CANCELLED, +} Virtual_AB_Status; + +bool partition_is_protected_during_merge(char *part); +bool virtual_ab_update_is_merging(void); +bool virtual_ab_update_is_snapshoted(void); +int virtual_ab_cancel_update(void); diff --git a/include/android_bootloader_message.h b/include/android_bootloader_message.h index 579a492bb2..0ba906803a 100644 --- a/include/android_bootloader_message.h +++ b/include/android_bootloader_message.h @@ -28,10 +28,12 @@ // 2K - 16K Used by Vendor's bootloader (the 2K - 4K range may be optionally used // as bootloader_message_ab struct) // 16K - 64K Used by uncrypt and recovery to store wipe_package for A/B devices +// 32K - 64K System space, used for miscellanious AOSP features. See below. // Note that these offsets are admitted by bootloader,recovery and uncrypt, so they // are not configurable without changing all of them. static const size_t BOOTLOADER_MESSAGE_OFFSET_IN_MISC = 0; static const size_t WIPE_PACKAGE_OFFSET_IN_MISC = 16 * 1024; +static const size_t SYSTEM_SPACE_SIZE_IN_MISC = 32 * 1024; /* Bootloader Message (2-KiB) * @@ -204,6 +206,17 @@ static_assert(sizeof(struct bootloader_control) == #endif #endif /* __UBOOT__ */ +typedef struct misc_virtual_ab_message { + uint8_t version; + uint32_t magic; + uint8_t merge_status; // IBootControl 1.1, MergeStatus enum. + uint8_t source_slot; // Slot number when merge_status was written. + uint8_t reserved[57]; +} __attribute__((packed)) misc_virtual_ab_message; + +#define MISC_VIRTUAL_AB_MESSAGE_VERSION 2 +#define MISC_VIRTUAL_AB_MAGIC_HEADER 0x56740AB0 + #ifndef __UBOOT__ #ifdef __cplusplus diff --git a/lib/Kconfig b/lib/Kconfig index c34fa5c587..5cf6a9f974 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -374,6 +374,9 @@ config TRUSTY_UNLOCK_PERMISSION config VENDOR_BOOT_SUPPORT bool "Support vendor boot load" +config VIRTUAL_AB_SUPPORT + bool "Support virtual AB update" + endmenu menu "Hashing Support" -- 2.17.1