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 <ji.luo@nxp.com>
Change-Id: I33f0041c5e76913d3970d943cad52353e0ac5f2d
(cherry picked from commit
30df087bfc5e31413473f85dfefaa7176bc394a8)
(cherry picked from commit
7fd03bcc8f1fc094362c11d71cf740ac9b5724c1)
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
#endif
#include "fb_fsl_common.h"
+#include "fb_fsl_virtual_ab.h"
#define EP_BUFFER_SIZE 4096
}
}
#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)
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)
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) {
}
#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;
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
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ */
+
+#include <part.h>
+#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;
+}
--- /dev/null
+// 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);
// 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)
*
#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
config VENDOR_BOOT_SUPPORT
bool "Support vendor boot load"
+config VIRTUAL_AB_SUPPORT
+ bool "Support virtual AB update"
+
endmenu
menu "Hashing Support"