:: commit af488d66c842523b6e3c197179c9f2df1952de9b

Marvin Friedrich <contact@marvinf.com> — 2024-10-18 19:29

parents: 6d2995a3f1

protos/limine: Filter `memory@...` nodes from device trees (#421)

* protos/limine: Filter `memory@...` nodes from device trees

* docs: Mention removal of `memory@...` nodes for the DTB response
diff --git a/PROTOCOL.md b/PROTOCOL.md
index 6efcaa96..e8bc800b 100644
--- a/PROTOCOL.md
+++ b/PROTOCOL.md
@@ -1289,3 +1289,6 @@ Note: If the DTB cannot be found, the response will *not* be generated.
 
 Note: Information contained in the `/chosen` node may not reflect the information
 given by bootloader tags, and as such the `/chosen` node properties should be ignored.
+
+Note: If the DTB contained `memory@...` nodes, they will get removed.
+Kernels may not rely on these nodes and should use the Memory Map feature instead.
diff --git a/common/protos/limine.c b/common/protos/limine.c
index 600b1b31..bcc95cf5 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -12,6 +12,8 @@
 #include <lib/real.h>
 #include <lib/libc.h>
 #include <lib/gterm.h>
+#include <lib/fdt.h>
+#include <libfdt/libfdt.h>
 #include <lib/uri.h>
 #include <sys/smp.h>
 #include <sys/cpu.h>
@@ -1017,6 +1019,25 @@ FEAT_START
     }
 
     if (dtb) {
+        // Delete all /memory@... nodes.
+        // The kernel must use the given UEFI memory map instead.
+        while (true) {
+            int offset = fdt_subnode_offset_namelen(dtb, 0, "memory@", 7);
+
+            if (offset == -FDT_ERR_NOTFOUND) {
+                break;
+            }
+
+            if (offset < 0) {
+                panic(true, "limine: failed to find node: '%s'", fdt_strerror(offset));
+            }
+
+            int ret = fdt_del_node(dtb, offset);
+            if (ret < 0) {
+                panic(true, "limine: failed to delete memory node: '%s'", fdt_strerror(ret));
+            }
+        }
+
         struct limine_dtb_response *dtb_response =
             ext_mem_alloc(sizeof(struct limine_dtb_response));
         dtb_response->dtb_ptr = reported_addr(dtb);
diff --git a/test/device_tree.dts b/test/device_tree.dts
index 268de0ff..8e981e97 100644
--- a/test/device_tree.dts
+++ b/test/device_tree.dts
@@ -4,9 +4,13 @@
 
 / {
     soc {
-        limine_node: limine-node@deadbeef {
+        limine_node: limine@deadbeef {
             reg = <0xdeadbeef 0x1000>;
             label = "KANKER";
         };
+        fake_memory: memory@ffff0000 {
+            reg = <0xffff0000 0xffff>;
+            label = "This node will be removed by Limine.";
+        };
     };
 };
tab: 248 wrap: offon