Merge "QcomModulePkg: Fix fail to bootup issue after pushing some file"
diff --git a/QcomModulePkg/Library/avb/VerifiedBoot.c b/QcomModulePkg/Library/avb/VerifiedBoot.c
index f46f7b6..d276294 100755
--- a/QcomModulePkg/Library/avb/VerifiedBoot.c
+++ b/QcomModulePkg/Library/avb/VerifiedBoot.c
@@ -1134,6 +1134,8 @@
IsDynamicPartitionSupport ()) &&
(Info->BootIntoRecovery &&
!IsBuildUseRecoveryAsBoot ())) {
+ if (!Info->MultiSlotBoot)
+ VerifyFlags = VerifyFlags | AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION;
AddRequestedPartition (RequestedPartitionAll, IMG_RECOVERY);
NumRequestedPartition += 1;
Result = avb_slot_verify (Ops, (CONST CHAR8 *CONST *)RequestedPartition,
diff --git a/QcomModulePkg/Library/avb/libavb/avb_ops.c b/QcomModulePkg/Library/avb/libavb/avb_ops.c
index f1aa812..1fe1258 100644
--- a/QcomModulePkg/Library/avb/libavb/avb_ops.c
+++ b/QcomModulePkg/Library/avb/libavb/avb_ops.c
@@ -370,6 +370,34 @@
return AVB_IO_RESULT_OK;
}
+
+AvbIOResult
+AvbValidatePartitionPublicKey(AvbOps *Ops, const char* Partition,
+ const uint8_t *PublicKeyData, size_t PublicKeyLength,
+ const uint8_t *PublicKeyMetadata, size_t PublicKeyMetadataLength,
+ bool *OutIsTrusted, uint32_t* OutRollbackIndexLocation)
+{
+ DEBUG((EFI_D_VERBOSE, "ValidatePartitionPublicKey PublicKeyLength %d, "
+ "PublicKeyMetadataLength %d\n",
+ PublicKeyLength, PublicKeyMetadataLength));
+
+ if (OutIsTrusted == NULL || PublicKeyData == NULL) {
+ DEBUG((EFI_D_ERROR, "Invalid parameters\n"));
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+
+ if (PublicKeyLength == ARRAY_SIZE(OEMPublicKey) &&
+ CompareMem(PublicKeyData, OEMPublicKey, PublicKeyLength) == 0) {
+ *OutIsTrusted = true;
+ } else {
+ *OutIsTrusted = false;
+ }
+ *OutRollbackIndexLocation = 1; // Recovery rollback index
+ DEBUG((EFI_D_ERROR,
+ "ValidateVbmetaPublicKey OutIsTrusted %d\n",*OutIsTrusted));
+ return AVB_IO_RESULT_OK;
+}
+
AvbIOResult AvbReadRollbackIndex(AvbOps *Ops, size_t RollbackIndexLocation,
uint64_t *OutRollbackIndex)
{
@@ -545,6 +573,7 @@
Ops->read_from_partition = AvbReadFromPartition;
Ops->write_to_partition = AvbWriteToPartition;
Ops->validate_vbmeta_public_key = AvbValidateVbmetaPublicKey;
+ Ops->validate_public_key_for_partition = AvbValidatePartitionPublicKey;
Ops->read_rollback_index = AvbReadRollbackIndex;
Ops->write_rollback_index = AvbWriteRollbackIndex;
Ops->read_is_device_unlocked = AvbReadIsDeviceUnlocked;
diff --git a/QcomModulePkg/Library/avb/libavb/avb_ops.h b/QcomModulePkg/Library/avb/libavb/avb_ops.h
index 8162194..76cc9d4 100644
--- a/QcomModulePkg/Library/avb/libavb/avb_ops.h
+++ b/QcomModulePkg/Library/avb/libavb/avb_ops.h
@@ -155,6 +155,10 @@
*
* If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set -
* true if trusted or false if untrusted.
+ *
+ * NOTE: If AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is passed to
+ * avb_slot_verify() then this operation is never used. Instead, the
+ * validate_public_key_for_partition() operation is used
*/
AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops,
const uint8_t* public_key_data,
@@ -223,6 +227,26 @@
AvbIOResult (*get_size_of_partition)(AvbOps* ops,
const char* partition,
uint64_t* out_size_num_bytes);
+
+ /* Like validate_vbmeta_public_key() but for when the flag
+ * AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is being used. The name of the
+ * partition to get the public key for is passed in |partition_name|.
+ *
+ * Also returns the rollback index location to use for the partition, in
+ * |out_rollback_index_location|.
+ *
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
+ */
+ AvbIOResult (*validate_public_key_for_partition)(
+ AvbOps* ops,
+ const char* partition,
+ const uint8_t* public_key_data,
+ size_t public_key_length,
+ const uint8_t* public_key_metadata,
+ size_t public_key_metadata_length,
+ bool* out_is_trusted,
+ uint32_t* out_rollback_index_location);
+
};
typedef struct {
diff --git a/QcomModulePkg/Library/avb/libavb/avb_slot_verify.c b/QcomModulePkg/Library/avb/libavb/avb_slot_verify.c
index fb6fc79..180e2d4 100644
--- a/QcomModulePkg/Library/avb/libavb/avb_slot_verify.c
+++ b/QcomModulePkg/Library/avb/libavb/avb_slot_verify.c
@@ -359,6 +359,7 @@
AvbOps* ops,
const char* const* requested_partitions,
const char* ab_suffix,
+ AvbSlotVerifyFlags flags,
bool allow_verification_error,
AvbVBMetaImageFlags toplevel_vbmeta_flags,
int rollback_index_location,
@@ -398,7 +399,12 @@
* rollback_index_location to determine whether we're the main
* vbmeta struct.
*/
- is_main_vbmeta = (rollback_index_location == 0);
+ is_main_vbmeta = false;
+ if (rollback_index_location == 0) {
+ if ((flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) == 0) {
+ is_main_vbmeta = true;
+ }
+ }
/* Don't use footers for vbmeta partitions ('vbmeta' or
* 'vbmeta_<partition_name>').
@@ -509,6 +515,7 @@
ret = load_and_verify_vbmeta(ops,
requested_partitions,
ab_suffix,
+ flags,
allow_verification_error,
0 /* toplevel_vbmeta_flags */,
0 /* rollback_index_location */,
@@ -585,6 +592,8 @@
}
}
+ uint32_t rollback_index_location_to_use = rollback_index_location;
+
/* Check if key used to make signature matches what is expected. */
if (pk_data != NULL) {
if (expected_public_key != NULL) {
@@ -612,9 +621,27 @@
pk_metadata_len = vbmeta_header.public_key_metadata_size;
}
- avb_assert(is_main_vbmeta);
- io_ret = ops->validate_vbmeta_public_key(
- ops, pk_data, pk_len, pk_metadata, pk_metadata_len, &key_is_trusted);
+ // If we're not using a vbmeta partition, need to use another AvbOps...
+ if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
+ io_ret = ops->validate_public_key_for_partition(
+ ops,
+ full_partition_name,
+ pk_data,
+ pk_len,
+ pk_metadata,
+ pk_metadata_len,
+ &key_is_trusted,
+ &rollback_index_location_to_use);
+ } else {
+ avb_assert(is_main_vbmeta);
+ io_ret = ops->validate_vbmeta_public_key(ops,
+ pk_data,
+ pk_len,
+ pk_metadata,
+ pk_metadata_len,
+ &key_is_trusted);
+ }
+
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
@@ -639,7 +666,7 @@
/* Check rollback index. */
io_ret = ops->read_rollback_index(
- ops, rollback_index_location, &stored_rollback_index);
+ ops, rollback_index_location_to_use, &stored_rollback_index);
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
@@ -679,7 +706,9 @@
if (is_main_vbmeta) {
avb_assert(slot_data->num_vbmeta_images == 0);
} else {
- avb_assert(slot_data->num_vbmeta_images > 0);
+ if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
+ avb_assert(slot_data->num_vbmeta_images > 0);
+ }
}
if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
@@ -804,6 +833,7 @@
sub_ret = load_and_verify_vbmeta(ops,
requested_partitions,
ab_suffix,
+ flags,
allow_verification_error,
toplevel_vbmeta_flags,
chain_desc.rollback_index_location,
@@ -1003,6 +1033,16 @@
}
}
+ /* It's possible there is no _PARTUUID for replacement above.
+ * Duplicate cmdline to ret for additional substitutions below.
+ */
+ if (ret == NULL) {
+ ret = avb_strdup(cmdline);
+ if (ret == NULL) {
+ goto fail;
+ }
+ }
+
return ret;
fail:
@@ -1127,6 +1167,7 @@
static AvbSlotVerifyResult append_options(
AvbOps* ops,
+ AvbSlotVerifyFlags flags,
AvbSlotVerifyData* slot_data,
AvbVBMetaImageHeader* toplevel_vbmeta,
AvbAlgorithmType algorithm_type,
@@ -1144,6 +1185,18 @@
goto out;
}
+ /* Add androidboot.vbmeta.device option... except if not using a vbmeta
+ * partition since it doesn't make sense in that case.
+ */
+ if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
+ if (!cmdline_append_option(slot_data,
+ "androidboot.vbmeta.device",
+ "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ }
+ }
+
/* Add androidboot.vbmeta.avb_version option. */
if (!cmdline_append_version(slot_data,
"androidboot.vbmeta.avb_version",
@@ -1334,10 +1387,9 @@
avb_assert(ops->read_is_device_unlocked != NULL);
avb_assert(ops->read_from_partition != NULL);
avb_assert(ops->get_size_of_partition != NULL);
- avb_assert(ops->validate_vbmeta_public_key != NULL);
avb_assert(ops->read_rollback_index != NULL);
avb_assert(ops->get_unique_guid_for_partition != NULL);
- /* avb_assert(ops->get_size_of_partition != NULL); */
+ avb_assert(ops->validate_public_key_for_partition != NULL);
if (out_data != NULL) {
*out_data = NULL;
@@ -1353,6 +1405,21 @@
goto fail;
}
+ /* Make sure passed-in AvbOps support verifying public keys and getting
+ * rollback index location if not using a vbmeta partition.
+ */
+ if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
+ if (ops->validate_public_key_for_partition == NULL) {
+ avb_error(
+ "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION was passed but the "
+ "validate_public_key_for_partition() operation isn't implemented.\n");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto fail;
+ }
+ } else {
+ avb_assert(ops->validate_vbmeta_public_key != NULL);
+ }
+
slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
if (slot_data == NULL) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
@@ -1371,30 +1438,67 @@
goto fail;
}
- ret = load_and_verify_vbmeta(ops,
- requested_partitions,
- ab_suffix,
- allow_verification_error,
- 0 /* toplevel_vbmeta_flags */,
- 0 /* rollback_index_location */,
- "vbmeta",
- avb_strlen("vbmeta"),
- NULL /* expected_public_key */,
- 0 /* expected_public_key_length */,
- slot_data,
- &algorithm_type);
- if ((!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) ||
- !result_should_continue(ret)) {
+ if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
+ if (requested_partitions == NULL || requested_partitions[0] == NULL) {
+ avb_fatal(
+ "Requested partitions cannot be empty when using "
+ "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION");
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
+ goto fail;
+ }
+
+ /* No vbmeta partition, go through each of the requested partitions... */
+ for (size_t n = 0; requested_partitions[n] != NULL; n++) {
+ ret = load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ flags,
+ allow_verification_error,
+ 0 /* toplevel_vbmeta_flags */,
+ 0 /* rollback_index_location */,
+ requested_partitions[n],
+ avb_strlen(requested_partitions[n]),
+ NULL /* expected_public_key */,
+ 0 /* expected_public_key_length */,
+ slot_data,
+ &algorithm_type);
+ if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto fail;
+ }
+ }
+
+ } else {
+ /* Usual path, load "vbmeta"... */
+ ret = load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ flags,
+ allow_verification_error,
+ 0 /* toplevel_vbmeta_flags */,
+ 0 /* rollback_index_location */,
+ "vbmeta",
+ avb_strlen("vbmeta"),
+ NULL /* expected_public_key */,
+ 0 /* expected_public_key_length */,
+ slot_data,
+ &algorithm_type);
+ if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ goto fail;
+ }
+ }
+
+ if (!result_should_continue(ret)) {
goto fail;
}
/* If things check out, mangle the kernel command-line as needed. */
- if (result_should_continue(ret)) {
+ if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
avb_assert(
avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
using_boot_for_vbmeta = true;
}
+ }
/* Byteswap top-level vbmeta header since we'll need it below. */
avb_vbmeta_image_header_to_host_byte_order(
@@ -1437,6 +1541,7 @@
* I/O or OOM error.
*/
AvbSlotVerifyResult sub_ret = append_options(ops,
+ flags,
slot_data,
&toplevel_vbmeta,
algorithm_type,
@@ -1464,7 +1569,6 @@
} else {
avb_slot_verify_data_free(slot_data);
}
- }
if (!allow_verification_error) {
avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
diff --git a/QcomModulePkg/Library/avb/libavb/avb_slot_verify.h b/QcomModulePkg/Library/avb/libavb/avb_slot_verify.h
index 2d460fc..9485e8e 100644
--- a/QcomModulePkg/Library/avb/libavb/avb_slot_verify.h
+++ b/QcomModulePkg/Library/avb/libavb/avb_slot_verify.h
@@ -99,10 +99,21 @@
* contents loaded from |requested_partition| will be the contents of
* the entire partition instead of just the size specified in the hash
* descriptor.
+ *
+ * If the AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION flag is set then
+ * data won't be loaded from the "vbmeta" partition and the
+ * |validate_vbmeta_public_key| operation is never called. Instead, the
+ * vbmeta structs in |requested_partitions| are loaded and processed and the
+ * |validate_public_key_for_partition| operation is called for each of these
+ * vbmeta structs. This flag is useful when booting into recovery on a device
+ * not using A/B - see section "Booting into recovery" in README.md for
+ * more information.
*/
typedef enum {
AVB_SLOT_VERIFY_FLAGS_NONE = 0,
- AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0)
+ AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0),
+ AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION = (1 << 1),
+ AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION = (1 << 2),
} AvbSlotVerifyFlags;
/* Get a textual representation of |result|. */
@@ -215,7 +226,9 @@
* PARTUUID=$(ANDROID_VBMETA_PARTUUID) before substitution so it
* will end up pointing to the vbmeta partition for the verified
* slot. If there is no vbmeta partition it will point to the boot
- * partition of the verified slot.
+ * partition of the verified slot. If the flag
+ * AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is used, this is not
+ * set.
*
* androidboot.vbmeta.avb_version: This is set to the decimal value
* of AVB_VERSION_MAJOR followed by a dot followed by the decimal