The branch main has been updated by andrew:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=0593e4110639d1a84bd7fd785f056998fe8df7e8

commit 0593e4110639d1a84bd7fd785f056998fe8df7e8
Author:     Andrew Turner <and...@freebsd.org>
AuthorDate: 2025-04-08 10:30:09 +0000
Commit:     Andrew Turner <and...@freebsd.org>
CommitDate: 2025-04-08 10:48:27 +0000

    dev/fdt: Add fdt_foreach_mem_region
    
    This is used early in the boot to find physical memory. Previously it
    needed an array of memory regions to be passed in. We keep finding
    hardware where this array is too small causing the kernel to smash the
    stack.
    
    Replace with a function that takes a callback that can insert the
    memory into the physical map directly.
    
    Reviewed by:    imp
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D49697
---
 sys/dev/fdt/fdt_common.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/fdt/fdt_common.h |  3 +++
 2 files changed, 50 insertions(+)

diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c
index 85d9061759c4..6c505ac2cd7c 100644
--- a/sys/dev/fdt/fdt_common.c
+++ b/sys/dev/fdt/fdt_common.c
@@ -540,6 +540,53 @@ fdt_get_reserved_mem(struct mem_region *reserved, int 
*mreserved)
        return (0);
 }
 
+int
+fdt_foreach_mem_region(fdt_mem_region_cb cb, void *arg)
+{
+       struct mem_region mr;
+       pcell_t reg[FDT_REG_CELLS * FDT_MEM_REGIONS];
+       pcell_t *regp;
+       phandle_t memory;
+       int addr_cells, size_cells;
+       int i, reg_len, rv, tuple_size, tuples;
+
+       memory = OF_finddevice("/memory");
+       if (memory == -1)
+               return (ENXIO);
+
+       if ((rv = fdt_addrsize_cells(OF_parent(memory), &addr_cells,
+           &size_cells)) != 0)
+               return (rv);
+
+       if (addr_cells > 2)
+               return (ERANGE);
+
+       tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
+       reg_len = OF_getproplen(memory, "reg");
+       if (reg_len <= 0 || reg_len > sizeof(reg))
+               return (ERANGE);
+
+       if (OF_getprop(memory, "reg", reg, reg_len) <= 0)
+               return (ENXIO);
+
+       tuples = reg_len / tuple_size;
+       regp = (pcell_t *)&reg;
+       for (i = 0; i < tuples; i++) {
+
+               rv = fdt_data_to_res(regp, addr_cells, size_cells,
+                       (u_long *)&mr.mr_start, (u_long *)&mr.mr_size);
+
+               if (rv != 0)
+                       return (rv);
+
+               cb(&mr, arg);
+
+               regp += addr_cells + size_cells;
+       }
+
+       return (0);
+}
+
 int
 fdt_get_mem_regions(struct mem_region *mr, int *mrcnt, uint64_t *memsize)
 {
diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h
index d19dc5c359a7..f450d976dfe0 100644
--- a/sys/dev/fdt/fdt_common.h
+++ b/sys/dev/fdt/fdt_common.h
@@ -76,11 +76,14 @@ extern u_char fdt_static_dtb;
 
 SYSCTL_DECL(_hw_fdt);
 
+typedef void (*fdt_mem_region_cb)(const struct mem_region *, void *);
+
 int fdt_addrsize_cells(phandle_t, int *, int *);
 u_long fdt_data_get(void *, int);
 int fdt_data_to_res(pcell_t *, int, int, u_long *, u_long *);
 phandle_t fdt_find_compatible(phandle_t, const char *, int);
 phandle_t fdt_depth_search_compatible(phandle_t, const char *, int);
+int fdt_foreach_mem_region(fdt_mem_region_cb, void *);
 int fdt_get_mem_regions(struct mem_region *, int *, uint64_t *);
 int fdt_get_reserved_mem(struct mem_region *, int *);
 int fdt_get_reserved_regions(struct mem_region *, int *);

Reply via email to