diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-04-21 23:11:19 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-04-21 23:11:19 +0800 |
| commit | 23fc4a0d6e57eb74248da8fb22d8c6a9d99f69c3 (patch) | |
| tree | 3787ce309e21c00e0615b1c59eaa4d70ce4f908e /na | |
| parent | de1e83c0a9e53b5549898083ef495878aaaf50b2 (diff) | |
| download | lume-23fc4a0d6e57eb74248da8fb22d8c6a9d99f69c3.tar.gz lume-23fc4a0d6e57eb74248da8fb22d8c6a9d99f69c3.tar.xz | |
feat: add DeviceNode, FdtManager, and FdtProperty classes for device tree management
Diffstat (limited to 'na')
| -rw-r--r-- | na/include/lume/device_node.h | 64 | ||||
| -rw-r--r-- | na/include/lume/fdt.h | 81 | ||||
| -rw-r--r-- | na/include/lume/fdt_prop.h | 24 |
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 +}; |
