MA-11349 [Android] Use fast avb_ab_flow for AVB verify
authorHaoran.Wang <elven.wang@nxp.com>
Tue, 14 Nov 2017 04:36:45 +0000 (12:36 +0800)
committerLuo Ji <ji.luo@nxp.com>
Thu, 8 Feb 2018 14:17:07 +0000 (22:17 +0800)
The verify process will check the higher priority slot
and once this slot bootable then continue this one.

Change-Id: I4667ccf45892040da913b88c2bb264da9861146a
Signed-off-by: Haoran.Wang <elven.wang@nxp.com>
drivers/usb/gadget/f_fastboot.c
lib/avb/libavb_ab/avb_ab_flow.c
lib/avb/libavb_ab/avb_ab_flow.h

index 6c46f44..0795e57 100755 (executable)
@@ -1555,7 +1555,7 @@ 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 */
-       avb_result = avb_ab_flow(&fsl_avb_ab_ops, requested_partitions, allow_fail, &avb_out_data);
+       avb_result = avb_ab_flow_fast(&fsl_avb_ab_ops, requested_partitions, allow_fail, &avb_out_data);
        /* get the duration of avb */
        metrics.avb = get_timer(avb_metric);
 
index 3adb927..ccd8e27 100644 (file)
@@ -202,6 +202,199 @@ static AvbIOResult save_metadata_if_changed(AvbABOps* ab_ops,
   return AVB_IO_RESULT_OK;
 }
 
+AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
+                            const char* const* requested_partitions,
+                            bool allow_verification_error,
+                            AvbSlotVerifyData** out_data) {
+  AvbOps* ops = ab_ops->ops;
+  AvbSlotVerifyData* slot_data[2] = {NULL, NULL};
+  AvbSlotVerifyData* data = NULL;
+  AvbABFlowResult ret;
+  AvbABData ab_data, ab_data_orig;
+  size_t slot_index_to_boot, n = 0;
+  AvbIOResult io_ret;
+  bool saw_and_allowed_verification_error = false;
+  size_t target_slot;
+  AvbSlotVerifyResult verify_result;
+  bool set_slot_unbootable = false;
+
+  io_ret = load_metadata(ab_ops, &ab_data, &ab_data_orig);
+  if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+    ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+    goto out;
+  } else if (io_ret != AVB_IO_RESULT_OK) {
+    ret = AVB_AB_FLOW_RESULT_ERROR_IO;
+    goto out;
+  }
+
+  slot_index_to_boot = 2;  // Means not 0 or 1
+  target_slot = (ab_data.slots[1].priority > ab_data.slots[0].priority? 1 : 0);
+
+  for (n = 0; n < 2; n++) {
+      if (!slot_is_bootable(&ab_data.slots[target_slot])) {
+        target_slot = (target_slot == 1 ? 0 : 1);
+        continue;
+      }
+
+      verify_result = avb_slot_verify(ops, requested_partitions, slot_suffixes[target_slot],
+                     allow_verification_error,
+                     &slot_data[target_slot]);
+      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:
+          slot_index_to_boot = target_slot;
+         n = 2;
+          break;
+
+        case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+        case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
+          /* Even with |allow_verification_error| these mean game over. */
+          set_slot_unbootable = true;
+          break;
+
+        /* 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 (allow_verification_error) {
+            /* Do nothing since we allow this. */
+            avb_debugv("Allowing slot ",
+                       slot_suffixes[target_slot],
+                       " which verified "
+                       "with result ",
+                       avb_slot_verify_result_to_string(verify_result),
+                       " because |allow_verification_error| is true.\n",
+                       NULL);
+            saw_and_allowed_verification_error = true;
+           slot_index_to_boot = target_slot;
+           n = 2;
+          } else {
+            set_slot_unbootable = true;
+          }
+          break;
+        default:
+          break;
+      }
+      if (set_slot_unbootable) {
+        avb_errorv("Error verifying slot ",
+                   slot_suffixes[target_slot],
+                   " with result ",
+                   avb_slot_verify_result_to_string(verify_result),
+                   " - setting unbootable.\n",
+                   NULL);
+        slot_set_unbootable(&ab_data.slots[target_slot]);
+       set_slot_unbootable = false;
+      }
+      /* switch to another slot */
+      target_slot = (target_slot == 1 ? 0 : 1);
+  }
+
+  if (slot_index_to_boot == 2) {
+    /* No bootable slots! */
+    avb_error("No bootable slots found.\n");
+    ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
+    goto out;
+  }
+
+  /* Update stored rollback index such that the stored rollback index
+   * is the largest value supporting all currently bootable slots. Do
+   * this for every rollback index location.
+   */
+  for (n = 0; n < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; n++) {
+    uint64_t rollback_index_value = 0;
+
+    if (slot_data[0] != NULL && slot_data[1] != NULL) {
+      uint64_t a_rollback_index = slot_data[0]->rollback_indexes[n];
+      uint64_t b_rollback_index = slot_data[1]->rollback_indexes[n];
+      rollback_index_value =
+          (a_rollback_index < b_rollback_index ? a_rollback_index
+                                               : b_rollback_index);
+    } else if (slot_data[0] != NULL) {
+      rollback_index_value = slot_data[0]->rollback_indexes[n];
+    } else if (slot_data[1] != NULL) {
+      rollback_index_value = slot_data[1]->rollback_indexes[n];
+    }
+
+    if (rollback_index_value != 0) {
+      uint64_t current_rollback_index_value;
+      io_ret = ops->read_rollback_index(ops, n, &current_rollback_index_value);
+      if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+        ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+        goto out;
+      } else if (io_ret != AVB_IO_RESULT_OK) {
+        avb_error("Error getting rollback index for slot.\n");
+        ret = AVB_AB_FLOW_RESULT_ERROR_IO;
+        goto out;
+      }
+      if (current_rollback_index_value != rollback_index_value) {
+        io_ret = ops->write_rollback_index(ops, n, rollback_index_value);
+        if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+          ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+          goto out;
+        } else if (io_ret != AVB_IO_RESULT_OK) {
+          avb_error("Error setting stored rollback index.\n");
+          ret = AVB_AB_FLOW_RESULT_ERROR_IO;
+          goto out;
+        }
+      }
+    }
+  }
+
+  /* Finally, select this slot. */
+  avb_assert(slot_data[slot_index_to_boot] != NULL);
+  data = slot_data[slot_index_to_boot];
+  slot_data[slot_index_to_boot] = NULL;
+  if (saw_and_allowed_verification_error) {
+    avb_assert(allow_verification_error);
+    ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
+  } else {
+    ret = AVB_AB_FLOW_RESULT_OK;
+  }
+
+  /* ... and decrement tries remaining, if applicable. */
+  if (!ab_data.slots[slot_index_to_boot].successful_boot &&
+      ab_data.slots[slot_index_to_boot].tries_remaining > 0) {
+    ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
+  }
+
+out:
+  io_ret = save_metadata_if_changed(ab_ops, &ab_data, &ab_data_orig);
+  if (io_ret != AVB_IO_RESULT_OK) {
+    if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+      ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+    } else {
+      ret = AVB_AB_FLOW_RESULT_ERROR_IO;
+    }
+    if (data != NULL) {
+      avb_slot_verify_data_free(data);
+      data = NULL;
+    }
+  }
+
+  for (n = 0; n < 2; n++) {
+    if (slot_data[n] != NULL) {
+      avb_slot_verify_data_free(slot_data[n]);
+    }
+  }
+
+  if (out_data != NULL) {
+    *out_data = data;
+  } else {
+    if (data != NULL) {
+      avb_slot_verify_data_free(data);
+    }
+  }
+
+  return ret;
+}
+
 AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops,
                             const char* const* requested_partitions,
                             bool allow_verification_error,
index b2584d8..54920a6 100644 (file)
@@ -215,6 +215,11 @@ AvbABFlowResult avb_ab_flow(AvbABOps* ab_ops,
                             bool allow_verification_error,
                             AvbSlotVerifyData** out_data);
 
+AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
+                            const char* const* requested_partitions,
+                            bool allow_verification_error,
+                            AvbSlotVerifyData** out_data);
+
 /* Marks the slot with the given slot number as active. Returns
  * AVB_IO_RESULT_OK on success, error code otherwise.
  *