summaryrefslogtreecommitdiff
path: root/na
diff options
context:
space:
mode:
Diffstat (limited to 'na')
-rw-r--r--na/include/lume/device_node.h64
-rw-r--r--na/include/lume/fdt.h81
-rw-r--r--na/include/lume/fdt_prop.h24
3 files changed, 169 insertions, 0 deletions
diff --git a/na/include/lume/device_node.h b/na/include/lume/device_node.h
new file mode 100644
index 0000000..14b4a9c
--- /dev/null
+++ b/na/include/lume/device_node.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2026 Richard Qin */
+
+#pragma once
+
+/*
+ * DeviceNode — FDT object tree node
+ *
+ * Each DeviceNode represents a single node in the unflattened device tree.
+ * Nodes form a parent-children hierarchy via intrusive linked lists.
+ * After unflattening, the tree is globally read-only and requires no locks.
+ *
+ * Created during Phase 2 (fdt_unflatten) when Slab is available.
+ *
+ * Reference: docs/specs/fdt.md §3.2
+ */
+
+#include <lume/types.h>
+#include <lume/list.h>
+#include <lume/fdt_prop.h>
+
+class DeviceNode {
+public:
+ // Construction / destruction (used by FdtManager::unflatten)
+ DeviceNode(DeviceNode *parent, const char *name);
+ ~DeviceNode();
+
+ // --- Property access ---
+
+ // Look up a property by name. Returns nullptr if not found.
+ const FdtProperty *get_prop(const char *name) const;
+
+ // Convenience helpers that decode the property value.
+ // Return default_val when the property does not exist.
+ uint32 get_prop_u32(const char *name, uint32 default_val = 0) const;
+ uint64 get_prop_u64(const char *name, uint64 default_val = 0) const;
+ const char *get_prop_string(const char *name) const;
+
+ // --- Child traversal ---
+
+ // Find a direct child by name. Returns nullptr if not found.
+ DeviceNode *find_child(const char *name);
+
+ // Invoke callback for every direct child.
+ void for_each_child(void (*callback)(DeviceNode *));
+
+ // --- Internal (used by FdtManager to build the tree) ---
+ void add_child(DeviceNode *child);
+ void add_prop(FdtProperty *prop);
+
+ // --- Accessors for tree traversal ---
+ const char *get_name() const { return name_; }
+ list_node *children_list_head() { return children_list_.next; }
+ list_node *children_list_sentinel() { return &children_list_; }
+
+ // sibling_link_ offset needed by container_of in fdt.cc
+ list_node sibling_link_; // Link in parent's children_list_
+
+private:
+ const char *name_; // Node name (e.g. "memory@80000000")
+ DeviceNode *parent_; // Parent node (nullptr for root)
+ list_node children_list_; // Head of the children linked list
+ list_node props_list_; // Head of the property linked list
+};
diff --git a/na/include/lume/fdt.h b/na/include/lume/fdt.h
new file mode 100644
index 0000000..8da223c
--- /dev/null
+++ b/na/include/lume/fdt.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2026 Richard Qin */
+
+#pragma once
+
+/*
+ * FdtManager — Flattened Device Tree parser
+ *
+ * Two-phase design:
+ * Phase 1 (Early Scan): Static methods that walk the raw FDT blob
+ * without any memory allocation. Used before PMM is available.
+ * Phase 2 (Unflatten): Builds a persistent C++ DeviceNode object
+ * tree once Slab is ready. The tree is then globally read-only.
+ *
+ * Concurrency: all init is done by BSP in the single-core window.
+ * After unflattening the tree is immutable — no locks required.
+ *
+ * Reference: docs/specs/fdt.md
+ */
+
+#include <lume/types.h>
+#include <lume/device_node.h>
+
+class FdtManager {
+public:
+ // Construct with the physical address of the FDT blob.
+ // Called via Placement New in fdt_init().
+ FdtManager(uint64 fdt_paddr);
+
+ // --- Phase 1: Early scan (static, allocation-free) ---
+
+ // Extract physical memory base and size from the /memory node.
+ // Panics if the FDT is invalid or /memory is missing.
+ static void early_scan_mem(uint64 fdt_paddr, uint64 *base, uint64 *size);
+
+ // Extract the UART base address by matching compatible = "ns16550a".
+ // Falls back to platform default (0x10000000) on failure.
+ static void early_scan_uart(uint64 fdt_paddr, uint64 *uart_addr);
+
+ // --- Phase 2: Object tree construction (requires Slab) ---
+
+ // Walk the FDT blob and build the DeviceNode tree.
+ void unflatten();
+
+ // --- Query interface (read-only after unflatten) ---
+
+ // Find the first node whose "compatible" property contains the string.
+ // Returns nullptr if no match.
+ DeviceNode *find_compatible(const char *compat_string);
+
+ // Look up a node by its full path (e.g. "/soc/uart@10000000").
+ // Returns nullptr if not found.
+ DeviceNode *get_node_by_path(const char *path);
+
+ // Return the stored FDT physical address.
+ uint64 get_paddr() const { return fdt_paddr_; }
+
+private:
+ uint64 fdt_paddr_; // Physical address of the FDT blob
+ bool is_unflattened_ = false; // True after unflatten() completes
+ DeviceNode *root_ = nullptr; // Root of the unflattened tree
+};
+
+/* Global FDT manager singleton (Placement New, see global_init.md §3.1) */
+extern FdtManager *g_fdt;
+
+// --- Public free-function API ---
+
+// Save FDT address and validate magic. Called early by BSP.
+void fdt_init(uint64 fdt_paddr);
+
+// Build the DeviceNode object tree. Requires Slab.
+void fdt_unflatten();
+
+// Driver probing helpers (delegate to g_fdt).
+DeviceNode *fdt_find_compatible(const char *compat_string);
+DeviceNode *fdt_get_node_by_path(const char *path);
+
+// Early scan wrappers (delegate to FdtManager static methods).
+void fdt_early_get_mem_info(uint64 *base, uint64 *size);
+void fdt_early_get_uart_info(uint64 *uart_addr);
diff --git a/na/include/lume/fdt_prop.h b/na/include/lume/fdt_prop.h
new file mode 100644
index 0000000..f8a263c
--- /dev/null
+++ b/na/include/lume/fdt_prop.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2026 Richard Qin */
+
+#pragma once
+
+/*
+ * FDT Property
+ *
+ * Represents a single property within a DeviceNode (e.g. "reg",
+ * "compatible"). The value pointer points directly into the
+ * original FDT blob — no copies are made.
+ *
+ * Reference: docs/specs/fdt.md §3.1
+ */
+
+#include <lume/types.h>
+#include <lume/list.h>
+
+struct FdtProperty {
+ const char *name; // Property name (points into FDT strings block)
+ const void *value; // Raw property data (points into FDT struct block)
+ int len; // Length of value in bytes
+ list_node link; // Intrusive link into DeviceNode's property list
+};