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;
+}