From: Haoran.Wang Date: Tue, 14 Nov 2017 04:36:45 +0000 (+0800) Subject: MA-11349 [Android] Use fast avb_ab_flow for AVB verify X-Git-Tag: rel_imx_4.9.88_2.0.0_ga~72 X-Git-Url: https://git.somdevices.com/?a=commitdiff_plain;h=998abae5eaee79db9b7016b7c638cf64f6fbda0a;p=u-boot.git MA-11349 [Android] Use fast avb_ab_flow for AVB verify 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 --- diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 6c46f44736..0795e57a8c 100755 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -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); diff --git a/lib/avb/libavb_ab/avb_ab_flow.c b/lib/avb/libavb_ab/avb_ab_flow.c index 3adb927acb..ccd8e27958 100644 --- a/lib/avb/libavb_ab/avb_ab_flow.c +++ b/lib/avb/libavb_ab/avb_ab_flow.c @@ -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, ¤t_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, diff --git a/lib/avb/libavb_ab/avb_ab_flow.h b/lib/avb/libavb_ab/avb_ab_flow.h index b2584d81c4..54920a6c1b 100644 --- a/lib/avb/libavb_ab/avb_ab_flow.h +++ b/lib/avb/libavb_ab/avb_ab_flow.h @@ -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. *