summaryrefslogtreecommitdiff
path: root/docs/specs/fdt.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/specs/fdt.md')
-rw-r--r--docs/specs/fdt.md191
1 files changed, 0 insertions, 191 deletions
diff --git a/docs/specs/fdt.md b/docs/specs/fdt.md
deleted file mode 100644
index 2a1d542..0000000
--- a/docs/specs/fdt.md
+++ /dev/null
@@ -1,191 +0,0 @@
-# 设备树 (Flattened Device Tree)
-
-## 1. 目标 (Objective)
-
-为 LumeOS 提供一套标准的硬件发现与配置机制,彻底摆脱硬编码的物理地址。本模块负责解析由 Bootloader 传入的 FDT 二进制数据,并分两个阶段将其转化为内核可用的数据结构:
-
-1. **早期扫描 (Early Scan):** 在内存管理(PMM)初始化之前,以只读、无分配的方式扫描 FDT,提取启动所必需的核心信息(如物理内存布局)。
-2. **对象化展开 (Unflattening):** 在内存管理(PMM/Slab)就绪后,将完整的 FDT 解析为一个常驻内存的 C++ `DeviceNode` 对象树,为后续的驱动探测(Driver Probing)提供面向对象的接口。
-
-## 2. 前置依赖 (Dependencies)
-
-- **引导协议契约 (`linker_and_entry.md`):** 依赖 Bootloader 在跳转至内核时,将 FDT 的物理基址置于 `a1` 寄存器。
-- **全局初始化契约 (`global_init.md`):** `fdt_init()` 在 `console_init()` 之后、`pmm_init()` 之前被 BSP 调用。`pmm_init()` 自身会回调 FDT 的早期扫描接口。
-- **内存管理契约 (`pmm.md`, `slab.md`):** 对象化展开阶段依赖 Slab 分配器(`operator new`)来动态创建 `DeviceNode` 对象。
-- **项目约定 (`00_conventions.md`):** 遵循所有命名、错误处理和 API 设计规范。
-
-## 3. 核心数据结构 (Data Structures)
-
-### 3.1 FDT 属性 (`struct FdtProperty`)
-
-表示设备节点中的一个属性(如 `reg`, `compatible`)。
-
-```cpp
-// 定义于 include/lume/fdt_prop.h
-struct FdtProperty {
- const char* name; // 属性名
- const void* value; // 指向 FDT blob 中原始数据的指针
- int len; // 数据长度(字节)
- list_node link; // 链接到下一个属性
-};
-```
-
-### 3.2 设备节点 (`class DeviceNode`)
-
-FDT 对象树的核心,代表一个硬件设备或总线。
-
-```cpp
-// 定义于 include/lume/device_node.h
-class DeviceNode {
-public:
- // 构造/析构
- DeviceNode(DeviceNode* parent, const char* name);
- ~DeviceNode();
-
- // 属性访问
- const FdtProperty* get_prop(const char* name) const;
- uint32_t get_prop_u32(const char* name, uint32_t 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;
-
- // 子节点遍历
- DeviceNode* find_child(const char* name);
- void for_each_child(void (*callback)(DeviceNode*));
-
- // 内部接口,供 FdtManager 构建树时使用
- void add_child(DeviceNode* child);
- void add_prop(FdtProperty* prop);
-
-private:
- const char* name_;
- DeviceNode* parent_;
- list_node children_list_; // list_head of children
- list_node props_list_; // list_head of properties
- list_node sibling_link_; // link in parent's children_list_
-};
-```
-
-### 3.3 FDT 管理器 (`class FdtManager`)
-
-全局单例,负责 FDT 的解析与查询。
-
-```cpp
-// 定义于 include/lume/fdt.h
-class FdtManager {
-public:
- // 由 fdt_init() 通过 Placement New 调用
- FdtManager(uint64 fdt_paddr);
-
- // 阶段二:对象化展开
- void unflatten();
-
- // 驱动探测接口
- DeviceNode* find_compatible(const char* compat_string);
- DeviceNode* get_node_by_path(const char* path);
-
- // 阶段一:早期扫描接口 (静态,无状态)
- static void early_scan_mem(uint64 fdt_paddr, uint64* base, uint64* size);
- static void early_scan_uart(uint64 fdt_paddr, uint64* uart_addr);
-
-private:
- uint64 fdt_paddr_;
- DeviceNode* root_ = nullptr;
- bool is_unflattened_ = false;
-};
-
-// 全局 FDT 管理器实例指针
-extern FdtManager* g_fdt;
-```
-
-## 4. 公共 API (Public APIs)
-
-```cpp
-// === 初始化 API (由 kernel_main 调用) ===
-
-// 阶段一和阶段二的入口。仅保存 FDT 地址,真正的解析被推迟。
-void fdt_init(uint64 fdt_paddr);
-
-// 在 Slab 就绪后调用,执行对象化展开。
-void fdt_unflatten();
-
-
-// === 驱动探测 API (供各驱动 init 函数调用) ===
-
-// 根据 "compatible" 字符串查找第一个匹配的设备节点。
-// 返回值:成功则为 DeviceNode 指针,失败为 nullptr。
-DeviceNode* fdt_find_compatible(const char* compat_string);
-
-// 根据完整路径查找设备节点。
-DeviceNode* fdt_get_node_by_path(const char* path);
-
-
-// === 早期扫描 API (供 PMM 和早期控制台调用) ===
-
-// 扫描 FDT blob 获取 /memory 节点的 base 和 size。
-// 失败则 panic。
-void fdt_early_get_mem_info(uint64* base, uint64* size);
-
-// 扫描 FDT blob 获取 /chosen/stdout-path 对应的 UART 物理地址。
-void fdt_early_get_uart_info(uint64* uart_addr);
-```
-
-## 5. 并发与锁契约 (Concurrency & Locks)
-
-- **无锁设计:** FDT 的所有初始化和解析操作(`fdt_init`, `fdt_unflatten`)均由 BSP 在多核启动前的**绝对单核期**完成。
-
-- **只读安全:** 一旦 `fdt_unflatten()` 完成,`DeviceNode` 对象树即被视为**全局只读**数据。任何 CPU 都可以随时无锁访问它进行驱动探测和属性查询。
-
-- **禁止修改:** 任何模块在初始化之后都**不得**修改 `DeviceNode` 树的内容。
-
-## 6. 错误路径 (Error Paths)
-
-- **FDT 损坏:** 在 `fdt_init()` 或 `fdt_unflatten()` 中,如果检测到 FDT 的 magic number 无效或结构损坏,必须立即调用 `kernel_panic()`。
-
-- **关键节点缺失:** `fdt_early_get_mem_info()` 如果找不到 `/memory` 节点,说明无法确定物理内存大小,属于致命错误,必须 `kernel_panic()`。
-
-- **内存分配失败:** `fdt_unflatten()` 在使用 `new` 创建 `DeviceNode` 时如果 Slab 返回 `nullptr`,说明内存耗尽,必须 `kernel_panic()`。
-
-- **查询失败:** `fdt_find_compatible()` 或 `fdt_get_node_by_path()` 在未找到匹配节点时,安全地返回 `nullptr`。调用方(驱动)负责处理此情况(通常意味着该硬件不存在,驱动不进行初始化)。
-
-## 7. 状态机 / 时序图 (State Machine / Sequence)
-
-### FDT 二阶段解析时序
-
-```
-[entry.S] -> a1 = fdt_paddr
- │
- ▼
-[kernel_main on BSP]
- │
- ├─> 1. fdt_init(fdt_paddr)
- │ └─ g_fdt = new FdtManager(fdt_paddr); // Placement New
- │ (仅保存地址,不进行任何解析)
- │
- ├─> 2. pmm_init()
- │ └─ fdt_early_get_mem_info(&base, &size);
- │ └─ FdtManager::early_scan_mem(fdt_paddr, ...);
- │ ├─ 遍历原始 FDT blob (无内存分配)
- │ ├─ 找到 /memory 节点
- │ └─ 返回 reg 属性值
- │
- ├─> 3. slab_init()
- │ └─ operator new 可用
- │
- ├─> 4. (稍后) fdt_unflatten()
- │ └─ g_fdt->unflatten();
- │ ├─ 再次遍历原始 FDT blob
- │ ├─ for each node: new DeviceNode(...)
- │ ├─ for each prop: new FdtProperty(...)
- │ └─ 构建完整的 C++ 对象树
- │
- ▼
-[驱动初始化阶段, e.g., plic_init()]
- │
- ├─> node = fdt_find_compatible("riscv,plic0");
- │ └─ g_fdt->find_compatible(...);
- │ └─ 遍历已构建的 DeviceNode C++ 对象树 (只读, 无锁)
- │
- ├─> reg_prop = node->get_prop("reg");
- │
- └─> (使用 reg_prop->value 初始化 PLIC 驱动)
-``` \ No newline at end of file