summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdrivers/usb/gadget/f_fastboot.c19
-rw-r--r--include/fsl_avb.h7
-rw-r--r--lib/avb/fsl/fsl_avb_ab_flow.c150
-rwxr-xr-xlib/avb/fsl/fsl_bootctl.c2
4 files changed, 175 insertions, 3 deletions
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 06d3809f20..78a694ad53 100755
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -1941,6 +1941,8 @@ 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 */
+#ifndef CONFIG_DUAL_BOOTLOADER
/* For imx6 on Android, we don't have a/b slot and we want to verify
* boot/recovery with AVB. For imx8 and Android Things we don't have
* recovery and support a/b slot for boot */
@@ -1949,7 +1951,7 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
const char *requested_partitions[] = {"boot", 0};
avb_result = avb_ab_flow_fast(&fsl_avb_ab_ops, requested_partitions, allow_fail,
AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &avb_out_data);
-#else /* CONFIG_ANDROID_AB_SUPPORT */
+#else
if (!is_recovery_mode) {
const char *requested_partitions[] = {"boot", 0};
avb_result = avb_single_flow(&fsl_avb_ab_ops, requested_partitions, allow_fail,
@@ -1959,7 +1961,20 @@ int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
avb_result = avb_single_flow(&fsl_avb_ab_ops, requested_partitions, allow_fail,
AVB_HASHTREE_ERROR_MODE_RESTART, &avb_out_data);
}
-#endif /* CONFIG_ANDROID_AB_SUPPORT */
+#endif
+#else /* !CONFIG_DUAL_BOOTLOADER */
+ /* We will only verify single one slot which has been selected in SPL */
+ const char *requested_partitions[] = {"boot", 0};
+ avb_result = avb_flow_dual_uboot(&fsl_avb_ab_ops, requested_partitions, allow_fail,
+ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &avb_out_data);
+
+ /* Goto fail early if current slot is not bootable. */
+ if (avb_result == AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS) {
+ printf("boota: slot verify fail!\n");
+ goto fail;
+ }
+#endif /* !CONFIG_DUAL_BOOTLOADER */
+
/* get the duration of avb */
metrics.avb = get_timer(avb_metric);
diff --git a/include/fsl_avb.h b/include/fsl_avb.h
index b480e9d62a..f992be91a1 100644
--- a/include/fsl_avb.h
+++ b/include/fsl_avb.h
@@ -153,6 +153,13 @@ AvbIOResult fsl_get_size_of_partition(AvbOps* ops,
* */
bool is_slotvar_avb(char *cmd);
+/* Get current bootable slot with higher priority.
+ * return 0 for the first slot
+ * return 1 for the second slot
+ * return -1 for not supported slot
+ * */
+int get_curr_slot(AvbABData *ab_data);
+
/* return 0 for the first slot
* return 1 for the second slot
* return -1 for not supported slot
diff --git a/lib/avb/fsl/fsl_avb_ab_flow.c b/lib/avb/fsl/fsl_avb_ab_flow.c
index e1bb3fb08d..a837e06721 100644
--- a/lib/avb/fsl/fsl_avb_ab_flow.c
+++ b/lib/avb/fsl/fsl_avb_ab_flow.c
@@ -353,6 +353,155 @@ static AvbIOResult fsl_load_metadata(AvbABOps* ab_ops,
return AVB_IO_RESULT_OK;
}
+#ifdef CONFIG_DUAL_BOOTLOADER
+AvbABFlowResult avb_flow_dual_uboot(AvbABOps* ab_ops,
+ const char* const* requested_partitions,
+ AvbSlotVerifyFlags flags,
+ AvbHashtreeErrorMode hashtree_error_mode,
+ AvbSlotVerifyData** out_data) {
+ AvbOps* ops = ab_ops->ops;
+ AvbSlotVerifyData* slot_data = NULL;
+ AvbSlotVerifyData* data = NULL;
+ AvbABFlowResult ret;
+ AvbABData ab_data, ab_data_orig;
+ AvbIOResult io_ret;
+ bool saw_and_allowed_verification_error = false;
+ AvbSlotVerifyResult verify_result;
+ bool set_slot_unbootable = false;
+ int target_slot;
+
+ io_ret = fsl_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;
+ }
+
+ /* Choose the target slot, it should be the same with the one in SPL. */
+ target_slot = get_curr_slot(&ab_data);
+ if (target_slot == -1) {
+ ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
+ printf("No bootable slot found!\n");
+ goto out;
+ }
+
+ printf("Verifying slot %s ...\n", slot_suffixes[target_slot]);
+ verify_result = avb_slot_verify(ops,
+ requested_partitions,
+ slot_suffixes[target_slot],
+ flags,
+ hashtree_error_mode,
+ &slot_data);
+
+ 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:
+ ret = AVB_AB_FLOW_RESULT_OK;
+ break;
+
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+ case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
+ /* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
+ * these mean game over.
+ */
+ set_slot_unbootable = true;
+ break;
+
+ 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 (flags & AVB_SLOT_VERIFY_FLAGS_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 "
+ "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
+ "is set.\n",
+ NULL);
+ saw_and_allowed_verification_error =
+ true;
+ } else {
+ set_slot_unbootable = true;
+ }
+ break;
+
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
+ ret = AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT;
+ goto out;
+ /* Do not add a 'default:' case here because
+ * of -Wswitch.
+ */
+ }
+
+ 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);
+ fsl_slot_set_unbootable(&ab_data.slots[target_slot]);
+
+ /* Only the slot chosen by SPL will be verified here so we
+ * return AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS if the
+ * slot should be set unbootable.
+ */
+ ret = AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS;
+ goto out;
+ }
+
+ /* Finally, select this slot. */
+ avb_assert(slot_data != NULL);
+ data = slot_data;
+ slot_data = NULL;
+ if (saw_and_allowed_verification_error) {
+ avb_assert(
+ flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
+ ret = AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR;
+ } else {
+ ret = AVB_AB_FLOW_RESULT_OK;
+ }
+
+out:
+ io_ret = fsl_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;
+ }
+ }
+
+ if (slot_data != NULL)
+ avb_slot_verify_data_free(slot_data);
+
+ if (out_data != NULL) {
+ *out_data = data;
+ } else {
+ if (data != NULL) {
+ avb_slot_verify_data_free(data);
+ }
+ }
+
+ return ret;
+}
+#else /* CONFIG_DUAL_BOOTLOADER */
/* For legacy i.mx6/7, we won't enable A/B due to the limitation of
* storage capacity, but we still want to verify boot/recovery with
* AVB. */
@@ -664,5 +813,6 @@ out:
return ret;
}
+#endif /* CONFIG_DUAL_BOOTLOADER */
#endif /* CONFIG_DUAL_BOOTLOADER && CONFIG_SPL_BUILD */
diff --git a/lib/avb/fsl/fsl_bootctl.c b/lib/avb/fsl/fsl_bootctl.c
index 9a57557e76..b7b02e2b84 100755
--- a/lib/avb/fsl/fsl_bootctl.c
+++ b/lib/avb/fsl/fsl_bootctl.c
@@ -56,7 +56,7 @@ bool is_slotvar_avb(char *cmd) {
return false;
}
-static int get_curr_slot(AvbABData *ab_data) {
+int get_curr_slot(AvbABData *ab_data) {
if (slot_is_bootable(&ab_data->slots[0]) &&
slot_is_bootable(&ab_data->slots[1])) {
if (ab_data->slots[1].priority > ab_data->slots[0].priority)