feat(uuids): add support for multiple UUIDs per partition
Add manifest parsing, population of load-time data structures,
and manifest unit tests needed for supporting usage of multiple
UUIDs per partition.
This patch does not add support to ffa_partition_info_get
for discovery of multiple UUIDs/partition. That will be
addressed in a subsequent patch and for now, only the first
UUID for a partition is reported in the partition info
descriptors.
Signed-off-by: Kathleen Capella <kathleen.capella@arm.com>
Change-Id: I23f6c21dfab2c24cb4a3f7e664616b7bd183b88d
diff --git a/src/api.c b/src/api.c
index 0e97c09..547b3f8 100644
--- a/src/api.c
+++ b/src/api.c
@@ -516,7 +516,8 @@
for (ffa_vm_count_t index = 0; index < vm_get_count(); ++index) {
struct vm *vm = vm_find_index(index);
- if (uuid_is_null || ffa_uuid_equal(uuid, &vm->uuid)) {
+ /*TODO fix logic to search through all uuids */
+ if (uuid_is_null || ffa_uuid_equal(uuid, &vm->uuids[0])) {
uint16_t array_index = vm_count;
++vm_count;
@@ -535,7 +536,7 @@
partitions[array_index].properties |=
FFA_PARTITION_AARCH64_EXEC;
if (uuid_is_null) {
- partitions[array_index].uuid = vm->uuid;
+ partitions[array_index].uuid = vm->uuids[0];
}
}
}
@@ -2584,11 +2585,24 @@
struct ffa_value args)
{
struct ffa_uuid target_uuid;
+ uint16_t i;
ffa_uuid_unpack_from_uint64(args.arg2, args.arg3, &target_uuid);
- return (ffa_uuid_is_null(&target_uuid) ||
- ffa_uuid_equal(&target_uuid, &receiver_vm->uuid));
+ /* Allow for use of Nil UUID. */
+ if (ffa_uuid_is_null(&target_uuid)) {
+ return true;
+ }
+
+ for (i = 0; i < PARTITION_MAX_UUIDS; i++) {
+ if (ffa_uuid_is_null(&receiver_vm->uuids[i])) {
+ break;
+ }
+ if (ffa_uuid_equal(&target_uuid, &receiver_vm->uuids[i])) {
+ return true;
+ }
+ }
+ return false;
}
/**
diff --git a/src/load.c b/src/load.c
index 1453219..59c3f1c 100644
--- a/src/load.c
+++ b/src/load.c
@@ -168,10 +168,20 @@
uint32_t k = 0;
vm_locked.vm->smc_whitelist = manifest_vm->smc_whitelist;
- vm_locked.vm->uuid = manifest_vm->partition.uuid;
vm_locked.vm->power_management =
manifest_vm->partition.power_management;
+ /* Populate array of UUIDs. */
+ for (uint16_t i = 0; i < PARTITION_MAX_UUIDS; i++) {
+ struct ffa_uuid current_uuid = manifest_vm->partition.uuids[i];
+
+ if (ffa_uuid_is_null(¤t_uuid)) {
+ break;
+ }
+
+ vm_locked.vm->uuids[i] = current_uuid;
+ }
+
/* Populate the interrupt descriptor for current VM. */
for (uint16_t i = 0; i < PARTITION_MAX_DEVICE_REGIONS; i++) {
dev_region = manifest_vm->partition.dev_regions[i];
diff --git a/src/manifest.c b/src/manifest.c
index 6be414a..5fbd87c 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -1000,6 +1000,7 @@
struct fdt_node *boot_info_node, const struct boot_params *boot_params)
{
unsigned int i = 0;
+ unsigned int j = 0;
struct uint32list_iter uuid;
uint32_t uuid_word;
struct fdt_node root;
@@ -1021,14 +1022,27 @@
TRY(read_uint32list(&root, "uuid", &uuid));
- while (uint32list_has_next(&uuid) && i < 4) {
- TRY(uint32list_get_next(&uuid, &uuid_word));
- vm->partition.uuid.uuid[i] = uuid_word;
- i++;
+ while (uint32list_has_next(&uuid) && j < PARTITION_MAX_UUIDS) {
+ while (uint32list_has_next(&uuid) && i < 4) {
+ TRY(uint32list_get_next(&uuid, &uuid_word));
+ vm->partition.uuids[j].uuid[i] = uuid_word;
+ i++;
+ }
+
+ if (ffa_uuid_is_null(&vm->partition.uuids[j])) {
+ return MANIFEST_ERROR_UUID_ALL_ZEROS;
+ }
+ dlog_verbose(" UUID %#x-%x-%x-%x\n",
+ vm->partition.uuids[j].uuid[0],
+ vm->partition.uuids[j].uuid[1],
+ vm->partition.uuids[j].uuid[2],
+ vm->partition.uuids[j].uuid[3]);
+ j++;
+ i = 0;
}
- dlog_verbose("UUID %#x-%x-%x-%x\n", vm->partition.uuid.uuid[0],
- vm->partition.uuid.uuid[1], vm->partition.uuid.uuid[2],
- vm->partition.uuid.uuid[3]);
+
+ vm->partition.uuid_count = j;
+ dlog_verbose(" Number of UUIDs %u\n", vm->partition.uuid_count);
TRY(read_uint32(&root, "ffa-version", &vm->partition.ffa_version));
dlog_verbose(" Expected FF-A version %u.%u\n",
@@ -1275,7 +1289,7 @@
manifest_address = va_add(va_init(load_address), header.pm_offset);
if (!fdt_init_from_ptr(&sp_fdt, ptr_from_va(manifest_address),
header.pm_size)) {
- dlog_error("FDT failed validation.\n");
+ dlog_error("manifest.c: FDT failed validation.\n");
goto out;
}
@@ -1514,6 +1528,8 @@
case MANIFEST_ERROR_INVALID_BOOT_ORDER:
return "Boot order should be a unique value less than "
"default largest value";
+ case MANIFEST_ERROR_UUID_ALL_ZEROS:
+ return "UUID should not be NIL";
}
panic("Unexpected manifest return code.");
diff --git a/src/manifest_test.cc b/src/manifest_test.cc
index 1adaa0e..427922d 100644
--- a/src/manifest_test.cc
+++ b/src/manifest_test.cc
@@ -1680,7 +1680,7 @@
vm = &m->vm[0];
ASSERT_EQ(vm->partition.ffa_version, 0x10000);
ASSERT_THAT(
- std::span(vm->partition.uuid.uuid, 4),
+ std::span(vm->partition.uuids[0].uuid, 4),
ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
ASSERT_EQ(vm->partition.execution_ctx_count, 1);
ASSERT_EQ(vm->partition.run_time_el, S_EL1);
@@ -1860,4 +1860,69 @@
ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, ¶ms, &ppool),
MANIFEST_ERROR_INVALID_BOOT_ORDER);
}
+TEST_F(manifest, ffa_valid_multiple_uuids)
+{
+ struct manifest_vm *vm;
+ struct_manifest *m;
+
+ /* clang-format off */
+ std::vector<char> dtb = ManifestDtBuilder()
+ .Compatible({ "arm,ffa-manifest-1.0" })
+ .Property("ffa-version", "<0x10002>")
+ .Property("uuid",
+ "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,\
+ <0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
+ .Property("execution-ctx-count", "<1>")
+ .Property("exception-level", "<2>")
+ .Property("execution-state", "<0>")
+ .Property("entrypoint-offset", "<0x00002000>")
+ .Property("xlat-granule", "<0>")
+ .Property("boot-order", "<0>")
+ .Property("messaging-method", "<4>")
+ .Property("ns-interrupts-action", "<1>")
+ .Build();
+ /* clang-format on */
+ ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
+
+ vm = &m->vm[0];
+ ASSERT_EQ(vm->partition.ffa_version, 0x10002);
+ ASSERT_THAT(
+ std::span(vm->partition.uuids[0].uuid, 4),
+ ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
+ ASSERT_THAT(
+ std::span(vm->partition.uuids[1].uuid, 4),
+ ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1daaa));
+ ASSERT_EQ(vm->partition.uuid_count, 2);
+ ASSERT_EQ(vm->partition.execution_ctx_count, 1);
+ ASSERT_EQ(vm->partition.run_time_el, S_EL1);
+ ASSERT_EQ(vm->partition.execution_state, AARCH64);
+ ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
+ ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
+ ASSERT_EQ(vm->partition.boot_order, 0);
+ ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
+ ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
+}
+TEST_F(manifest, ffa_uuid_all_zeros)
+{
+ struct_manifest *m;
+
+ /* clang-format off */
+ std::vector<char> dtb = ManifestDtBuilder()
+ .Compatible({ "arm,ffa-manifest-1.0" })
+ .Property("ffa-version", "<0x10002>")
+ .Property("uuid",
+ "<0x0 0x0 0x0 0x0>, <0x0 0x0 0x0 0x0>")
+ .Property("execution-ctx-count", "<1>")
+ .Property("exception-level", "<2>")
+ .Property("execution-state", "<0>")
+ .Property("entrypoint-offset", "<0x00002000>")
+ .Property("xlat-granule", "<0>")
+ .Property("boot-order", "<0>")
+ .Property("messaging-method", "<4>")
+ .Property("ns-interrupts-action", "<1>")
+ .Build();
+ /* clang-format on */
+ ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
+ MANIFEST_ERROR_UUID_ALL_ZEROS);
+}
} /* namespace */