Add A/B implementation.
This CL add routines for working with A/B metadata, including A/B
selection and managing rollback indexes.
A/B metadata is stored in the 'misc' partition in the |slot_suffix|
field using a format private to libavb - see bootable/recovery/bootloader.h
for more details. A new set_ab_metadata sub-command has been added to
avbtool for initializing A/B metadata at build time.
A/B metadata integrity is provided by a simple magic marker and a CRC-32
checksum. If invalid A/B metadata is detected, the behavior is to reset
the A/B metadata to a known state where both slots are given seven boot
tries.
An implementation of the boot_control HAL using AVB-specific A/B
metadata is also provided.
Also factored out the test-side AvbOps into a FakeAvbOps class and put
it in its own file.
Saw a couple of references to things like "Brillo Boot Image" and the
like. Fixed these up.
This CL is based on work done by Kevin Chavez - see b/29072323 - during
his internship at Google.
BUG=31264229
TEST=New unit tests + all unit tests pass.
TEST=Manual testing of boot_control HAL using the bootctl command.
Change-Id: I594ea4173a051ecb72636058440372ff1ca5855b
diff --git a/libavb/avb_slot_verify.c b/libavb/avb_slot_verify.c
index 5d4910f..12f139e 100644
--- a/libavb/avb_slot_verify.c
+++ b/libavb/avb_slot_verify.c
@@ -633,6 +633,13 @@
/* If things check out, mangle the kernel command-line as needed. */
if (ret == AVB_SLOT_VERIFY_RESULT_OK) {
+ /* Fill in |ab_suffix| field. */
+ slot_data->ab_suffix = avb_strdup(ab_suffix);
+ if (slot_data->ab_suffix == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+
/* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
if (slot_data->cmdline != NULL) {
char* new_cmdline = sub_cmdline(ops, slot_data->cmdline, ab_suffix);
@@ -729,6 +736,9 @@
}
void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
+ if (data->ab_suffix != NULL) {
+ avb_free(data->ab_suffix);
+ }
if (data->boot_data != NULL) {
avb_free(data->boot_data);
}
@@ -737,3 +747,39 @@
}
avb_free(data);
}
+
+const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
+ const char* ret = NULL;
+
+ switch (result) {
+ case AVB_SLOT_VERIFY_RESULT_OK:
+ ret = "OK";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
+ ret = "ERROR_OOM";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
+ ret = "ERROR_IO";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+ ret = "ERROR_VERIFICATION";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
+ ret = "ERROR_ROLLBACK_INDEX";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
+ ret = "ERROR_PUBLIC_KEY_REJECTED";
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+ ret = "ERROR_INVALID_METADATA";
+ break;
+ /* Do not add a 'default:' case here because of -Wswitch. */
+ }
+
+ if (ret == NULL) {
+ avb_error("Unknown AvbSlotVerifyResult value.\n");
+ ret = "(unknown)";
+ }
+
+ return ret;
+}