summaryrefslogtreecommitdiffstats
path: root/sys/dev/fdt
diff options
context:
space:
mode:
authorgonzo <gonzo@FreeBSD.org>2012-11-30 03:08:49 +0000
committergonzo <gonzo@FreeBSD.org>2012-11-30 03:08:49 +0000
commitd948e0882e798da2fb0f38e973079ae7839f2115 (patch)
treedfbf5aaca3ed3e3634d721421c377d441b2d267e /sys/dev/fdt
parentd2c9c61563d322702376b7c7cf487f8df07a5f67 (diff)
downloadFreeBSD-src-d948e0882e798da2fb0f38e973079ae7839f2115.zip
FreeBSD-src-d948e0882e798da2fb0f38e973079ae7839f2115.tar.gz
Add fdt_get_reserved_regions function. API is simmilar to fdt_get_mem_regions
It returns memory regions restricted from being used by kernel. These regions are dfined in "memreserve" property of root node in the same format as "reg" property of /memory node
Diffstat (limited to 'sys/dev/fdt')
-rw-r--r--sys/dev/fdt/fdt_common.c60
-rw-r--r--sys/dev/fdt/fdt_common.h1
2 files changed, 61 insertions, 0 deletions
diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c
index 706396b..e1913c1 100644
--- a/sys/dev/fdt/fdt_common.c
+++ b/sys/dev/fdt/fdt_common.c
@@ -634,6 +634,66 @@ fdt_get_phyaddr(phandle_t node, device_t dev, int *phy_addr, void **phy_sc)
}
int
+fdt_get_reserved_regions(struct mem_region *mr, int *mrcnt)
+{
+ pcell_t reserve[FDT_REG_CELLS * FDT_MEM_REGIONS];
+ pcell_t *reservep;
+ phandle_t memory, root;
+ uint32_t memory_size;
+ int addr_cells, size_cells;
+ int i, max_size, res_len, rv, tuple_size, tuples;
+
+ max_size = sizeof(reserve);
+ root = OF_finddevice("/");
+ memory = OF_finddevice("/memory");
+ if (memory == -1) {
+ rv = ENXIO;
+ goto out;
+ }
+
+ if ((rv = fdt_addrsize_cells(OF_parent(memory), &addr_cells,
+ &size_cells)) != 0)
+ goto out;
+
+ if (addr_cells > 2) {
+ rv = ERANGE;
+ goto out;
+ }
+
+ tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
+
+ res_len = OF_getproplen(root, "memreserve");
+ if (res_len <= 0 || res_len > sizeof(reserve)) {
+ rv = ERANGE;
+ goto out;
+ }
+
+ if (OF_getprop(root, "memreserve", reserve, res_len) <= 0) {
+ rv = ENXIO;
+ goto out;
+ }
+
+ memory_size = 0;
+ tuples = res_len / tuple_size;
+ reservep = (pcell_t *)&reserve;
+ for (i = 0; i < tuples; i++) {
+
+ rv = fdt_data_to_res(reservep, addr_cells, size_cells,
+ (u_long *)&mr[i].mr_start, (u_long *)&mr[i].mr_size);
+
+ if (rv != 0)
+ goto out;
+
+ reservep += addr_cells + size_cells;
+ }
+
+ *mrcnt = i;
+ rv = 0;
+out:
+ return (rv);
+}
+
+int
fdt_get_mem_regions(struct mem_region *mr, int *mrcnt, uint32_t *memsize)
{
pcell_t reg[FDT_REG_CELLS * FDT_MEM_REGIONS];
diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h
index 4761cd7..68e3708 100644
--- a/sys/dev/fdt/fdt_common.h
+++ b/sys/dev/fdt/fdt_common.h
@@ -90,6 +90,7 @@ int fdt_data_to_res(pcell_t *, int, int, u_long *, u_long *);
int fdt_data_verify(void *, int);
phandle_t fdt_find_compatible(phandle_t, const char *, int);
int fdt_get_mem_regions(struct mem_region *, int *, uint32_t *);
+int fdt_get_reserved_regions(struct mem_region *, int *);
int fdt_get_phyaddr(phandle_t, device_t, int *, void **);
int fdt_get_range(phandle_t, int, u_long *, u_long *);
int fdt_immr_addr(vm_offset_t);
OpenPOWER on IntegriCloud