summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/commonlib/device_tree.c97
-rw-r--r--src/commonlib/include/commonlib/device_tree.h2
2 files changed, 73 insertions, 26 deletions
diff --git a/src/commonlib/device_tree.c b/src/commonlib/device_tree.c
index 0ec6ea92cd..a8a64ecbbe 100644
--- a/src/commonlib/device_tree.c
+++ b/src/commonlib/device_tree.c
@@ -59,10 +59,49 @@ static struct device_tree_property *alloc_prop(void)
return xzalloc(sizeof(struct device_tree_property));
}
+
+/*
+ * internal functions used by both unflattened and flattened device tree variants
+ */
+
+
+static size_t read_reg_prop(struct fdt_property *prop, u32 addr_cells, u32 size_cells,
+ struct device_tree_region regions[], size_t regions_count)
+{
+ // we found the reg property, no need to parse all regions in 'reg'
+ size_t count = prop->size / (4 * addr_cells + 4 * size_cells);
+ if (count > regions_count) {
+ printk(BIOS_ERR, "reg property has more entries (%zd) than regions array can hold (%zd)\n", count, regions_count);
+ count = regions_count;
+ }
+ if (addr_cells > 2 || size_cells > 2) {
+ printk(BIOS_ERR, "addr_cells (%d) or size_cells (%d) bigger than 2\n",
+ addr_cells, size_cells);
+ return 0;
+ }
+ uint32_t *ptr = prop->data;
+ for (int i = 0; i < count; i++) {
+ if (addr_cells == 1)
+ regions[i].addr = be32dec(ptr);
+ else if (addr_cells == 2)
+ regions[i].addr = be64dec(ptr);
+ ptr += addr_cells;
+ if (size_cells == 1)
+ regions[i].size = be32dec(ptr);
+ else if (size_cells == 2)
+ regions[i].size = be64dec(ptr);
+ ptr += size_cells;
+ }
+
+ return count; // return the number of regions found in the reg property
+}
+
+
/*
* Functions for picking apart flattened trees.
*/
+
static int fdt_skip_nops(const void *blob, uint32_t offset)
{
uint32_t *ptr = (uint32_t *)(((uint8_t *)blob) + offset);
@@ -203,32 +242,7 @@ u32 fdt_read_reg_prop(const void *blob, u32 node_offset, u32 addr_cells, u32 siz
return 0;
}
- // we found the reg property, now need to parse all regions in 'reg'
- size_t count = prop.size / (4 * addr_cells + 4 * size_cells);
- if (count > regions_count) {
- printk(BIOS_ERR, "reg property at node_offset: %x has more entries (%zd) than regions array can hold (%zd)\n", node_offset, count, regions_count);
- count = regions_count;
- }
- if (addr_cells > 2 || size_cells > 2) {
- printk(BIOS_ERR, "addr_cells (%d) or size_cells (%d) bigger than 2\n",
- addr_cells, size_cells);
- return 0;
- }
- uint32_t *ptr = prop.data;
- for (int i = 0; i < count; i++) {
- if (addr_cells == 1)
- regions[i].addr = be32dec(ptr);
- else if (addr_cells == 2)
- regions[i].addr = be64dec(ptr);
- ptr += addr_cells;
- if (size_cells == 1)
- regions[i].size = be32dec(ptr);
- else if (size_cells == 2)
- regions[i].size = be64dec(ptr);
- ptr += size_cells;
- }
-
- return count; // return the number of regions found in the reg property
+ return read_reg_prop(&prop, addr_cells, size_cells, regions, regions_count);
}
static u32 fdt_read_cell_props(const void *blob, u32 node_offset, u32 *addrcp, u32 *sizecp)
@@ -981,6 +995,37 @@ void dt_print_node(const struct device_tree_node *node)
*/
/*
+ * dt_read_reg_prop reads the reg property inside a node
+ *
+ * @params node device tree node to read reg property from
+ * @params addr_cells number of cells used for one address
+ * @params size_cells number of cells used for one size
+ * @params regions all regions that are read inside the reg property are saved inside
+ * this array
+ * @params regions_count maximum number of entries that can be saved inside the regions array.
+ *
+ * Returns: Either 0 on error or returns the number of regions put into the regions array.
+ */
+size_t dt_read_reg_prop(struct device_tree_node *node, u32 addr_cells, u32 size_cells,
+ struct device_tree_region regions[], size_t regions_count)
+{
+ struct device_tree_property *prop;
+ bool found = false;
+ list_for_each(prop, node->properties, list_node) {
+ if (!strcmp("reg", prop->prop.name)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ printk(BIOS_DEBUG, "no reg property found\n");
+ return 0;
+ }
+ return read_reg_prop(&prop->prop, addr_cells, size_cells, regions, regions_count);
+}
+
+/*
* Read #address-cells and #size-cells properties from a node.
*
* @param node The device tree node to read from.
diff --git a/src/commonlib/include/commonlib/device_tree.h b/src/commonlib/include/commonlib/device_tree.h
index 81377fa9df..c15d7ae5b1 100644
--- a/src/commonlib/include/commonlib/device_tree.h
+++ b/src/commonlib/include/commonlib/device_tree.h
@@ -147,6 +147,8 @@ uint32_t dt_flat_size(const struct device_tree *tree);
/* Flatten a device tree into the buffer pointed to by dest. */
void dt_flatten(const struct device_tree *tree, void *dest);
void dt_print_node(const struct device_tree_node *node);
+size_t dt_read_reg_prop(struct device_tree_node *node, u32 addr_cells, u32 size_cells,
+ struct device_tree_region regions[], size_t regions_count);
/* Read #address-cells and #size-cells properties from a node. */
void dt_read_cell_props(const struct device_tree_node *node, u32 *addrcp,
u32 *sizecp);