feat(manifest): parse relative addresses in memory regions
FF-A v.1. REL0 Table 5.2 specifies that memory regions can use base
address, or relative offset.
This patch updates the manifest parser to parse a new, optional
`relative-address` property in memory regions.
Change-Id: I0a2396b41de660f98e6a96c6da7097b2db843648
Signed-off-by: Karl Meakin <karl.meakin@arm.com>
diff --git a/src/manifest.c b/src/manifest.c
index 9a87ed4..9de465d 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -533,12 +533,13 @@
}
static enum manifest_return_code parse_ffa_memory_region_node(
- struct fdt_node *mem_node, struct memory_region *mem_regions,
- uint16_t *count, struct rx_tx *rxtx,
+ struct fdt_node *mem_node, uintptr_t load_address,
+ struct memory_region *mem_regions, uint16_t *count, struct rx_tx *rxtx,
const struct boot_params *boot_params)
{
uint32_t phandle;
uint16_t i = 0;
+ uintptr_t relative_address;
dlog_verbose(" Partition memory regions\n");
@@ -558,11 +559,38 @@
dlog_verbose(" Name: %s\n",
string_data(&mem_regions[i].name));
- TRY(read_uint64(mem_node, "base-address",
- &mem_regions[i].base_address));
+ TRY(read_optional_uint64(mem_node, "base-address",
+ MANIFEST_INVALID_ADDRESS,
+ &mem_regions[i].base_address));
dlog_verbose(" Base address: %#x\n",
mem_regions[i].base_address);
+ TRY(read_optional_uint64(mem_node, "relative-address",
+ MANIFEST_INVALID_ADDRESS,
+ &relative_address));
+ dlog_verbose(" Relative address: %#x\n",
+ relative_address);
+
+ if (mem_regions[i].base_address == MANIFEST_INVALID_ADDRESS &&
+ relative_address == MANIFEST_INVALID_ADDRESS) {
+ return MANIFEST_ERROR_PROPERTY_NOT_FOUND;
+ }
+
+ if (mem_regions[i].base_address != MANIFEST_INVALID_ADDRESS &&
+ relative_address != MANIFEST_INVALID_ADDRESS) {
+ return MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS;
+ }
+
+ if (relative_address != MANIFEST_INVALID_ADDRESS &&
+ relative_address > UINT64_MAX - load_address) {
+ return MANIFEST_ERROR_INTEGER_OVERFLOW;
+ }
+
+ if (relative_address != MANIFEST_INVALID_ADDRESS) {
+ mem_regions[i].base_address =
+ load_address + relative_address;
+ }
+
TRY(read_uint32(mem_node, "pages-count",
&mem_regions[i].page_count));
dlog_verbose(" Pages_count: %u\n",
@@ -1122,7 +1150,8 @@
ffa_node = root;
if (fdt_find_child(&ffa_node, &mem_region_node_name)) {
TRY(parse_ffa_memory_region_node(
- &ffa_node, vm->partition.mem_regions,
+ &ffa_node, vm->partition.load_addr,
+ vm->partition.mem_regions,
&vm->partition.mem_region_count, &vm->partition.rxtx,
boot_params));
}
@@ -1394,6 +1423,8 @@
return "RX and TX buffers should be of same size";
case MANIFEST_ERROR_MEM_REGION_EMPTY:
return "Memory region should have at least one page";
+ case MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS:
+ return "Base and relative addresses are mutually exclusive";
case MANIFEST_ERROR_MEM_REGION_OVERLAP:
return "Memory region overlaps with one already allocated";
case MANIFEST_ERROR_MEM_REGION_UNALIGNED: