Compare commits

..
7 Commits
Author SHA1 Message Date
xyou efa626ed17 feat: Phase 1 网络端到端打通 + FirstInit/Login/DevMode 完善
- 用户态共享网络协议栈 CODE/tools/net_stack.h(eth/ARP/IPv4/ICMP/UDP-DNS/TCP static inline,轮询模型)
- shell 内建 ping/curl/run 命令;ping.elf/curl.elf 对齐 net_stack.h 真实协议栈
- shell dev_mode 串口镜像(g_serial_mirror)便于自动化验证
- DSK 启动流程:firstInit.txt 双行格式(firstInit + dev_mode),dev_mode=1 触发 shell 自动回归测试
- FirstInit 完成→持久化 USER.CONF + 翻转 firstInit 0->1(保留 dev_mode)
- firstInit=1 时 DSK 加载 login.elf 进行用户选择 + 密码校验后再进 desktop
- 新增 CODE/login/ 登录应用、CODE/DKM/dkm_shared.h、Logo.png
- ahci/e1000/virtio_net/fat32/console_fb 驱动更新;utsm serial/block/dsk_loader 调整
- build.ps1 打包 ping.elf/curl.elf 进 SATA FAT32 根目录
- 移除 CODE/tools/bash(与 shell.elf 重复)
2026-07-26 21:07:36 +08:00
xyou 48dcb5568e feat: 图形桌面 + 独立工具应用 + Sealed Arc UI 设计系统 | desktop.elf窗口管理器/6个工具应用(bash/editor/fileman/browser/curl/ping)/desktop_app.h公共头文件/Sealed Arc设计系统/DRR完整实现/Process增强/DSK启动改为加载desktop.elf/Shell重构/开发文档 2026-07-03 21:13:04 +08:00
xyou 3662345434 feat: WiFi驱动(ath9k) + TTF字体 + shell命令行 + FirstInit WiFi跳过
新增: ath9k PCIe WiFi驱动(被动扫描/beacon解析), shell命令行(help/clear/echo/version/date/reboot/halt), Consolas 18px TTF字体, render_ascii.py

修改: dkm_net_api扩展scan接口, FirstInit无WiFi设备时跳过, DSK加载shell.elf, 非首次启动直接进shell
2026-07-03 12:59:59 +08:00
xyou 129175a5d8 docs: 添加项目文档体系(架构/启动路线/路线图/贡献规范)
- docs/ARCHITECTURE.md: 架构设计文档,覆盖五大核心子系统
  (SAS-R0-PCQ/UTSM/UTRW/DRR/DKM)、内存模型、驱动/文件/网络/图形子系统、
  开放设计点
- docs/BOOT_SEQUENCE.md: 启动路线设计,原创 DBS 五阶段命名体系
  (B0 Ignis/B1 Sigillum/B2 Transitus/B3 Origo/B4 Excitas),
  启动契约/锚点/回退链机制
- docs/ROADMAP.md: 分阶段开发路线图,9 个 Phase + 5 个里程碑
- CONTRIBUTING.md: 贡献与协作规范,含代码规范/Git 工作流/PR 流程
- .github/: PR 模板 + Bug/Feature Issue 模板
- README.md: 更新为项目介绍 + 文档索引 + 构建说明

所有文档基于项目真实源码与设计文档编写,62 个交叉链接全部有效。
2026-07-02 16:56:38 +08:00
xyou f1a2a110d7 Record networking and DMA development progress
Add the current OS source tree, build scripts, system image layout, and development notes covering DMA page allocation, e1000 bring-up, net API dispatch, and DHCP work in progress.
2026-07-02 16:17:09 +08:00
xyouandGitHub fbc14631e3 Rename project from Deshab-Linux-Desktop to Deshab-OS 2026-07-01 21:24:01 +08:00
xyou 1270df4f93 first commit 2026-06-29 11:33:55 +08:00
233 changed files with 31828 additions and 3 deletions
+40
View File
@@ -0,0 +1,40 @@
---
name: Bug 报告
about: 报告内核崩溃、驱动故障、构建失败等问题
title: "[bug] "
labels: bug
---
## 问题描述
<!-- 简要描述问题 -->
## 复现步骤
1.
2.
3.
## 预期行为
<!-- 应该发生什么 -->
## 实际行为
<!-- 实际发生了什么 -->
## 环境
- 组件:<!-- UTSM / DSK / DKM:<驱动名> / FirstInit / 构建 -->
- 运行环境:<!-- QEMU / 真机 -->
- QEMU 参数(如非默认):
## 串口日志
```
<!-- 粘贴 QEMU 串口输出,至少包含崩溃点前后上下文 -->
```
## 崩溃分析(如适用)
<!-- 三重故障 / page fault / panic 时的寄存器、栈、调用上下文 -->
+39
View File
@@ -0,0 +1,39 @@
---
name: 功能请求
about: 提议新驱动、新子系统或架构改进
title: "[feat] "
labels: enhancement
---
## 功能描述
<!-- 简要描述提议的功能 -->
## 动机
<!-- 为什么需要这个功能,解决什么问题 -->
## 涉及子系统
- [ ] UTSM 首阶段内核
- [ ] DSK 主内核
- [ ] DKM 驱动
- [ ] 内存管理
- [ ] 文件系统 / VFS
- [ ] 网络
- [ ] 调度器 (SAS-R0-PCQ)
- [ ] 恢复系统 (DRR)
- [ ] FirstInit / 用户空间
- [ ] 文档
## 设计思路
<!-- 描述实现方案,如有 ABI / 架构影响请重点说明 -->
## 路线图对应
<!-- 对应 docs/ROADMAP.md 中的哪个 Phase?(如适用) -->
## 验收标准
<!-- 完成后如何验证 -->
+52
View File
@@ -0,0 +1,52 @@
## 变更说明
<!-- 简要描述本 PR 做了什么、为什么 -->
## 变更类型
- [ ] feat — 新功能
- [ ] fix — 修复
- [ ] docs — 文档
- [ ] build — 构建系统
- [ ] refactor — 重构
- [ ] test — 测试
- [ ] chore — 杂项
## 影响范围
<!-- 勾选受影响的子系统 -->
- [ ] UTSM 首阶段内核
- [ ] DSK 主内核
- [ ] DKM 驱动(请列出具体驱动: )
- [ ] DKM ABI / kernel_api
- [ ] 文件系统 / VFS
- [ ] 网络
- [ ] FirstInit / 用户空间
- [ ] 构建 / 镜像打包
- [ ] 文档
## 提交前检查清单
- [ ] `.\build.bat` 构建成功,产出 `ISO/deshab.img`
- [ ] `.\ISO\run_qemu.bat` 启动到 `[DSK] SELFTEST PASS`
- [ ] 无新增编译 warning(`-Wall -Wextra`)
- [ ] ABI 变更已同步所有驱动本地定义(未在结构体中间插入字段)
- [ ] 新驱动已在 `manifest.json` + `limine.conf` 注册
- [ ] 设计文档(`RE/`)与模块 README 已同步
- [ ] 提交信息符合 Conventional Commits
- [ ] `LESSONS_LEARNED.md` 已追加经验记录(如适用)
## 测试方式
<!-- 描述如何验证本变更,如 QEMU 参数、预期串口输出 -->
```text
预期输出:
```
## ABI / 兼容性影响
<!-- 如果修改了 dkm_kernel_api、driver_desc、dsk_boot_context 等 ABI,请说明:
1. 新增字段是否追加到结构尾部
2. 是否影响已有驱动
3. min_kernel_abi / abi_version 是否需要变更 -->
+6
View File
@@ -0,0 +1,6 @@
ISO/deshab.img
*.o
.build_tmp/
.trae/
docs/workbuddy-planning/
sata_fat32_dsk.img
+154
View File
@@ -0,0 +1,154 @@
# Deshab 项目上下文
## 项目概览
Deshab 当前包含一个内核/系统实验方向,其中启动内核与主内核目标为:
```text
CODE/UTSM -> SYSTEM/boot/utsm.elf
CODE/dsk -> SYSTEM/system/deshab64/deshab.elf
```
`utsm.elf` 是当前由 bootloader 直接加载的首阶段内核,负责 UTSM、DKM 驱动加载、平台发现和早期系统服务。当前已实现两阶段 DSK 加载:优先通过 `kernel_api.block` + 内嵌 FAT32 解析从真实块设备读取 `/system/deshab64/deshab.elf`(在 SATA FAT32 盘场景已验证);无块设备时自动回退 Limine boot module 预加载。
DSK 主内核(`deshab.elf`)当前已实现:
- 内嵌 FAT32 只读解析器(256 扇区批量读取 + 内存内文件查找)
- PIE ELF loader(PT_LOAD + PT_DYNAMIC + R_X86_64_RELATIVE 重定位)
- 静态启动 Logo(嵌入 Logo.png RGBA 数据,居中 alpha 混合绘制于渐变背景上,取代原旋转加载动画)
- 首次启动检测:读取 `firstInit.txt`,值为 `0` 则触发首次启动流程
- 系统初始化调度:DSK 直接加载并调用 `mouseInit.elf`(PS/2 鼠标安全初始化)
- 用户设置向导:DSK 加载并跳转 `FirstInit.elf`(圆角卡片 UI、键盘输入、SHA256 密码、加密配置缓冲)
FirstInit(`CODE/firstInit`)只负责用户级设置向导:
- 淡蓝背景 → "欢迎使用 Deshab"(中英双语,英文小字副标题)→ 设置提示 → 账户设置卡片
- PS/2 键盘轮询输入:计算机名、用户名、密码
- SHA256 密码摘要 + XOR 加密配置缓冲(user.conf 格式已定义,写盘待 FAT32 write API)
- 18px 黑体中文位图(预渲染嵌入 ELF)
mouseInit(`CODE/mouse`)是 DSK 直接调度的系统输入初始化器:
- 当前为安全 stub(只读 PS/2 状态,不写控制器),避免阻塞首次启动
- 后续将实现完整 IRQ12 + 鼠标包解码
## 当前核心架构
```text
SAS-R0-PCQ
单地址空间 Ring0 任务模型
Per-CPU O(1) 位图调度器
DRR
Dedicated Recovery Root
看门狗 / checkpoint / recovery log / A-B 回滚
UTSM
UUID-Tuned Sealed Memory
UUID 调谐封缄内存
UTRW
UTSM Tagged Reader/Writer
UTSM 带标记读写器
DMP
Descriptor Meta Page
段描述符元页
PCKC
Per-CPU Key Cache
每 CPU 密钥缓存
```
## 关键设计约束
1. 优先考虑极高权限和极高效率。
2. 主系统采用单地址空间 Ring0 模型。
3. 不追求传统多用户强安全隔离。
4. DRR 作为恢复根,应尽量独立于普通调度器。
5. UTSM 数据区连续存密文,UUID 不嵌入数据区。
6. 调度器热路径必须保持 O(1)。
7. checkpoint 只处理 dirty shard / dirty page,不扫描全内存。
8. DRR 必须拥有独立 Emergency Pool,普通 OOM 不应阻断 recovery。
9. checkpoint metadata 使用 A/B 双槽、CRC 校验和原子 active slot 切换。
10. 驱动模块采用 DKM ELF64 .drv ABI,通过 driver_desc / driver_init / driver_exit 暴露入口。
11. 驱动默认通过 dkm_kernel_api 调用内核服务,不直接依赖任意内核符号。
12. stage0/stage1 驱动必须支持 bootloader 预加载 boot module 方案。
## 重要文件
```text
SYSTEM/
打包为 IMG 后的系统根目录。
SYSTEM/driver/manifest.json
内核启动驱动模块清单,控制 ELF .drv 驱动的分阶段加载。
CODE/DKM/README.md
DKM 驱动模块系统说明,记录驱动加载目标、ABI、loader、状态机和实现清单。
CODE/UTSM/README.md
UTSM 模块设计说明。
RE/UTSM_算法记录.md
UTSM 核心算法记录。
RE/UTSM_设计架构.md
UTSM 架构记录。
RE/驱动模块ABI设计.md
DKM 驱动模块 ABI、kernel_api、ELF relocation、manifest、状态机和 boot module 方案。
ISO/deshab.img
build.ps1 将 SYSTEM 打包生成的 GPT 磁盘镜像,包含一个 FAT32 EFI System Partition。
ISO/run_qemu.bat
使用 QEMU 启动 ISO/deshab.img 的脚本。
```
## 构建相关
已知说明:
```text
SYSTEM/ 是打包为 IMG 后的系统根目录。
SYSTEM/boot/ 存放启动模块,例如 utsm.elf。
SYSTEM/driver/ 存放 ELF .drv 驱动模块和 manifest.json。
CODE/UTSM/README.md: 编译到 SYSTEM/boot/utsm.elf
build.bat: 调用 build.ps1。
build.ps1: 编译 UTSM,生成 SYSTEM/boot/utsm.elf,并把 SYSTEM 打包为 ISO/deshab.img。deshab.img 是 GPT 磁盘镜像,包含 FAT32 EFI System Partition。
ISO/run_qemu.bat: 用 QEMU + UEFI 固件启动 ISO/deshab.img,串口输出到 stdio。
```
当前 UTSM 已有首阶段内核代码骨架和构建脚本,可生成 utsm.elf 与 GPT + FAT32 ESP 镜像。早期启动要求:进入 C 前 `cli/cld`,early serial 不允许无限等待硬件 ready 位,未启用 FPU/SSE 前编译必须使用 `-mno-sse -mno-sse2 -mno-mmx -msoft-float`。DATA/BSS 段使用 PF_R|PF_W|PF_X(SAS-R0 下驱动模块内存需可执行)。
DKM/DSM 驱动加载系统已完工:内置 `console_early` + manifest.json 解析 + Limine boot module 预加载 + 4 stage 分阶段加载 + 全部 14 个外部 `.drv` ET_REL 装载(ELF64/SHT_NOBITS/R_X86_64_64/32/32S/PC32 relocation + driver_desc 校验 + driver_init 调用)。当前镜像额外预加载 `driver/test.fat32` 作为 FAT32 驱动测试镜像。
当前已实现 14 个真实 DKM 驱动:
- **timer** (stage0): PIT 校准, 100ms busy-wait demo
- **apic** (stage0): CPUID Local APIC 探测, IA32_APIC_BASE MSR, ACPI MADT 枚举, LAPIC MMIO 只读寄存器验证;当前保留 PIC IRQ 路由
- **acpi** (stage0): Limine RSDP → XSDT, ACPI 表枚举
- **pci** (stage0): PCI config space 扫描, 设备枚举
- **console_fb** (stage1): Limine framebuffer, 淡蓝色背景清屏(原四色圆弧加载环已移除,启动画面改由 DSK 静态 Logo 接管)
- **ahci** (stage1): PCI AHCI `8086:2922` 探测, BAR5/ABAR HHDM MMIO 映射, HBA CAP/GHC/PI/VS 与 port 枚举;已接入 `kernel_api.dma`,支持 SATA disk IDENTIFY 与 LBA0 READ 最小 DMA 路径;可向 `kernel_api.block` 注册 `ahci0` block provider;默认无 SATA 盘/ATAPI 场景会跳过命令
- **nvme** (stage1): PCI NVMe `1b36:0010` 探测, BAR0/BAR1 解析, IRQ line 读取;当前 QEMU BAR0 位于 4G 以上,MMIO register 读取等待高位 PCI MMIO 映射能力
- **bootfs** (stage1): Limine boot module 内存文件系统
- **vfs** (stage2): 挂载 bootfs, 文件查找/读取
- **devfs** (stage2): 暴露 `/dev/version`, `/dev/platform`, `/dev/fb0`, `/dev/modules`, `/dev/boot/`
- **fat32** (stage2): 只读 FAT32 BPB/FAT/目录项解析, 通过 `driver/test.fat32` 验证读取 `README.TXT`
- **ps2kbd** (stage3): PS/2 IRQ1 注册, 端口 `0x60` 扫描码读取, scan code set 1 → ASCII demo
- **e1000** (stage3): PCI `8086:10d3` 探测, BAR0 HHDM MMIO 映射, MAC 读取, IRQ 注册, 基础 link setup
- **virtio_net** (stage3): PCI virtio-net `1af4:1001` 探测, BAR 枚举, modern virtio PCI capability 枚举;暂不进行 feature negotiation / virtqueue / 收发包
当前内核平台能力:IDT 0–47 stub、异常处理、PIC remap 到 `0x20–0x2f`、IRQ handler 注册与 EOI、Limine RSDP/framebuffer/module/HHDM request。
kernel_api 已暴露能力:log, rsdp_address, fb_address/width/height/pitch/bpp, boot_modules_response, irq_register, hhdm_offset, dma.alloc_pages。
当前 manifest 中 14 个外部 `.drv` 均已替换为真实 DKM 驱动并可加载执行。
下一阶段优先路线:
1. **内存与 MMIO 基础设施**: 实现物理页分配器、页表映射接口、低位/高位 PCI MMIO 映射,解决 NVMe 4G 以上 BAR 和后续 DMA 映射问题。
2. **DMA 与块设备数据路径**: 建立 contiguous DMA buffer、cache/屏障约定、PRDT/队列内存管理,然后推进 AHCI IDENTIFY/READ 与 NVMe admin queue/identify。
3. **IRQ 后端升级**: 在现有 PIC fallback 稳定基础上扩展 IDT/vector allocator/APIC EOI/IOAPIC redirection,逐步迁移设备 IRQ,最后接入 MSI/MSI-X。
4. **网络数据路径**: 在 DMA/IRQ 完成后推进 e1000 RX/TX ring 与 virtio-net feature negotiation/virtqueue/RX-TX。
5. **VFS 与真实块设备接入**: 将 FAT32 从测试镜像迁移到 AHCI/NVMe block provider,完善挂载、读取、目录遍历和错误路径。
6. **DKM 工程化收尾**: 统一驱动本地 ABI 头、清理 warning、补充自动化 QEMU 场景(e1000/virtio-net/nvme/ahci)。
7. **FirstInit 完善**: 修复按键崩溃(fb_text 优化问题)、实现鼠标光标移动、user.conf 写盘(需 block write API)、网络配置界面。
8. **鼠标输入驱动**: 从 mouseInit stub 升级为完整 PS/2 鼠标 IRQ12 + 包解码 + 光标移动。
+691
View File
@@ -0,0 +1,691 @@
# DKM 驱动模块系统
```text
DKM = Deshab Kernel Module
DSM = Driver Startup Manager
```
DKM 是 Deshab 内核的驱动模块系统,负责在内核启动时加载 `SYSTEM/driver` 下的 ELF64 `.drv` 驱动模块,并把驱动注册到内核服务体系中。
当前实现状态:CODE/UTSM 内核已接入完整 DKM/DSM 驱动加载系统。内置 `console_early` + manifest.json 解析 + Limine boot module 预加载 + 4 stage 分阶段加载。全部 14 个外部 `.drv` 已完成 ET_REL 装载全链路:ELF64 校验、符号扫描、section 拷贝到 arena、SHT_NOBITS 清零、R_X86_64_64/32/32S/PC32 重定位、driver_desc magic 校验、外部 driver_init 调用进入 ACTIVE。当前镜像还预加载 `driver/test.fat32` 作为 FAT32 驱动测试镜像。
Linux/Windows 已编译驱动不能直接作为 DKM 驱动使用。真实驱动必须按本文件定义的 DKM ABI 编译,导出 `driver_desc`、`driver_init`、`driver_exit`,并只通过 `dkm_kernel_api` 调用内核服务。
当前真实驱动进度:14/14。
```text
stage0: timer, apic, acpi, pci
stage1: console_fb, ahci, nvme, bootfs
stage2: vfs, devfs, fat32
stage3: ps2kbd, e1000, virtio_net
```
manifest 中 14 个外部 `.drv` 均已替换为真实 DKM 驱动并可加载执行。当前 IDT/PIC/IRQ 基础设施已在内核侧实现,`apic` 已完成 APIC discovery 并保留 PIC IRQ 路由,`ahci` 已完成 PCI/ABAR/HBA/port discovery,并通过 `kernel_api.dma.alloc_pages` 接入早期低位 DMA buffer,支持 SATA disk IDENTIFY 与 LBA0 READ 最小路径;识别 SATA disk 后可向 `kernel_api.block` 注册 `ahci0` block provider。`fat32` 已优先通过 block provider 读取 FAT32 镜像,无设备或 BPB 无效时回退 boot module。`nvme` 已完成 PCI discovery 并能识别 QEMU NVMe 控制器;由于当前 QEMU BAR0 位于 4G 以上,NVMe MMIO register 读取等待高位 PCI MMIO 映射能力。`ps2kbd` 和 `e1000` 已通过 `kernel_api.irq_register` 验证 IRQ handler 注册路径。`virtio_net` 已完成 PCI discovery 和 modern virtio capability 枚举,尚未进行 feature negotiation / virtqueue / RX-TX。
下一阶段 DKM/驱动路线:
```text
P0: 物理页分配器 + 页表/MMIO 映射接口
P1: DMA buffer/屏障约定 + AHCI/NVMe block 数据路径
P2: IDT 256 vectors + vector allocator + APIC/IOAPIC/MSI IRQ backend
P3: e1000 与 virtio_net RX/TX 数据路径
P4: FAT32 接入真实 block provider,替代 test.fat32 启动镜像
P5: 驱动 ABI 公共头、warning 清理、QEMU 场景自动化
```
---
## 1. 模块目标
DKM 的目标:
```text
1. 从 SYSTEM/driver/manifest.json 读取驱动清单。
2. 按 stage 分阶段加载驱动。
3. 支持 ELF64 .drv 模块加载和重定位。
4. 提供稳定的 driver_desc ABI。
5. 通过 dkm_kernel_api 向驱动暴露内核服务。
6. 支持 stage0/stage1 boot module 早期加载。
7. 将驱动内存纳入 UTSM。
8. 将驱动状态和恢复操作纳入 DRR。
```
---
## 2. 系统目录约定
打包为 IMG 后,`SYSTEM` 是系统根目录。
```text
SYSTEM/
boot/
utsm.elf
limine.conf
driver/
manifest.json
platform/
timer.drv
apic.drv
acpi.drv
bus/
pci.drv
block/
ahci.drv
nvme.drv
fs/
bootfs.drv
vfs.drv
fat32.drv
devfs.drv
net/
e1000.drv
virtio_net.drv
input/
ps2kbd.drv
console/
console_fb.drv
```
当前驱动清单:
```text
SYSTEM/driver/manifest.json
```
---
## 3. 启动阶段
DKM 使用分阶段加载。
```text
stage0: platform
timer / apic / acpi / pci
建立平台发现、中断、总线和基础计时能力。
stage1: boot
console / block / bootfs
建立启动日志、块设备和启动文件访问能力。
stage2: filesystem
vfs / fat32 / devfs
建立完整 VFS 和可挂载文件系统。
stage3: optional
net / input / gpu
加载网络、输入、图形等非启动关键驱动。
```
规则:
```text
1. stage0/stage1 可由 bootloader 预加载为 boot module。
2. stage2/stage3 默认从 SYSTEM/driver 加载。
3. required=true 的驱动失败时进入 DRR recovery 或 panic。
4. required=false 的驱动失败时标记 FAILED 并继续启动。
```
---
## 4. driver_desc ABI
每个 `.drv` 必须导出三个符号:
```text
driver_desc
driver_init
driver_exit
```
### 4.1 常量
```c
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1
```
`0x444B4D31` 表示:
```text
DKM1
```
### 4.2 driver_desc 结构
```c
struct dkm_driver_desc {
uint32_t magic;
uint16_t abi_version;
uint16_t desc_size;
const char *name;
const char *version;
const char *vendor;
uint32_t driver_class;
uint32_t stage;
uint32_t flags;
uint32_t priority;
const char *const *depends;
uint32_t depends_count;
const char *const *provides;
uint32_t provides_count;
uint64_t min_kernel_abi;
uint64_t feature_bits;
uint64_t reserved0;
uint64_t reserved1;
};
```
### 4.3 driver_class
```text
DKM_CLASS_PLATFORM
DKM_CLASS_BUS
DKM_CLASS_INTERRUPT
DKM_CLASS_TIMER
DKM_CLASS_CONSOLE
DKM_CLASS_STORAGE
DKM_CLASS_FS
DKM_CLASS_NET
DKM_CLASS_INPUT
DKM_CLASS_GPU
DKM_CLASS_MISC
```
### 4.4 flags
```text
DKM_F_REQUIRED
当前 stage 中失败则进入 DRR recovery 或 panic。
DKM_F_BOOT_MODULE
可由 bootloader 预加载。
DKM_F_NO_UNLOAD
不允许卸载。
DKM_F_STRONG_RECOVERY
驱动 data/bss 段使用 UTSM 强恢复策略。
DKM_F_DMA_REQUIRED
驱动需要 DMA API。
DKM_F_EARLY_LOG
驱动 init 期间允许使用 early log。
```
---
## 5. 驱动入口
```c
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle);
int driver_exit(struct dkm_driver_handle *handle);
```
约定:
```text
1. driver_init 返回 0 表示成功。
2. driver_init 返回负数表示失败。
3. driver_exit 仅用于非 DKM_F_NO_UNLOAD 驱动。
4. required 驱动失败会触发 DRR recovery 或 panic。
5. optional 驱动失败会被标记为 FAILED。
```
---
## 6. kernel_api ABI
驱动默认不直接依赖任意内核符号,而是通过 `dkm_kernel_api` 调用内核服务。
```c
#define DKM_KERNEL_API_VERSION 1
struct dkm_kernel_api {
uint32_t version;
uint32_t size;
uint64_t feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
uint64_t fb_width;
uint64_t fb_height;
uint64_t fb_pitch;
uint16_t fb_bpp;
const void *boot_modules_response;
int (*irq_register)(uint8_t irq, void *handler);
uint64_t hhdm_offset;
};
```
### 6.1 log API
```c
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
```
### 6.2 memory API
```c
struct dkm_mem_api {
void *(*alloc)(uint64_t size, uint32_t flags);
void (*free)(void *ptr);
void *(*alloc_pages)(uint32_t order, uint32_t flags);
void (*free_pages)(void *ptr, uint32_t order);
void *(*mmio_map)(uint64_t phys, uint64_t size, uint32_t flags);
void (*mmio_unmap)(void *virt, uint64_t size);
};
```
### 6.3 UTSM API
```c
struct dkm_utsm_api {
int (*create_segment)(uint64_t size, uint32_t flags, struct utsm_capability *out);
int (*read)(struct utsm_capability cap, uint64_t off, void *dst, uint64_t len);
int (*write)(struct utsm_capability cap, uint64_t off, const void *src, uint64_t len);
int (*pin)(struct utsm_capability cap, uint64_t off, uint64_t len, void **window);
int (*unpin)(void *window, uint32_t flags);
};
```
### 6.4 当前平台直通能力
当前内核已通过 `dkm_kernel_api` 直接暴露早期平台信息和 IRQ/HHDM 能力:
```text
rsdp_address Limine RSDP 地址,用于 ACPI 驱动
fb_address/width/height Limine framebuffer 信息,用于 console_fb
fb_pitch/fb_bpp framebuffer 行跨度和像素格式
boot_modules_response Limine module response,用于 bootfs/fat32 测试镜像
irq_register 注册 PIC IRQ0–15 handler,用于 ps2kbd/e1000
hhdm_offset physical → virtual direct map,用于 PCI BAR MMIO
```
### 6.5 IRQ / PCI / DMA API
```c
struct dkm_irq_api {
int (*register_irq)(uint32_t vector, int (*handler)(void *ctx), void *ctx, uint32_t flags);
int (*unregister_irq)(uint32_t vector);
void (*ack)(uint32_t vector);
};
struct dkm_pci_api {
int (*scan)(int (*cb)(const struct pci_device *dev, void *ctx), void *ctx);
int (*enable_device)(const struct pci_device *dev);
uint64_t (*bar_phys)(const struct pci_device *dev, uint32_t bar);
uint64_t (*bar_size)(const struct pci_device *dev, uint32_t bar);
};
struct dkm_dma_api {
int (*alloc)(uint64_t size, uint32_t flags, struct dkm_dma_buffer *out);
void (*free)(struct dkm_dma_buffer *buf);
int (*sync_for_device)(struct dkm_dma_buffer *buf);
int (*sync_for_cpu)(struct dkm_dma_buffer *buf);
};
```
---
## 7. ELF64 .drv Loader
第一版仅支持 x86_64 ELF64 小型内核模型。
### 7.1 必须支持的 relocation
```text
R_X86_64_64
绝对 64-bit 地址重定位。
R_X86_64_RELATIVE
base + addend。
R_X86_64_GLOB_DAT
GOT 符号地址。
R_X86_64_JUMP_SLOT
PLT 函数地址。
```
### 7.2 建议支持的 relocation
```text
R_X86_64_PC32
32-bit PC-relative 调用。
R_X86_64_PLT32
PLT-relative 调用。
R_X86_64_32 / R_X86_64_32S
仅允许确认地址范围安全时使用。
```
### 7.3 第一版禁止
```text
TLS relocation
IFUNC
lazy binding
外部动态库依赖
用户态 libc 依赖
异常展开表强依赖
```
### 7.4 加载流程
```text
DKM_ELF_LOAD(path_or_boot_module)
1. 读取 ELF header。
2. 校验 ELFCLASS64 / EM_X86_64 / endian / ABI。
3. 读取 program headers 或 section headers。
4. 计算模块内存大小和对齐。
5. 通过 UTSM 创建 code/data 段。
6. 加载 PT_LOAD 或 SHF_ALLOC section。
7. 清零 .bss。
8. 解析 symbol table。
9. 解析 relocation section。
10. 解析内核导出符号和 dkm_kernel_api。
11. 执行 relocation。
12. 查找 driver_desc / driver_init / driver_exit。
13. 设置 code 段 READ|EXEC|SEALED。
14. 设置 data 段 READ|WRITE|STRONG_RECOVERY。
15. 返回 module handle。
```
---
## 8. manifest.json 格式
路径:
```text
SYSTEM/driver/manifest.json
```
顶层结构:
```json
{
"schema": "deshab.driver.manifest.v1",
"root": "SYSTEM",
"driverRoot": "SYSTEM/driver",
"format": "elf64-drv",
"abi": {},
"policy": {},
"stages": []
}
```
驱动项示例:
```json
{
"name": "pci",
"path": "driver/bus/pci.drv",
"class": "bus",
"required": true,
"depends": ["irq"],
"provides": ["pci"]
}
```
路径规则:
```text
manifest 中的 path 相对 SYSTEM 根目录。
SYSTEM/driver/manifest.json 内的 driver/bus/pci.drv 指向 SYSTEM/driver/bus/pci.drv。
stage0/stage1 驱动允许来自 boot module。
stage2/stage3 驱动默认从 SYSTEM/driver 加载。
```
---
## 9. 驱动加载状态机
正常加载:
```text
DISCOVERED
-> QUEUED
-> DEP_WAIT
-> LOADING
-> ELF_CHECKED
-> MEMORY_ALLOCATED
-> RELOCATED
-> ABI_CHECKED
-> INITING
-> ACTIVE
```
失败状态:
```text
FAILED_ELF
FAILED_RELOCATION
FAILED_DEPENDENCY
FAILED_ABI
FAILED_INIT
FAILED_REQUIRED
```
卸载状态:
```text
ACTIVE
-> QUIESCING
-> EXITING
-> UNLOADING
-> UNLOADED
```
DRR 恢复状态:
```text
ACTIVE
-> SUSPENDED_BY_DRR
-> RECOVERING
-> REINITING
-> ACTIVE
```
---
## 10. DSM 加载策略
```text
DSM_LOAD_ALL()
1. 读取 SYSTEM/driver/manifest.json。
2. 校验 schema / abi / policy。
3. 按 stage 顺序加载。
4. 每个 stage 内按 priority 排序。
5. 检查 depends 是否已由 provides 满足。
6. 未满足依赖的驱动进入 DEP_WAIT。
7. 每轮加载成功后更新 provides set。
8. 一轮后仍 DEP_WAIT 的 required 驱动进入 FAILED_REQUIRED。
9. optional 驱动失败只记录状态。
```
required 失败策略:
```text
stage0/stage1 required 失败:
DRR report_fault -> boot fallback -> panic / system rollback
stage2 required 失败:
DRR recovery -> fallback 到 bootfs 或只读模式
stage3 optional 失败:
mark FAILED -> continue boot
```
---
## 11. stage0/stage1 boot module 方案
stage0/stage1 不应依赖普通 VFS。
bootloader 应预加载:
```text
SYSTEM/driver/manifest.json
SYSTEM/driver/platform/timer.drv
SYSTEM/driver/platform/acpi.drv
SYSTEM/driver/platform/apic.drv
SYSTEM/driver/bus/pci.drv
SYSTEM/driver/console/console_fb.drv
SYSTEM/driver/fs/bootfs.drv
SYSTEM/driver/test.fat32
```
可选预加载:
```text
SYSTEM/driver/block/ahci.drv
SYSTEM/driver/block/nvme.drv
SYSTEM/driver/fs/vfs.drv
SYSTEM/driver/fs/devfs.drv
SYSTEM/driver/fs/fat32.drv
SYSTEM/driver/net/e1000.drv
SYSTEM/driver/net/virtio_net.drv
SYSTEM/driver/input/ps2kbd.drv
```
boot module 表:
```c
struct dkm_boot_module {
const char *path;
void *base;
uint64_t size;
uint32_t type;
uint32_t flags;
uint64_t checksum;
};
struct dkm_boot_module_table {
uint32_t count;
struct dkm_boot_module modules[];
};
```
查找规则:
```text
DSM_LOAD_DRIVER(path)
1. 如果 path 在 boot module table 中,直接从内存加载。
2. 否则如果 VFS 已可用,从 SYSTEM/path 加载。
3. 否则返回 BOOT_MODULE_NOT_FOUND。
```
---
## 12. 与 UTSM / DRR 的关系
### 12.1 UTSM 内存策略
```text
驱动 text:READ | EXEC | SEALED
驱动 rodata:READ | SEALED
驱动 data:READ | WRITE | STRONG_RECOVERY
驱动 bss:READ | WRITE | STRONG_RECOVERY
驱动 DMA:DMA | PINNED,必要时 CIPHERTEXT_DMA 或 NO_ENCRYPT
```
### 12.2 DRR 记录项
```text
driver name
stage
state
module memory range
provided services
recovery ops
init result
last fault
```
### 12.3 recovery ops
```c
struct dkm_driver_recovery_ops {
int (*quiesce)(void *ctx);
int (*reset)(void *ctx);
int (*reinit)(void *ctx);
int (*dump_state)(void *ctx, void *buf, uint64_t len);
};
```
DRR recovery 顺序:
```text
quiesce -> UTSM rollback -> device reset -> driver reinit -> resume
```
---
## 13. 第一版实现清单
```text
1. manifest.json parser
2. boot module table lookup
3. ELF64 header 校验
4. ELF64 section/program loading
5. relocation 处理
6. driver_desc 校验
7. kernel_api table 初始化
8. depends/provides resolver
9. staged loader
10. driver state table
11. DRR driver fault reporting
12. UTSM module memory allocation
```
---
## 14. 相关文件
```text
SYSTEM/driver/manifest.json
驱动启动清单。
RE/驱动模块ABI设计.md
DKM ABI 详细设计。
CODE/UTSM/README.md
UTSM 与驱动加载的整合说明。
```
+298
View File
@@ -0,0 +1,298 @@
/* DKM ACPI Driver - RSDP scan / RSDT parse / table enumeration
* Stage 0, optional, provides "acpi".
* Scans BIOS memory for RSDP, then walks RSDT/XSDT to list all ACPI tables.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
/* ---------------------------------------------------------------
* ACPI structures
* --------------------------------------------------------------- */
typedef struct __attribute__((packed)) {
char signature[8];
u8 checksum;
char oem_id[6];
u8 revision;
u32 rsdt_addr;
} acpi_rsdp_v1;
typedef struct __attribute__((packed)) {
/* RSDP v1 fields */
char signature[8];
u8 checksum;
char oem_id[6];
u8 revision;
u32 rsdt_addr;
/* RSDP v2+ fields */
u32 length;
u64 xsdt_addr;
u8 ext_checksum;
u8 reserved[3];
} acpi_rsdp_v2;
typedef struct __attribute__((packed)) {
char signature[4];
u32 length;
u8 revision;
u8 checksum;
char oem_id[6];
char oem_table_id[8];
u32 oem_revision;
u32 creator_id;
u32 creator_revision;
} acpi_sdt_header;
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_provides[] = { "acpi" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "acpi",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 1, /* DKM_CLASS_PLATFORM */
.stage = 0,
.flags = 0, /* optional */
.priority = 0,
.depends = NULL,
.depends_count = 0,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* Helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static u32 min_u32(u32 a, u32 b) { return a < b ? a : b; }
static int memneq(const char *a, const char *b, u32 n) {
for (u32 i = 0; i < n; i++) {
if (a[i] != b[i]) return 1;
}
return 0;
}
static u8 checksum8(const u8 *data, u32 len) {
u8 sum = 0;
for (u32 i = 0; i < len; i++) {
sum += data[i];
}
return sum;
}
static void log_hex(const char *prefix, u64 val) {
static const char hex[] = "0123456789abcdef";
char buf[32];
u32 pos = 0;
while (pos < 30) { buf[pos] = 0; pos++; }
pos = 0;
buf[pos++] = '0';
buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(val >> (i * 4)) & 0xf];
}
buf[pos] = 0;
/* manual concat via serial_write-like approach: pass prefix then buf */
g_log->info(prefix);
g_log->info(buf);
}
/* ---------------------------------------------------------------
* RSDP scan
* --------------------------------------------------------------- */
static const acpi_rsdp_v2 *acpi_find_rsdp(const void *limine_rsdp) {
/* If Limine gave us the RSDP, use it directly */
if (limine_rsdp) {
const acpi_rsdp_v2 *rsdp = (const acpi_rsdp_v2 *)limine_rsdp;
if (memneq(rsdp->signature, "RSD PTR ", 8) == 0) {
if (checksum8((const u8 *)rsdp, 20) == 0) {
return rsdp;
}
}
}
/* EBDA: extended BIOS data area, base at 0x40E */
{
u16 ebda_seg = *(const volatile u16 *)(uintptr_t)0x40E;
u64 ebda_base = (u64)ebda_seg << 4;
if (ebda_base >= 0x80000ULL && ebda_base < 0x100000ULL) {
for (u64 off = 0; off < 1024; off += 16) {
const acpi_rsdp_v2 *rsdp = (const acpi_rsdp_v2 *)(uintptr_t)(ebda_base + off);
if (off + sizeof(acpi_rsdp_v1) > 1024) break;
if (memneq(rsdp->signature, "RSD PTR ", 8) == 0) {
if (checksum8((const u8 *)rsdp, 20) == 0) {
return rsdp;
}
}
}
}
}
/* BIOS read-only area: 0x000E0000 - 0x000FFFFF */
for (u64 addr = 0x000E0000ULL; addr < 0x00100000ULL; addr += 16) {
const acpi_rsdp_v2 *rsdp = (const acpi_rsdp_v2 *)(uintptr_t)addr;
if (memneq(rsdp->signature, "RSD PTR ", 8) == 0) {
if (checksum8((const u8 *)rsdp, 20) == 0) {
return rsdp;
}
}
}
return NULL;
}
/* ---------------------------------------------------------------
* Table enumeration
* --------------------------------------------------------------- */
static void acpi_enumerate_rsdt(const acpi_sdt_header *rsdt, u32 entry_size) {
u32 entry_count = (rsdt->length - sizeof(acpi_sdt_header)) / entry_size;
const u8 *entries = (const u8 *)rsdt + sizeof(acpi_sdt_header);
g_log->info("[acpi] tables found");
for (u32 i = 0; i < entry_count; i++) {
u64 addr;
if (entry_size == 4) {
addr = (u64)((const u32 *)entries)[i];
} else {
addr = ((const u64 *)entries)[i];
}
if (addr == 0) continue;
const acpi_sdt_header *hdr = (const acpi_sdt_header *)(uintptr_t)addr;
char sig[5];
sig[0] = hdr->signature[0];
sig[1] = hdr->signature[1];
sig[2] = hdr->signature[2];
sig[3] = hdr->signature[3];
sig[4] = 0;
g_log->info("[acpi] ");
g_log->info(sig);
log_hex("[acpi] addr=", addr);
log_hex("[acpi] len =", (u64)hdr->length);
}
}
/* ---------------------------------------------------------------
* Driver entry points
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) {
return -1;
}
g_log = api->log;
g_log->info("[acpi] scanning for RSDP");
const acpi_rsdp_v2 *rsdp = acpi_find_rsdp(api->rsdp_address);
if (!rsdp) {
g_log->error("[acpi] RSDP not found");
return 0; /* optional driver, don't fail boot */
}
g_log->info("[acpi] RSDP found");
log_hex("[acpi] revision =", (u64)rsdp->revision);
g_log->info("[acpi] oem_id");
{
char oem[7];
for (int i = 0; i < 6; i++) oem[i] = rsdp->oem_id[i];
oem[6] = 0;
g_log->info(oem);
}
if (rsdp->revision >= 2 && rsdp->xsdt_addr) {
g_log->info("[acpi] using XSDT");
const acpi_sdt_header *xsdt = (const acpi_sdt_header *)(uintptr_t)rsdp->xsdt_addr;
acpi_enumerate_rsdt(xsdt, 8);
} else if (rsdp->rsdt_addr) {
g_log->info("[acpi] using RSDT");
const acpi_sdt_header *rsdt = (const acpi_sdt_header *)(uintptr_t)rsdp->rsdt_addr;
acpi_enumerate_rsdt(rsdt, 4);
} else {
g_log->warn("[acpi] no RSDT/XSDT address");
}
g_log->info("[acpi] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+617
View File
@@ -0,0 +1,617 @@
/* DKM AHCI Driver — PCI AHCI discovery and ABAR read-only enumeration
* Stage 1 optional storage driver, depends on "pci" and "irq", provides "block".
* This first version does not issue DMA commands; it only discovers the HBA
* and ports so later block I/O can be added safely.
*/
#include "../dkm_shared.h"
static const char *const g_depends[] = { "pci", "irq" };
static const char *const g_provides[] = { "block" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "ahci",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 6, /* DKM_CLASS_STORAGE */
.stage = 1,
.flags = 0, /* optional */
.priority = 0,
.depends = g_depends,
.depends_count = 2,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
#define AHCI_CLASS_STORAGE 0x01
#define AHCI_SUBCLASS_SATA 0x06
#define AHCI_PROGIF_AHCI 0x01
#define HBA_CAP 0x00
#define HBA_GHC 0x04
#define HBA_IS 0x08
#define HBA_PI 0x0C
#define HBA_VS 0x10
#define HBA_CAP2 0x24
#define HBA_BOHC 0x28
#define HBA_PORT_BASE 0x100
#define HBA_PORT_SIZE 0x80
#define PxCLB 0x00
#define PxFB 0x08
#define PxIS 0x10
#define PxIE 0x14
#define PxCMD 0x18
#define PxTFD 0x20
#define PxSIG 0x24
#define PxSSTS 0x28
#define PxSCTL 0x2C
#define PxSERR 0x30
#define PxSACT 0x34
#define PxCI 0x38
#define PxSNTF 0x3C
#define PxFBS 0x40
#define AHCI_CMD_ST (1u << 0)
#define AHCI_CMD_FRE (1u << 4)
#define AHCI_CMD_W (1u << 6)
#define AHCI_CMD_FR (1u << 14)
#define AHCI_CMD_CR (1u << 15)
#define AHCI_CMD_ICC_ACTIVE (1u << 28)
#define ATA_CMD_IDENTIFY 0xEC
#define ATA_CMD_IDENTIFY_PACKET 0xA1
#define ATA_CMD_READ_DMA_EXT 0x25
#define ATA_CMD_WRITE_DMA_EXT 0x35
typedef struct __attribute__((packed)) ahci_cmd_header {
u16 flags;
u16 prdtl;
u32 prdbc;
u32 ctba;
u32 ctbau;
u32 reserved[4];
} ahci_cmd_header;
typedef struct __attribute__((packed)) ahci_prdt_entry {
u32 dba;
u32 dbau;
u32 reserved;
u32 dbc_i;
} ahci_prdt_entry;
typedef struct __attribute__((packed)) ahci_cmd_table {
u8 cfis[64];
u8 acmd[16];
u8 reserved[48];
ahci_prdt_entry prdt[1];
} ahci_cmd_table;
static const struct dkm_log_api *g_log;
static volatile u32 *g_abar;
static u32 g_ready_port = 0xffffffffu;
static ahci_cmd_header *g_cmd_header;
static struct dkm_dma_buffer g_cmd_table;
static struct dkm_dma_buffer g_data;
static u32 pci_read(u8 bus, u8 dev, u8 func, u8 reg) {
return dkm_pci_read(bus, dev, func, reg);
}
static void pci_write(u8 bus, u8 dev, u8 func, u8 reg, u32 value) {
dkm_pci_write(bus, dev, func, reg, value);
}
static void log_hex(const char *prefix, u64 value) {
static const char hex[] = "0123456789abcdef";
char buf[19];
u32 pos = 0;
buf[pos++] = '0';
buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(value >> (i * 4)) & 0xf];
}
buf[pos] = 0;
g_log->info(prefix);
g_log->info(buf);
}
static void ahci_zero(void *ptr, u32 len) {
u8 *p = (u8 *)ptr;
for (u32 i = 0; i < len; i++) p[i] = 0;
}
static int ahci_find(u8 *out_bus, u8 *out_dev, u8 *out_func) {
for (u8 bus = 0; bus < 8; bus++) {
for (u8 dev = 0; dev < 32; dev++) {
u32 vd = pci_read(bus, dev, 0, PCI_VENDOR_ID);
if ((vd & 0xffff) == 0xffff) continue;
u8 header = (u8)(pci_read(bus, dev, 0, PCI_HEADER) >> 16);
u8 func_count = (header & 0x80) ? 8 : 1;
for (u8 func = 0; func < func_count; func++) {
u32 vd2 = pci_read(bus, dev, func, PCI_VENDOR_ID);
if ((vd2 & 0xffff) == 0xffff) continue;
u32 class_reg = pci_read(bus, dev, func, 0x08);
u8 prog_if = (u8)((class_reg >> 8) & 0xff);
u8 subclass = (u8)((class_reg >> 16) & 0xff);
u8 class_code = (u8)((class_reg >> 24) & 0xff);
if (class_code == AHCI_CLASS_STORAGE &&
subclass == AHCI_SUBCLASS_SATA &&
prog_if == AHCI_PROGIF_AHCI) {
*out_bus = bus;
*out_dev = dev;
*out_func = func;
return 0;
}
}
}
}
return -1;
}
static const char *sata_sig_name(u32 sig) {
if (sig == 0x00000101u) return "SATA drive";
if (sig == 0xEB140101u) return "ATAPI device";
if (sig == 0xC33C0101u) return "Enclosure mgmt";
if (sig == 0x96690101u) return "Port multiplier";
if (sig == 0x00000000u) return "empty/unknown";
return "unknown signature";
}
static void ahci_log_port(u32 port) {
if (!g_abar || port >= 32) {
return;
}
u32 base = HBA_PORT_BASE + port * HBA_PORT_SIZE;
u32 ssts = g_abar[(base + PxSSTS) / 4];
u32 sig = g_abar[(base + PxSIG) / 4];
u32 cmd = g_abar[(base + PxCMD) / 4];
u32 tfd = g_abar[(base + PxTFD) / 4];
u32 serr = g_abar[(base + PxSERR) / 4];
u32 ci = g_abar[(base + PxCI) / 4];
u32 sact = g_abar[(base + PxSACT) / 4];
u32 det = ssts & 0xf;
u32 spd = (ssts >> 4) & 0xf;
u32 ipm = (ssts >> 8) & 0xf;
log_hex("[ahci] port=", port);
log_hex("[ahci] SSTS=", ssts);
log_hex("[ahci] DET=", det);
log_hex("[ahci] SPD=", spd);
log_hex("[ahci] IPM=", ipm);
log_hex("[ahci] SIG=", sig);
g_log->info("[ahci] type");
g_log->info(sata_sig_name(sig));
log_hex("[ahci] CMD=", cmd);
log_hex("[ahci] TFD=", tfd);
log_hex("[ahci] SERR=", serr);
log_hex("[ahci] CI=", ci);
log_hex("[ahci] SACT=", sact);
}
static int ahci_stop_port(u32 port) {
u32 base = HBA_PORT_BASE + port * HBA_PORT_SIZE;
u32 cmd = g_abar[(base + PxCMD) / 4];
cmd &= ~AHCI_CMD_ST;
g_abar[(base + PxCMD) / 4] = cmd;
/* 实机: 500ms TSC 超时等待 CR 清除 */
u64 deadline = dkm_rdtsc() + dkm_tsc_per_ms * 500;
while (dkm_rdtsc() < deadline) {
cmd = g_abar[(base + PxCMD) / 4];
if (!(cmd & AHCI_CMD_CR)) break;
__asm__ volatile("pause");
}
cmd &= ~AHCI_CMD_FRE;
g_abar[(base + PxCMD) / 4] = cmd;
/* 实机: 500ms TSC 超时等待 FR 清除 */
deadline = dkm_rdtsc() + dkm_tsc_per_ms * 500;
while (dkm_rdtsc() < deadline) {
cmd = g_abar[(base + PxCMD) / 4];
if (!(cmd & AHCI_CMD_FR)) return 0;
__asm__ volatile("pause");
}
return -1;
}
static int ahci_start_port(u32 port) {
u32 base = HBA_PORT_BASE + port * HBA_PORT_SIZE;
u32 cmd = g_abar[(base + PxCMD) / 4];
cmd |= AHCI_CMD_FRE;
g_abar[(base + PxCMD) / 4] = cmd;
cmd |= AHCI_CMD_ST;
g_abar[(base + PxCMD) / 4] = cmd;
return 0;
}
static void ahci_fill_identify_fis(u8 *fis, u8 command) {
for (u32 i = 0; i < 64; i++) fis[i] = 0;
fis[0] = 0x27; /* Register H2D FIS */
fis[1] = 1u << 7; /* command */
fis[2] = command;
fis[7] = 1u << 6; /* LBA mode */
}
static void ahci_fill_read_fis(u8 *fis, u64 lba, u32 count) {
ahci_zero(fis, 64);
fis[0] = 0x27;
fis[1] = 1u << 7;
fis[2] = ATA_CMD_READ_DMA_EXT;
fis[4] = (u8)(lba & 0xff);
fis[5] = (u8)((lba >> 8) & 0xff);
fis[6] = (u8)((lba >> 16) & 0xff);
fis[7] = (1u << 6) | (u8)((lba >> 24) & 0x0f);
fis[8] = (u8)((lba >> 24) & 0xff);
fis[9] = (u8)((lba >> 32) & 0xff);
fis[10] = (u8)((lba >> 40) & 0xff);
fis[12] = (u8)(count & 0xff);
fis[13] = (u8)((count >> 8) & 0xff);
}
static void ahci_fill_write_fis(u8 *fis, u64 lba, u32 count) {
ahci_zero(fis, 64);
fis[0] = 0x27;
fis[1] = 1u << 7;
fis[2] = ATA_CMD_WRITE_DMA_EXT;
fis[4] = (u8)(lba & 0xff);
fis[5] = (u8)((lba >> 8) & 0xff);
fis[6] = (u8)((lba >> 16) & 0xff);
fis[7] = (1u << 6) | (u8)((lba >> 24) & 0x0f);
fis[8] = (u8)((lba >> 24) & 0xff);
fis[9] = (u8)((lba >> 32) & 0xff);
fis[10] = (u8)((lba >> 40) & 0xff);
fis[12] = (u8)(count & 0xff);
fis[13] = (u8)((count >> 8) & 0xff);
}
static int ahci_read_blocks_internal(u32 port, ahci_cmd_header *hdr, struct dkm_dma_buffer *table, struct dkm_dma_buffer *data, u64 lba, u32 count, void *buffer) {
if (!buffer || count == 0) return -1;
if (count > 8) return -2;
u32 base = HBA_PORT_BASE + port * HBA_PORT_SIZE;
ahci_cmd_table *tbl = (ahci_cmd_table *)table->virt;
u32 bytes = count * 512;
ahci_zero(tbl, sizeof(ahci_cmd_table));
ahci_zero(data->virt, bytes);
hdr[0].flags = 5;
hdr[0].prdtl = 1;
hdr[0].prdbc = 0;
hdr[0].ctba = (u32)(table->phys & 0xffffffffu);
hdr[0].ctbau = (u32)(table->phys >> 32);
tbl->prdt[0].dba = (u32)(data->phys & 0xffffffffu);
tbl->prdt[0].dbau = (u32)(data->phys >> 32);
tbl->prdt[0].dbc_i = (bytes - 1) | (1u << 31);
ahci_fill_read_fis(tbl->cfis, lba, count);
g_abar[(base + PxIS) / 4] = 0xffffffffu;
g_abar[HBA_IS / 4] = (1u << port);
g_abar[(base + PxCI) / 4] = 1;
for (u32 i = 0; i < 5000000; i++) {
if ((g_abar[(base + PxCI) / 4] & 1u) == 0) {
u8 *dst = (u8 *)buffer;
u8 *src = (u8 *)data->virt;
for (u32 j = 0; j < bytes; j++) dst[j] = src[j];
return 0;
}
}
g_log->warn("[ahci] READ timeout");
log_hex("[ahci] READ lba=", lba);
log_hex("[ahci] READ count=", count);
log_hex("[ahci] READ CI=", g_abar[(base + PxCI) / 4]);
log_hex("[ahci] READ IS=", g_abar[(base + PxIS) / 4]);
log_hex("[ahci] READ TFD=", g_abar[(base + PxTFD) / 4]);
return -3;
}
static int ahci_write_blocks_internal(u32 port, ahci_cmd_header *hdr, struct dkm_dma_buffer *table, struct dkm_dma_buffer *data, u64 lba, u32 count, const void *buffer) {
if (!buffer || count == 0) return -1;
if (count > 8) return -2;
u32 base = HBA_PORT_BASE + port * HBA_PORT_SIZE;
ahci_cmd_table *tbl = (ahci_cmd_table *)table->virt;
u32 bytes = count * 512;
ahci_zero(tbl, sizeof(ahci_cmd_table));
/* copy data from user buffer into DMA buffer */
{
u8 *dst = (u8 *)data->virt;
const u8 *src = (const u8 *)buffer;
for (u32 j = 0; j < bytes; j++) dst[j] = src[j];
}
hdr[0].flags = 5 | (1u << 6); /* CFL=5, W=1 (write) */
hdr[0].prdtl = 1;
hdr[0].prdbc = 0;
hdr[0].ctba = (u32)(table->phys & 0xffffffffu);
hdr[0].ctbau = (u32)(table->phys >> 32);
tbl->prdt[0].dba = (u32)(data->phys & 0xffffffffu);
tbl->prdt[0].dbau = (u32)(data->phys >> 32);
tbl->prdt[0].dbc_i = (bytes - 1) | (1u << 31);
ahci_fill_write_fis(tbl->cfis, lba, count);
/* set PxCMD.W to indicate write direction */
u32 cmd = g_abar[(base + PxCMD) / 4];
cmd |= AHCI_CMD_W;
g_abar[(base + PxCMD) / 4] = cmd;
g_abar[(base + PxIS) / 4] = 0xffffffffu;
g_abar[HBA_IS / 4] = (1u << port);
g_abar[(base + PxCI) / 4] = 1;
for (u32 i = 0; i < 5000000; i++) {
if ((g_abar[(base + PxCI) / 4] & 1u) == 0) {
/* clear PxCMD.W after write completes */
cmd = g_abar[(base + PxCMD) / 4];
cmd &= ~AHCI_CMD_W;
g_abar[(base + PxCMD) / 4] = cmd;
return 0;
}
}
/* timeout: clear PxCMD.W */
cmd = g_abar[(base + PxCMD) / 4];
cmd &= ~AHCI_CMD_W;
g_abar[(base + PxCMD) / 4] = cmd;
g_log->warn("[ahci] WRITE timeout");
log_hex("[ahci] WRITE lba=", lba);
log_hex("[ahci] WRITE count=", count);
log_hex("[ahci] WRITE CI=", g_abar[(base + PxCI) / 4]);
log_hex("[ahci] WRITE IS=", g_abar[(base + PxIS) / 4]);
log_hex("[ahci] WRITE TFD=", g_abar[(base + PxTFD) / 4]);
return -3;
}
static int ahci_block_read(void *ctx, u64 lba, u32 count, void *buffer) {
(void)ctx;
if (g_ready_port == 0xffffffffu || !g_cmd_header) return -1;
log_hex("[ahci] block_read lba=", lba);
log_hex("[ahci] block_read count=", count);
while (count > 0) {
u32 chunk = count > 8 ? 8 : count;
int status = ahci_read_blocks_internal(g_ready_port, g_cmd_header, &g_cmd_table, &g_data, lba, chunk, buffer);
if (status != 0) return status;
lba += chunk;
count -= chunk;
buffer = (void *)((u8 *)buffer + (chunk * 512));
}
return 0;
}
static int ahci_block_write(void *ctx, u64 lba, u32 count, const void *buffer) {
(void)ctx;
if (g_ready_port == 0xffffffffu || !g_cmd_header) return -1;
/* ensure port is in ST+FRE state */
u32 base = HBA_PORT_BASE + g_ready_port * HBA_PORT_SIZE;
u32 cmd = g_abar[(base + PxCMD) / 4];
if (!(cmd & AHCI_CMD_ST) || !(cmd & AHCI_CMD_FRE)) {
g_log->warn("[ahci] port not ready; restarting");
ahci_stop_port(g_ready_port);
ahci_start_port(g_ready_port);
}
while (count > 0) {
u32 chunk = count > 8 ? 8 : count;
int status = ahci_write_blocks_internal(g_ready_port, g_cmd_header, &g_cmd_table, &g_data, lba, chunk, buffer);
if (status != 0) return status;
lba += chunk;
count -= chunk;
buffer = (const void *)((const u8 *)buffer + (chunk * 512));
}
return 0;
}
static int ahci_read_lba0(u32 port, ahci_cmd_header *hdr, struct dkm_dma_buffer *table, struct dkm_dma_buffer *data) {
int status = ahci_read_blocks_internal(port, hdr, table, data, 0, 1, data->virt);
if (status == 0) {
log_hex("[ahci] READ LBA0 port=", port);
log_hex("[ahci] READ LBA0 bytes=", hdr[0].prdbc);
log_hex("[ahci] READ LBA0 word0=", ((u16 *)data->virt)[0]);
log_hex("[ahci] READ LBA0 word255=", ((u16 *)data->virt)[255]);
return 1;
}
return status;
}
static int ahci_identify_port(u32 port, const struct dkm_dma_api *dma) {
if (!dma || !dma->alloc_pages) return -1;
u32 base = HBA_PORT_BASE + port * HBA_PORT_SIZE;
u32 ssts = g_abar[(base + PxSSTS) / 4];
u32 sig = g_abar[(base + PxSIG) / 4];
u32 det = ssts & 0xf;
u32 ipm = (ssts >> 8) & 0xf;
if (det != 3 || ipm != 1) return 0;
if (sig != 0x00000101u) {
g_log->info("[ahci] IDENTIFY skipped non-SATA port");
log_hex("[ahci] IDENTIFY skip port=", port);
log_hex("[ahci] IDENTIFY skip sig=", sig);
return 0;
}
struct dkm_dma_buffer clb;
struct dkm_dma_buffer fis;
struct dkm_dma_buffer table;
struct dkm_dma_buffer data;
if (dma->alloc_pages(1, 1024, 0x100000000ULL, &clb) != 0) return -2;
if (dma->alloc_pages(1, 256, 0x100000000ULL, &fis) != 0) return -3;
if (dma->alloc_pages(1, 128, 0x100000000ULL, &table) != 0) return -4;
if (dma->alloc_pages(1, 512, 0x100000000ULL, &data) != 0) return -5;
if (ahci_stop_port(port) != 0) {
g_log->warn("[ahci] port stop timeout");
return -6;
}
g_abar[(base + PxCLB) / 4] = (u32)(clb.phys & 0xffffffffu);
g_abar[(base + PxCLB + 4) / 4] = (u32)(clb.phys >> 32);
g_abar[(base + PxFB) / 4] = (u32)(fis.phys & 0xffffffffu);
g_abar[(base + PxFB + 4) / 4] = (u32)(fis.phys >> 32);
ahci_cmd_header *hdr = (ahci_cmd_header *)clb.virt;
ahci_cmd_table *tbl = (ahci_cmd_table *)table.virt;
hdr[0].flags = 5; /* FIS length in DWORDS */
hdr[0].prdtl = 1;
hdr[0].ctba = (u32)(table.phys & 0xffffffffu);
hdr[0].ctbau = (u32)(table.phys >> 32);
tbl->prdt[0].dba = (u32)(data.phys & 0xffffffffu);
tbl->prdt[0].dbau = (u32)(data.phys >> 32);
tbl->prdt[0].dbc_i = (512 - 1) | (1u << 31);
u8 cmd = ATA_CMD_IDENTIFY;
ahci_fill_identify_fis(tbl->cfis, cmd);
g_abar[(base + PxIS) / 4] = 0xffffffffu;
g_abar[HBA_IS / 4] = (1u << port);
ahci_start_port(port);
g_abar[(base + PxCI) / 4] = 1;
for (u32 i = 0; i < 5000000; i++) {
if ((g_abar[(base + PxCI) / 4] & 1u) == 0) {
log_hex("[ahci] IDENTIFY port=", port);
log_hex("[ahci] IDENTIFY status=", g_abar[(base + PxTFD) / 4]);
log_hex("[ahci] IDENTIFY bytes=", hdr[0].prdbc);
u16 *id = (u16 *)data.virt;
log_hex("[ahci] IDENTIFY word0=", id[0]);
log_hex("[ahci] IDENTIFY word49=", id[49]);
log_hex("[ahci] IDENTIFY word83=", id[83]);
ahci_read_lba0(port, hdr, &table, &data);
g_ready_port = port;
g_cmd_header = hdr;
g_cmd_table = table;
g_data = data;
return 1;
}
}
g_log->warn("[ahci] IDENTIFY timeout");
log_hex("[ahci] IDENTIFY CI=", g_abar[(base + PxCI) / 4]);
log_hex("[ahci] IDENTIFY IS=", g_abar[(base + PxIS) / 4]);
log_hex("[ahci] IDENTIFY TFD=", g_abar[(base + PxTFD) / 4]);
return -7;
}
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
/* 实机要求: 先校准 TSC, 再使用基于 CPU 频率的延迟 */
dkm_tsc_calibrate();
if (!api || !api->log) return -1;
g_log = api->log;
g_log->info("[ahci] init begin");
u8 bus = 0;
u8 dev = 0;
u8 func = 0;
if (ahci_find(&bus, &dev, &func) != 0) {
g_log->warn("[ahci] AHCI controller not found");
g_log->info("[ahci] driver ready");
return 0;
}
g_log->info("[ahci] AHCI controller found");
log_hex("[ahci] bus=", bus);
log_hex("[ahci] dev=", dev);
log_hex("[ahci] func=", func);
u32 vd = pci_read(bus, dev, func, PCI_VENDOR_ID);
log_hex("[ahci] vendor=", vd & 0xffff);
log_hex("[ahci] device=", vd >> 16);
u32 command = pci_read(bus, dev, func, PCI_COMMAND) & 0xffff;
command |= PCI_CMD_MEM | PCI_CMD_BUSM;
pci_write(bus, dev, func, PCI_COMMAND, command);
log_hex("[ahci] PCI command=", command);
u64 abar_phys = (u64)(pci_read(bus, dev, func, PCI_BAR5) & 0xFFFFFFF0u);
u32 irq_line = pci_read(bus, dev, func, PCI_IRQ_LINE) & 0xff;
log_hex("[ahci] ABAR phys=", abar_phys);
log_hex("[ahci] PCI IRQ line=", irq_line);
if (!api->hhdm_offset || !abar_phys) {
g_log->warn("[ahci] missing HHDM or ABAR; skip MMIO enumeration");
g_log->info("[ahci] driver ready");
return 0;
}
g_abar = (volatile u32 *)(uintptr_t)(api->hhdm_offset + abar_phys);
log_hex("[ahci] HHDM offset=", api->hhdm_offset);
u32 cap = g_abar[HBA_CAP / 4];
u32 ghc = g_abar[HBA_GHC / 4];
u32 is = g_abar[HBA_IS / 4];
u32 pi = g_abar[HBA_PI / 4];
u32 vs = g_abar[HBA_VS / 4];
u32 cap2 = g_abar[HBA_CAP2 / 4];
u32 bohc = g_abar[HBA_BOHC / 4];
log_hex("[ahci] CAP=", cap);
log_hex("[ahci] GHC=", ghc);
log_hex("[ahci] IS=", is);
log_hex("[ahci] PI=", pi);
log_hex("[ahci] VS=", vs);
log_hex("[ahci] CAP2=", cap2);
log_hex("[ahci] BOHC=", bohc);
log_hex("[ahci] ports count=", (cap & 0x1f) + 1);
log_hex("[ahci] cmd slots=", ((cap >> 8) & 0x1f) + 1);
u32 implemented = 0;
for (u32 port = 0; port < 32; port++) {
if (pi & (1u << port)) {
implemented++;
ahci_log_port(port);
}
}
log_hex("[ahci] implemented ports=", implemented);
u32 identified = 0;
if (api->dma) {
for (u32 port = 0; port < 32; port++) {
if (pi & (1u << port)) {
int ident = ahci_identify_port(port, api->dma);
if (ident > 0) {
identified++;
break;
}
}
}
} else {
g_log->warn("[ahci] DMA API unavailable; skip IDENTIFY");
}
log_hex("[ahci] identified ports=", identified);
if (identified && api->block && api->block->register_device) {
struct dkm_block_device_desc desc;
desc.name = "ahci0";
desc.sector_size = 512;
desc.sector_count = 0;
desc.ctx = 0;
desc.read = ahci_block_read;
desc.write = ahci_block_write;
int index = api->block->register_device(&desc);
log_hex("[ahci] block provider index=", (u64)(i64)index);
} else if (identified) {
g_log->warn("[ahci] block API unavailable; provider not registered");
}
g_log->info("[ahci] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+358
View File
@@ -0,0 +1,358 @@
/* DKM APIC Driver — APIC discovery with PIC fallback
* Stage 0, required, depends on "timer", provides "irq" and "apic".
* Current kernel IRQ backend is still PIC; this driver only discovers APIC
* topology and keeps PIC routing active.
*/
#include <stdint.h>
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response;
int (*irq_register)(u8 irq, void *handler);
u64 hhdm_offset;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
static const char *const g_depends[] = { "timer" };
static const char *const g_provides[] = { "irq", "apic" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "apic",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 3, /* DKM_CLASS_INTERRUPT */
.stage = 0,
.flags = 1, /* DKM_F_REQUIRED */
.priority = 0,
.depends = g_depends,
.depends_count = 1,
.provides = g_provides,
.provides_count = 2,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
typedef struct __attribute__((packed)) {
char signature[8];
u8 checksum;
char oem_id[6];
u8 revision;
u32 rsdt_addr;
} acpi_rsdp_v1;
typedef struct __attribute__((packed)) {
char signature[8];
u8 checksum;
char oem_id[6];
u8 revision;
u32 rsdt_addr;
u32 length;
u64 xsdt_addr;
u8 ext_checksum;
u8 reserved[3];
} acpi_rsdp_v2;
typedef struct __attribute__((packed)) {
char signature[4];
u32 length;
u8 revision;
u8 checksum;
char oem_id[6];
char oem_table_id[8];
u32 oem_revision;
u32 creator_id;
u32 creator_revision;
} acpi_sdt_header;
typedef struct __attribute__((packed)) {
acpi_sdt_header hdr;
u32 lapic_addr;
u32 flags;
} acpi_madt;
struct madt_info {
u64 lapic_phys;
u32 flags;
u32 lapic_count;
u32 ioapic_count;
u32 iso_count;
};
static const struct dkm_log_api *g_log;
static int memeq(const char *a, const char *b, u32 n) {
for (u32 i = 0; i < n; i++) {
if (a[i] != b[i]) return 0;
}
return 1;
}
static u8 checksum8(const u8 *data, u32 len) {
u8 sum = 0;
for (u32 i = 0; i < len; i++) sum += data[i];
return sum;
}
static void log_hex(const char *prefix, u64 val) {
static const char hex[] = "0123456789abcdef";
char buf[19];
u32 pos = 0;
buf[pos++] = '0';
buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(val >> (i * 4)) & 0xf];
}
buf[pos] = 0;
g_log->info(prefix);
g_log->info(buf);
}
static void cpuid(u32 leaf, u32 *a, u32 *b, u32 *c, u32 *d) {
__asm__ volatile ("cpuid"
: "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d)
: "a"(leaf), "c"(0));
}
static u64 rdmsr(u32 msr) {
u32 lo;
u32 hi;
__asm__ volatile ("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
return ((u64)hi << 32) | lo;
}
static int cpu_has_lapic(void) {
u32 a, b, c, d;
cpuid(1, &a, &b, &c, &d);
(void)a;
(void)b;
(void)c;
return (d & (1u << 9)) != 0;
}
static const acpi_sdt_header *find_table_from_rsdt(const acpi_sdt_header *rsdt, const char sig[4], u32 entry_size) {
if (!rsdt || rsdt->length < sizeof(acpi_sdt_header)) return NULL;
if (checksum8((const u8 *)rsdt, rsdt->length) != 0) return NULL;
u32 count = (rsdt->length - sizeof(acpi_sdt_header)) / entry_size;
const u8 *entries = (const u8 *)rsdt + sizeof(acpi_sdt_header);
for (u32 i = 0; i < count; i++) {
u64 addr;
if (entry_size == 4) {
addr = (u64)((const u32 *)entries)[i];
} else {
addr = ((const u64 *)entries)[i];
}
if (!addr) continue;
const acpi_sdt_header *hdr = (const acpi_sdt_header *)(uintptr_t)addr;
if (hdr->length >= sizeof(acpi_sdt_header) && memeq(hdr->signature, sig, 4)) {
if (checksum8((const u8 *)hdr, hdr->length) == 0) return hdr;
}
}
return NULL;
}
static const acpi_madt *find_madt(const void *rsdp_addr) {
if (!rsdp_addr) return NULL;
const acpi_rsdp_v2 *rsdp = (const acpi_rsdp_v2 *)rsdp_addr;
if (!memeq(rsdp->signature, "RSD PTR ", 8)) return NULL;
if (checksum8((const u8 *)rsdp, 20) != 0) return NULL;
if (rsdp->revision >= 2 && rsdp->length >= sizeof(acpi_rsdp_v2) && rsdp->xsdt_addr) {
if (checksum8((const u8 *)rsdp, rsdp->length) == 0) {
const acpi_sdt_header *xsdt = (const acpi_sdt_header *)(uintptr_t)rsdp->xsdt_addr;
const acpi_sdt_header *madt = find_table_from_rsdt(xsdt, "APIC", 8);
if (madt) return (const acpi_madt *)madt;
}
}
if (rsdp->rsdt_addr) {
const acpi_sdt_header *rsdt = (const acpi_sdt_header *)(uintptr_t)(u64)rsdp->rsdt_addr;
const acpi_sdt_header *madt = find_table_from_rsdt(rsdt, "APIC", 4);
if (madt) return (const acpi_madt *)madt;
}
return NULL;
}
static void parse_madt_entries(const acpi_madt *madt, struct madt_info *info) {
const u8 *base = (const u8 *)madt;
u32 off = (u32)sizeof(acpi_madt);
while (off + 2 <= madt->hdr.length) {
const u8 *entry = base + off;
u8 type = entry[0];
u8 len = entry[1];
if (len < 2 || off + len > madt->hdr.length) {
g_log->warn("[apic] malformed MADT entry");
return;
}
if (type == 0 && len >= 8) {
u8 apic_id = entry[3];
u32 flags = *(const u32 *)(const void *)(entry + 4);
if (flags & 1u) info->lapic_count++;
log_hex("[apic] CPU LAPIC id=", apic_id);
} else if (type == 1 && len >= 12) {
u8 ioapic_id = entry[2];
u32 addr = *(const u32 *)(const void *)(entry + 4);
u32 gsi = *(const u32 *)(const void *)(entry + 8);
info->ioapic_count++;
log_hex("[apic] IOAPIC id=", ioapic_id);
log_hex("[apic] IOAPIC addr=", addr);
log_hex("[apic] IOAPIC gsi_base=", gsi);
} else if (type == 2 && len >= 10) {
u8 source = entry[3];
u32 gsi = *(const u32 *)(const void *)(entry + 4);
u16 flags = *(const u16 *)(const void *)(entry + 8);
info->iso_count++;
log_hex("[apic] ISO source=", source);
log_hex("[apic] ISO gsi=", gsi);
log_hex("[apic] ISO flags=", flags);
} else if (type == 5 && len >= 12) {
u64 override = *(const u64 *)(const void *)(entry + 4);
info->lapic_phys = override;
log_hex("[apic] LAPIC override=", override);
}
off += len;
}
}
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
g_log->info("[apic] init begin");
if (!api->irq_register) {
g_log->error("[apic] kernel irq_register missing");
return -1;
}
g_log->info("[apic] kernel IRQ backend present: PIC");
if (!cpu_has_lapic()) {
g_log->warn("[apic] CPUID local APIC not present; PIC fallback active");
g_log->info("[apic] driver ready");
return 0;
}
g_log->info("[apic] CPUID local APIC present");
u64 apic_base = rdmsr(0x1B);
u64 lapic_phys = apic_base & 0xFFFFF000ULL;
log_hex("[apic] IA32_APIC_BASE=", apic_base);
log_hex("[apic] LAPIC phys base=", lapic_phys);
if (apic_base & (1ULL << 8)) g_log->info("[apic] bootstrap processor");
if (apic_base & (1ULL << 11)) g_log->info("[apic] LAPIC enabled by firmware");
struct madt_info info;
info.lapic_phys = lapic_phys;
info.flags = 0;
info.lapic_count = 0;
info.ioapic_count = 0;
info.iso_count = 0;
const acpi_madt *madt = find_madt(api->rsdp_address);
if (madt) {
g_log->info("[apic] MADT found");
info.lapic_phys = (u64)madt->lapic_addr;
info.flags = madt->flags;
log_hex("[apic] MADT lapic_phys=", info.lapic_phys);
log_hex("[apic] MADT flags=", info.flags);
parse_madt_entries(madt, &info);
log_hex("[apic] CPU LAPIC count=", info.lapic_count);
log_hex("[apic] IOAPIC count=", info.ioapic_count);
log_hex("[apic] ISO count=", info.iso_count);
} else {
g_log->warn("[apic] MADT not found; PIC fallback active");
}
if (api->hhdm_offset && info.lapic_phys) {
volatile u32 *lapic = (volatile u32 *)(uintptr_t)(api->hhdm_offset + info.lapic_phys);
log_hex("[apic] LAPIC ID reg=", lapic[0x20 / 4]);
log_hex("[apic] LAPIC version reg=", lapic[0x30 / 4]);
log_hex("[apic] LAPIC SVR reg=", lapic[0xF0 / 4]);
} else {
g_log->warn("[apic] HHDM unavailable; skip LAPIC MMIO read");
}
g_log->info("[apic] discovery complete; PIC routing retained");
g_log->info("[apic] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+798
View File
@@ -0,0 +1,798 @@
/* DKM ath9k Driver — Atheros AR928x 802.11abgn WiFi
* Stage 3, optional, depends on "pci" and "irq", provides "netdev".
*
* 实现范围:
* - PCI 探测(vendor 0x168c,AR9280/9285/9287 等常见 PCIe chip)
* - BAR0 MMIO 映射(HHDM 模式,与 e1000 相同)
* - 软件复位 + RTC 唤醒序列
* - EEPROM 读取(4KB ATF EEPROM,读 MAC 地址 + 校准数据基址)
* - 简化硬件初始化(ath9k_hw_init 关键寄存器序列)
* - RX 描述符环 + beacon 接收
* - 信道切换 + 被动扫描状态机
* - 802.11 beacon IE 解析(SSID/RSSI/DS channel/RSN/RSN capabilities)
* - netdev 注册 + 扫描结果查询回调(通过 kernel_api.net.scan_*)
*
* 注意:QEMU 不支持 WiFi 网卡模拟,本驱动只能在真实硬件测试。
* 完整 ath9k HAL 寄存器初始化序列非常庞大,本驱动保留核心扫描路径,
* 部分高级特性(ANI/MRR/AGC 调优)留待硬件验证后增量完善。
*/
#include "../dkm_shared.h"
static const char *const g_depends[] = {"pci","irq"};
static const char *const g_provides[] = {"netdev"};
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic=DKM_DRIVER_MAGIC,.abi_version=DKM_ABI_VERSION,
.desc_size=sizeof(struct dkm_driver_desc),
.name="ath9k",.version="0.1.0",.vendor="Deshab",
.driver_class=9,.stage=3,.flags=0,.priority=0,
.depends=g_depends,.depends_count=2,
.provides=g_provides,.provides_count=1,.min_kernel_abi=1,
};
/* ---- ath9k 寄存器(AR9280/9285/9287 PCIe MAC,Linux ath9k reg.h 关键子集) ---- */
#define AR_RC 0x4000u
#define AR_RC_MAC 0x00000001u
#define AR_RC_BB 0x00000002u
#define AR_RC_RPCU 0x00000004u
#define AR_RC_RDMA 0x00000008u
#define AR_RTC_RESET 0x0040u
#define AR_RTC_FORCE_WAKE 0x0044u
#define AR_RTC_FORCE_WAKE_ON 0x00000001u
#define AR_RTC_FORCE_WAKE_INT 0x00000002u
#define AR_RTC_STATUS 0x0048u
#define AR_RTC_STATUS_SHUTDOWN 0x00000001u
#define AR_RTC_STATUS_ON 0x00000002u
#define AR_RTC_SLEEP_CLK 0x004Cu
#define AR_EEPROM_CMD 0x4008u
#define AR_EEPROM_STS 0x400Cu
#define AR_EEPROM_DATA 0x4010u
#define AR_EEPROM_CMD_READ 0x00000001u
#define AR_EEPROM_CMD_RESET 0x00000004u
#define AR_EEPROM_STS_RDBUSY 0x00010000u
#define AR_EEPROM_STS_DATA_M 0x0000FFFFu
#define AR_EEPROM_STS_VALID 0x00000100u
/* MAC address registers */
#define AR_STA_ID0 0x0800u
#define AR_STA_ID1 0x0804u
#define AR_BSSMSKL 0x0808u
#define AR_BSSMSKH 0x080Cu
/* RX DMA */
#define AR_RXDP 0x0000u
#define AR_RXCFG 0x0004u
#define AR_RXCFG_ZLFDMA 0x08000000u
#define AR_MIBC 0x0044u
#define AR_CR 0x0008u
#define AR_CR_RXE 0x00000004u
#define AR_CR_RXD 0x00000001u
#define AR_RXNOPTR 0x0064u
/* Interrupts */
#define AR_IMR 0x0080u
#define AR_ISR 0x0084u
#define AR_ISR_RAC 0x00C0u
#define AR_ISR_RXOK 0x00000001u
#define AR_ISR_RXERR 0x00000002u
#define AR_ISR_RXORN 0x00000020u
#define AR_ISR_RXKINT 0x00000100u
#define AR_IMR_RXOK AR_ISR_RXOK
#define AR_IMR_RXERR AR_ISR_RXERR
#define AR_IMR_RXORN AR_ISR_RXORN
#define AR_IMR_RXKINT AR_ISR_RXKINT
/* Channel registers (PHY) */
#define AR_PHY_BASE 0x9800u
#define AR_PHY(_n) (AR_PHY_BASE + ((_n) << 2))
#define AR_PHY_CCK_DETECT AR_PHY(0x0A14)
#define AR_PHY_SYNTH_CONTROL AR_PHY(0x9874)
#define AR_PHY_RFBUS_REQ AR_PHY(0x987C)
#define AR_PHY_RFBUS_GRANT AR_PHY(0x987C)
#define AR_PHY_PLL 0x9914u
#define AR_PHY_PLL_CONTROL AR_PHY(0x9914)
/*---- RX 描述符 (ath9k RX status descriptor, 8 words = 32 bytes) ---- */
struct ath9k_rx_desc {
u32 ds_link; /* next descriptor phys (32-bit) */
u32 ds_data; /* data buffer phys (32-bit) */
u32 ds_ctl0; /* buffer len + control */
u32 ds_ctl1; /* frame type */
u32 ds_status0; /* RX status 0 */
u32 ds_status1; /* RX status 1 */
u32 ds_status2; /* RX status 2 (RSSI) */
u32 ds_status3; /* RX status 3 */
} __attribute__((packed));
#define ATH9K_RXCTL_BUF_LEN_S 0
#define ATH9K_RXCTL_BUF_LEN_M 0x00000FFFu
#define ATH9K_RXCTL_INTREQ 0x00020000u
#define ATH9K_RXSTATUS_DONE 0x00000001u
#define ATH9K_RXSTATUS_OK 0x00000002u
#define ATH9K_RXSTATUS_CRC 0x00000004u
#define ATH9K_RXSTATUS_DECRYPT_BUSY 0x00000008u
#define ATH9K_RXSTATUS_FRAME_LEN_S 0
#define ATH9K_RXSTATUS_FRAME_LEN_M 0x0000FFF8u
#define ATH9K_RX_BUF_SIZE 4096u
#define ATH9K_RX_DESC_COUNT 16u
/* ---- 802.11 帧解析 ---- */
/* frame_control: type=2 bits, subtype=4 bits */
#define IEEE80211_FTYPE_MGMT 0x0000u
#define IEEE80211_STYPE_BEACON 0x0008u
#define IEEE80211_STYPE_PROBE_RESP 0x0005u
/* Information Element IDs */
#define WLAN_EID_SSID 0
#define WLAN_EID_DS_PARAMS 3
#define WLAN_EID_RSN 48
#define WLAN_EID_VENDOR 221
#define ATH9K_MAX_SCAN_RESULTS 32u
#define ATH9K_SSID_MAX 32u
struct ath9k_scan_result {
char ssid[ATH9K_SSID_MAX + 1];
u8 bssid[6];
u8 channel;
i8 rssi;
u8 security;
};
/* 2.4GHz 信道表 (channel -> freq MHz) */
__attribute__((used))
static const u16 g_chan2g[] = {
2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447,
2452, 2457, 2462, 2467, 2472
};
#define ATH9K_CHAN_2G_COUNT (sizeof(g_chan2g) / sizeof(g_chan2g[0]))
/* ---- 全局状态 ---- */
static const struct dkm_log_api *g_log;
static volatile u8 *g_mmio;
static u64 g_bar0_phys;
static u8 g_mac[6];
static u16 g_pci_device_id;
static u8 g_pci_irq;
static struct dkm_dma_buffer g_rx_desc_dma;
static struct ath9k_rx_desc *g_rx_desc;
static struct dkm_dma_buffer g_rx_buf_dma[ATH9K_RX_DESC_COUNT];
static u8 *g_rx_buf[ATH9K_RX_DESC_COUNT];
static u32 g_rx_head;
static int g_rx_ready;
/* 扫描状态 */
static struct ath9k_scan_result g_scan_results[ATH9K_MAX_SCAN_RESULTS];
static u32 g_scan_count;
static int g_scanning;
/* ---- 串口日志(参考 e1000 raw_log) ---- */
#define COM1 0x3F8
/* 串口发送等待 thin wrapper — 调用 dkm 共享实现 */
static void serial_wait_tx(void) { dkm_serial_wait_tx(COM1); }
static void raw_log(const char *s) {
while (*s) {
char c = *s++;
if (c == '\n') {
serial_wait_tx();
dkm_outb(COM1, '\r');
}
serial_wait_tx();
dkm_outb(COM1, (u8)c);
}
}
static void raw_hex(const char *prefix, u64 v) {
static const char h[] = "0123456789abcdef";
raw_log(prefix);
raw_log("0x");
for (int i=15; i>=0; i--) {
serial_wait_tx();
dkm_outb(COM1, (u8)h[(v >> (i * 4)) & 0xf]);
}
raw_log("\n");
}
/* ---- PCI 配置空间 ---- */
static u32 pci_read(u8 bus, u8 dev, u8 func, u8 reg) {
return dkm_pci_read(bus, dev, func, reg);
}
static void pci_write(u8 bus, u8 dev, u8 func, u8 reg, u32 v) {
dkm_pci_write(bus, dev, func, reg, v);
}
/* ath9k PCI 设备 ID 表(vendor 0x168c Atheros) */
static int ath9k_find(u8 *bus, u8 *dev) {
for (u8 d=0; d<32; d++) {
u32 vd = pci_read(0,d,0,PCI_VENDOR_ID);
if ((vd&0xffff)==0xffff) continue;
if ((vd&0xffff)!=0x168c) continue;
u16 did = (u16)(vd>>16);
/* AR9280/9285/9287/9380/9580/9565 等常见 PCIe chip */
if (did==0x002A || did==0x002B || did==0x002C || did==0x002D ||
did==0x002E || did==0x0030 || did==0x0032 || did==0x0033 ||
did==0x0034 || did==0x0036 || did==0x0037 || did==0xAB34 ||
did==0x0029 || did==0x1A56 || did==0x2A37 || did==0x003C ||
did==0x003D || did==0x003E || did==0x0042 || did==0x0043 ||
did==0x0044 || did==0x0046 || did==0x0047 || did==0x0051 ||
did==0x0052 || did==0x0053 || did==0x0059 || did==0x005A ||
did==0x005B || did==0x005C || did==0x0061 || did==0x0063 ||
did==0x0065 || did==0x0066 || did==0x0067 || did==0x0068 ||
did==0x0069 || did==0x006A || did==0x006B || did==0x006C ||
did==0x006E || did==0x006F || did==0x0070 || did==0x0071 ||
did==0x0072 || did==0x0073 || did==0x0074 || did==0x0075 ||
did==0x0076 || did==0x0077 || did==0x0078 || did==0x0079 ||
did==0x007A || did==0x0080 || did==0x0081 || did==0x0082 ||
did==0x0083 || did==0x0085 || did==0x0086 || did==0x0087 ||
did==0x0088 || did==0x0089 || did==0x008A || did==0x008B ||
did==0x008C || did==0x008D || did==0x008E || did==0x008F ||
did==0x0090 || did==0x0091 || did==0x0092 || did==0x0093 ||
did==0x0094 || did==0x0095 || did==0x0096 || did==0x0097 ||
did==0x0098 || did==0x0099 || did==0x009A || did==0x009B ||
did==0x009C || did==0x009D || did==0x009E || did==0x009F ||
did==0x00A0 || did==0x00A1 || did==0x00A2 || did==0x00A3 ||
did==0x00A4 || did==0x00A5 || did==0x00A6 || did==0x00A7 ||
did==0x00A8 || did==0x00A9 || did==0x00AA || did==0x00AB ||
did==0x00AC || did==0x00AD || did==0x00AE || did==0x00AF) {
*bus=0; *dev=d; return 0;
}
/* 兜底:所有 Atheros 设备都接受(驱动加载后会校验 chip ID) */
*bus=0; *dev=d;
raw_log("[ath9k.raw] found Atheros device, did=0x");
static const char hh[] = "0123456789abcdef";
char hex[5];
hex[0]=hh[(did>>12)&0xf]; hex[1]=hh[(did>>8)&0xf];
hex[2]=hh[(did>>4)&0xf]; hex[3]=hh[did&0xf]; hex[4]=0;
raw_log(hex); raw_log("\n");
return 0;
}
return -1;
}
/* ---- MMIO 寄存器读写 ---- */
static u32 ath9k_reg_read(u32 reg) {
if (!g_mmio) return 0;
u32 v = *(volatile u32 *)(g_mmio + reg);
__asm__ volatile("" ::: "memory");
return v;
}
static void ath9k_reg_write(u32 reg, u32 v) {
if (!g_mmio) return;
*(volatile u32 *)(g_mmio + reg) = v;
__asm__ volatile("" ::: "memory");
}
static void ath9k_reg_rmw(u32 reg, u32 set, u32 clr) {
u32 v = ath9k_reg_read(reg);
v &= ~clr;
v |= set;
ath9k_reg_write(reg, v);
}
/* ---- EEPROM 读取(AR5416/AR9280 I2C-style EEPROM 接口) ---- */
static u16 ath9k_eeprom_read(u16 addr) {
/* AR5416_EEPROM_CMD: bit0=READ, bit1=BUSY, bit2=RESET */
/* 启动 read:写 cmd=READ | addr<<3 */
ath9k_reg_write(AR_EEPROM_CMD, AR_EEPROM_CMD_RESET);
dkm_delay_us(5);
u32 cmd = AR_EEPROM_CMD_READ | ((u32)(addr & 0x3FF) << 3);
ath9k_reg_write(AR_EEPROM_CMD, cmd);
/* 等待 RDBUSY 清除 (实机: 100ms TSC 超时) */
u64 deadline = dkm_rdtsc() + dkm_tsc_per_ms * 100;
while (dkm_rdtsc() < deadline) {
u32 sts = ath9k_reg_read(AR_EEPROM_STS);
if (!(sts & AR_EEPROM_STS_RDBUSY)) {
if (sts & AR_EEPROM_STS_VALID) {
return (u16)(sts & AR_EEPROM_STS_DATA_M);
}
return 0xffff;
}
dkm_delay_us(1);
}
return 0xffff;
}
/* ---- 软件复位 + RTC 唤醒 ---- */
static int ath9k_reset(void) {
raw_log("[ath9k.raw] reset sequence\n");
/* 1. 强制唤醒(Power-On) */
ath9k_reg_write(AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON | AR_RTC_FORCE_WAKE_INT);
dkm_delay_us(50);
/* 2. 等待 RTC 进入 ON 状态 (实机: 100ms TSC 超时) */
u64 deadline = dkm_rdtsc() + dkm_tsc_per_ms * 100;
while (dkm_rdtsc() < deadline) {
u32 s = ath9k_reg_read(AR_RTC_STATUS);
if ((s & 0x3) == AR_RTC_STATUS_ON) break;
dkm_delay_us(1);
}
/* 3. 全 chip 复位 */
ath9k_reg_write(AR_RC, AR_RC_MAC | AR_RC_BB | AR_RC_RPCU);
dkm_delay_us(100);
ath9k_reg_write(AR_RC, 0);
dkm_delay_us(100);
/* 4. 重新唤醒 */
ath9k_reg_write(AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON | AR_RTC_FORCE_WAKE_INT);
dkm_delay_us(50);
/* 5. 等待 RTC ON (实机: 100ms TSC 超时) */
u32 ok = 0;
u64 deadline2 = dkm_rdtsc() + dkm_tsc_per_ms * 100;
while (dkm_rdtsc() < deadline2) {
u32 s = ath9k_reg_read(AR_RTC_STATUS);
if ((s & 0x3) == AR_RTC_STATUS_ON) { ok = 1; break; }
dkm_delay_us(1);
}
if (!ok) { raw_log("[ath9k.raw] reset: RTC not ON\n"); return -1; }
raw_log("[ath9k.raw] reset: RTC ON\n");
return 0;
}
/* ---- 简化硬件初始化(ath9k_hw_init 关键序列) ----
* 完整 ath9k HAL 涉及 PLL/ADCDCO/AGC/ANI/Noise Floor 等数百寄存器魔法值,
* 本驱动保留最小可加载序列:基础时钟 + MAC 寄存器清零 + RX 使能准备。
* 真实扫描路径在硬件验证后增量完善。
*/
static int ath9k_hw_init(void) {
raw_log("[ath9k.raw] hw_init minimal\n");
/* 关闭 RX/DMA,清 STA_ID1 */
ath9k_reg_write(AR_CR, AR_CR_RXD);
dkm_delay_us(10);
ath9k_reg_write(AR_STA_ID1, 0);
/* 清中断 */
ath9k_reg_write(AR_ISR, 0xFFFFFFFFu);
ath9k_reg_read(AR_ISR_RAC);
/* 写 MAC 地址到 STA_ID0/1(驱动本地缓存) */
u32 mac_lo = (u32)g_mac[0] | ((u32)g_mac[1] << 8) |
((u32)g_mac[2] << 16) | ((u32)g_mac[3] << 24);
u32 mac_hi = (u32)g_mac[4] | ((u32)g_mac[5] << 8);
ath9k_reg_write(AR_STA_ID0, mac_lo);
ath9k_reg_rmw(AR_STA_ID1, (mac_hi & 0xFFFF), 0xFFFFu);
raw_log("[ath9k.raw] hw_init: MAC written\n");
return 0;
}
/* ---- RX 环初始化 ---- */
static int ath9k_rx_init(const struct dkm_dma_api *dma) {
if (!dma || !dma->alloc_pages || !g_mmio) return -1;
/* 分配 RX 描述符环(1页 = 4096 字节,足够 16 个 32B 描述符) */
if (dma->alloc_pages(1, 16, 0x100000000ULL, &g_rx_desc_dma) != 0) {
raw_log("[ath9k.raw] rx_init: desc alloc failed\n");
return -2;
}
g_rx_desc = (struct ath9k_rx_desc *)g_rx_desc_dma.virt;
/* 清零描述符 */
for (u32 i = 0; i < sizeof(struct ath9k_rx_desc) * ATH9K_RX_DESC_COUNT; i++) {
((u8 *)g_rx_desc)[i] = 0;
}
/* 分配每个 RX 缓冲区 */
for (u32 i = 0; i < ATH9K_RX_DESC_COUNT; i++) {
if (dma->alloc_pages(1, 16, 0x100000000ULL, &g_rx_buf_dma[i]) != 0) {
raw_log("[ath9k.raw] rx_init: buf alloc failed\n");
return -3;
}
g_rx_buf[i] = (u8 *)g_rx_buf_dma[i].virt;
/* 填描述符:link 指向下一个,data 指向缓冲区 */
g_rx_desc[i].ds_link = (u32)(g_rx_desc_dma.phys +
(((i + 1) % ATH9K_RX_DESC_COUNT) * sizeof(struct ath9k_rx_desc)));
g_rx_desc[i].ds_data = (u32)g_rx_buf_dma[i].phys;
g_rx_desc[i].ds_ctl0 = ATH9K_RX_BUF_SIZE & ATH9K_RXCTL_BUF_LEN_M;
g_rx_desc[i].ds_ctl1 = ATH9K_RXCTL_INTREQ;
g_rx_desc[i].ds_status0 = 0;
g_rx_desc[i].ds_status1 = 0;
g_rx_desc[i].ds_status2 = 0;
g_rx_desc[i].ds_status3 = 0;
}
__asm__ volatile("" ::: "memory");
raw_log("[ath9k.raw] rx_init: rings allocated\n");
/* 写 RXDP 指向第一个描述符,启用 RX */
ath9k_reg_write(AR_RXDP, (u32)g_rx_desc_dma.phys);
ath9k_reg_write(AR_RXCFG, 0); /* 默认 RX 配置 */
ath9k_reg_write(AR_MIBC, 0); /* 关闭 MIB 计数器,避免中断风暴 */
/* 使能 RXOK/RXERR 中断 */
ath9k_reg_write(AR_IMR, AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN);
/* 启动 RX DMA */
ath9k_reg_write(AR_CR, AR_CR_RXE);
g_rx_head = 0;
g_rx_ready = 1;
raw_log("[ath9k.raw] rx_init: RX enabled\n");
return 0;
}
/* ---- 802.11 beacon IE 解析 ----
* 从 beacon/probe-response 帧中提取 SSID、信道、加密类型。
* 返回 0 = 解析成功,-1 = 非 beacon,-2 = 太短
*/
static int parse_beacon(const u8 *frame, u32 len, struct ath9k_scan_result *out) {
if (len < 24 + 12) return -2;
/* frame_control(2) + duration(2) + DA(6) + SA(6) + BSSID(6) + seq(2) = 24 */
u16 fctl = (u16)frame[0] | ((u16)frame[1] << 8);
u16 ftype = fctl & 0x000Cu;
u16 fsubtype = fctl & 0x00F0u;
if (ftype != IEEE80211_FTYPE_MGMT) return -1;
if (fsubtype != IEEE80211_STYPE_BEACON && fsubtype != IEEE80211_STYPE_PROBE_RESP) return -1;
/* BSSID 在 offset 16 */
for (int i = 0; i < 6; i++) out->bssid[i] = frame[16 + i];
/* fixed: timestamp(8) + beacon_interval(2) + capability(2) = 12 bytes */
u32 ie_off = 24 + 12;
/* 默认值 */
out->ssid[0] = 0;
out->channel = 0;
out->security = DKM_NET_SEC_OPEN;
/* 遍历 IE */
while (ie_off + 2 <= len) {
u8 eid = frame[ie_off];
u8 elen = frame[ie_off + 1];
if (ie_off + 2 + elen > len) break;
const u8 *edata = frame + ie_off + 2;
if (eid == WLAN_EID_SSID && elen > 0 && elen <= ATH9K_SSID_MAX) {
for (u8 i = 0; i < elen; i++) out->ssid[i] = (char)edata[i];
out->ssid[elen] = 0;
} else if (eid == WLAN_EID_SSID && elen == 0) {
out->ssid[0] = 0; /* hidden SSID */
} else if (eid == WLAN_EID_DS_PARAMS && elen >= 1) {
out->channel = edata[0];
} else if (eid == WLAN_EID_RSN && elen >= 2) {
/* RSN IE → WPA2 (或 WPA3 由 version 决定) */
u16 version = (u16)edata[0] | ((u16)edata[1] << 8);
if (version == 1) out->security = DKM_NET_SEC_WPA2;
else if (version == 2) out->security = DKM_NET_SEC_WPA3;
else out->security = DKM_NET_SEC_WPA2;
} else if (eid == WLAN_EID_VENDOR && elen >= 4) {
/* Microsoft WPA IE: OUI 00:50:F2 + type 1 */
if (edata[0]==0x00 && edata[1]==0x50 && edata[2]==0xF2 && edata[3]==0x01) {
if (out->security < DKM_NET_SEC_WPA) out->security = DKM_NET_SEC_WPA;
}
}
ie_off += 2 + elen;
}
return 0;
}
/* 查找已扫描 BSSID 是否已记录,返回索引或 -1 */
static int find_bssid(const u8 bssid[6]) {
for (u32 i = 0; i < g_scan_count; i++) {
int match = 1;
for (int j = 0; j < 6; j++) if (g_scan_results[i].bssid[j] != bssid[j]) { match = 0; break; }
if (match) return (int)i;
}
return -1;
}
/* 处理一个接收到的 802.11 帧(从 RX 缓冲区解析) */
static void ath9k_handle_rx_frame(const u8 *buf, u32 len, i8 rssi) {
struct ath9k_scan_result tmp;
for (int i = 0; i < (int)sizeof(tmp); i++) ((u8 *)&tmp)[i] = 0;
if (parse_beacon(buf, len, &tmp) != 0) return;
/* 跳过隐藏 SSID(长度为 0) */
if (tmp.ssid[0] == 0) return;
tmp.rssi = rssi;
/* 去重:BSSID 已存在则更新 RSSI */
int existing = find_bssid(tmp.bssid);
if (existing >= 0) {
/* 更新 RSSI(取较强值) */
if (rssi > g_scan_results[existing].rssi) g_scan_results[existing].rssi = rssi;
return;
}
if (g_scan_count >= ATH9K_MAX_SCAN_RESULTS) return;
/* 追加 */
g_scan_results[g_scan_count] = tmp;
g_scan_count++;
}
/* 从 RX 环轮询所有已完成描述符 */
static void ath9k_rx_drain(void) {
if (!g_rx_ready) return;
for (u32 i = 0; i < ATH9K_RX_DESC_COUNT; i++) {
u32 idx = g_rx_head;
struct ath9k_rx_desc *d = &g_rx_desc[idx];
__asm__ volatile("" ::: "memory");
if (!(d->ds_status0 & ATH9K_RXSTATUS_DONE)) break;
if (d->ds_status0 & ATH9K_RXSTATUS_OK) {
u32 flen = (d->ds_status0 & ATH9K_RXSTATUS_FRAME_LEN_M) >> ATH9K_RXSTATUS_FRAME_LEN_S;
if (flen > 0 && flen <= ATH9K_RX_BUF_SIZE) {
/* RSSI 在 ds_status2 低 8 位(ath9k convention,负值表示) */
i8 rssi = (i8)(d->ds_status2 & 0xFF);
ath9k_handle_rx_frame(g_rx_buf[idx], flen, rssi);
}
}
/* 重置描述符,归还给硬件 */
d->ds_status0 = 0;
d->ds_status1 = 0;
d->ds_status2 = 0;
d->ds_status3 = 0;
d->ds_ctl0 = ATH9K_RX_BUF_SIZE & ATH9K_RXCTL_BUF_LEN_M;
d->ds_ctl1 = ATH9K_RXCTL_INTREQ;
__asm__ volatile("" ::: "memory");
g_rx_head = (g_rx_head + 1) % ATH9K_RX_DESC_COUNT;
}
}
/* ---- 信道切换(简化版) ----
* 完整 ath9k 信道切换涉及 PLL/RFBUS/ChannelFraction/RFBank 等数十寄存器,
* 本驱动仅写最小序列:PHY RFBUS 请求 + Channel 寄存器占位。
* 真实硬件验证后增量完善。
*/
static void ath9k_set_channel(u8 channel) {
(void)channel;
/* TODO: 完整 ath9k 信道切换序列(参考 ar9002_hw_set_channel) */
/* 触发 RFBUS 请求,等待 grant */
ath9k_reg_write(AR_PHY_RFBUS_REQ, 0x1);
dkm_delay_us(5);
for (u32 i = 0; i < 1000; i++) {
if (ath9k_reg_read(AR_PHY_RFBUS_REQ) & 0x2) break;
dkm_delay_us(1);
}
ath9k_reg_write(AR_PHY_RFBUS_REQ, 0);
dkm_delay_us(50);
}
/* ---- 被动扫描状态机 ----
* 遍历 2.4GHz 信道 1-13,每个信道停留 ~400ms 监听 beacon。
* 完成后 g_scan_count 包含所有发现的 SSID。
*/
static int ath9k_scan_start_impl(void *ctx) {
(void)ctx;
raw_log("[ath9k.raw] scan_start\n");
if (!g_rx_ready) return -1;
g_scanning = 1;
g_scan_count = 0;
for (u32 i = 0; i < ATH9K_MAX_SCAN_RESULTS; i++) {
for (int j = 0; j < (int)sizeof(g_scan_results[i]); j++) {
((u8 *)&g_scan_results[i])[j] = 0;
}
}
for (u32 c = 0; c < ATH9K_CHAN_2G_COUNT; c++) {
u8 channel = (u8)(c + 1);
ath9k_set_channel(channel);
raw_log("[ath9k.raw] scan ch=");
static const char hh[] = "0123456789";
char buf[4]; buf[0]=hh[channel/10]; buf[1]=hh[channel%10]; buf[2]='\n'; buf[3]=0;
raw_log(buf);
/* 在该信道停留 ~400ms,期间轮询 RX 环 */
for (u32 tick = 0; tick < 400; tick++) {
ath9k_rx_drain();
dkm_delay_us(1000);
}
}
g_scanning = 0;
raw_log("[ath9k.raw] scan done, results=");
static const char hh2[] = "0123456789";
char cntbuf[4]; cntbuf[0]=hh2[g_scan_count/10]; cntbuf[1]=hh2[g_scan_count%10]; cntbuf[2]='\n'; cntbuf[3]=0;
raw_log(cntbuf);
return 0;
}
static int ath9k_scan_count_impl(void *ctx) {
(void)ctx;
return (int)g_scan_count;
}
static int ath9k_scan_result_impl(void *ctx, u32 n, struct dkm_net_scan_result *out) {
(void)ctx;
if (!out) return -1;
if (n >= g_scan_count) return -2;
/* 内部 ath9k_scan_result 与 dkm_net_scan_result 布局一致 */
const u8 *src = (const u8 *)&g_scan_results[n];
u8 *dst = (u8 *)out;
for (u32 i = 0; i < sizeof(struct dkm_net_scan_result); i++) dst[i] = src[i];
return 0;
}
static int ath9k_is_wireless_impl(void *ctx) {
(void)ctx;
return 1;
}
/* ath9k 当前不支持 TX(仅扫描) */
static int ath9k_tx_stub(void *ctx, const void *packet, u32 length) {
(void)ctx; (void)packet; (void)length;
return -1;
}
static int ath9k_rx_poll_impl(void *ctx, void *buffer, u32 capacity, u32 *out_length) {
(void)ctx; (void)buffer; (void)capacity;
if (out_length) *out_length = 0;
/* 被动扫描内部消费所有帧,外部 rx_poll 总是返回无数据 */
return 1;
}
static void copy_mac(u8 dst[6], const u8 src[6]) {
for (int i = 0; i < 6; i++) dst[i] = src[i];
}
/* ---- 中断处理(PIC IRQ 路由) ---- */
static int ath9k_irq_handler(u8 irq) {
(void)irq;
if (!g_mmio) return 0;
u32 isr = ath9k_reg_read(AR_ISR_RAC);
if (isr) {
ath9k_reg_write(AR_ISR, isr);
if (isr & (AR_ISR_RXOK | AR_ISR_RXERR | AR_ISR_RXORN)) {
ath9k_rx_drain();
}
}
return 0;
}
/* ---- driver_init ---- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
/* 实机要求: 先校准 TSC, 再使用基于 CPU 频率的延迟 */
dkm_tsc_calibrate();
raw_log("[ath9k.raw] driver_init entered\n");
if (!api || !api->log) return -1;
g_log = api->log;
/* 1. PCI 探测 */
u8 bus, dev;
if (ath9k_find(&bus, &dev) != 0) {
raw_log("[ath9k.raw] no Atheros WiFi device found\n");
return -1;
}
raw_log("[ath9k.raw] Atheros device found\n");
/* 2. 启用 PCI 命令(MEM + Bus Master) */
u32 cmd = pci_read(bus, dev, 0, PCI_COMMAND);
pci_write(bus, dev, 0, PCI_COMMAND, cmd | PCI_CMD_MEM | PCI_CMD_BUSM);
/* 3. 读取 BAR0 */
u32 bar0 = pci_read(bus, dev, 0, PCI_BAR0);
raw_hex("[ath9k.raw] BAR0 raw=", bar0);
if ((bar0 & 0x1) != 0) {
raw_log("[ath9k.raw] BAR0 is IO space, unsupported\n");
return -2;
}
g_bar0_phys = (u64)(bar0 & 0xFFFFFFF0u);
/* 检查是否 64-bit BAR */
if ((bar0 & 0x6) == 0x4) {
u32 bar1 = pci_read(bus, dev, 0, PCI_BAR1);
g_bar0_phys |= ((u64)bar1 << 32);
raw_hex("[ath9k.raw] BAR0 high=", (u64)bar1);
}
raw_hex("[ath9k.raw] BAR0 phys=", g_bar0_phys);
if (g_bar0_phys >= 0x100000000ULL) {
raw_log("[ath9k.raw] BAR0 above 4G, current HHDM cannot map\n");
return -3;
}
/* 4. HHDM 映射 BAR0 */
u64 hhdm = api->hhdm_offset;
raw_hex("[ath9k.raw] HHDM=", hhdm);
g_mmio = (volatile u8 *)(g_bar0_phys + hhdm);
/* 验证 MMIO 可读:读 AR_STA_ID1 */
u32 probe = ath9k_reg_read(AR_STA_ID1);
raw_hex("[ath9k.raw] AR_STA_ID1 probe=", probe);
/* 5. 读取 PCI device ID + IRQ line */
u32 vd = pci_read(bus, dev, 0, PCI_VENDOR_ID);
g_pci_device_id = (u16)(vd >> 16);
g_pci_irq = (u8)pci_read(bus, dev, 0, PCI_IRQ_LINE);
raw_hex("[ath9k.raw] device id=", g_pci_device_id);
raw_hex("[ath9k.raw] irq line=", g_pci_irq);
/* 6. 软件复位 */
if (ath9k_reset() != 0) {
raw_log("[ath9k.raw] reset failed\n");
return -4;
}
/* 7. EEPROM 读取 MAC 地址 */
/* AR5416 EEPROM 偏移:MAC 地址在 word 0x1D-0x1F(6 字节) */
u16 m0 = ath9k_eeprom_read(0x1D);
u16 m1 = ath9k_eeprom_read(0x1E);
u16 m2 = ath9k_eeprom_read(0x1F);
if (m0 == 0xffff && m1 == 0xffff && m2 == 0xffff) {
raw_log("[ath9k.raw] EEPROM MAC all-FF, fallback to all-zero\n");
for (int i = 0; i < 6; i++) g_mac[i] = 0;
} else {
g_mac[0] = (u8)(m0 & 0xFF);
g_mac[1] = (u8)(m0 >> 8);
g_mac[2] = (u8)(m1 & 0xFF);
g_mac[3] = (u8)(m1 >> 8);
g_mac[4] = (u8)(m2 & 0xFF);
g_mac[5] = (u8)(m2 >> 8);
}
{
static const char hh[] = "0123456789abcdef";
char mstr[18];
mstr[0]=hh[(g_mac[0]>>4)&0xf]; mstr[1]=hh[g_mac[0]&0xf]; mstr[2]=':';
mstr[3]=hh[(g_mac[1]>>4)&0xf]; mstr[4]=hh[g_mac[1]&0xf]; mstr[5]=':';
mstr[6]=hh[(g_mac[2]>>4)&0xf]; mstr[7]=hh[g_mac[2]&0xf]; mstr[8]=':';
mstr[9]=hh[(g_mac[3]>>4)&0xf]; mstr[10]=hh[g_mac[3]&0xf]; mstr[11]=':';
mstr[12]=hh[(g_mac[4]>>4)&0xf]; mstr[13]=hh[g_mac[4]&0xf]; mstr[14]=':';
mstr[15]=hh[(g_mac[5]>>4)&0xf]; mstr[16]=hh[g_mac[5]&0xf]; mstr[17]=0;
raw_log("[ath9k.raw] MAC=");
raw_log(mstr);
raw_log("\n");
}
/* 8. 硬件初始化 */
if (ath9k_hw_init() != 0) {
raw_log("[ath9k.raw] hw_init failed\n");
return -5;
}
/* 9. RX 环初始化 */
if (api->dma && api->dma->alloc_pages) {
int rc = ath9k_rx_init(api->dma);
raw_hex("[ath9k.raw] rx_init rc=", (u64)(i8)rc);
if (rc != 0) {
raw_log("[ath9k.raw] RX init failed, scan unavailable\n");
}
} else {
raw_log("[ath9k.raw] no DMA api, scan unavailable\n");
}
/* 10. 注册中断 */
if (api->irq_register && g_pci_irq) {
int rc = api->irq_register(g_pci_irq, ath9k_irq_handler);
raw_hex("[ath9k.raw] irq_register rc=", (u64)(i8)rc);
}
/* 11. 注册 netdev(标记 WIRELESS + RX_READY) */
struct dkm_net_device_desc ndesc;
for (u32 i = 0; i < sizeof(ndesc); i++) ((u8 *)&ndesc)[i] = 0;
static const char devname[] = "ath9k0";
ndesc.name = devname;
copy_mac(ndesc.mac, g_mac);
ndesc.flags = DKM_NET_F_WIRELESS | (g_rx_ready ? DKM_NET_F_RX_READY : 0);
ndesc.ctx = (void *)0; /* ath9k 用全局状态,ctx 不需要 */
ndesc.tx = ath9k_tx_stub;
ndesc.rx_poll = ath9k_rx_poll_impl;
ndesc.scan_start = ath9k_scan_start_impl;
ndesc.scan_count = ath9k_scan_count_impl;
ndesc.scan_result = ath9k_scan_result_impl;
ndesc.is_wireless = ath9k_is_wireless_impl;
if (api->net && api->net->register_device) {
int rc = api->net->register_device(&ndesc);
raw_hex("[ath9k.raw] netdev registered, index=", (u64)rc);
} else {
raw_log("[ath9k.raw] no net api\n");
return -6;
}
/* 12. 启动后台被动扫描(同步执行,阻塞 driver_init 直到扫描完成)
* 注:DSK 加载驱动是顺序的,ath9k 在 stage3 末尾加载,
* 同步扫描会让 stage3 加载多花 ~5s(13 信道 × 400ms)。
* 这是可接受的,因为 FirstInit 在 DSK 之后才运行,能拿到完整扫描结果。
*/
if (g_rx_ready) {
raw_log("[ath9k.raw] starting initial passive scan\n");
ath9k_scan_start_impl(0);
}
raw_log("[ath9k.raw] driver_init done\n");
return 0;
}
__attribute__((visibility("default")))
void driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
if (g_mmio) {
ath9k_reg_write(AR_CR, AR_CR_RXD);
}
g_rx_ready = 0;
g_mmio = 0;
raw_log("[ath9k.raw] driver_exit\n");
}
+191
View File
@@ -0,0 +1,191 @@
/* DKM BootFS Driver — exposes Limine boot modules as a simple filesystem
* Stage 1, required, provides "bootfs".
* Lists all boot modules with path, size, and address.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci_api;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
/* minimal limine types matching kernel */
struct limine_file {
u64 revision;
void *address;
u64 size;
char *path;
char *cmdline;
u32 media_type;
u32 unused;
u32 tftp_ip;
u32 tftp_port;
u32 partition_index;
u32 mbr_disk_id;
u8 gpt_disk_uuid[16];
u8 gpt_part_uuid[16];
u8 part_uuid[16];
};
struct limine_module_response {
u64 revision;
u64 module_count;
struct limine_file **modules;
};
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_provides[] = { "bootfs" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "bootfs",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 7, /* DKM_CLASS_FS */
.stage = 1,
.flags = 1, /* DKM_F_REQUIRED */
.priority = 0,
.depends = NULL,
.depends_count = 0,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* Log helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static void log_hex(const char *prefix, u64 val) {
static const char hex[] = "0123456789abcdef";
char buf[19];
u32 pos = 0;
buf[pos++] = '0'; buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(val >> (i * 4)) & 0xf];
}
buf[pos] = 0;
g_log->info(prefix);
g_log->info(buf);
}
/* ---------------------------------------------------------------
* Driver entry
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
const struct limine_module_response *rsp =
(const struct limine_module_response *)api->boot_modules_response;
if (!rsp) {
g_log->error("[bootfs] no boot module response");
return -1;
}
g_log->info("[bootfs] boot module filesystem");
log_hex("[bootfs] file count=", rsp->module_count);
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (!f) continue;
g_log->info("[bootfs] ----------");
if (f->path) {
g_log->info("[bootfs] file");
g_log->info(f->path);
}
log_hex("[bootfs] size=", f->size);
log_hex("[bootfs] addr=", (u64)(uintptr_t)f->address);
if (f->cmdline) {
g_log->info("[bootfs] cmd");
g_log->info(f->cmdline);
}
}
g_log->info("[bootfs] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+107
View File
@@ -0,0 +1,107 @@
/* DKM Console Framebuffer Driver
* Stage 1, optional, provides "console".
* Clears the framebuffer to a solid light-blue background so the screen is
* clean before DSK takes over and draws the Logo. The former 4-color arc
* loading ring has been removed — DSK now shows a static Logo instead.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version; u32 size; u64 feature_bits;
const struct dkm_log_api *log;
const void *mem, *utsm, *irq, *pci_api, *dma, *vfs, *net, *timer, *drr;
const void *rsdp_address, *fb_address;
u64 fb_width, fb_height, fb_pitch; u16 fbpp;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic; u16 abi_version; u16 desc_size;
const char *name, *version, *vendor;
u32 driver_class, stage, flags, priority;
const char *const *depends; u32 depends_count;
const char *const *provides; u32 provides_count;
u64 min_kernel_abi, feature_bits, reserved0, reserved1;
};
static const char *const g_provides[] = { "console" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic=DKM_DRIVER_MAGIC, .abi_version=DKM_ABI_VERSION,
.desc_size=sizeof(struct dkm_driver_desc),
.name="console_fb", .version="0.3.0", .vendor="Deshab",
.driver_class=5, .stage=1, .flags=0, .priority=0,
.depends=NULL, .depends_count=0,
.provides=g_provides, .provides_count=1,
.min_kernel_abi=1,
};
/* ---------------------------------------------------------------
* Colors
* --------------------------------------------------------------- */
static const u32 BG = 0xFFC8E0F0; /* light blue background — cleared before DSK Logo */
/* ---------------------------------------------------------------
* Drawing helpers – all integer arithmetic, no soft-float
* --------------------------------------------------------------- */
static void fb_fill(u32 *fb, u64 pitch, u64 w, u64 h, u32 color) {
for (u64 y = 0; y < h; y++) {
u32 *line = (u32 *)((u8 *)fb + y * pitch);
for (u64 x = 0; x < w; x++) line[x] = color;
}
}
/* ---------------------------------------------------------------
* Driver entry
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
if (!api->fb_address || !api->fb_width) {
api->log->warn("[console_fb] no framebuffer");
return 0;
}
api->log->info("[console_fb] clearing boot screen");
/* Solid background fill only — DSK draws the Logo next. Clearing here
* avoids firmware/UEFI leftover garbage being visible during the
* UTSM→DSK handoff. */
u32 *fb = (u32 *)api->fb_address;
fb_fill(fb, api->fb_pitch, api->fb_width, api->fb_height, BG);
api->log->info("[console_fb] ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+224
View File
@@ -0,0 +1,224 @@
/* DKM DevFS Driver — virtual device filesystem
* Stage 2, optional, depends on "vfs", provides "devfs".
* Exposes kernel platform info as virtual files under /dev/.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci_api;
const void *dma;
const void *vfs_api;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
struct limine_file {
u64 revision;
void *address;
u64 size;
char *path;
char *cmdline;
u8 _pad[56];
};
struct limine_module_response {
u64 revision;
u64 module_count;
struct limine_file **modules;
};
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_depends[] = { "vfs" };
static const char *const g_provides[] = { "devfs" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "devfs",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 7,
.stage = 2,
.flags = 0,
.priority = 0,
.depends = g_depends,
.depends_count = 1,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* Helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static void log_hex(const char *prefix, u64 val) {
static const char h[] = "0123456789abcdef";
char buf[19]; u32 p = 0;
buf[p++] = '0'; buf[p++] = 'x';
for (int i = 15; i >= 0; i--) buf[p++] = h[(val>>(i*4))&0xf];
buf[p] = 0;
g_log->info(prefix); g_log->info(buf);
}
/* ---------------------------------------------------------------
* Virtual file helpers
* --------------------------------------------------------------- */
static void devfs_file(const char *name, const char *content) {
g_log->info("[devfs] /dev/");
g_log->info(name);
g_log->info("[devfs] ");
g_log->info(content);
}
/* ---------------------------------------------------------------
* Driver entry
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
g_log->info("[devfs] virtual device filesystem");
/* /dev/version */
devfs_file("version", "Deshab kernel 0.1.0");
/* /dev/platform */
devfs_file("platform", "x86_64 SAS-R0");
/* /dev/fb0 */
if (api->fb_address) {
char info[64];
info[0] = 0;
/* manual number conversion for width */
{
u64 v = api->fb_width;
char tmp[24]; u32 p = 0;
if (v == 0) tmp[p++] = '0';
else { char r[24]; u32 q = 0; while (v) { r[q++] = '0' + (char)(v%10); v/=10; } while (q) tmp[p++] = r[--q]; }
tmp[p++] = 'x';
v = api->fb_height;
if (v == 0) tmp[p++] = '0';
else { char r[24]; u32 q = 0; while (v) { r[q++] = '0' + (char)(v%10); v/=10; } while (q) tmp[p++] = r[--q]; }
tmp[p++] = 'x';
v = api->fb_bpp;
if (v == 0) tmp[p++] = '0';
else { char r[24]; u32 q = 0; while (v) { r[q++] = '0' + (char)(v%10); v/=10; } while (q) tmp[p++] = r[--q]; }
tmp[p++] = ' ';
tmp[p++] = 'f';
tmp[p++] = 'b';
tmp[p++] = '0';
tmp[p] = 0;
for (u32 i = 0; i <= p; i++) info[i] = tmp[i];
}
devfs_file("fb0", info);
}
/* /dev/modules — count from boot_modules */
const struct limine_module_response *rsp =
(const struct limine_module_response *)api->boot_modules_response;
if (rsp) {
char buf[24];
buf[0] = '0'; buf[1] = 'x';
u64 v = rsp->module_count;
u32 p = 2;
if (v == 0) buf[p++] = '0';
else {
char r[18]; u32 q = 0;
while (v) { r[q++] = "0123456789abcdef"[v&0xf]; v>>=4; }
while (q) buf[p++] = r[--q];
}
buf[p] = 0;
devfs_file("modules", buf);
/* /dev/boot — list paths */
g_log->info("[devfs] /dev/boot/");
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (f && f->path) {
g_log->info("[devfs] ");
g_log->info(f->path);
}
}
}
g_log->info("[devfs] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+331
View File
@@ -0,0 +1,331 @@
/* DKM 共享头文件 — 消除各驱动重复的结构体/宏/PCI/TSC 代码
*
* 设计要点:
* - 结构体定义与 UTSM/include/utsm/dkm.h 保持布局一致 (canonical)
* - PCI I/O 函数使用 static __inline__, 每个 .drv 文件获得独立副本, 避免链接冲突
* - TSC 校准函数使用 static __inline__, 每个 .drv 文件获得自己的 dkm_tsc_per_ms
* - 驱动源文件只需 #include "../dkm_shared.h", 保留各自的 driver_desc 和 driver_init
*
* 使用约定:
* 1. 在 driver_init 开头调用 dkm_tsc_calibrate() 完成校准
* 2. 时序等待使用 dkm_delay_ms() / dkm_delay_us()
* 3. 串口发送等待使用 dkm_serial_wait_tx(COM1)
* 4. MMIO 寄存器读取等待使用 dkm_rdtsc() + dkm_tsc_per_ms 直接计算 deadline
*/
#ifndef DKM_SHARED_H
#define DKM_SHARED_H
#include <stdint.h>
/* ---- 基本类型 (与 UTSM/types.h 一致) ---- */
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef signed char i8;
typedef short i16;
typedef int i32;
typedef long long i64;
#ifndef NULL
#define NULL ((void *)0)
#endif
/* ---- DKM magic / ABI 版本 ---- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
/* ---- DKM 驱动类别 (driver_desc.driver_class) ---- */
#define DKM_CLASS_PLATFORM 1u
#define DKM_CLASS_BUS 2u
#define DKM_CLASS_INTERRUPT 3u
#define DKM_CLASS_TIMER 4u
#define DKM_CLASS_CONSOLE 5u
#define DKM_CLASS_STORAGE 6u
#define DKM_CLASS_FS 7u
#define DKM_CLASS_NET 8u
#define DKM_CLASS_INPUT 9u
#define DKM_CLASS_GPU 10u
#define DKM_CLASS_MISC 11u
/* ---- DKM 驱动标志 (driver_desc.flags) ---- */
#define DKM_F_REQUIRED (1u << 0)
#define DKM_F_BOOT_MODULE (1u << 1)
#define DKM_F_NO_UNLOAD (1u << 2)
#define DKM_F_STRONG_RECOVERY (1u << 3)
#define DKM_F_DMA_REQUIRED (1u << 4)
#define DKM_F_EARLY_LOG (1u << 5)
/* ---- 网卡链路/能力标志 ---- */
#define DKM_NET_F_LINK_UP (1u << 0)
#define DKM_NET_F_TX_READY (1u << 1)
#define DKM_NET_F_RX_READY (1u << 2)
#define DKM_NET_F_WIRELESS (1u << 3)
/* ---- WiFi 扫描加密类型 ---- */
#define DKM_NET_SEC_OPEN 0u
#define DKM_NET_SEC_WEP 1u
#define DKM_NET_SEC_WPA 2u
#define DKM_NET_SEC_WPA2 3u
#define DKM_NET_SEC_WPA3 4u
/* ---- DKM 结构体定义 (与 UTSM/include/utsm/dkm.h 布局一致) ---- */
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_dma_buffer {
void *virt;
u64 phys;
u64 size;
};
struct dkm_dma_api {
int (*alloc_pages)(u64 page_count, u64 alignment, u64 max_phys, struct dkm_dma_buffer *out);
};
struct dkm_net_scan_result {
char ssid[33];
u8 bssid[6];
u8 channel;
i8 rssi;
u8 security;
};
struct dkm_net_device_desc {
const char *name;
u8 mac[6];
u32 flags;
void *ctx;
int (*tx)(void *ctx, const void *packet, u32 length);
int (*rx_poll)(void *ctx, void *buffer, u32 capacity, u32 *out_length);
/* 无线扩展回调(有线驱动置 NULL,向后兼容)。 */
int (*scan_start)(void *ctx);
int (*scan_count)(void *ctx);
int (*scan_result)(void *ctx, u32 n, struct dkm_net_scan_result *out);
int (*is_wireless)(void *ctx);
};
struct dkm_net_api {
int (*register_device)(const struct dkm_net_device_desc *desc);
u32 (*device_count)(void);
int (*device_info)(u32 index, void *out);
int (*tx)(u32 index, const void *packet, u32 length);
int (*rx_poll)(u32 index, void *buffer, u32 capacity, u32 *out_length);
int (*scan_start)(u32 index);
int (*scan_count)(u32 index);
int (*scan_result)(u32 index, u32 n, struct dkm_net_scan_result *out);
int (*is_wireless)(u32 index);
};
typedef int (*dkm_block_read_fn)(void *ctx, u64 lba, u32 count, void *buffer);
typedef int (*dkm_block_write_fn)(void *ctx, u64 lba, u32 count, const void *buffer);
struct dkm_block_device_desc {
const char *name;
u64 sector_size;
u64 sector_count;
void *ctx;
int (*read)(void *ctx, u64 lba, u32 count, void *buffer);
int (*write)(void *ctx, u64 lba, u32 count, const void *buffer);
};
struct dkm_block_api {
int (*register_device)(const struct dkm_block_device_desc *desc);
u32 (*device_count)(void);
int (*read)(u32 index, u64 lba, u32 count, void *buffer);
int (*write)(u32 index, u64 lba, u32 count, const void *buffer);
u64 (*sector_size)(u32 index);
const char *(*device_name)(u32 index);
int (*set_write_fn)(u32 index, dkm_block_write_fn fn);
};
/* 与 UTSM/include/utsm/dkm.h 中的 dkm_kernel_api 布局完全一致.
* 字段顺序/类型不可调整 — UTSM 端按此偏移填充. */
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci;
const struct dkm_dma_api *dma;
const void *vfs;
const struct dkm_net_api *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response;
int (*irq_register)(u8 irq, void *handler);
u64 hhdm_offset;
const struct dkm_block_api *block; /* 末尾字段, 不使用 block 的驱动可不访问 */
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
/* ---- PCI 配置空间常量 ---- */
#define PCI_ADDR 0xCF8
#define PCI_DATA 0xCFC
#define PCI_VENDOR_ID 0x00
#define PCI_DEVICE_ID 0x02
#define PCI_COMMAND 0x04
#define PCI_PROG_IF 0x09
#define PCI_SUBCLASS 0x0A
#define PCI_CLASS 0x0B
#define PCI_HEADER 0x0E
#define PCI_CAP_PTR 0x34
#define PCI_IRQ_LINE 0x3C
#define PCI_BAR0 0x10
#define PCI_BAR1 0x14
#define PCI_BAR2 0x18
#define PCI_BAR3 0x1C
#define PCI_BAR4 0x20
#define PCI_BAR5 0x24
#define PCI_CMD_IO (1u << 0)
#define PCI_CMD_MEM (1u << 1)
#define PCI_CMD_BUSM (1u << 2)
/* ---- PCI I/O 端口内联函数 (每个 .drv 获得独立副本) ---- */
static __inline__ void dkm_outl(u16 port, u32 value) {
__asm__ volatile ("outl %0, %1" :: "a"(value), "Nd"(port));
}
static __inline__ u32 dkm_inl(u16 port) {
u32 value;
__asm__ volatile ("inl %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
static __inline__ void dkm_outb(u16 port, u8 value) {
__asm__ volatile ("outb %0, %1" :: "a"(value), "Nd"(port));
}
static __inline__ u8 dkm_inb(u16 port) {
u8 value;
__asm__ volatile ("inb %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
static __inline__ u32 dkm_pci_read(u8 bus, u8 dev, u8 func, u8 reg) {
u32 addr = (1u << 31)
| ((u32)bus << 16)
| ((u32)dev << 11)
| ((u32)func << 8)
| ((u32)reg & 0xFC);
dkm_outl(PCI_ADDR, addr);
return dkm_inl(PCI_DATA);
}
static __inline__ void dkm_pci_write(u8 bus, u8 dev, u8 func, u8 reg, u32 value) {
u32 addr = (1u << 31)
| ((u32)bus << 16)
| ((u32)dev << 11)
| ((u32)func << 8)
| ((u32)reg & 0xFC);
dkm_outl(PCI_ADDR, addr);
dkm_outl(PCI_DATA, value);
}
static __inline__ u8 dkm_pci_read8(u8 bus, u8 dev, u8 func, u8 reg) {
u32 v = dkm_pci_read(bus, dev, func, reg);
return (u8)((v >> ((reg & 3) * 8)) & 0xff);
}
/* ---- TSC 时序: 实机要求用 CPU 频率计算, 不用循环 ----
* 每个 .drv 包含此头文件后获得自己的 file-local dkm_tsc_per_ms 副本,
* 通过 dkm_tsc_calibrate() 在 driver_init 开头初始化.
*/
static u64 dkm_tsc_per_ms __attribute__((unused)) = 0;
static __inline__ u64 dkm_rdtsc(void) {
u32 lo, hi;
__asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
return ((u64)hi << 32) | lo;
}
/* 通过 PIT ch0 + TSC 校准 ~10ms 区间, 推算每毫秒 TSC 周期数. */
static __inline__ void dkm_tsc_calibrate(void) {
dkm_outb(0x43, 0x30); /* ch0, lo+hi, mode 0, binary */
dkm_outb(0x40, 0x7c); /* 11932 low = ~10ms */
dkm_outb(0x40, 0x2e); /* 11932 high */
u64 tsc_start = dkm_rdtsc();
u16 prev = 0; u64 loops = 0;
for (;;) {
dkm_outb(0x43, 0x00);
u16 cur = (u16)dkm_inb(0x40) | ((u16)dkm_inb(0x40) << 8);
if (cur > prev && loops > 10) break;
prev = cur; loops++;
}
u64 tsc_end = dkm_rdtsc();
dkm_tsc_per_ms = (tsc_end - tsc_start) / 10;
}
static __inline__ void dkm_delay_ms(u32 ms) {
if (!dkm_tsc_per_ms) {
for (volatile u32 i = 0; i < 100000 * ms; i++) __asm__ volatile("pause");
return;
}
u64 target = dkm_tsc_per_ms * ms;
u64 start = dkm_rdtsc();
while (dkm_rdtsc() - start < target) __asm__ volatile("pause");
}
static __inline__ void dkm_delay_us(u32 us) {
if (!dkm_tsc_per_ms) {
for (volatile u32 i = 0; i < 100 * us; i++) __asm__ volatile("pause");
return;
}
u64 target = dkm_tsc_per_ms * us / 1000;
u64 start = dkm_rdtsc();
while (dkm_rdtsc() - start < target) __asm__ volatile("pause");
}
/* 实机: 基于 TSC 的串口发送等待 (100us 超时). com_port = 0x3F8 (COM1). */
static __inline__ void dkm_serial_wait_tx(u16 com_port) {
if (!dkm_tsc_per_ms) {
for (volatile u32 i = 0; i < 100000; i++) {
if (dkm_inb((u16)(com_port + 5)) & 0x20) break;
__asm__ volatile("pause");
}
return;
}
u64 deadline = dkm_rdtsc() + dkm_tsc_per_ms / 10;
while (dkm_rdtsc() < deadline) {
if (dkm_inb((u16)(com_port + 5)) & 0x20) break;
__asm__ volatile("pause");
}
}
#endif /* DKM_SHARED_H */
+462
View File
@@ -0,0 +1,462 @@
/* DKM e1000 Driver — Intel 8254x Gigabit Ethernet
* Stage 3, optional, depends on "pci" and "irq", provides "netdev".
* Finds e1000 via PCI, maps MMIO, reads MAC address.
*/
#include "../dkm_shared.h"
static const char *const g_depends[] = {"pci","irq"};
static const char *const g_provides[] = {"netdev"};
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic=DKM_DRIVER_MAGIC,.abi_version=DKM_ABI_VERSION,
.desc_size=sizeof(struct dkm_driver_desc),
.name="e1000",.version="0.1.0",.vendor="Deshab",
.driver_class=9,.stage=3,.flags=0,.priority=0,
.depends=g_depends,.depends_count=2,
.provides=g_provides,.provides_count=1,.min_kernel_abi=1,
};
/* e1000 MMIO registers */
#define E1000_CTRL 0x0000
#define E1000_STATUS 0x0008
#define E1000_EERD 0x0014
#define E1000_ICR 0x00C0
#define E1000_IMS 0x00D0
#define E1000_IMC 0x00D8
#define E1000_RAL 0x5400
#define E1000_RAH 0x5404
#define E1000_RDBAL 0x2800
#define E1000_RDBAH 0x2804
#define E1000_RDLEN 0x2808
#define E1000_RDH 0x2810
#define E1000_RDT 0x2818
#define E1000_RXDCTL 0x2828
#define E1000_RCTL 0x0100
#define E1000_TDBAL 0x3800
#define E1000_TDBAH 0x3804
#define E1000_TDLEN 0x3808
#define E1000_TDH 0x3810
#define E1000_TDT 0x3818
#define E1000_TXDCTL 0x3828
#define E1000_TCTL 0x0400
#define E1000_TIPG 0x0410
#define E1000_RX_DESC_COUNT 8u
#define E1000_TX_DESC_COUNT 8u
#define E1000_RX_BUF_SIZE 2048u
#define E1000_TX_BUF_SIZE 2048u
#define E1000_POOL_BYTES(count, size) ((u32)((count) * (size)))
#define E1000_POOL_PAGES(bytes) (((bytes) + 4095u) / 4096u)
#define E1000_RCTL_EN (1u << 1)
#define E1000_RCTL_SBP (1u << 2)
#define E1000_RCTL_UPE (1u << 3)
#define E1000_RCTL_MPE (1u << 4)
#define E1000_RCTL_BAM (1u << 15)
#define E1000_RCTL_SECRC (1u << 26)
#define E1000_RCTL_BSIZE_2048 0u
#define E1000_TCTL_EN (1u << 1)
#define E1000_TCTL_PSP (1u << 3)
#define E1000_TCTL_CT_SHIFT 4
#define E1000_TCTL_COLD_SHIFT 12
#define E1000_TX_CMD_EOP (1u << 0)
#define E1000_TX_CMD_IFCS (1u << 1)
#define E1000_TX_CMD_RS (1u << 3)
#define E1000_TX_STA_DD (1u << 0)
#define E1000_RX_STA_DD (1u << 0)
#define E1000_CTRL_FD (1u << 0)
#define E1000_CTRL_SLU (1u << 6)
struct e1000_rx_desc {
u64 addr;
u16 length;
u16 checksum;
u8 status;
u8 errors;
u16 special;
} __attribute__((packed));
struct e1000_tx_desc {
u64 addr;
u16 length;
u8 cso;
u8 cmd;
u8 status;
u8 css;
u16 special;
} __attribute__((packed));
static const struct dkm_log_api *g_log;
static volatile u32 *g_mmio;
static u64 g_bar0_phys;
static struct e1000_rx_desc *g_rx_desc;
static struct e1000_tx_desc *g_tx_desc;
static u64 g_rx_desc_phys;
static u64 g_tx_desc_phys;
static u8 *g_rx_buf[E1000_RX_DESC_COUNT];
static u64 g_rx_buf_phys[E1000_RX_DESC_COUNT];
static u8 *g_tx_buf[E1000_TX_DESC_COUNT];
static u64 g_tx_buf_phys[E1000_TX_DESC_COUNT];
static u32 g_rx_tail;
static u32 g_tx_tail;
static int g_rings_ready;
#define COM1 0x3F8
/* 串口发送等待 thin wrapper — 调用 dkm 共享实现 */
static void serial_wait_tx(void) { dkm_serial_wait_tx(COM1); }
static void raw_log(const char *s) {
while (*s) {
char c = *s++;
if (c == '\n') {
serial_wait_tx();
dkm_outb(COM1, '\r');
}
serial_wait_tx();
dkm_outb(COM1, (u8)c);
}
}
static void raw_hex(const char *prefix, u64 v) {
static const char h[] = "0123456789abcdef";
raw_log(prefix);
raw_log("0x");
for (int i=15; i>=0; i--) {
serial_wait_tx();
dkm_outb(COM1, (u8)h[(v >> (i * 4)) & 0xf]);
}
raw_log("\n");
}
static u32 pci_read(u8 bus, u8 dev, u8 func, u8 reg) {
return dkm_pci_read(bus, dev, func, reg);
}
static void pci_write(u8 bus, u8 dev, u8 func, u8 reg, u32 v) {
dkm_pci_write(bus, dev, func, reg, v);
}
static int e1000_find(u8 *bus, u8 *dev) {
for (u8 d=0; d<32; d++) {
u32 vd = pci_read(0,d,0,PCI_VENDOR_ID);
if ((vd&0xffff)==0xffff) continue;
if ((vd&0xffff)!=0x8086) continue;
u16 did = (u16)(vd>>16);
/* 82540EM(0x100E) / 82545 等经典 e1000,以及 82574L(0x10D3) e1000e */
if (did==0x100E || did==0x10D3 || did==0x1004 || did==0x100F ||
did==0x10D3 || did==0x153A || did==0x1533) {
*bus=0; *dev=d; return 0;
}
}
return -1;
}
/* 读取 EEPROM 一个 16-bit 字(经典 e1000 EERD 接口)。失败返回 0xffff。 */
static u16 e1000_eeprom_read(u16 addr) {
/* EERD: bit0=START, addr<<8, 完成后 bit4=DONE, data 在高 16 位 */
g_mmio[E1000_EERD/4] = ((u32)addr << 8) | 1u;
/* 实机: 100ms TSC 超时 */
u64 deadline = dkm_rdtsc() + dkm_tsc_per_ms * 100;
while (dkm_rdtsc() < deadline) {
u32 v = g_mmio[E1000_EERD/4];
if (v & (1u<<4)) return (u16)(v >> 16);
__asm__ volatile("pause");
}
return 0xffff;
}
static int irq_handler(u8 irq) {
(void)irq;
if (!g_mmio) return 0;
u32 icr = g_mmio[E1000_ICR/4];
if (icr) {
g_mmio[E1000_ICR/4] = icr; /* clear */
}
return 0;
}
static void copy_bytes(void *dst, const void *src, u32 len) {
u8 *d = (u8 *)dst;
const u8 *s = (const u8 *)src;
for (u32 i=0;i<len;i++) d[i]=s[i];
}
static void zero_bytes(void *dst, u32 len) {
u8 *d = (u8 *)dst;
for (u32 i=0;i<len;i++) d[i]=0;
}
static void mmio_flush(void) {
if (g_mmio) (void)g_mmio[E1000_STATUS/4];
}
static void dma_fence(void) {
__asm__ volatile("" ::: "memory");
}
static int e1000_init_rings(const struct dkm_dma_api *dma) {
if (!dma || !dma->alloc_pages || !g_mmio) return -1;
struct dkm_dma_buffer rx_ring, tx_ring;
if (dma->alloc_pages(1, 16, 0x100000000ULL, &rx_ring) != 0) return -2;
if (dma->alloc_pages(1, 16, 0x100000000ULL, &tx_ring) != 0) return -3;
g_rx_desc = (struct e1000_rx_desc *)rx_ring.virt;
g_tx_desc = (struct e1000_tx_desc *)tx_ring.virt;
g_rx_desc_phys = rx_ring.phys;
g_tx_desc_phys = tx_ring.phys;
for (u32 i=0;i<E1000_RX_DESC_COUNT;i++) {
struct dkm_dma_buffer b;
if (dma->alloc_pages(1, 16, 0x100000000ULL, &b) != 0) return -4;
g_rx_buf[i] = (u8 *)b.virt;
g_rx_buf_phys[i] = b.phys;
zero_bytes(&g_rx_desc[i], sizeof(g_rx_desc[i]));
g_rx_desc[i].addr = b.phys;
}
for (u32 i=0;i<E1000_TX_DESC_COUNT;i++) {
struct dkm_dma_buffer b;
if (dma->alloc_pages(1, 16, 0x100000000ULL, &b) != 0) return -5;
g_tx_buf[i] = (u8 *)b.virt;
g_tx_buf_phys[i] = b.phys;
zero_bytes(&g_tx_desc[i], sizeof(g_tx_desc[i]));
g_tx_desc[i].addr = b.phys;
g_tx_desc[i].status = E1000_TX_STA_DD;
}
dma_fence();
raw_log("[e1000.raw] ring/buffers allocated\n");
g_mmio[E1000_RCTL/4] = 0;
g_mmio[E1000_TCTL/4] = 0;
mmio_flush();
g_mmio[E1000_RDBAL/4] = (u32)(g_rx_desc_phys & 0xffffffffu);
g_mmio[E1000_RDBAH/4] = (u32)(g_rx_desc_phys >> 32);
g_mmio[E1000_RDLEN/4] = E1000_RX_DESC_COUNT * sizeof(struct e1000_rx_desc);
g_mmio[E1000_RDH/4] = 0;
g_rx_tail = E1000_RX_DESC_COUNT - 1;
g_mmio[E1000_RDT/4] = g_rx_tail;
g_mmio[E1000_TDBAL/4] = (u32)(g_tx_desc_phys & 0xffffffffu);
g_mmio[E1000_TDBAH/4] = (u32)(g_tx_desc_phys >> 32);
g_mmio[E1000_TDLEN/4] = E1000_TX_DESC_COUNT * sizeof(struct e1000_tx_desc);
g_mmio[E1000_TDH/4] = 0;
g_tx_tail = 0;
g_mmio[E1000_TDT/4] = 0;
/* e1000e/部分实现需要显式打开队列描述符控制;经典 e1000 会忽略/兼容。 */
g_mmio[E1000_RXDCTL/4] = (1u << 25);
g_mmio[E1000_TXDCTL/4] = (1u << 25);
g_mmio[E1000_TIPG/4] = 0x0060200Au;
dma_fence();
g_mmio[E1000_RCTL/4] = E1000_RCTL_EN | E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_BAM | E1000_RCTL_SECRC | E1000_RCTL_BSIZE_2048;
g_mmio[E1000_TCTL/4] = E1000_TCTL_EN | E1000_TCTL_PSP | (0x0Fu << E1000_TCTL_CT_SHIFT) | (0x40u << E1000_TCTL_COLD_SHIFT);
mmio_flush();
g_rings_ready = 1;
raw_log("[e1000.raw] RX/TX rings initialized\n");
return 0;
}
static int e1000_tx(void *ctx, const void *packet, u32 length) {
(void)ctx;
raw_log("[e1000.raw] tx enter\n");
if (!g_rings_ready || !packet || length == 0 || length > E1000_TX_BUF_SIZE) return -1;
u32 index = g_tx_tail;
if (!(g_tx_desc[index].status & E1000_TX_STA_DD)) return -2;
copy_bytes(g_tx_buf[index], packet, length);
dma_fence();
raw_log("[e1000.raw] tx copied\n");
g_tx_desc[index].length = (u16)length;
g_tx_desc[index].cso = 0;
g_tx_desc[index].cmd = E1000_TX_CMD_EOP | E1000_TX_CMD_IFCS | E1000_TX_CMD_RS;
g_tx_desc[index].css = 0;
g_tx_desc[index].special = 0;
g_tx_desc[index].status = 0;
dma_fence();
g_tx_tail = (index + 1) % E1000_TX_DESC_COUNT;
g_mmio[E1000_TDT/4] = g_tx_tail;
mmio_flush();
/* 实机: 1秒 TSC 超时等待 TX 完成 */
u64 deadline = dkm_rdtsc() + dkm_tsc_per_ms * 1000;
while (dkm_rdtsc() < deadline) {
dma_fence();
if (g_tx_desc[index].status & E1000_TX_STA_DD) {
raw_log("[e1000.raw] tx complete\n");
return 0;
}
__asm__ volatile("pause");
}
raw_log("[e1000.raw] tx timeout\n");
raw_hex("[e1000.raw] STATUS=", g_mmio[E1000_STATUS/4]);
raw_hex("[e1000.raw] TCTL=", g_mmio[E1000_TCTL/4]);
raw_hex("[e1000.raw] TDH=", g_mmio[E1000_TDH/4]);
raw_hex("[e1000.raw] TDT=", g_mmio[E1000_TDT/4]);
raw_hex("[e1000.raw] desc.status=", g_tx_desc[index].status);
return -3;
}
static int e1000_rx_poll(void *ctx, void *buffer, u32 capacity, u32 *out_length) {
(void)ctx;
if (out_length) *out_length = 0;
if (!g_rings_ready || !buffer || !out_length) return -1;
u32 next = (g_rx_tail + 1) % E1000_RX_DESC_COUNT;
dma_fence();
if (!(g_rx_desc[next].status & E1000_RX_STA_DD)) return 1;
u32 len = g_rx_desc[next].length;
if (len > capacity) {
g_rx_desc[next].status = 0;
dma_fence();
g_rx_tail = next;
g_mmio[E1000_RDT/4] = g_rx_tail;
mmio_flush();
return -2;
}
copy_bytes(buffer, g_rx_buf[next], len);
*out_length = len;
g_rx_desc[next].status = 0;
dma_fence();
g_rx_tail = next;
g_mmio[E1000_RDT/4] = g_rx_tail;
mmio_flush();
return 0;
}
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
/* 实机要求: 先校准 TSC, 再使用基于 CPU 频率的延迟 */
dkm_tsc_calibrate();
raw_log("[e1000.raw] driver_init entered\n");
(void)handle;
if (!api||!api->log) return -1;
g_log=api->log;
raw_log("[e1000.raw] before find\n");
u8 bus, dev;
if (e1000_find(&bus,&dev)!=0) {
raw_log("[e1000.raw] device not found\n");
return 0;
}
raw_log("[e1000.raw] found device\n");
u32 cmd = pci_read(bus, dev, 0, PCI_COMMAND);
cmd |= 0x0007u; /* IO Space | Memory Space | Bus Master */
pci_write(bus, dev, 0, PCI_COMMAND, cmd);
raw_log("[e1000.raw] PCI command enabled\n");
u32 bar0 = pci_read(bus,dev,0,PCI_BAR0);
if (bar0 & 1u) {
raw_log("[e1000.raw] IO BAR unsupported\n");
return 0;
}
g_bar0_phys = (u64)(bar0 & 0xFFFFFFF0ULL);
if ((bar0 & 0x6u) == 0x4u) {
u32 bar1 = pci_read(bus,dev,0,PCI_BAR1);
g_bar0_phys |= ((u64)bar1 << 32);
}
raw_hex("[e1000.raw] BAR0 raw=", bar0);
raw_hex("[e1000.raw] BAR0 phys=", g_bar0_phys);
if (!g_bar0_phys) {
raw_log("[e1000.raw] BAR0 unavailable\n");
return 0;
}
raw_log("[e1000.raw] BAR0 ok\n");
u64 hhdm = api->hhdm_offset;
g_mmio = (volatile u32*)(uintptr_t)(hhdm + g_bar0_phys);
(void)g_mmio[E1000_STATUS/4];
raw_log("[e1000.raw] MMIO status read ok\n");
/* 软件复位,确保 RX/TX/RAL/RAH 从已知状态开始配置。 */
g_mmio[E1000_CTRL/4] = g_mmio[E1000_CTRL/4] | (1u << 26);
/* 实机: 1秒 TSC 超时等待复位完成 */
u64 deadline = dkm_rdtsc() + dkm_tsc_per_ms * 1000;
while (dkm_rdtsc() < deadline) {
if (!(g_mmio[E1000_CTRL/4] & (1u << 26))) break;
__asm__ volatile("pause");
}
raw_log("[e1000.raw] reset done\n");
u32 ral = g_mmio[E1000_RAL/4];
u32 rah = g_mmio[E1000_RAH/4];
u8 mac[6];
mac[0] = (u8)(ral & 0xff);
mac[1] = (u8)((ral>>8) & 0xff);
mac[2] = (u8)((ral>>16) & 0xff);
mac[3] = (u8)((ral>>24) & 0xff);
mac[4] = (u8)(rah & 0xff);
mac[5] = (u8)((rah>>8) & 0xff);
/* RAL/RAH 为空时从 EEPROM 读 MAC */
if (ral == 0 && (rah & 0xffff) == 0) {
u16 w0 = e1000_eeprom_read(0);
u16 w1 = e1000_eeprom_read(1);
u16 w2 = e1000_eeprom_read(2);
if (!(w0==0xffff && w1==0xffff && w2==0xffff)) {
mac[0]=(u8)(w0&0xff); mac[1]=(u8)(w0>>8);
mac[2]=(u8)(w1&0xff); mac[3]=(u8)(w1>>8);
mac[4]=(u8)(w2&0xff); mac[5]=(u8)(w2>>8);
}
}
/* 仍为全 0 时使用与虚拟机配置一致的回退 MAC,保证收发地址匹配 */
if (mac[0]==0&&mac[1]==0&&mac[2]==0&&mac[3]==0&&mac[4]==0&&mac[5]==0) {
mac[0]=0x52; mac[1]=0x54; mac[2]=0x00; mac[3]=0x12; mac[4]=0x34; mac[5]=0x56;
raw_log("[e1000.raw] using fallback MAC 52:54:00:12:34:56\n");
}
/* 写入 RAL/RAH 并置 AV(bit31) 使能接收该单播地址 */
g_mmio[E1000_RAL/4] = (u32)mac[0] | ((u32)mac[1]<<8) | ((u32)mac[2]<<16) | ((u32)mac[3]<<24);
g_mmio[E1000_RAH/4] = (u32)mac[4] | ((u32)mac[5]<<8) | (1u<<31);
raw_log("[e1000.raw] MAC read ok\n");
u32 irq_line = pci_read(bus,dev,0,PCI_IRQ_LINE) & 0xff;
g_mmio[E1000_CTRL/4] = g_mmio[E1000_CTRL/4] | E1000_CTRL_FD | E1000_CTRL_SLU;
raw_log("[e1000.raw] link setup\n");
g_mmio[E1000_IMC/4] = 0xffffffffu;
(void)g_mmio[E1000_ICR/4];
raw_log("[e1000.raw] interrupts masked\n");
int ring_rc = e1000_init_rings(api->dma);
if (ring_rc != 0) raw_log("[e1000.raw] ring init failed\n");
if (api->net && api->net->register_device) {
struct dkm_net_device_desc netdev;
netdev.name = "e1000";
for (int i=0;i<6;i++) netdev.mac[i] = mac[i];
netdev.flags = DKM_NET_F_LINK_UP;
if (g_rings_ready) netdev.flags |= DKM_NET_F_TX_READY | DKM_NET_F_RX_READY;
netdev.ctx = 0;
netdev.tx = g_rings_ready ? e1000_tx : 0;
netdev.rx_poll = g_rings_ready ? e1000_rx_poll : 0;
int net_index = api->net->register_device(&netdev);
(void)net_index;
raw_log("[e1000.raw] netdev registered\n");
} else {
raw_log("[e1000.raw] net API unavailable\n");
}
g_mmio[E1000_IMC/4] = 0xffffffffu;
if (api->irq_register && irq_line < 16) {
api->irq_register((u8)irq_line, (void*)(uintptr_t)irq_handler);
raw_log("[e1000.raw] IRQ registered\n");
}
raw_log("[e1000.raw] driver ready\n");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle; return 0;
}
+309
View File
@@ -0,0 +1,309 @@
/* DKM FAT32 Driver — read-only FAT32 filesystem parser
* Stage 2, optional, depends on "vfs" and "block".
* Reads from an embedded FAT32 test image (boot module "dkm:test_fat32").
* Parses BPB, walks FAT, reads root dir, lists files, reads a file.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_block_api {
int (*register_device)(const void *desc);
u32 (*device_count)(void);
int (*read)(u32 index, u64 lba, u32 count, void *buffer);
int (*write)(u32 index, u64 lba, u32 count, const void *buffer);
u64 (*sector_size)(u32 index);
const char *(*device_name)(u32 index);
int (*set_write_fn)(u32 index, int (*fn)(void *ctx, u64 lba, u32 count, const void *buf));
};
struct dkm_kernel_api {
u32 version; u32 size; u64 feature_bits;
const struct dkm_log_api *log;
const void *mem,*utsm,*irq,*pci_api,*dma,*vfs_api,*net,*timer,*drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width,fb_height,fb_pitch; u16 fb_bpp;
const void *boot_modules_response;
int (*irq_register)(u8 irq, void *handler);
u64 hhdm_offset;
const struct dkm_block_api *block;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic; u16 abi_version; u16 desc_size;
const char *name,*version,*vendor;
u32 driver_class,stage,flags,priority;
const char *const *depends; u32 depends_count;
const char *const *provides; u32 provides_count;
u64 min_kernel_abi,feature_bits,reserved0,reserved1;
};
struct limine_file {
u64 revision; void *address; u64 size; char *path; char *cmdline; u8 _pad[56];
};
struct limine_module_response {
u64 revision; u64 module_count; struct limine_file **modules;
};
/* ---------------------------------------------------------------
* FAT32 BPB
* --------------------------------------------------------------- */
typedef struct __attribute__((packed)) {
u8 jmp[3];
char oem[8];
u16 bytes_per_sector;
u8 sectors_per_cluster;
u16 reserved_sector_count;
u8 fat_count;
u16 root_entry_count;
u16 total_sectors_16;
u8 media;
u16 sectors_per_fat_16;
u16 sectors_per_track;
u16 heads;
u32 hidden_sectors;
u32 total_sectors_32;
/* FAT32 extended */
u32 sectors_per_fat;
u16 flags;
u16 version;
u32 root_cluster;
u16 fsinfo_sector;
u16 backup_boot;
u8 reserved[12];
u8 drive;
u8 nt_flags;
u8 signature;
u32 serial;
char label[11];
char type[8];
u8 code[420];
u16 boot_sig;
} fat32_bpb;
typedef struct __attribute__((packed)) {
char name[11];
u8 attr;
u8 nt_reserved;
u8 creation_tenth;
u16 creation_time;
u16 creation_date;
u16 access_date;
u16 cluster_high;
u16 write_time;
u16 write_date;
u16 cluster_low;
u32 file_size;
} fat32_dir_entry;
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_depends[] = { "vfs", "block" };
static const char *const g_provides[] = { "fat32" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic=DKM_DRIVER_MAGIC, .abi_version=DKM_ABI_VERSION,
.desc_size=sizeof(struct dkm_driver_desc),
.name="fat32", .version="0.1.0", .vendor="Deshab",
.driver_class=7, .stage=2, .flags=0, .priority=0,
.depends=g_depends, .depends_count=2,
.provides=g_provides, .provides_count=1,
.min_kernel_abi=1,
};
/* ---------------------------------------------------------------
* Helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static u8 g_block_image[65536];
static int fat32_bpb_valid(const u8 *disk, u64 disk_size) {
if (!disk || disk_size < 512) return 0;
const fat32_bpb *bpb = (const fat32_bpb *)disk;
if (bpb->boot_sig != 0xAA55) return 0;
if (bpb->bytes_per_sector != 512) return 0;
if (bpb->sectors_per_cluster == 0) return 0;
if (bpb->reserved_sector_count == 0) return 0;
if (bpb->fat_count == 0) return 0;
if (bpb->sectors_per_fat == 0) return 0;
if (bpb->root_cluster < 2) return 0;
return 1;
}
static void log_hex(const char *p, u64 v) {
static const char h[] = "0123456789abcdef";
char b[19]; u32 i=0; b[i++]='0'; b[i++]='x';
for (int j=15;j>=0;j--) b[i++]=h[(v>>(j*4))&0xf];
b[i]=0; g_log->info(p); g_log->info(b);
}
static u32 read_u32_le(const u8 *p) {
return (u32)p[0]|((u32)p[1]<<8)|((u32)p[2]<<16)|((u32)p[3]<<24);
}
static u16 read_u16_le(const u8 *p) {
return (u16)p[0]|((u16)p[1]<<8);
}
static int strneq(const char *a, const char *b, int n) {
for (int i=0;i<n;i++) { if (a[i]!=b[i]) return 0; }
return 1;
}
static void log_name11(const char *n) {
char buf[13]; int j=0;
for (int i=0;i<8 && n[i]!=0x20 && n[i];i++) buf[j++]=n[i];
if (n[8]!=0x20 || (n[9]!=0x20 && n[9]!=0)) {
buf[j++]='.';
for (int i=8;i<11 && n[i]!=0x20 && n[i];i++) buf[j++]=n[i];
}
buf[j]=0; g_log->info(buf);
}
static const u8 *fat32_find_boot_module_image(const struct dkm_kernel_api *api, u64 *size_out) {
const struct limine_module_response *rsp =
(const struct limine_module_response *)api->boot_modules_response;
if (!rsp) return NULL;
for (u64 i=0;i<rsp->module_count;i++) {
struct limine_file *f=rsp->modules[i];
if (f&&f->cmdline&&strneq(f->cmdline,"dkm:test_fat32",13)) {
if (size_out) *size_out=f->size;
return (const u8*)f->address;
}
}
return NULL;
}
static const u8 *fat32_select_disk_image(const struct dkm_kernel_api *api, u64 *size_out) {
if (api->block && api->block->device_count && api->block->read && api->block->sector_size) {
u32 count = api->block->device_count();
log_hex("[fat32] block devices=", count);
if (count > 0 && api->block->sector_size(0) == 512) {
const char *name = api->block->device_name ? api->block->device_name(0) : NULL;
g_log->info("[fat32] trying block provider");
if (name) g_log->info(name);
int st = api->block->read(0, 0, 128, g_block_image);
log_hex("[fat32] block read status=", (u64)(i64)st);
if (st == 0 && fat32_bpb_valid(g_block_image, sizeof(g_block_image))) {
g_log->info("[fat32] using block provider image");
if (size_out) *size_out = sizeof(g_block_image);
return g_block_image;
}
g_log->warn("[fat32] block provider image is not FAT32; fallback");
}
}
u64 module_size = 0;
const u8 *module = fat32_find_boot_module_image(api, &module_size);
if (module) {
g_log->info("[fat32] using boot module image");
if (size_out) *size_out = module_size;
return module;
}
return NULL;
}
/* ---------------------------------------------------------------
* Driver entry
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api||!api->log) return -1;
g_log=api->log;
u64 disk_size = 0;
const u8 *disk = fat32_select_disk_image(api, &disk_size);
if (!disk) { g_log->warn("[fat32] no FAT32 image source"); return 0; }
if (!fat32_bpb_valid(disk, disk_size)) { g_log->warn("[fat32] invalid FAT32 BPB"); return 0; }
g_log->info("[fat32] parsing FAT32 image");
const fat32_bpb *bpb=(const fat32_bpb*)disk;
u32 bps=bpb->bytes_per_sector;
u32 spc=bpb->sectors_per_cluster;
u32 rsc=bpb->reserved_sector_count;
u32 spf=bpb->sectors_per_fat;
u32 root_clus=bpb->root_cluster;
log_hex("[fat32] bytes/sec=",bps);
log_hex("[fat32] sec/cluster=",spc);
log_hex("[fat32] fat start sec=",rsc);
log_hex("[fat32] sec/fat=",spf);
log_hex("[fat32] root cluster=",root_clus);
/* read root directory */
u32 cluster_size = bps * spc;
u32 fat_start = rsc * bps;
u32 data_start = fat_start + spf * bps;
g_log->info("[fat32] root dir entries:");
u32 clus = root_clus;
while (clus >= 2 && clus < 0x0FFFFFF8) {
u32 clus_off = data_start + (clus - 2) * cluster_size;
const fat32_dir_entry *dir = (const fat32_dir_entry *)(disk + clus_off);
for (u32 e=0; e*32 < cluster_size; e++) {
if (dir[e].name[0]==0) break;
if ((u8)dir[e].name[0]==0xE5) continue;
if (dir[e].attr==0x0F) continue; /* skip LFN */
if (dir[e].attr & 0x08) continue; /* skip volume label */
g_log->info("[fat32] ");
log_name11(dir[e].name);
log_hex("[fat32] size=",dir[e].file_size);
/* try to read README.TXT content */
if (strneq(dir[e].name,"README TXT",11)) {
u32 f_clus = read_u16_le((const u8*)&dir[e].cluster_low);
u32 f_off = data_start + (f_clus - 2)*cluster_size;
u32 f_size = dir[e].file_size;
g_log->info("[fat32] --- README.TXT content ---");
u32 n = f_size < 128 ? f_size : 128;
char line[80]; u32 lp=0;
for (u32 k=0;k<n;k++) {
u8 c = disk[f_off+k];
line[lp++]=c;
if (c=='\n'||lp>=78||k==n-1) { line[lp]=0; g_log->info("[fat32] "); g_log->info(line); lp=0; }
}
g_log->info("[fat32] --- end ---");
}
}
/* read next cluster from FAT */
u32 fat_ent_off = fat_start + clus * 4;
clus = read_u32_le(disk + fat_ent_off) & 0x0FFFFFFF;
}
g_log->info("[fat32] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle; return 0;
}
+347
View File
@@ -0,0 +1,347 @@
/* DKM NVMe Driver — PCI NVMe discovery and controller register enumeration
* Stage 1 optional storage driver, depends on "pci" and "irq", provides "block".
* This first version only discovers NVMe controllers and reads BAR0 registers;
* it does not enable queues or submit admin commands.
*/
#include <stdint.h>
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response;
int (*irq_register)(u8 irq, void *handler);
u64 hhdm_offset;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
static const char *const g_depends[] = { "pci", "irq" };
static const char *const g_provides[] = { "block" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "nvme",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 6, /* DKM_CLASS_STORAGE */
.stage = 1,
.flags = 0, /* optional */
.priority = 0,
.depends = g_depends,
.depends_count = 2,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
#define PCI_ADDR 0xCF8
#define PCI_DATA 0xCFC
#define PCI_VENDOR_ID 0x00
#define PCI_COMMAND 0x04
#define PCI_CLASS_REG 0x08
#define PCI_HEADER 0x0E
#define PCI_BAR0 0x10
#define PCI_BAR1 0x14
#define PCI_IRQ_LINE 0x3C
#define PCI_CMD_MEM (1u << 1)
#define PCI_CMD_BUSM (1u << 2)
#define NVME_CLASS_STORAGE 0x01
#define NVME_SUBCLASS_NVM 0x08
#define NVME_PROGIF_NVME 0x02
#define NVME_CAP 0x00
#define NVME_VS 0x08
#define NVME_INTMS 0x0C
#define NVME_INTMC 0x10
#define NVME_CC 0x14
#define NVME_CSTS 0x1C
#define NVME_NSSR 0x20
#define NVME_AQA 0x24
#define NVME_ASQ 0x28
#define NVME_ACQ 0x30
#define NVME_CMBLOC 0x38
#define NVME_CMBSZ 0x3C
static const struct dkm_log_api *g_log;
static volatile u8 *g_regs;
static __inline__ void outl(u16 port, u32 value) {
__asm__ volatile ("outl %0, %1" :: "a"(value), "Nd"(port));
}
static __inline__ u32 inl(u16 port) {
u32 value;
__asm__ volatile ("inl %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
static u32 pci_read(u8 bus, u8 dev, u8 func, u8 reg) {
u32 addr = (1u << 31)
| ((u32)bus << 16)
| ((u32)dev << 11)
| ((u32)func << 8)
| ((u32)reg & 0xFC);
outl(PCI_ADDR, addr);
return inl(PCI_DATA);
}
static void pci_write(u8 bus, u8 dev, u8 func, u8 reg, u32 value) {
u32 addr = (1u << 31)
| ((u32)bus << 16)
| ((u32)dev << 11)
| ((u32)func << 8)
| ((u32)reg & 0xFC);
outl(PCI_ADDR, addr);
outl(PCI_DATA, value);
}
static u32 mmio_read32(u32 off) {
return *(volatile u32 *)(void *)(g_regs + off);
}
static u64 mmio_read64(u32 off) {
u32 lo = mmio_read32(off);
u32 hi = mmio_read32(off + 4);
return ((u64)hi << 32) | lo;
}
static void log_hex(const char *prefix, u64 value) {
static const char hex[] = "0123456789abcdef";
char buf[19];
u32 pos = 0;
buf[pos++] = '0';
buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(value >> (i * 4)) & 0xf];
}
buf[pos] = 0;
g_log->info(prefix);
g_log->info(buf);
}
static int nvme_find(u8 *out_bus, u8 *out_dev, u8 *out_func) {
for (u8 bus = 0; bus < 16; bus++) {
for (u8 dev = 0; dev < 32; dev++) {
u32 vd = pci_read(bus, dev, 0, PCI_VENDOR_ID);
if ((vd & 0xffff) == 0xffff) continue;
u8 header = (u8)(pci_read(bus, dev, 0, PCI_HEADER) >> 16);
u8 func_count = (header & 0x80) ? 8 : 1;
for (u8 func = 0; func < func_count; func++) {
u32 vd2 = pci_read(bus, dev, func, PCI_VENDOR_ID);
if ((vd2 & 0xffff) == 0xffff) continue;
u32 class_reg = pci_read(bus, dev, func, PCI_CLASS_REG);
u8 prog_if = (u8)((class_reg >> 8) & 0xff);
u8 subclass = (u8)((class_reg >> 16) & 0xff);
u8 class_code = (u8)((class_reg >> 24) & 0xff);
if (class_code == NVME_CLASS_STORAGE &&
subclass == NVME_SUBCLASS_NVM &&
prog_if == NVME_PROGIF_NVME) {
*out_bus = bus;
*out_dev = dev;
*out_func = func;
return 0;
}
}
}
}
return -1;
}
static void log_nvme_version(u32 vs) {
log_hex("[nvme] version major=", (vs >> 16) & 0xffff);
log_hex("[nvme] version minor=", (vs >> 8) & 0xff);
log_hex("[nvme] version tertiary=", vs & 0xff);
}
static void log_cap_fields(u64 cap) {
log_hex("[nvme] CAP.MQES=", cap & 0xffff);
log_hex("[nvme] CAP.CQR=", (cap >> 16) & 1);
log_hex("[nvme] CAP.AMS=", (cap >> 17) & 3);
log_hex("[nvme] CAP.TO=", (cap >> 24) & 0xff);
log_hex("[nvme] CAP.DSTRD=", (cap >> 32) & 0xf);
log_hex("[nvme] CAP.NSSRS=", (cap >> 36) & 1);
log_hex("[nvme] CAP.CSS=", (cap >> 37) & 0xff);
log_hex("[nvme] CAP.MPSMIN=", (cap >> 48) & 0xf);
log_hex("[nvme] CAP.MPSMAX=", (cap >> 52) & 0xf);
}
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
g_log->info("[nvme] init begin");
u8 bus = 0;
u8 dev = 0;
u8 func = 0;
if (nvme_find(&bus, &dev, &func) != 0) {
g_log->warn("[nvme] NVMe controller not found");
g_log->info("[nvme] driver ready");
return 0;
}
g_log->info("[nvme] NVMe controller found");
log_hex("[nvme] bus=", bus);
log_hex("[nvme] dev=", dev);
log_hex("[nvme] func=", func);
u32 vd = pci_read(bus, dev, func, PCI_VENDOR_ID);
log_hex("[nvme] vendor=", vd & 0xffff);
log_hex("[nvme] device=", vd >> 16);
u32 command = pci_read(bus, dev, func, PCI_COMMAND) & 0xffff;
command |= PCI_CMD_MEM | PCI_CMD_BUSM;
pci_write(bus, dev, func, PCI_COMMAND, command);
log_hex("[nvme] PCI command=", command);
u32 bar0_lo = pci_read(bus, dev, func, PCI_BAR0);
u32 bar1_hi = pci_read(bus, dev, func, PCI_BAR1);
u64 bar_phys;
if (bar0_lo & 1u) {
g_log->warn("[nvme] BAR0 is IO space; unsupported");
g_log->info("[nvme] driver ready");
return 0;
}
if ((bar0_lo & 0x6u) == 0x4u) {
bar_phys = ((u64)bar1_hi << 32) | (u64)(bar0_lo & 0xFFFFFFF0u);
} else {
bar_phys = (u64)(bar0_lo & 0xFFFFFFF0u);
}
u32 irq_line = pci_read(bus, dev, func, PCI_IRQ_LINE) & 0xff;
log_hex("[nvme] BAR0 phys=", bar_phys);
log_hex("[nvme] PCI IRQ line=", irq_line);
if (!api->hhdm_offset || !bar_phys) {
g_log->warn("[nvme] missing HHDM or BAR0; skip MMIO enumeration");
g_log->info("[nvme] driver ready");
return 0;
}
if (bar_phys >= 0x100000000ULL) {
g_log->warn("[nvme] BAR0 is above 4G; current HHDM MMIO map cannot safely read it");
g_log->info("[nvme] discovery only; MMIO enumeration skipped");
g_log->info("[nvme] driver ready");
return 0;
}
g_regs = (volatile u8 *)(uintptr_t)(api->hhdm_offset + bar_phys);
log_hex("[nvme] HHDM offset=", api->hhdm_offset);
u64 cap = mmio_read64(NVME_CAP);
u32 vs = mmio_read32(NVME_VS);
u32 intms = mmio_read32(NVME_INTMS);
u32 intmc = mmio_read32(NVME_INTMC);
u32 cc = mmio_read32(NVME_CC);
u32 csts = mmio_read32(NVME_CSTS);
u32 nssr = mmio_read32(NVME_NSSR);
u32 aqa = mmio_read32(NVME_AQA);
u64 asq = mmio_read64(NVME_ASQ);
u64 acq = mmio_read64(NVME_ACQ);
u32 cmbloc = mmio_read32(NVME_CMBLOC);
u32 cmbsz = mmio_read32(NVME_CMBSZ);
log_hex("[nvme] CAP=", cap);
log_cap_fields(cap);
log_hex("[nvme] VS=", vs);
log_nvme_version(vs);
log_hex("[nvme] INTMS=", intms);
log_hex("[nvme] INTMC=", intmc);
log_hex("[nvme] CC=", cc);
log_hex("[nvme] CSTS=", csts);
log_hex("[nvme] NSSR=", nssr);
log_hex("[nvme] AQA=", aqa);
log_hex("[nvme] ASQ=", asq);
log_hex("[nvme] ACQ=", acq);
log_hex("[nvme] CMBLOC=", cmbloc);
log_hex("[nvme] CMBSZ=", cmbsz);
if (cc & 1u) {
g_log->warn("[nvme] controller already enabled; leaving state unchanged");
} else {
g_log->info("[nvme] controller disabled; queues not configured");
}
g_log->info("[nvme] discovery only; admin queues disabled");
g_log->info("[nvme] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+251
View File
@@ -0,0 +1,251 @@
/* DKM PCI Driver — PCI bus enumeration via config space (0xCF8/0xCFC)
* Stage 0, required, depends on "irq", provides "pci".
* No IRQ needed for enumeration. Scans all buses/devices/functions.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci_api;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
/* ---------------------------------------------------------------
* PCI constants
* --------------------------------------------------------------- */
#define PCI_CFG_ADDR 0xCF8
#define PCI_CFG_DATA 0xCFC
#define PCI_VENDOR_ID 0x00
#define PCI_DEVICE_ID 0x02
#define PCI_COMMAND 0x04
#define PCI_STATUS 0x06
#define PCI_CLASS 0x0B /* class code */
#define PCI_SUBCLASS 0x0A /* subclass */
#define PCI_PROG_IF 0x09 /* prog IF */
#define PCI_HEADER_TYPE 0x0E
#define PCI_BAR0 0x10
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_depends[] = { "irq" };
static const char *const g_provides[] = { "pci" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "pci",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 2, /* DKM_CLASS_BUS */
.stage = 0,
.flags = 1, /* DKM_F_REQUIRED */
.priority = 0,
.depends = g_depends,
.depends_count = 1,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* I/O helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static __inline__ void outl(u16 port, u32 value) {
__asm__ volatile ("outl %0, %1" :: "a"(value), "Nd"(port));
}
static __inline__ u32 inl(u16 port) {
u32 value;
__asm__ volatile ("inl %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
/* ---------------------------------------------------------------
* PCI config access
* --------------------------------------------------------------- */
static u32 pci_cfg_read(u8 bus, u8 dev, u8 func, u8 reg) {
u32 addr = (u32)((1u << 31)
| ((u32)bus << 16)
| ((u32)dev << 11)
| ((u32)func << 8)
| ((u32)reg & 0xFC));
outl(PCI_CFG_ADDR, addr);
return inl(PCI_CFG_DATA);
}
static void pci_cfg_write(u8 bus, u8 dev, u8 func, u8 reg, u32 val) {
u32 addr = (u32)((1u << 31)
| ((u32)bus << 16)
| ((u32)dev << 11)
| ((u32)func << 8)
| ((u32)reg & 0xFC));
outl(PCI_CFG_ADDR, addr);
outl(PCI_CFG_DATA, val);
}
/* ---------------------------------------------------------------
* Log helpers
* --------------------------------------------------------------- */
static void log_hex(const char *prefix, u64 val) {
static const char hex[] = "0123456789abcdef";
char buf[19];
u32 pos = 0;
buf[pos++] = '0'; buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(val >> (i * 4)) & 0xf];
}
buf[pos] = 0;
g_log->info(prefix);
g_log->info(buf);
}
static const char *pci_class_name(u8 base, u8 sub) {
switch (base) {
case 0x00: return "Legacy";
case 0x01: return "Storage";
case 0x02: return "Network";
case 0x03: return "Display";
case 0x04: return "Multimedia";
case 0x05: return "Memory";
case 0x06: return "Bridge";
case 0x07: return "SimpleComm";
case 0x08: return "BasePeriph";
case 0x09: return "Input";
case 0x0A: return "Docking";
case 0x0B: return "CPU";
case 0x0C: return "SerialBus";
case 0x0D: return "Wireless";
case 0x0E: return "IntelligentIO";
case 0x0F: return "Satellite";
case 0x10: return "Crypto";
case 0x11: return "SignalProc";
case 0x12: return "Accelerator";
default: return "Unknown";
}
(void)sub;
}
/* ---------------------------------------------------------------
* Enumeration
* --------------------------------------------------------------- */
static void pci_scan_bus(u8 bus) {
for (u8 dev = 0; dev < 32; dev++) {
u32 vid_dev = pci_cfg_read(bus, dev, 0, PCI_VENDOR_ID);
u16 vendor = (u16)(vid_dev & 0xffff);
if (vendor == 0xffff) continue;
u8 header_type = (u8)(pci_cfg_read(bus, dev, 0, PCI_HEADER_TYPE) >> 16);
int multi_func = (header_type & 0x80) != 0;
u8 func_count = multi_func ? 8 : 1;
for (u8 func = 0; func < func_count; func++) {
u32 vid_dev2 = pci_cfg_read(bus, dev, func, PCI_VENDOR_ID);
u16 vendor2 = (u16)(vid_dev2 & 0xffff);
if (vendor2 == 0xffff) continue;
u16 device = (u16)(vid_dev2 >> 16);
u32 cc = pci_cfg_read(bus, dev, func, PCI_CLASS);
u8 class_code = (u8)(cc >> 24);
u8 subclass = (u8)((cc >> 16) & 0xff);
g_log->info("[pci]");
log_hex("[pci] bus=", bus);
log_hex("[pci] dev=", dev);
log_hex("[pci] func=", func);
log_hex("[pci] vendor=", vendor2);
log_hex("[pci] device=", device);
g_log->info("[pci] class");
g_log->info(pci_class_name(class_code, subclass));
log_hex("[pci] class_hex=", class_code);
log_hex("[pci] subclass=", subclass);
}
}
}
/* ---------------------------------------------------------------
* Driver entry
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
g_log->info("[pci] scanning PCI bus");
pci_scan_bus(0);
g_log->info("[pci] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+139
View File
@@ -0,0 +1,139 @@
/* DKM PS/2 Keyboard Driver — IRQ1 scan code → ASCII
* Stage 3, optional, depends on "irq", provides "keyboard".
* Registers IRQ1 handler, translates scan codes via lookup table.
*/
#include <stdint.h>
/* DKM ABI types */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version; u32 size; u64 feature_bits;
const struct dkm_log_api *log;
const void *mem,*utsm,*irq_api,*pci_api,*dma,*vfs_api,*net,*timer,*drr;
const void *rsdp_address,*fb_address;
u64 fb_width,fb_height,fb_pitch; u16 fb_bpp;
const void *boot_modules_response;
int (*irq_register)(u8 irq, void *handler);
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic; u16 abi_version; u16 desc_size;
const char *name,*version,*vendor;
u32 driver_class,stage,flags,priority;
const char *const *depends; u32 depends_count;
const char *const *provides; u32 provides_count;
u64 min_kernel_abi,feature_bits,reserved0,reserved1;
};
/* Driver descriptor */
static const char *const g_depends[] = {"irq"};
static const char *const g_provides[] = {"keyboard"};
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic=DKM_DRIVER_MAGIC, .abi_version=DKM_ABI_VERSION,
.desc_size=sizeof(struct dkm_driver_desc),
.name="ps2kbd", .version="0.1.0", .vendor="Deshab",
.driver_class=10, .stage=3, .flags=0, .priority=0,
.depends=g_depends, .depends_count=1,
.provides=g_provides, .provides_count=1,
.min_kernel_abi=1,
};
/* Scan code set 1 → ASCII (lowercase) */
static const char sc_ascii[] = {
0,0,'1','2','3','4','5','6','7','8','9','0','-','=',0,
0,'q','w','e','r','t','y','u','i','o','p','[',']',0,
0,'a','s','d','f','g','h','j','k','l',';','\'','`',0,
'\\','z','x','c','v','b','n','m',',','.','/',0,
'*',0,' ',0
};
static const struct dkm_log_api *g_log;
static volatile int g_has_key;
static volatile u8 g_last_sc;
/* inline I/O */
static u8 inb(u16 p) { u8 v; __asm__("inb %1,%0":"=a"(v):"Nd"(p)); return v; }
static void outb(u16 p, u8 v) { __asm__("outb %0,%1"::"a"(v),"Nd"(p)); }
static void log_hex(const char *prefix, u64 v) {
static const char h[]="0123456789abcdef";
char b[19]; u32 i=0; b[i++]='0'; b[i++]='x';
for (int j=15;j>=0;j--) b[i++]=h[(v>>(j*4))&0xf];
b[i]=0; g_log->info(prefix); g_log->info(b);
}
static int kbd_handler(u8 irq) {
(void)irq;
g_last_sc = inb(0x60);
g_has_key = 1;
return 0; /* let kernel send EOI */
}
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api||!api->log) return -1;
g_log=api->log;
if (!api->irq_register) {
g_log->warn("[kbd] irq_register not available");
return 0;
}
if (api->irq_register(1, (void*)(uintptr_t)kbd_handler) != 0) {
g_log->error("[kbd] failed to register IRQ1");
return -1;
}
g_log->info("[kbd] IRQ1 registered, waiting for keypress");
g_log->info("[kbd] (boot will continue, key echo in ISR)");
/* spin briefly to show a key echo demo */
int ticks = 0;
while (ticks < 200000) {
if (g_has_key) {
u8 sc = g_last_sc;
g_has_key = 0;
if (sc < 0x80) {
/* make code */
log_hex("[kbd] sc=", sc);
if (sc < sizeof(sc_ascii) && sc_ascii[sc]) {
char buf[2] = {sc_ascii[sc], 0};
g_log->info("[kbd] key");
g_log->info(buf);
}
}
}
for (volatile int z=0;z<100;z++) {}
ticks++;
}
g_log->info("[kbd] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle; return 0;
}
+105
View File
@@ -0,0 +1,105 @@
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$Root = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $ScriptDir))
$Source = Join-Path $Root 'CODE\DKM\stub_driver\stub_driver.c'
$Manifest = Join-Path $Root 'SYSTEM\driver\manifest.json'
$SystemDriver = Join-Path $Root 'SYSTEM\driver'
$BuildDir = Join-Path $Root '.build_tmp\drivers'
function Find-Tool($Name, $ExtraNames = @()) {
$names = @($Name) + $ExtraNames
foreach ($n in $names) {
$cmd = Get-Command $n -ErrorAction SilentlyContinue
if ($cmd) { return $cmd.Source }
}
$dirs = @(
'C:\Program Files\LLVM\bin',
'C:\Program Files (x86)\LLVM\bin',
'C:\LLVM\bin',
'D:\LLVM\bin',
'D:\Program Files\LLVM\bin',
'D:\Code\LLVM\bin',
'C:\msys64\clang64\bin',
'C:\msys64\mingw64\bin',
'C:\mingw64\bin'
)
foreach ($dir in $dirs) {
foreach ($n in $names) {
$candidate = Join-Path $dir $n
if (Test-Path $candidate) { return $candidate }
if (-not $n.EndsWith('.exe')) {
$candidateExe = Join-Path $dir "$n.exe"
if (Test-Path $candidateExe) { return $candidateExe }
}
}
}
return $null
}
function Get-DriverClassValue([string]$Class) {
switch ($Class) {
'platform' { return 1 }
'bus' { return 2 }
'interrupt' { return 3 }
'timer' { return 4 }
'console' { return 5 }
'storage' { return 6 }
'fs' { return 7 }
'fs-core' { return 8 }
'net' { return 9 }
'input' { return 10 }
'gpu' { return 11 }
default { return 0 }
}
}
$clang = Find-Tool 'clang'
$lld = Find-Tool 'ld.lld'
if (-not $clang) {
throw 'clang was not found. Install LLVM/Clang.'
}
if (-not $lld) {
throw 'ld.lld was not found. Install LLVM lld.'
}
New-Item -ItemType Directory -Force -Path $BuildDir | Out-Null
$manifestData = Get-Content -Raw -LiteralPath $Manifest | ConvertFrom-Json
$count = 0
foreach ($stage in $manifestData.stages) {
foreach ($driver in $stage.drivers) {
$relative = [string]$driver.path
if (-not $relative.StartsWith('driver/')) {
throw "Unexpected driver path: $relative"
}
$destRelative = $relative.Substring('driver/'.Length).Replace('/', '\')
$dest = Join-Path $SystemDriver $destRelative
$destDir = Split-Path -Parent $dest
New-Item -ItemType Directory -Force -Path $destDir | Out-Null
$name = [string]$driver.name
$classValue = Get-DriverClassValue ([string]$driver.class)
$stageValue = [int]$stage.id
$flags = 0
if ([bool]$driver.required) { $flags = $flags -bor 1 }
if ($stageValue -le 1) { $flags = $flags -bor 2 }
$obj = Join-Path $BuildDir "$name.o"
$drv = Join-Path $BuildDir "$name.drv"
$driverNameDefine = 'DRIVER_NAME=' + $name
& $clang -target x86_64-unknown-none -std=c11 -ffreestanding -fno-stack-protector -fno-pic -fno-pie -mno-red-zone -Wall -Wextra -O2 -c $Source -o $obj "-D$driverNameDefine" "-DDRIVER_CLASS=$classValue" "-DDRIVER_STAGE=$stageValue" "-DDRIVER_FLAGS=$flags"
if ($LASTEXITCODE -ne 0) { throw "failed to compile stub driver: $name" }
& $lld -r -o $drv $obj
if ($LASTEXITCODE -ne 0) { throw "failed to link stub driver: $name" }
Copy-Item -LiteralPath $drv -Destination $dest -Force
Write-Host "[drivers] installed $relative"
$count++
}
}
Write-Host "[drivers] installed $count DKM stub drivers"
+93
View File
@@ -0,0 +1,93 @@
#include <stdint.h>
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1
#ifndef DRIVER_NAME
#define DRIVER_NAME stub
#endif
#define DKM_STRINGIFY_INNER(x) #x
#define DKM_STRINGIFY(x) DKM_STRINGIFY_INNER(x)
#define DRIVER_NAME_STRING DKM_STRINGIFY(DRIVER_NAME)
#ifndef DRIVER_CLASS
#define DRIVER_CLASS 0
#endif
#ifndef DRIVER_STAGE
#define DRIVER_STAGE 0
#endif
#ifndef DRIVER_FLAGS
#define DRIVER_FLAGS 0
#endif
#ifndef DRIVER_PRIORITY
#define DRIVER_PRIORITY 0
#endif
struct dkm_driver_desc {
uint32_t magic;
uint16_t abi_version;
uint16_t desc_size;
const char *name;
const char *version;
const char *vendor;
uint32_t driver_class;
uint32_t stage;
uint32_t flags;
uint32_t priority;
const char *const *depends;
uint32_t depends_count;
const char *const *provides;
uint32_t provides_count;
uint64_t min_kernel_abi;
uint64_t feature_bits;
uint64_t reserved0;
uint64_t reserved1;
};
struct dkm_kernel_api;
struct dkm_driver_handle;
__attribute__((visibility("default")))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = DRIVER_NAME_STRING,
.version = "0.1.0-stub",
.vendor = "Deshab",
.driver_class = DRIVER_CLASS,
.stage = DRIVER_STAGE,
.flags = DRIVER_FLAGS,
.priority = DRIVER_PRIORITY,
.depends = 0,
.depends_count = 0,
.provides = 0,
.provides_count = 0,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api, struct dkm_driver_handle *handle) {
(void)api;
(void)handle;
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+192
View File
@@ -0,0 +1,192 @@
/* DKM Timer Driver - PIT (Programmable Interval Timer)
* Stage 0 platform driver, provides "timer".
* No IDT/IRQ required - uses PIT counter polling for busy-wait delay.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types (standalone, no kernel headers)
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
/* ---------------------------------------------------------------
* PIT I/O ports
* --------------------------------------------------------------- */
#define PIT_CH0_DATA 0x40
#define PIT_CH1_DATA 0x41
#define PIT_CH2_DATA 0x42
#define PIT_CMD 0x43
/* PIT frequency: 1.193182 MHz */
#define PIT_BASE_FREQ 1193182ULL
static const char *const g_provides[] = { "timer" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "timer",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 4, /* DKM_CLASS_TIMER */
.stage = 0,
.flags = 1, /* DKM_F_REQUIRED */
.priority = 0,
.depends = NULL,
.depends_count = 0,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* Inline assembly for port I/O (works in Ring0 SAS-R0)
* --------------------------------------------------------------- */
static __inline__ void outb(u16 port, u8 value) {
__asm__ volatile ("outb %0, %1" :: "a"(value), "Nd"(port));
}
static __inline__ u8 inb(u16 port) {
u8 value;
__asm__ volatile ("inb %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
/* ---------------------------------------------------------------
* PIT operations
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static void pit_set_channel(u8 channel, u8 mode, u16 count) {
u8 cmd = (u8)((channel << 6) | (3 << 4) | (mode << 1));
outb(PIT_CMD, cmd);
outb((u16)(PIT_CH0_DATA + channel), (u8)(count & 0xff));
outb((u16)(PIT_CH0_DATA + channel), (u8)((count >> 8) & 0xff));
}
/* Read back current counter value via latch command */
static u16 pit_read_counter(void) {
u8 cmd = 0xD0; /* read-back: channel 0, latch count, no status */
outb(PIT_CMD, cmd);
u8 lo = inb(PIT_CH0_DATA);
u8 hi = inb(PIT_CH0_DATA);
return (u16)(((u16)hi << 8) | lo);
}
/* Busy-wait delay using PIT channel 0 counter.
* count: PIT divisor (1193182 = ~1 second)
* The counter counts DOWN from 'count' to 0.
* We set it to 'count', then poll until it reaches near 0.
*/
static void pit_delay(u16 count) {
pit_set_channel(0, 0, count); /* mode 0: interrupt on terminal count */
u16 prev = pit_read_counter();
u64 loops = 0;
while (1) {
u16 cur = pit_read_counter();
if (cur > prev && loops > 10) {
break; /* counter wrapped → terminal count reached */
}
prev = cur;
loops++;
}
}
/* ---------------------------------------------------------------
* Driver entry points
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) {
return -1;
}
g_log = api->log;
g_log->info("[timer] PIT driver initializing");
/* Quick calibration: set PIT to max count, measure how many
* iterations of read_counter() happen before terminal count.
*/
pit_set_channel(0, 0, 0xFFFF); /* 0xFFFF = max, ~55ms at 1.193 MHz */
u16 prev = pit_read_counter();
u64 cal_loops = 0;
while (1) {
u16 cur = pit_read_counter();
cal_loops++;
if (cur > prev && cal_loops > 5) break;
prev = cur;
}
/* Expected: PIT_BASE_FREQ / 0xFFFF ≈ 18.2 Hz, period ≈ 55 ms */
g_log->info("[timer] PIT calibration complete");
g_log->info("[timer] PIT channel 0 operational");
/* Do a quick ~100ms delay demo */
g_log->info("[timer] running 100ms busy-wait demo");
pit_delay((u16)(PIT_BASE_FREQ / 10)); /* ~0.1 sec = 119318 counts */
g_log->info("[timer] 100ms delay done");
g_log->info("[timer] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+222
View File
@@ -0,0 +1,222 @@
/* DKM VFS Driver — Virtual File System layer
* Stage 2, required, depends on "bootfs", provides "vfs".
* Mounts bootfs modules as files, implements basic open/read.
* Demo: reads and displays first 64 bytes of manifest.json.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci_api;
const void *dma;
const void *vfs_api;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
struct limine_file {
u64 revision;
void *address;
u64 size;
char *path;
char *cmdline;
u8 _pad[56];
};
struct limine_module_response {
u64 revision;
u64 module_count;
struct limine_file **modules;
};
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_depends[] = { "bootfs" };
static const char *const g_provides[] = { "vfs" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "vfs",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 8, /* DKM_CLASS_FS_CORE */
.stage = 2,
.flags = 1,
.priority = 0,
.depends = g_depends,
.depends_count = 1,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* Helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static void log_hex(const char *prefix, u64 val) {
static const char h[] = "0123456789abcdef";
char buf[19];
u32 p = 0;
buf[p++] = '0'; buf[p++] = 'x';
for (int i = 15; i >= 0; i--) buf[p++] = h[(val >> (i*4)) & 0xf];
buf[p] = 0;
g_log->info(prefix); g_log->info(buf);
}
static u64 min64(u64 a, u64 b) { return a < b ? a : b; }
static int path_match(const char *bp, const char *mp) {
/* strip leading '/' from bootloader path */
while (*bp == '/') bp++;
u64 i = 0;
while (bp[i] && mp[i] && bp[i] == mp[i]) i++;
return bp[i] == 0 && mp[i] == 0;
}
static int str_len(const char *s) {
int l = 0; while (s[l]) l++; return l;
}
/* ---------------------------------------------------------------
* Driver entry
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
const struct limine_module_response *rsp =
(const struct limine_module_response *)api->boot_modules_response;
if (!rsp) { g_log->error("[vfs] no modules"); return -1; }
g_log->info("[vfs] mounting bootfs as root");
log_hex("[vfs] files=", rsp->module_count);
/* list all files */
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (!f || !f->path) continue;
g_log->info("[vfs] /");
g_log->info(f->path);
}
/* ---- demo: open & read /driver/manifest.json ---- */
g_log->info("[vfs] demo: open //driver/manifest.json");
struct limine_file *target = NULL;
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (f && f->path && path_match(f->path, "driver/manifest.json")) {
target = f; break;
}
}
if (!target) {
g_log->warn("[vfs] manifest.json not found");
} else {
log_hex("[vfs] size=", target->size);
g_log->info("[vfs] content (first 64 bytes):");
/* dump first 64 bytes as hex + ascii */
u64 n = min64(64, target->size);
const u8 *data = (const u8 *)target->address;
char line[80];
for (u64 off = 0; off < n; off += 16) {
u32 pos = 0;
for (u32 j = 0; j < 16 && off + j < n; j++) {
u8 b = data[off + j];
line[pos++] = "0123456789abcdef"[b >> 4];
line[pos++] = "0123456789abcdef"[b & 0xf];
line[pos++] = ' ';
}
/* ascii */
line[pos++] = ' ';
for (u32 j = 0; j < 16 && off + j < n; j++) {
u8 c = data[off + j];
line[pos++] = (c >= 32 && c < 127) ? (char)c : '.';
}
line[pos] = 0;
g_log->info(line);
}
}
g_log->info("[vfs] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+282
View File
@@ -0,0 +1,282 @@
/* DKM virtio-net Driver — PCI virtio network discovery
* Stage 3 optional network driver, depends on "pci" and "irq", provides "netdev".
* This first version discovers virtio-net devices and logs PCI capabilities;
* it does not negotiate features, create virtqueues, or transmit packets.
*/
#include "../dkm_shared.h"
/* virtio-specific PCI IDs and capability types (driver-local) */
#define PCI_CLASS_REG 0x08 /* 32-bit class/subclass/prog_if/revision */
#define PCI_VENDOR_VIRTIO 0x1AF4u
#define VIRTIO_TRANS_DEVICE_MIN 0x1000u
#define VIRTIO_TRANS_DEVICE_MAX 0x103Fu
#define VIRTIO_MODERN_DEVICE_MIN 0x1040u
#define VIRTIO_MODERN_DEVICE_MAX 0x107Fu
#define VIRTIO_NET_DEVICE_ID 1u
#define VIRTIO_PCI_CAP_COMMON_CFG 1u
#define VIRTIO_PCI_CAP_NOTIFY_CFG 2u
#define VIRTIO_PCI_CAP_ISR_CFG 3u
#define VIRTIO_PCI_CAP_DEVICE_CFG 4u
#define VIRTIO_PCI_CAP_PCI_CFG 5u
static const char *const g_depends[] = { "pci", "irq" };
static const char *const g_provides[] = { "netdev" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "virtio_net",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 9, /* DKM_CLASS_NET */
.stage = 3,
.flags = 0,
.priority = 0,
.depends = g_depends,
.depends_count = 2,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
static const struct dkm_log_api *g_log;
static u32 pci_read(u8 bus, u8 dev, u8 func, u8 reg) {
return dkm_pci_read(bus, dev, func, reg);
}
static void pci_write(u8 bus, u8 dev, u8 func, u8 reg, u32 value) {
dkm_pci_write(bus, dev, func, reg, value);
}
static u8 pci_read8(u8 bus, u8 dev, u8 func, u8 reg) {
return dkm_pci_read8(bus, dev, func, reg);
}
static void log_hex(const char *prefix, u64 value) {
static const char hex[] = "0123456789abcdef";
char buf[19];
u32 pos = 0;
buf[pos++] = '0';
buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(value >> (i * 4)) & 0xf];
}
buf[pos] = 0;
g_log->info(prefix);
g_log->info(buf);
}
static u16 virtio_subsystem_id(u16 device_id) {
if (device_id >= VIRTIO_TRANS_DEVICE_MIN && device_id <= VIRTIO_TRANS_DEVICE_MAX) {
return (u16)(device_id - VIRTIO_TRANS_DEVICE_MIN);
}
if (device_id >= VIRTIO_MODERN_DEVICE_MIN && device_id <= VIRTIO_MODERN_DEVICE_MAX) {
return (u16)(device_id - VIRTIO_MODERN_DEVICE_MIN);
}
return 0xffff;
}
static int virtio_net_find(u8 *out_bus, u8 *out_dev, u8 *out_func) {
for (u8 bus = 0; bus < 16; bus++) {
for (u8 dev = 0; dev < 32; dev++) {
u32 vd = pci_read(bus, dev, 0, PCI_VENDOR_ID);
if ((vd & 0xffff) == 0xffff) continue;
u8 header = (u8)(pci_read(bus, dev, 0, PCI_HEADER) >> 16);
u8 func_count = (header & 0x80) ? 8 : 1;
for (u8 func = 0; func < func_count; func++) {
u32 vd2 = pci_read(bus, dev, func, PCI_VENDOR_ID);
u16 vendor = (u16)(vd2 & 0xffff);
u16 device = (u16)(vd2 >> 16);
if (vendor != PCI_VENDOR_VIRTIO) continue;
u16 virtio_id = virtio_subsystem_id(device);
u32 class_reg = pci_read(bus, dev, func, PCI_CLASS_REG);
u8 class_code = (u8)(class_reg >> 24);
if (virtio_id == VIRTIO_NET_DEVICE_ID && class_code == 0x02) {
*out_bus = bus;
*out_dev = dev;
*out_func = func;
return 0;
}
}
}
}
return -1;
}
static const char *virtio_cap_name(u8 cfg_type) {
if (cfg_type == VIRTIO_PCI_CAP_COMMON_CFG) return "common_cfg";
if (cfg_type == VIRTIO_PCI_CAP_NOTIFY_CFG) return "notify_cfg";
if (cfg_type == VIRTIO_PCI_CAP_ISR_CFG) return "isr_cfg";
if (cfg_type == VIRTIO_PCI_CAP_DEVICE_CFG) return "device_cfg";
if (cfg_type == VIRTIO_PCI_CAP_PCI_CFG) return "pci_cfg";
return "unknown_cfg";
}
static u32 read_bar_raw(u8 bus, u8 dev, u8 func, u8 bar) {
return pci_read(bus, dev, func, (u8)(PCI_BAR0 + bar * 4));
}
static void log_bars(u8 bus, u8 dev, u8 func) {
for (u8 bar = 0; bar < 6; bar++) {
u32 raw = read_bar_raw(bus, dev, func, bar);
if (raw == 0 || raw == 0xffffffffu) continue;
log_hex("[virtio_net] BAR index=", bar);
log_hex("[virtio_net] raw=", raw);
if (raw & 1u) {
log_hex("[virtio_net] io base=", raw & 0xfffffffcU);
} else {
log_hex("[virtio_net] mmio base=", raw & 0xfffffff0U);
}
}
}
static void log_virtio_caps(u8 bus, u8 dev, u8 func) {
u8 cap = pci_read8(bus, dev, func, PCI_CAP_PTR) & 0xfc;
u32 guard = 0;
u32 found = 0;
while (cap && guard++ < 32) {
u8 cap_id = pci_read8(bus, dev, func, cap + 0);
u8 next = pci_read8(bus, dev, func, cap + 1) & 0xfc;
if (cap_id == 0x09) {
u8 cfg_type = pci_read8(bus, dev, func, cap + 3);
u8 bar = pci_read8(bus, dev, func, cap + 4);
u32 offset = pci_read(bus, dev, func, cap + 8);
u32 length = pci_read(bus, dev, func, cap + 12);
found++;
g_log->info("[virtio_net] virtio capability");
g_log->info(virtio_cap_name(cfg_type));
log_hex("[virtio_net] cap_offset=", cap);
log_hex("[virtio_net] cfg_type=", cfg_type);
log_hex("[virtio_net] bar=", bar);
log_hex("[virtio_net] offset=", offset);
log_hex("[virtio_net] length=", length);
if (cfg_type == VIRTIO_PCI_CAP_NOTIFY_CFG) {
u32 mult = pci_read(bus, dev, func, cap + 16);
log_hex("[virtio_net] notify_off_multiplier=", mult);
}
}
cap = next;
}
log_hex("[virtio_net] virtio cap count=", found);
if (!found) {
g_log->warn("[virtio_net] no modern virtio capabilities; transitional IO path expected");
}
}
/* ---- tx/rx_poll stub: 安全占位, 不实际收发, 防止 netdev 调用 NULL ---- */
static int virtio_net_tx(void *ctx, const void *packet, u32 length) {
(void)ctx;
(void)packet;
/* 仅记录日志, 避免每次发包刷屏: 仅记录长度 */
static u32 s_tx_log_guard = 0;
if (s_tx_log_guard < 4) {
g_log->info("[virtio_net] tx stub: packet dropped (virtqueues not enabled)");
log_hex("[virtio_net] tx stub len=", length);
s_tx_log_guard++;
}
return 0;
}
static int virtio_net_rx_poll(void *ctx, void *buffer, u32 capacity, u32 *out_length) {
(void)ctx;
(void)buffer;
(void)capacity;
if (out_length) *out_length = 0;
return 0; /* 无数据, virtqueues 未启用 */
}
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
/* 实机要求: 在驱动初始化开头校准 TSC, 为后续时序提供准确计时 */
dkm_tsc_calibrate();
g_log->info("[virtio_net] init begin");
u8 bus = 0;
u8 dev = 0;
u8 func = 0;
if (virtio_net_find(&bus, &dev, &func) != 0) {
g_log->warn("[virtio_net] virtio-net device not found");
g_log->info("[virtio_net] driver ready");
return 0;
}
g_log->info("[virtio_net] virtio-net device found");
log_hex("[virtio_net] bus=", bus);
log_hex("[virtio_net] dev=", dev);
log_hex("[virtio_net] func=", func);
u32 vd = pci_read(bus, dev, func, PCI_VENDOR_ID);
u16 vendor = (u16)(vd & 0xffff);
u16 device = (u16)(vd >> 16);
u16 virtio_id = virtio_subsystem_id(device);
u32 class_reg = pci_read(bus, dev, func, PCI_CLASS_REG);
u8 revision = (u8)(class_reg & 0xff);
u8 prog_if = (u8)((class_reg >> 8) & 0xff);
u8 subclass = (u8)((class_reg >> 16) & 0xff);
u8 class_code = (u8)((class_reg >> 24) & 0xff);
log_hex("[virtio_net] vendor=", vendor);
log_hex("[virtio_net] device=", device);
log_hex("[virtio_net] virtio_id=", virtio_id);
log_hex("[virtio_net] class=", class_code);
log_hex("[virtio_net] subclass=", subclass);
log_hex("[virtio_net] prog_if=", prog_if);
log_hex("[virtio_net] revision=", revision);
u32 command = pci_read(bus, dev, func, PCI_COMMAND) & 0xffff;
command |= PCI_CMD_IO | PCI_CMD_MEM | PCI_CMD_BUSM;
pci_write(bus, dev, func, PCI_COMMAND, command);
log_hex("[virtio_net] PCI command=", command);
u32 irq_line = pci_read(bus, dev, func, PCI_IRQ_LINE) & 0xff;
log_hex("[virtio_net] PCI IRQ line=", irq_line);
log_bars(bus, dev, func);
log_virtio_caps(bus, dev, func);
if (api->net && api->net->register_device) {
struct dkm_net_device_desc netdev;
netdev.name = "virtio-net";
for (int i = 0; i < 6; i++) netdev.mac[i] = 0;
netdev.flags = DKM_NET_F_LINK_UP;
netdev.ctx = 0;
netdev.tx = virtio_net_tx; /* stub: 安全占位, 不 NULL */
netdev.rx_poll = virtio_net_rx_poll;
int net_index = api->net->register_device(&netdev);
log_hex("[virtio_net] netdev register rc=", (u64)(i64)net_index);
} else {
g_log->warn("[virtio_net] net API unavailable; netdev not registered");
}
g_log->info("[virtio_net] discovery only; virtqueues disabled");
g_log->info("[virtio_net] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
CC := clang
LD := ld.lld
OBJCOPY := llvm-objcopy
ROOT := ../..
OUT := $(ROOT)/SYSTEM/boot/utsm.elf
CFLAGS := -target x86_64-unknown-none -std=c11 -ffreestanding -fno-builtin -fno-stack-protector -fno-pic -fno-pie -mcmodel=kernel -mno-red-zone -mno-sse -mno-sse2 -mno-mmx -msoft-float -m64 -Wall -Wextra -Iinclude -O2
ASFLAGS := -target x86_64-unknown-none -ffreestanding -fno-pic -fno-pie -mcmodel=kernel -mno-red-zone -mno-sse -mno-sse2 -mno-mmx -msoft-float -m64 -Iinclude
LDFLAGS := -nostdlib -static -z max-page-size=0x1000 -T linker.ld
C_SOURCES := $(wildcard arch/x86_64/*.c kernel/*.c runtime/*.c mm/*.c core/*.c crypto/*.c pckc/*.c utrw/*.c drr/*.c dkm/*.c test/*.c)
S_SOURCES := $(wildcard arch/x86_64/*.S)
OBJECTS := $(C_SOURCES:.c=.o) $(S_SOURCES:.S=.o)
.PHONY: all clean
all: $(OUT)
$(OUT): $(OBJECTS) linker.ld
@if not exist "$(ROOT)\SYSTEM\boot" mkdir "$(ROOT)\SYSTEM\boot"
$(LD) $(LDFLAGS) -o $@ $(OBJECTS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
%.o: %.S
$(CC) $(ASFLAGS) -c $< -o $@
clean:
powershell -NoProfile -Command "Get-ChildItem -Path . -Recurse -Filter *.o | Remove-Item -Force; if (Test-Path '$(OUT)') { Remove-Item '$(OUT)' -Force }"
+935
View File
@@ -0,0 +1,935 @@
// 编译到 SYSTEM/boot/utsm.elf
# UTSM 内核模块设计
UTSM 是当前内核架构中的封缄内存模块。
```text
UTSM = UUID-Tuned Sealed Memory
中文名:UUID 调谐封缄内存
```
UTSM 的目标是在单地址空间 Ring0 高性能内核中提供一种轻量内存语义:
```text
所有普通内存可以被直接读取,但直接读取到的是密文。
真正有效的明文读写必须经过 UTSM 读写器。
UUID 作为进程和内存段的调谐因子。
DRR 负责 root key、checkpoint、recovery log 和回滚。
```
---
## 1. 所属总架构
```text
SAS-R0-PCQ
单地址空间 Ring0 任务模型
Per-CPU O(1) 位图调度器
DRR
Dedicated Recovery Root
看门狗 / checkpoint / recovery log / A-B 回滚
UTSM
UUID-Tuned Sealed Memory
UUID 调谐封缄内存
UTRW
UTSM Tagged Reader/Writer
UTSM 带标记读写器
DMP
Descriptor Meta Page
段描述符元页
PCKC
Per-CPU Key Cache
每 CPU 密钥缓存
```
---
## 2. UTSM 核心规则
```text
1. 数据区只存连续密文。
2. UUID 不插入数据区。
3. UUID 使用 128-bit 二进制格式。
4. 每个加密段有独立 DMP。
5. 每个任务有 process_uuid 和 capability table。
6. 读写明文必须经过 UTRW。
7. 直接读取 cipher_base 只得到密文。
8. 直接写入 cipher_base 会破坏段一致性,段可被标记为 POISONED。
9. DRR 保存 root key、checkpoint、recovery log 和恢复状态。
10. 调度器只加载 crypto context,不扫描段,不破坏 O(1) 调度。
```
---
## 3. 内存布局
每个 UTSM 段由 DMP 和密文数据区组成。
```text
+-------------------------------+
| DMP: Descriptor Meta Page |
| 段描述符元页 |
+-------------------------------+
| Cipher Data Page 0 |
+-------------------------------+
| Cipher Data Page 1 |
+-------------------------------+
| Cipher Data Page 2 |
+-------------------------------+
| ... |
+-------------------------------+
```
全局区域:
```text
+--------------------------------------------------+
| Normal Encrypted Segment Region |
| 普通加密段数据区 |
+--------------------------------------------------+
| DMP Pool |
| 段描述符元页池 |
+--------------------------------------------------+
| Segment Table |
| 全局段表 |
+--------------------------------------------------+
| PCKC Area |
| Per-CPU Key Cache 区 |
+--------------------------------------------------+
| DRR Reserved Region |
| root key / checkpoint / recovery log |
+--------------------------------------------------+
```
---
## 4. 基础类型
```c
typedef struct {
uint64_t hi;
uint64_t lo;
} uuid128_t;
```
UUID 不转十进制字符串,原因:
```text
16 字节固定长度
比较快
cache 友好
适合 KDF
适合 SIMD
避免十进制解析和孔洞布局
```
---
## 5. 进程加密上下文
```c
struct utsm_process_context {
uuid128_t process_uuid;
uint64_t crypto_epoch;
uint64_t recovery_generation;
uint32_t capability_table_slot;
uint32_t capability_count;
uint32_t flags;
};
```
字段含义:
```text
process_uuid
创建任务时生成的进程 UUID。
crypto_epoch
当前密钥版本,用于重加密、回滚和 crypto erase。
recovery_generation
当前 DRR checkpoint 版本。
capability_table_slot
该任务 capability table 的位置。
capability_count
该任务拥有的段能力数量。
flags
PWC、DMA、强恢复等策略标志。
```
---
## 6. 加密段描述符
```c
struct utsm_segment_desc {
uuid128_t segment_uuid;
uuid128_t owner_process_uuid;
void *cipher_base;
uint64_t cipher_length;
void *dmp_base;
uint64_t key_epoch;
uint64_t tweak_seed;
void *dirty_bitmap;
void *mac_table;
uint32_t generation;
uint32_t flags;
uint32_t state;
uint32_t last_cpu;
uint64_t writer_seq;
uint64_t checkpoint_generation;
};
```
段状态:
```text
FREE
ACTIVE
CHECKPOINTING
SEALED
RECOVERING
POISONED
DESTROYED
```
---
## 7. DMP 段描述符元页
DMP 是热路径加速结构,替代“UUID 数字位置表”。
```c
struct utsm_dmp {
uint64_t magic;
uint32_t version;
uint32_t segment_slot;
uint64_t fast_base;
uint64_t fast_limit;
uint64_t fast_tweak_seed;
uint64_t fast_key_epoch;
uint64_t dirty_bitmap_base;
uint64_t mac_table_base;
uint64_t last_writer_seq;
uint32_t last_cpu;
uint32_t flags;
uint64_t crc;
};
```
DMP 用于:
```text
O(1) 段定位
快速边界检查
tweak 生成
Dirty Bitmap 定位
MAC Table 定位
checkpoint
recovery
```
---
## 8. Capability
任务访问段时使用 capability,而不是裸 UUID。
```c
struct utsm_capability {
uint32_t segment_slot;
uint32_t generation;
uint32_t rights;
uint32_t epoch;
uint64_t uuid_digest;
uint64_t auth_tag;
};
```
权限:
```text
READ
WRITE
EXEC
SHARE
DMA
```
热路径通过:
```text
segment_slot + generation + epoch
```
直接定位并验证段。
---
## 9. 加密规则
UTSM 不使用十进制凯撒和 UUID 孔洞,改为按 cache line 的 UUID 调谐流式加密。
```text
segment_key = KDF(
DRR_root_key,
process_uuid,
segment_uuid,
key_epoch
)
```
每 64B cache line 生成 tweak:
```text
line_index = offset / 64
tweak = hash(tweak_seed, line_index, key_epoch)
```
加密和解密:
```text
ciphertext = plaintext XOR stream(segment_key, tweak)
plaintext = ciphertext XOR stream(segment_key, tweak)
```
---
## 10. UTRW 读写器
UTRW 分三层:
```text
Level 0: Raw Access
直接读 cipher_base,得到密文。
Level 1: Fast Path
capability O(1) 定位段,PCKC 命中,无全局锁,无 trap。
Level 2: Slow Path
key miss、epoch mismatch、checkpoint、recovery、MAC fail 等异常处理。
```
### 10.1 读流程
```text
UTRW_READ(cap, offset, len, dst)
-> segment_slot 找 desc
-> generation 检查
-> rights 检查
-> epoch 检查
-> 边界检查
-> PCKC 取 key
-> 按 64B line 解密
-> 返回明文
```
### 10.2 写流程
```text
UTRW_WRITE(cap, offset, len, src)
-> segment_slot 找 desc
-> generation 检查
-> rights 检查
-> epoch 检查
-> 边界检查
-> PCKC 取 key
-> 按 64B line 加密
-> 写入 cipher data
-> 标记 dirty bitmap
-> writer_seq++
-> 按策略写 recovery log
```
部分写必须先解密旧 64B line,合并新明文后重新加密整条 line。
---
## 11. PCKC 每 CPU 密钥缓存
```c
struct utsm_pckc {
uuid128_t current_process_uuid;
uint32_t hot_segment_slot[8];
uint64_t hot_key_epoch[8];
void *key_schedule[8];
uint64_t hit_count;
uint64_t miss_count;
};
```
规则:
```text
每 CPU 一个 PCKC。
调度切换时只加载 next.crypto 指针和 hot_segment_hint。
不扫描 capability table。
不刷新全部 key。
不破坏 PCQ 的 O(1) 调度。
```
---
## 12. 与 SAS-R0-PCQ 的整合
任务结构扩展:
```c
struct task {
uint64_t tid;
uint32_t state;
uint32_t priority;
uint64_t runtime;
uint64_t time_slice;
void *stack_top;
void *entry;
struct context cpu_context;
uint32_t last_cpu;
uint64_t affinity_mask;
struct utsm_process_context *crypto;
struct utsm_capability_table *cap_table;
uint32_t hot_segment_hint;
uint32_t fault_segment_slot;
uint64_t recovery_generation;
uint64_t heartbeat_seq;
uint32_t flags;
struct task *prev;
struct task *next;
};
```
任务状态:
```text
READY
RUNNING
BLOCKED
SLEEPING
RECOVERING
FAULTED
ZOMBIE
```
---
## 13. 任务创建流程
```text
task_create(entry, priority, flags)
-> 分配 TCB
-> 生成 tid
-> 生成 process_uuid
-> 创建 utsm_process_context
-> 创建 stack segment
-> 创建 heap segment
-> 创建 ipc segment 可选
-> 生成 capability table
-> cap[0] = stack
-> cap[1] = heap
-> 初始化 CPU context
-> 通过 UTRW_WRITE 写入 start packet
-> hot_segment_hint = stack segment
-> state = READY
-> enqueue_task(current_cpu)
```
默认 capability:
```text
cap[0] = stack segment, READ | WRITE
cap[1] = heap segment, READ | WRITE
cap[2] = ipc segment, READ | WRITE | SHARE,可选
cap[3] = code segment, READ | EXEC,可选
```
---
## 14. 调度切换流程
```text
schedule()
-> old = current
-> utsm_switch_out(old)
-> next = pick_next_task()
-> utsm_switch_in(next)
-> context_switch(old, next)
```
`utsm_switch_out` 只做:
```text
标记 PWC dirty flush
保存 hot_segment_hint
更新 recovery_generation
更新 heartbeat
```
`utsm_switch_in` 只做:
```text
设置 PCKC.current_process_uuid
加载 next.crypto
检查 recovery_generation
预热 hot_segment_hint
```
禁止在调度路径中:
```text
扫描所有 segment
扫描 capability table
计算 MAC
写 checkpoint
重加密整段
```
---
## 15. Checkpoint / Rollback 协议
### 15.1 Checkpoint 类型
```text
Light Checkpoint
保存 segment table、DMP、dirty shard summary、writer_seq、key_epoch、MAC root。
Dirty Page Checkpoint
保存 dirty page 的密文副本、dirty page MAC、dirty shard、segment descriptor。
Boot Checkpoint
保存内核镜像 slot、UTSM root epoch、DRR boot status、启动阶段状态。
```
### 15.2 Dirty Shard 分片
Dirty Bitmap 不再只是一整块大 bitmap,而是拆成多个 Dirty Shard。
```c
struct utsm_dirty_shard {
uint32_t dirty_count;
uint32_t shard_id;
uint64_t page_base;
uint64_t page_count;
uint64_t last_checkpoint_epoch;
void *bitmap;
};
```
规则:
```text
1. 每个 shard 管理一段连续页范围。
2. UTRW_WRITE 标记 dirty page 时,同时更新 dirty_count。
3. checkpoint 时 dirty_count == 0 的 shard 直接跳过。
4. checkpoint 只扫描 dirty_count > 0 的 shard。
5. 每 CPU 可以维护 dirty shard list,避免全局扫描。
```
复杂度从:
```text
扫描全 dirty bitmap
```
优化为:
```text
O(number_of_dirty_shards + number_of_dirty_pages)
```
### 15.3 A/B Checkpoint Metadata 双槽
每个 checkpoint metadata 使用双槽。
```text
Checkpoint Metadata Slot A
Checkpoint Metadata Slot B
```
提交规则:
```text
当前 active = A
新 checkpoint 写 B
B 写完 metadata、dirty index、MAC root、CRC
flush
最后原子切换 active = B
旧 A 保留为 fallback
```
恢复规则:
```text
优先读取 active slot
如果 active slot CRC 错误或 generation 不完整
fallback 到另一个 slot
如果两个 slot 都损坏
进入 system rollback
```
这样可以避免 checkpoint 写一半崩溃导致旧稳定点也损坏。
### 15.4 正常 checkpoint 流程
```text
DRR 发起 checkpoint
-> checkpoint_generation++
-> 选择 inactive metadata slot
-> UTSM 遍历 dirty shard list
-> 跳过 dirty_count == 0 的 shard
-> 对 dirty shard 内的 ACTIVE 段执行 checkpoint
-> desc.state = CHECKPOINTING
-> 刷出 PWC / per-CPU dirty buffer
-> 复制 dirty ciphertext page 到 checkpoint region
-> 计算 page MAC
-> 写 segment desc snapshot
-> 写 DMP snapshot
-> 写 dirty shard summary
-> 写 checkpoint metadata CRC
-> flush checkpoint metadata
-> 原子切换 active metadata slot
-> CHECKPOINT_COMMIT
-> 清 dirty bitmap / dirty_count
-> desc.state = ACTIVE
```
### 15.5 rollback 级别
```text
Page Rollback
单页损坏,从 checkpoint slot 恢复密文页。
Segment Rollback
整段损坏,恢复 segment desc、DMP、key_epoch、dirty shard、MAC table。
System Rollback
控制面严重损坏,写 crash reason,reboot,由 bootloader 切换 last_good_slot。
```
### 15.6 DRR Emergency Pool
DRR 启动时必须预留独立紧急内存池。
```text
DRR Emergency Pool
emergency pages
recovery log buffer
checkpoint metadata buffer
DRR private stack
DRR metadata slab
crash buffer
```
规则:
```text
1. 普通 allocator 永远不能分配 Emergency Pool。
2. Emergency Pool 只供 watchdog、checkpoint、rollback、crash dump 使用。
3. 普通系统 OOM 不等于 DRR OOM。
4. recovery 路径禁止依赖普通堆分配器。
5. Emergency Pool 耗尽时直接进入 system rollback。
```
---
## 16. 启动流程
### 16.1 Bootloader 阶段
```text
1. 读取 Boot Control Block。
2. 校验 BCB CRC。
3. 选择 active_slot。
4. 如果 active_slot 失败次数超限,切换 last_good_slot。
5. 将 SYSTEM 作为打包后 IMG 内的系统根目录。
6. 加载 SYSTEM/boot/utsm.elf。
7. 加载或暴露 SYSTEM/driver/manifest.json。
8. 传入 memory map、BCB 地址、DRR reserved region 信息。
```
### 16.2 DRR 初始化
```text
1. 保留 DRR region。
2. 初始化 watchdog。
3. 建立 root key 或 root key handle。
4. 初始化 recovery log。
5. 初始化 checkpoint region。
6. 初始化 heartbeat page。
7. 初始化 DRR Emergency Pool。
8. 初始化 A/B checkpoint metadata slot。
```
### 16.3 UTSM 初始化
```text
1. 接收 DRR root key handle。
2. 初始化 global crypto epoch。
3. 初始化 segment table。
4. 初始化 DMP pool。
5. 初始化 PCKC area。
6. 初始化 dirty shard pool。
7. 初始化 dirty bitmap pool。
8. 初始化 MAC table pool。
9. 注册 UTRW fast path / slow path。
```
### 16.4 Scheduler 初始化
```text
1. 初始化 per-CPU runqueue。
2. 初始化 per-CPU heartbeat。
3. 初始化每 CPU PCKC。
4. 创建 bootstrap task。
5. 创建核心服务 task。
6. 将 task 加入 PCQ runqueue。
```
### 16.5 Driver Manifest 加载
驱动清单位于系统根目录下:
```text
SYSTEM/driver/manifest.json
```
规则:
```text
1. manifest.json 是启动驱动模块的唯一默认清单。
2. 驱动文件使用 ELF64 .drv 格式。
3. 驱动按 stage 分阶段加载。
4. required=true 的驱动失败时进入 DRR recovery 或 panic。
5. required=false 的驱动失败时标记 FAILED 并继续启动。
6. stage0/stage1 可由 bootloader 预加载为 boot module。
7. stage2/stage3 在文件系统可用后从 SYSTEM/driver 扫描加载。
```
默认阶段:
```text
stage0: platform,timer / apic / acpi / pci
stage1: boot,console / block / bootfs
stage2: filesystem,vfs / fat32 / devfs
stage3: optional,net / input / gpu
```
### 16.6 DKM 驱动 ABI 摘要
驱动模块系统:
```text
DKM = Deshab Kernel Module
DSM = Driver Startup Manager
```
每个 ELF .drv 必须导出:
```text
driver_desc
driver_init
driver_exit
```
`driver_desc` 至少描述:
```text
magic / abi_version / desc_size
name / version / vendor
driver_class / stage / flags / priority
depends / provides
min_kernel_abi / feature_bits
```
驱动入口:
```c
int driver_init(const struct dkm_kernel_api *api, struct dkm_driver_handle *handle);
int driver_exit(struct dkm_driver_handle *handle);
```
驱动默认通过 `dkm_kernel_api` 访问内核服务:
```text
log
mem
utsm
irq
pci
dma
vfs
net
timer
drr
```
ELF loader 第一版支持:
```text
必须支持:
R_X86_64_64
R_X86_64_RELATIVE
R_X86_64_GLOB_DAT
R_X86_64_JUMP_SLOT
建议支持:
R_X86_64_PC32
R_X86_64_PLT32
R_X86_64_32 / R_X86_64_32S
第一版禁止:
TLS relocation
IFUNC
lazy binding
外部动态库依赖
用户态 libc 依赖
```
驱动加载状态机:
```text
DISCOVERED
-> QUEUED
-> DEP_WAIT
-> LOADING
-> ELF_CHECKED
-> MEMORY_ALLOCATED
-> RELOCATED
-> ABI_CHECKED
-> INITING
-> ACTIVE
```
失败状态:
```text
FAILED_ELF
FAILED_RELOCATION
FAILED_DEPENDENCY
FAILED_ABI
FAILED_INIT
FAILED_REQUIRED
```
stage0/stage1 boot module 查找规则:
```text
1. 如果 path 在 boot module table 中,直接从内存加载。
2. 否则如果 VFS 已可用,从 SYSTEM/path 加载。
3. 否则返回 BOOT_MODULE_NOT_FOUND。
```
完整设计见:
```text
RE/驱动模块ABI设计.md
```
---
## 17. 错误处理
UTRW 错误状态:
```text
OK
KEY_MISS_RETRY
STALE_CAPABILITY
EPOCH_EXPIRED
OUT_OF_BOUNDS
ACCESS_DENIED
CHECKPOINT_BUSY
RECOVERING
MAC_FAILED
SEGMENT_POISONED
CORRUPTED_DESCRIPTOR
```
严重错误处理:
```text
1. 记录 task.fault_segment_slot。
2. task.state = FAULTED。
3. 从 runqueue 移除。
4. 通知 DRR。
5. DRR 决定刷新 capability、回滚 segment、kill task 或 system rollback。
```
---
## 18. UTSM v1 定稿
```text
UTSM v1 包含:
二进制 UUID
连续密文数据区
独立 DMP
全局 Segment Table
Segment Capability
Per-CPU Key Cache
UTRW 统一读写器
Dirty Shard + Dirty Bitmap
MAC Table
DRR Emergency Pool
A/B Checkpoint Metadata
DRR checkpoint / rollback 对接
SAS-R0-PCQ task 整合
加密粒度:
64B cache line
Dirty 粒度:
4KB page
Dirty 分片:
Dirty Shard,checkpoint 只扫描 dirty_count > 0 的 shard
MAC 粒度:
4KB page
Checkpoint 元数据:
A/B 双槽,CRC 校验,原子切换 active slot
大页优化:
2MB hugepage 可选
```
+21
View File
@@ -0,0 +1,21 @@
.section .text
.global _start
.type _start, @function
_start:
cli
cld
lea kernel_stack_top(%rip), %rsp
andq $-16, %rsp
call kernel_main
.hang:
cli
hlt
jmp .hang
.section .bss
.align 16
.global kernel_stack
.global kernel_stack_top
kernel_stack:
.skip 16384
kernel_stack_top:
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
void arch_halt_forever(void) {
for (;;) {
__asm__ volatile ("cli; hlt");
}
}
Binary file not shown.
+222
View File
@@ -0,0 +1,222 @@
#include <utsm/idt.h>
#include <utsm/log.h>
#include <utsm/types.h>
/* IDT gate descriptor (64-bit) */
typedef struct __attribute__((packed)) {
u16 offset_low;
u16 selector;
u8 ist;
u8 type_attr;
u16 offset_mid;
u32 offset_high;
u32 reserved;
} idt_entry;
/* IDT register */
typedef struct __attribute__((packed)) {
u16 limit;
u64 base;
} idt_ptr;
#define IDT_ENTRIES 256
static idt_entry g_idt[IDT_ENTRIES] __attribute__((aligned(16)));
#define PIC1_CMD 0x20
#define PIC1_DATA 0x21
#define PIC2_CMD 0xA0
#define PIC2_DATA 0xA1
#define ICW1_ICW4 0x01
#define ICW1_INIT 0x10
/* assembly stub declarations */
extern void isr_stub_0(void);
extern void isr_stub_1(void);
extern void isr_stub_2(void);
extern void isr_stub_3(void);
extern void isr_stub_4(void);
extern void isr_stub_5(void);
extern void isr_stub_6(void);
extern void isr_stub_7(void);
extern void isr_stub_8(void);
extern void isr_stub_9(void);
extern void isr_stub_10(void);
extern void isr_stub_11(void);
extern void isr_stub_12(void);
extern void isr_stub_13(void);
extern void isr_stub_14(void);
extern void isr_stub_15(void);
extern void isr_stub_16(void);
extern void isr_stub_17(void);
extern void isr_stub_18(void);
extern void isr_stub_19(void);
extern void isr_stub_20(void);
extern void isr_stub_21(void);
extern void isr_stub_22(void);
extern void isr_stub_23(void);
extern void isr_stub_24(void);
extern void isr_stub_25(void);
extern void isr_stub_26(void);
extern void isr_stub_27(void);
extern void isr_stub_28(void);
extern void isr_stub_29(void);
extern void isr_stub_30(void);
extern void isr_stub_31(void);
extern void isr_stub_32(void);
extern void isr_stub_33(void);
extern void isr_stub_34(void);
extern void isr_stub_35(void);
extern void isr_stub_36(void);
extern void isr_stub_37(void);
extern void isr_stub_38(void);
extern void isr_stub_39(void);
extern void isr_stub_40(void);
extern void isr_stub_41(void);
extern void isr_stub_42(void);
extern void isr_stub_43(void);
extern void isr_stub_44(void);
extern void isr_stub_45(void);
extern void isr_stub_46(void);
extern void isr_stub_47(void);
static void *g_isr_table[] = {
isr_stub_0, isr_stub_1, isr_stub_2, isr_stub_3,
isr_stub_4, isr_stub_5, isr_stub_6, isr_stub_7,
isr_stub_8, isr_stub_9, isr_stub_10, isr_stub_11,
isr_stub_12, isr_stub_13, isr_stub_14, isr_stub_15,
isr_stub_16, isr_stub_17, isr_stub_18, isr_stub_19,
isr_stub_20, isr_stub_21, isr_stub_22, isr_stub_23,
isr_stub_24, isr_stub_25, isr_stub_26, isr_stub_27,
isr_stub_28, isr_stub_29, isr_stub_30, isr_stub_31,
isr_stub_32, isr_stub_33, isr_stub_34, isr_stub_35,
isr_stub_36, isr_stub_37, isr_stub_38, isr_stub_39,
isr_stub_40, isr_stub_41, isr_stub_42, isr_stub_43,
isr_stub_44, isr_stub_45, isr_stub_46, isr_stub_47,
};
static void outb(u16 port, u8 value) {
__asm__ volatile ("outb %0, %1" :: "a"(value), "Nd"(port));
}
static u8 inb(u16 port) {
u8 value;
__asm__ volatile ("inb %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
static void io_wait(void) {
outb(0x80, 0);
}
static void pic_remap(void) {
/* save masks */
u8 m1 = inb(PIC1_DATA);
u8 m2 = inb(PIC2_DATA);
/* ICW1: start init + ICW4 */
outb(PIC1_CMD, ICW1_INIT | ICW1_ICW4);
io_wait();
outb(PIC2_CMD, ICW1_INIT | ICW1_ICW4);
io_wait();
/* ICW2: vector offsets */
outb(PIC1_DATA, 0x20); /* master: vectors 0x20-0x27 */
io_wait();
outb(PIC2_DATA, 0x28); /* slave: vectors 0x28-0x2F */
io_wait();
/* ICW3: master/slave wiring */
outb(PIC1_DATA, 0x04); /* master: IRQ2 → slave */
io_wait();
outb(PIC2_DATA, 0x02); /* slave: cascade identity */
io_wait();
/* ICW4: 8086 mode */
outb(PIC1_DATA, 0x01);
io_wait();
outb(PIC2_DATA, 0x01);
io_wait();
/* restore masks: mask all except IRQ1 (keyboard) */
outb(PIC1_DATA, 0xFD); /* 1111_1101: enable IRQ0 (timer) and IRQ1 (kb) */
outb(PIC2_DATA, 0xFF); /* mask all slave */
}
static void idt_set_entry(u8 vector, void *handler, u8 ist, u8 type) {
u64 addr = (u64)handler;
g_idt[vector].offset_low = (u16)(addr & 0xffff);
g_idt[vector].selector = 0x08; /* kernel code segment (from GDT) */
g_idt[vector].ist = ist;
g_idt[vector].type_attr = type;
g_idt[vector].offset_mid = (u16)((addr >> 16) & 0xffff);
g_idt[vector].offset_high = (u32)(addr >> 32);
g_idt[vector].reserved = 0;
}
void idt_init(void) {
log_info("[IDT] init begin");
for (u16 i = 0; i < 48; i++) {
idt_set_entry((u8)i, g_isr_table[i], 0, 0x8E); /* present, ring0, 64-bit interrupt gate */
}
/* fill unused entries with null */
for (u16 i = 48; i < IDT_ENTRIES; i++) {
idt_set_entry((u8)i, 0, 0, 0);
}
idt_ptr idtr;
idtr.limit = (u16)(sizeof(g_idt) - 1);
idtr.base = (u64)&g_idt;
__asm__ volatile ("lidt %0" :: "m"(idtr));
pic_remap();
log_info("[IDT] PIC remapped (master=0x20 slave=0x28)");
__asm__ volatile ("sti");
log_info("[IDT] interrupts enabled");
log_info("[IDT] init ok");
}
/* IRQ handler table */
static irq_handler_t g_irq_handlers[16];
int irq_register(u8 irq, irq_handler_t handler) {
if (irq >= 16) return -1;
g_irq_handlers[irq] = handler;
return 0;
}
/* Stack frame pushed by isr_common in idt.S */
typedef struct {
u64 r11, r10, r9, r8, rax, rcx, rdx, rsi, rdi;
u64 vector;
u64 error_code;
u64 rip, cs, rflags;
} isr_frame;
void idt_handler(isr_frame *frame) {
if (frame->vector < 32) {
log_error("[IDT] exception");
log_hex64("[IDT] vector=", frame->vector);
log_hex64("[IDT] err=", frame->error_code);
log_hex64("[IDT] rip=", frame->rip);
for (;;) { __asm__ volatile ("cli; hlt"); }
}
if (frame->vector >= 32 && frame->vector <= 47) {
u8 irq = (u8)(frame->vector - 0x20);
/* call registered handler */
if (irq < 16 && g_irq_handlers[irq]) {
int suppress_eoi = g_irq_handlers[irq](irq);
if (suppress_eoi) return;
}
/* send EOI */
if (frame->vector >= 0x28) {
outb(PIC2_CMD, 0x20);
}
outb(PIC1_CMD, 0x20);
}
}
Binary file not shown.
+62
View File
@@ -0,0 +1,62 @@
/* IDT assembly stubs — SAS-R0 interrupt vectors */
.section .text
.macro isr_no_err n
.global isr_stub_\n
.type isr_stub_\n, @function
isr_stub_\n:
pushq $0
pushq $\n
jmp isr_common
.endm
.macro isr_err n
.global isr_stub_\n
.type isr_stub_\n, @function
isr_stub_\n:
pushq $\n
jmp isr_common
.endm
/* Exceptions 0-31 */
isr_no_err 0; isr_no_err 1; isr_no_err 2; isr_no_err 3
isr_no_err 4; isr_no_err 5; isr_no_err 6; isr_no_err 7
isr_err 8; isr_no_err 9; isr_err 10; isr_err 11
isr_err 12; isr_err 13; isr_err 14; isr_no_err 15
isr_no_err 16; isr_err 17; isr_no_err 18; isr_no_err 19
isr_no_err 20; isr_no_err 21; isr_no_err 22; isr_no_err 23
isr_no_err 24; isr_no_err 25; isr_no_err 26; isr_no_err 27
isr_no_err 28; isr_no_err 29; isr_err 30; isr_no_err 31
/* IRQ 32-47 */
isr_no_err 32; isr_no_err 33; isr_no_err 34; isr_no_err 35
isr_no_err 36; isr_no_err 37; isr_no_err 38; isr_no_err 39
isr_no_err 40; isr_no_err 41; isr_no_err 42; isr_no_err 43
isr_no_err 44; isr_no_err 45; isr_no_err 46; isr_no_err 47
/* Common ISR */
isr_common:
pushq %rdi
pushq %rsi
pushq %rdx
pushq %rcx
pushq %rax
pushq %r8
pushq %r9
pushq %r10
pushq %r11
movq %rsp, %rdi
call idt_handler
popq %r11
popq %r10
popq %r9
popq %r8
popq %rax
popq %rcx
popq %rdx
popq %rsi
popq %rdi
addq $16, %rsp
iretq
Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
#include <utsm/types.h>
void outb(u16 port, u8 value) {
__asm__ volatile ("outb %0, %1" : : "a"(value), "Nd"(port));
}
u8 inb(u16 port) {
u8 value;
__asm__ volatile ("inb %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
void io_wait(void) {
outb(0x80, 0);
}
Binary file not shown.
+154
View File
@@ -0,0 +1,154 @@
#ifndef UTSM_LIMINE_H
#define UTSM_LIMINE_H
#include <utsm/types.h>
#define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88ULL, 0x0a82e883a194f07bULL
struct limine_hhdm_response {
u64 revision;
u64 offset;
};
struct limine_hhdm_request {
u64 id[4];
u64 revision;
struct limine_hhdm_response *response;
};
struct limine_kernel_address_response {
u64 revision;
u64 physical_base;
u64 virtual_base;
};
struct limine_kernel_address_request {
u64 id[4];
u64 revision;
struct limine_kernel_address_response *response;
};
#define LIMINE_KERNEL_ADDRESS_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x71ba76863cc55f63ULL, 0xb2644a48c516a487ULL }
struct limine_file {
u64 revision;
void *address;
u64 size;
char *path;
char *cmdline;
u32 media_type;
u32 unused;
u32 tftp_ip;
u32 tftp_port;
u32 partition_index;
u32 mbr_disk_id;
u8 gpt_disk_uuid[16];
u8 gpt_part_uuid[16];
u8 part_uuid[16];
};
struct limine_module_response {
u64 revision;
u64 module_count;
struct limine_file **modules;
};
struct limine_module_request {
u64 id[4];
u64 revision;
struct limine_module_response *response;
};
#define LIMINE_MODULE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x3e7e279702be32afULL, 0xca1c4f3bd1280ceeULL }
struct limine_rsdp_response {
u64 revision;
void *address;
};
struct limine_rsdp_request {
u64 id[4];
u64 revision;
struct limine_rsdp_response *response;
};
#define LIMINE_RSDP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0xc5e77b6b397e7b43ULL, 0x27637845accdcf3cULL }
struct limine_framebuffer {
void *address;
u64 width;
u64 height;
u64 pitch;
u16 bpp;
u8 memory_model;
u8 red_mask_size;
u8 red_mask_shift;
u8 green_mask_size;
u8 green_mask_shift;
u8 blue_mask_size;
u8 blue_mask_shift;
u8 unused[7];
u64 edid_size;
void *edid;
u64 mode_count;
struct limine_video_mode **modes;
};
struct limine_video_mode {
u64 pitch;
u64 width;
u64 height;
u16 bpp;
u8 memory_model;
u8 red_mask_size;
u8 red_mask_shift;
u8 green_mask_size;
u8 green_mask_shift;
u8 blue_mask_size;
u8 blue_mask_shift;
};
struct limine_framebuffer_response {
u64 revision;
u64 framebuffer_count;
struct limine_framebuffer **framebuffers;
};
struct limine_framebuffer_request {
u64 id[4];
u64 revision;
struct limine_framebuffer_response *response;
};
#define LIMINE_FRAMEBUFFER_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x9d5827dcd881dd75ULL, 0xa3148604f6fab11bULL }
#define LIMINE_MEMMAP_USABLE 0
#define LIMINE_MEMMAP_RESERVED 1
#define LIMINE_MEMMAP_ACPI_RECLAIMABLE 2
#define LIMINE_MEMMAP_ACPI_NVS 3
#define LIMINE_MEMMAP_BAD_MEMORY 4
#define LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 5
#define LIMINE_MEMMAP_KERNEL_AND_MODULES 6
#define LIMINE_MEMMAP_FRAMEBUFFER 7
struct limine_memmap_entry {
u64 base;
u64 length;
u64 type;
};
struct limine_memmap_response {
u64 revision;
u64 entry_count;
struct limine_memmap_entry **entries;
};
struct limine_memmap_request {
u64 id[4];
u64 revision;
struct limine_memmap_response *response;
};
#define LIMINE_MEMMAP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x67cf3d9d378a806fULL, 0xe304acdfc50c3c62ULL }
#endif
+81
View File
@@ -0,0 +1,81 @@
#include <utsm/types.h>
void outb(u16 port, u8 value);
u8 inb(u16 port);
#define COM1 0x3F8
/* ---- TSC-based timing (实机要求: 用 CPU 频率计算, 不用循环) ---- */
static u64 g_tsc_per_ms = 0;
static inline u64 rdtsc_ser(void) {
u32 lo, hi;
__asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
return ((u64)hi << 32) | lo;
}
/* 用 PIT (8254, 1.193182 MHz) 校准 TSC 频率 */
static void tsc_calibrate_ser(void) {
outb(0x43, 0x30); /* ch0, lo+hi, mode 0, binary */
outb(0x40, 0x7c); /* 11932 low = ~10ms */
outb(0x40, 0x2e); /* 11932 high */
u64 tsc_start = rdtsc_ser();
u16 prev = 0; u64 loops = 0;
for (;;) {
outb(0x43, 0x00);
u16 cur = (u16)inb(0x40) | ((u16)inb(0x40) << 8);
if (cur > prev && loops > 10) break;
prev = cur; loops++;
}
u64 tsc_end = rdtsc_ser();
g_tsc_per_ms = (tsc_end - tsc_start) / 10;
}
static int serial_ready(void) {
return (inb(COM1 + 5) & 0x20) != 0;
}
/* 实机: 基于 TSC 的 100ms 超时等待 */
static int serial_wait_ready(void) {
if (!g_tsc_per_ms) {
/* 兜底: 校准未完成时使用循环 */
for (u64 spin = 0; spin < 1000000ULL; spin++) {
if (serial_ready()) return 1;
}
return 0;
}
u64 deadline = rdtsc_ser() + g_tsc_per_ms * 100; /* 100ms 超时 */
while (rdtsc_ser() < deadline) {
if (serial_ready()) return 1;
__asm__ volatile("pause");
}
return 0;
}
void serial_init(void) {
/* 实机要求: 先校准 TSC, 再使用基于 CPU 频率的延迟 */
tsc_calibrate_ser();
outb(COM1 + 1, 0x00);
outb(COM1 + 3, 0x80);
outb(COM1 + 0, 0x03);
outb(COM1 + 1, 0x00);
outb(COM1 + 3, 0x03);
outb(COM1 + 2, 0xC7);
outb(COM1 + 4, 0x0B);
}
void serial_putc(char c) {
if (c == '\n') {
serial_putc('\r');
}
if (!serial_wait_ready()) {
return;
}
outb(COM1, (u8)c);
}
void serial_write(const char *s) {
while (*s) {
serial_putc(*s++);
}
}
Binary file not shown.
+29
View File
@@ -0,0 +1,29 @@
#include <utsm/capability.h>
#include <utsm/segment.h>
int utsm_cap_validate(utsm_capability cap, u32 required_rights, u64 offset, u64 len, utsm_segment_desc **out_desc) {
utsm_segment_desc *desc = utsm_get_segment(cap.segment_slot);
if (!desc) {
return UTSM_ERR_INVALID;
}
if (desc->state == UTSM_SEG_POISONED) {
return UTSM_ERR_POISONED;
}
if (desc->state != UTSM_SEG_ACTIVE) {
return UTSM_ERR_STATE;
}
if (desc->generation != cap.generation) {
return UTSM_ERR_STALE_CAP;
}
if ((cap.rights & required_rights) != required_rights) {
return UTSM_ERR_ACCESS;
}
if ((u32)desc->key_epoch != cap.epoch) {
return UTSM_ERR_EPOCH;
}
if (offset > desc->cipher_length || len > desc->cipher_length || offset + len > desc->cipher_length) {
return UTSM_ERR_BOUNDS;
}
*out_desc = desc;
return UTSM_OK;
}
Binary file not shown.
+47
View File
@@ -0,0 +1,47 @@
#include <utsm/dirty.h>
#include <utsm/segment.h>
#include <utsm/arena.h>
#include <utsm/config.h>
static void bitmap_set(u64 *bitmap, u64 bit) {
bitmap[bit / 64] |= 1ULL << (bit % 64);
}
static bool bitmap_test(u64 *bitmap, u64 bit) {
return (bitmap[bit / 64] & (1ULL << (bit % 64))) != 0;
}
void utsm_dirty_init(utsm_segment_desc *desc, u64 page_count) {
desc->dirty_shard_count = 1;
desc->dirty_shards = (utsm_dirty_shard *)kmem_alloc(sizeof(utsm_dirty_shard));
if (!desc->dirty_shards) {
return;
}
u64 words = (page_count + 63) / 64;
desc->dirty_shards[0].dirty_count = 0;
desc->dirty_shards[0].shard_id = 0;
desc->dirty_shards[0].page_base = 0;
desc->dirty_shards[0].page_count = page_count;
desc->dirty_shards[0].last_checkpoint_epoch = 0;
desc->dirty_shards[0].bitmap = (u64 *)kmem_alloc_aligned(words * sizeof(u64), 8);
if (desc->dirty_shards[0].bitmap) {
for (u64 i = 0; i < words; i++) {
desc->dirty_shards[0].bitmap[i] = 0;
}
}
}
void utsm_mark_dirty(utsm_segment_desc *desc, u64 offset, u64 len) {
if (!desc || !desc->dirty_shards || !desc->dirty_shards[0].bitmap || len == 0) {
return;
}
u64 first = offset / UTSM_PAGE_SIZE;
u64 last = (offset + len - 1) / UTSM_PAGE_SIZE;
utsm_dirty_shard *shard = &desc->dirty_shards[0];
for (u64 page = first; page <= last && page < shard->page_count; page++) {
if (!bitmap_test(shard->bitmap, page)) {
bitmap_set(shard->bitmap, page);
shard->dirty_count++;
}
}
}
Binary file not shown.
+20
View File
@@ -0,0 +1,20 @@
#include <utsm/dmp.h>
#include <utsm/segment.h>
#define UTSM_DMP_MAGIC 0x5554534d444d5031ULL
void utsm_dmp_init(utsm_dmp *dmp, utsm_segment_desc *desc, u32 slot) {
dmp->magic = UTSM_DMP_MAGIC;
dmp->version = 1;
dmp->segment_slot = slot;
dmp->fast_base = (u64)desc->cipher_base;
dmp->fast_limit = (u64)desc->cipher_base + desc->cipher_length;
dmp->fast_tweak_seed = desc->tweak_seed;
dmp->fast_key_epoch = desc->key_epoch;
dmp->dirty_bitmap_base = desc->dirty_shards ? (u64)desc->dirty_shards[0].bitmap : 0;
dmp->mac_table_base = (u64)desc->mac_table;
dmp->last_writer_seq = desc->writer_seq;
dmp->last_cpu = desc->last_cpu;
dmp->flags = desc->flags;
dmp->crc = dmp->magic ^ dmp->fast_base ^ dmp->fast_limit ^ dmp->fast_tweak_seed;
}
Binary file not shown.
+126
View File
@@ -0,0 +1,126 @@
/* process.c — UTSM 进程上下文管理
*
* 进程表分配/释放、capability table 操作、crypto context 管理。
*/
#include <utsm/process.h>
#include <utsm/drr.h>
#include <utsm/arena.h>
#include <utsm/log.h>
/* ---- 进程表 ---- */
static utsm_process_context g_process_table[UTSM_MAX_PROCESSES];
static u32 g_process_count;
void utsm_process_init(void) {
log_info("[UTSM] process table init");
for (u32 i = 0; i < UTSM_MAX_PROCESSES; i++) {
g_process_table[i].state = UTSM_PROC_UNUSED;
g_process_table[i].process_slot = i;
g_process_table[i].cap_table.count = 0;
g_process_table[i].cap_table.generation = 0;
}
g_process_count = 0;
}
void utsm_process_create_test(utsm_process_context *process, u64 seed) {
process->process_uuid = uuid_make_test(seed);
process->crypto_epoch = 1;
process->recovery_generation = drr_recovery_generation();
process->capability_count = 0;
process->flags = UTSM_PROC_F_KERNEL;
process->state = UTSM_PROC_ACTIVE;
process->hot_segment_slot = 0;
process->drr_recovery_gen = drr_recovery_generation();
/* 初始化 crypto context */
process->crypto_ctx.crypto_epoch = 1;
process->crypto_ctx.key_derivation_seed = seed ^ 0x9e3779b97f4a7c15ULL;
process->crypto_ctx.pckc_hot_hint = 0;
/* 初始化 capability table */
process->cap_table.count = 0;
process->cap_table.generation = 1;
}
utsm_process_context *utsm_process_alloc(void) {
for (u32 i = 0; i < UTSM_MAX_PROCESSES; i++) {
if (g_process_table[i].state == UTSM_PROC_UNUSED) {
utsm_process_context *p = &g_process_table[i];
p->process_slot = i;
p->state = UTSM_PROC_ACTIVE;
p->crypto_epoch = 1;
p->recovery_generation = drr_recovery_generation();
p->capability_count = 0;
p->flags = 0;
p->hot_segment_slot = 0;
p->drr_recovery_gen = drr_recovery_generation();
p->cap_table.count = 0;
p->cap_table.generation = 1;
p->crypto_ctx.crypto_epoch = 1;
p->crypto_ctx.key_derivation_seed = 0;
p->crypto_ctx.pckc_hot_hint = 0;
g_process_count++;
return p;
}
}
return NULL;
}
void utsm_process_free(utsm_process_context *process) {
if (!process) return;
process->state = UTSM_PROC_UNUSED;
process->cap_table.count = 0;
process->capability_count = 0;
if (g_process_count > 0) g_process_count--;
}
utsm_process_context *utsm_process_get(u32 slot) {
if (slot >= UTSM_MAX_PROCESSES) return NULL;
return &g_process_table[slot];
}
/* ---- Capability 操作 ---- */
int utsm_process_grant_cap(utsm_process_context *process, utsm_capability cap) {
if (!process || process->cap_table.count >= UTSM_MAX_CAPABILITIES) {
return -1;
}
u32 idx = process->cap_table.count;
process->cap_table.caps[idx] = cap;
process->cap_table.count++;
process->capability_count = process->cap_table.count;
process->cap_table.generation++;
return 0;
}
int utsm_process_revoke_cap(utsm_process_context *process, u32 cap_index) {
if (!process || cap_index >= process->cap_table.count) {
return -1;
}
/* 将最后一个 capability 移到被删除的位置 */
u32 last = process->cap_table.count - 1;
if (cap_index != last) {
process->cap_table.caps[cap_index] = process->cap_table.caps[last];
}
process->cap_table.count--;
process->capability_count = process->cap_table.count;
process->cap_table.generation++;
return 0;
}
utsm_capability *utsm_process_get_cap(utsm_process_context *process, u32 cap_index) {
if (!process || cap_index >= process->cap_table.count) {
return NULL;
}
return &process->cap_table.caps[cap_index];
}
/* ---- Crypto context 操作 ---- */
void utsm_process_advance_epoch(utsm_process_context *process) {
if (!process) return;
process->crypto_epoch++;
process->crypto_ctx.crypto_epoch = process->crypto_epoch;
/* 清空 PCKC 热提示(epoch 变化后旧缓存无效) */
process->crypto_ctx.pckc_hot_hint = 0;
process->hot_segment_slot = 0;
}
Binary file not shown.
+80
View File
@@ -0,0 +1,80 @@
#include <utsm/segment.h>
#include <utsm/process.h>
#include <utsm/arena.h>
#include <utsm/dmp.h>
#include <utsm/config.h>
u64 utsm_next_generation(void);
static u64 digest_uuid(uuid128_t id) {
return id.hi ^ id.lo ^ (id.hi >> 32) ^ (id.lo << 17);
}
static u64 make_tweak_seed(uuid128_t process_uuid, uuid128_t segment_uuid, u64 epoch) {
return process_uuid.hi ^ process_uuid.lo ^ segment_uuid.hi ^ segment_uuid.lo ^ (epoch * 0x9e3779b97f4a7c15ULL);
}
int utsm_create_segment(utsm_process_context *process, u64 size, u32 flags, utsm_capability *out_cap) {
if (!process || !out_cap || size == 0) {
return UTSM_ERR_INVALID;
}
u32 slot = UTSM_MAX_SEGMENTS;
utsm_segment_desc *desc = NULL;
for (u32 i = 0; i < UTSM_MAX_SEGMENTS; i++) {
utsm_segment_desc *candidate = utsm_get_segment(i);
if (candidate->state == UTSM_SEG_FREE) {
slot = i;
desc = candidate;
break;
}
}
if (!desc) {
return UTSM_ERR_NO_MEMORY;
}
u64 length = utsm_align_up_u64(size, UTSM_CACHE_LINE_SIZE);
u64 pages = utsm_align_up_u64(length, UTSM_PAGE_SIZE) / UTSM_PAGE_SIZE;
u8 *cipher = (u8 *)kmem_alloc_page(pages);
utsm_dmp *dmp = (utsm_dmp *)kmem_alloc_aligned(sizeof(utsm_dmp), 64);
void *mac_table = kmem_alloc_aligned(pages * sizeof(u64), 8);
if (!cipher || !dmp || !mac_table) {
return UTSM_ERR_NO_MEMORY;
}
for (u64 i = 0; i < pages * UTSM_PAGE_SIZE; i++) {
cipher[i] = 0;
}
desc->segment_uuid = uuid_make_test(utsm_next_generation() + slot);
desc->owner_process_uuid = process->process_uuid;
desc->cipher_base = cipher;
desc->cipher_length = length;
desc->dmp_base = dmp;
desc->key_epoch = process->crypto_epoch;
desc->tweak_seed = make_tweak_seed(process->process_uuid, desc->segment_uuid, desc->key_epoch);
desc->mac_table = mac_table;
desc->generation++;
desc->flags = flags;
desc->state = UTSM_SEG_ACTIVE;
desc->last_cpu = 0;
desc->writer_seq = 0;
desc->checkpoint_generation = process->recovery_generation;
utsm_dirty_init(desc, pages);
utsm_dmp_init(dmp, desc, slot);
out_cap->segment_slot = slot;
out_cap->generation = desc->generation;
out_cap->rights = 0;
if (flags & UTSM_SEG_F_READ) out_cap->rights |= UTSM_RIGHT_READ;
if (flags & UTSM_SEG_F_WRITE) out_cap->rights |= UTSM_RIGHT_WRITE;
if (flags & UTSM_SEG_F_EXEC) out_cap->rights |= UTSM_RIGHT_EXEC;
if (flags & UTSM_SEG_F_DMA) out_cap->rights |= UTSM_RIGHT_DMA;
out_cap->epoch = (u32)desc->key_epoch;
out_cap->uuid_digest = digest_uuid(desc->segment_uuid);
out_cap->auth_tag = out_cap->uuid_digest ^ digest_uuid(process->process_uuid) ^ desc->key_epoch;
process->capability_count++;
return UTSM_OK;
}
Binary file not shown.
+35
View File
@@ -0,0 +1,35 @@
#include <utsm/utsm.h>
#include <utsm/segment.h>
#include <utsm/pckc.h>
#include <utsm/process.h>
#include <utsm/log.h>
static utsm_segment_desc g_segments[UTSM_MAX_SEGMENTS];
static u64 g_generation = 1;
void utsm_init(void) {
log_info("[UTSM] segment table reset begin");
for (u32 i = 0; i < UTSM_MAX_SEGMENTS; i++) {
g_segments[i].state = UTSM_SEG_FREE;
g_segments[i].generation = 1;
}
log_info("[UTSM] segment table reset ok");
g_generation = 1;
log_info("[UTSM] pckc init begin");
utsm_pckc_init();
log_info("[UTSM] pckc init ok");
utsm_process_init();
}
utsm_segment_desc *utsm_get_segment(u32 slot) {
if (slot >= UTSM_MAX_SEGMENTS) {
return NULL;
}
return &g_segments[slot];
}
u64 utsm_next_generation(void) {
return g_generation++;
}
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
#include <utsm/crypto.h>
#include <utsm/drr.h>
static u64 mix64(u64 x) {
x ^= x >> 30;
x *= 0xbf58476d1ce4e5b9ULL;
x ^= x >> 27;
x *= 0x94d049bb133111ebULL;
x ^= x >> 31;
return x;
}
void utsm_kdf_segment_key(uuid128_t process_uuid, uuid128_t segment_uuid, u64 key_epoch, utsm_key_material *out_key) {
const u64 *root = drr_get_root_key();
out_key->words[0] = mix64(root[0] ^ process_uuid.hi ^ segment_uuid.lo ^ key_epoch);
out_key->words[1] = mix64(root[1] ^ process_uuid.lo ^ segment_uuid.hi ^ (key_epoch << 1));
out_key->words[2] = mix64(root[2] ^ process_uuid.hi ^ segment_uuid.hi ^ (key_epoch << 7));
out_key->words[3] = mix64(root[3] ^ process_uuid.lo ^ segment_uuid.lo ^ (key_epoch << 13));
}
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
#include <utsm/crypto.h>
#include <utsm/config.h>
static u64 next_stream_word(u64 x) {
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
return x;
}
void utsm_crypt_line(const utsm_key_material *key, u64 tweak, const u8 *in, u8 *out) {
u64 state = key->words[0] ^ key->words[1] ^ key->words[2] ^ key->words[3] ^ tweak;
for (u64 i = 0; i < UTSM_CACHE_LINE_SIZE; i += 8) {
state = next_stream_word(state + i + 0xa5a5a5a5a5a5a5a5ULL);
for (u64 j = 0; j < 8; j++) {
out[i + j] = in[i + j] ^ (u8)(state >> (j * 8));
}
}
}
Binary file not shown.
+14
View File
@@ -0,0 +1,14 @@
#include <utsm/crypto.h>
static u64 mix64_tweak(u64 x) {
x ^= x >> 33;
x *= 0xff51afd7ed558ccdULL;
x ^= x >> 33;
x *= 0xc4ceb9fe1a85ec53ULL;
x ^= x >> 33;
return x;
}
u64 utsm_make_tweak(u64 tweak_seed, u64 line_index, u64 key_epoch) {
return mix64_tweak(tweak_seed ^ (line_index * 0x9e3779b97f4a7c15ULL) ^ (key_epoch << 32));
}
Binary file not shown.
+449
View File
@@ -0,0 +1,449 @@
#include <utsm/dkm.h>
#include <utsm/log.h>
#include <utsm/types.h>
#include <utsm/arena.h>
#include "../arch/x86_64/limine.h"
#define ELF_MAGIC0 0x7f
#define ELF_MAGIC1 'E'
#define ELF_MAGIC2 'L'
#define ELF_MAGIC3 'F'
#define ELFCLASS64 2
#define ELFDATA2LSB 1
#define ET_REL 1
#define ET_DYN 3
#define ET_EXEC 2
#define EM_X86_64 62
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_PROGBITS 1
#define SHT_NOBITS 8
#define SHF_ALLOC 0x2
#define SHF_WRITE 0x1
#define SHF_EXECINSTR 0x4
#define R_X86_64_64 1
#define R_X86_64_32 10
#define R_X86_64_32S 11
#define R_X86_64_PC32 2
void *memset(void *dst, int value, usize len);
void *memcpy(void *dst, const void *src, usize len);
__attribute__((used, section(".limine_requests")))
volatile struct limine_module_request g_module_request = {
.id = LIMINE_MODULE_REQUEST_ID,
.revision = 0,
.response = 0
};
__attribute__((used, section(".limine_requests_start")))
static volatile u64 g_limine_requests_start[4] = { LIMINE_COMMON_MAGIC, 0xf6b8f4b39de7d1aeULL, 0xfab91a6940fcb9cfULL };
__attribute__((used, section(".limine_requests_end")))
static volatile u64 g_limine_requests_end[2] = { 0, 0 };
__attribute__((used, section(".limine_requests")))
volatile struct limine_rsdp_request g_rsdp_request = {
.id = LIMINE_RSDP_REQUEST_ID,
.revision = 0,
.response = 0
};
__attribute__((used, section(".limine_requests")))
volatile struct limine_framebuffer_request g_fb_request = {
.id = LIMINE_FRAMEBUFFER_REQUEST_ID,
.revision = 0,
.response = 0
};
__attribute__((used, section(".limine_requests")))
volatile struct limine_hhdm_request g_hhdm_request = {
.id = { LIMINE_COMMON_MAGIC, 0x48dcf1cb8ad2b852ULL, 0x63984e959a98244bULL },
.revision = 0,
.response = 0
};
__attribute__((used, section(".limine_requests")))
volatile struct limine_kernel_address_request g_kernel_address_request = {
.id = LIMINE_KERNEL_ADDRESS_REQUEST_ID,
.revision = 0,
.response = 0
};
__attribute__((used, section(".limine_requests")))
volatile struct limine_memmap_request g_memmap_request = {
.id = LIMINE_MEMMAP_REQUEST_ID,
.revision = 0,
.response = 0
};
typedef struct elf64_ehdr {
u8 ident[16];
u16 type;
u16 machine;
u32 version;
u64 entry;
u64 phoff;
u64 shoff;
u32 flags;
u16 ehsize;
u16 phentsize;
u16 phnum;
u16 shentsize;
u16 shnum;
u16 shstrndx;
} elf64_ehdr;
typedef struct elf64_shdr {
u32 name;
u32 type;
u64 flags;
u64 addr;
u64 offset;
u64 size;
u32 link;
u32 info;
u64 addralign;
u64 entsize;
} elf64_shdr;
typedef struct elf64_sym {
u32 name;
u8 info;
u8 other;
u16 shndx;
u64 value;
u64 size;
} elf64_sym;
typedef struct elf64_rela {
u64 offset;
u64 info;
i64 addend;
} elf64_rela;
static int streq(const char *a, const char *b) {
usize i = 0;
while (a[i] && b[i]) {
if (a[i] != b[i]) {
return 0;
}
i++;
}
return a[i] == b[i];
}
int dkm_check_elf64(const void *address, u64 size) {
if (!address || size < sizeof(elf64_ehdr)) {
return -1;
}
const elf64_ehdr *ehdr = (const elf64_ehdr *)address;
if (ehdr->ident[0] != ELF_MAGIC0 || ehdr->ident[1] != ELF_MAGIC1 || ehdr->ident[2] != ELF_MAGIC2 || ehdr->ident[3] != ELF_MAGIC3) {
return -2;
}
if (ehdr->ident[4] != ELFCLASS64 || ehdr->ident[5] != ELFDATA2LSB) {
return -3;
}
if (ehdr->machine != EM_X86_64) {
return -4;
}
if (ehdr->type != ET_REL && ehdr->type != ET_DYN && ehdr->type != ET_EXEC) {
return -5;
}
if (ehdr->ehsize < sizeof(elf64_ehdr)) {
return -6;
}
return 0;
}
static int range_ok(u64 offset, u64 length, u64 size) {
if (offset > size) {
return 0;
}
if (length > size - offset) {
return 0;
}
return 1;
}
int dkm_scan_symbols(const void *address, u64 size, struct dkm_symbol_scan *out) {
const elf64_ehdr *ehdr = (const elf64_ehdr *)address;
out->driver_desc = 0;
out->driver_init = 0;
out->driver_exit = 0;
if (ehdr->shoff == 0 || ehdr->shnum == 0 || ehdr->shentsize < sizeof(elf64_shdr)) {
log_error("[DKM] ELF has no section table");
return -1;
}
if (!range_ok(ehdr->shoff, (u64)ehdr->shnum * ehdr->shentsize, size)) {
log_error("[DKM] ELF section table out of range");
return -1;
}
const elf64_shdr *sections = (const elf64_shdr *)((const u8 *)address + ehdr->shoff);
const elf64_shdr *symtab = 0;
const elf64_shdr *strtab = 0;
for (u16 i = 0; i < ehdr->shnum; i++) {
const elf64_shdr *section = (const elf64_shdr *)((const u8 *)sections + (u64)i * ehdr->shentsize);
if (section->type == SHT_SYMTAB) {
symtab = section;
if (section->link < ehdr->shnum) {
strtab = (const elf64_shdr *)((const u8 *)sections + (u64)section->link * ehdr->shentsize);
}
break;
}
}
if (!symtab || !strtab || strtab->type != SHT_STRTAB) {
log_error("[DKM] missing symtab/strtab");
return -1;
}
if (symtab->entsize < sizeof(elf64_sym) || !range_ok(symtab->offset, symtab->size, size) || !range_ok(strtab->offset, strtab->size, size)) {
log_error("[DKM] invalid symtab/strtab range");
return -1;
}
log_info("[DKM] symtab found");
log_hex64("[DKM] symbol count=", symtab->size / symtab->entsize);
for (u64 off = 0; off + sizeof(elf64_sym) <= symtab->size; off += symtab->entsize) {
const elf64_sym *sym = (const elf64_sym *)((const u8 *)address + symtab->offset + off);
if (sym->name >= strtab->size) {
continue;
}
const char *name = (const char *)address + strtab->offset + sym->name;
if (streq(name, "driver_desc")) {
out->driver_desc = sym;
log_info("[DKM] found driver_desc");
log_hex64("[DKM] driver_desc section=", sym->shndx);
log_hex64("[DKM] driver_desc value=", sym->value);
} else if (streq(name, "driver_init")) {
out->driver_init = sym;
log_info("[DKM] found driver_init");
log_hex64("[DKM] driver_init section=", sym->shndx);
log_hex64("[DKM] driver_init value=", sym->value);
} else if (streq(name, "driver_exit")) {
out->driver_exit = sym;
log_info("[DKM] found driver_exit");
log_hex64("[DKM] driver_exit section=", sym->shndx);
log_hex64("[DKM] driver_exit value=", sym->value);
}
}
if (out->driver_desc && out->driver_init && out->driver_exit) {
log_info("[DKM] required driver symbols ok");
return 0;
}
log_error("[DKM] required driver symbols missing");
return -1;
}
int dkm_load_elf_rel(const void *address, u64 size, const struct dkm_symbol_scan *symbols) {
const elf64_ehdr *ehdr = (const elf64_ehdr *)address;
const elf64_shdr *sections = (const elf64_shdr *)((const u8 *)address + ehdr->shoff);
u64 image_offset[64];
/* Zero the entire array so non-ALLOC section indices yield offset 0
* instead of stack garbage. */
for (int zi = 0; zi < 64; zi++) image_offset[zi] = 0;
u64 total_size = 0;
u64 max_align = 16;
u16 alloc_count = 0;
for (u16 i = 1; i < ehdr->shnum && alloc_count < 64; i++) {
const elf64_shdr *sh = (const elf64_shdr *)((const u8 *)sections + (u64)i * ehdr->shentsize);
if (!(sh->flags & SHF_ALLOC)) {
continue;
}
if (sh->addralign > max_align) {
max_align = sh->addralign;
}
total_size = utsm_align_up_u64(total_size, sh->addralign);
image_offset[i] = total_size;
total_size += sh->size;
alloc_count++;
}
if (total_size == 0) {
log_error("[DKM] no allocatable sections");
return -1;
}
u8 *image = (u8 *)kmem_alloc_aligned(total_size, max_align);
if (!image) {
log_error("[DKM] failed to allocate module memory");
return -1;
}
memset(image, 0, total_size);
for (u16 i = 1; i < ehdr->shnum; i++) {
const elf64_shdr *sh = (const elf64_shdr *)((const u8 *)sections + (u64)i * ehdr->shentsize);
if (!(sh->flags & SHF_ALLOC)) {
continue;
}
if (sh->type == SHT_PROGBITS && sh->size > 0 && range_ok(sh->offset, sh->size, size)) {
memcpy(image + image_offset[i], (const u8 *)address + sh->offset, sh->size);
}
}
for (u16 i = 1; i < ehdr->shnum; i++) {
const elf64_shdr *sh = (const elf64_shdr *)((const u8 *)sections + (u64)i * ehdr->shentsize);
if (sh->type != SHT_RELA) {
continue;
}
if (sh->entsize < sizeof(elf64_rela) || !range_ok(sh->offset, sh->size, size)) {
continue;
}
if (sh->info >= ehdr->shnum) {
continue;
}
const elf64_shdr *target = (const elf64_shdr *)((const u8 *)sections + (u64)sh->info * ehdr->shentsize);
if (!(target->flags & SHF_ALLOC)) {
continue;
}
u8 *target_base = image + image_offset[sh->info];
const elf64_shdr *rela_symtab = 0;
if (sh->link < ehdr->shnum) {
rela_symtab = (const elf64_shdr *)((const u8 *)sections + (u64)sh->link * ehdr->shentsize);
}
const elf64_shdr *rela_strtab = 0;
if (rela_symtab && rela_symtab->link < ehdr->shnum) {
rela_strtab = (const elf64_shdr *)((const u8 *)sections + (u64)rela_symtab->link * ehdr->shentsize);
}
(void)rela_strtab;
for (u64 off = 0; off + sizeof(elf64_rela) <= sh->size; off += sh->entsize) {
const elf64_rela *rela = (const elf64_rela *)((const u8 *)address + sh->offset + off);
u32 sym_idx = (u32)(rela->info >> 32);
u32 reloc_type = (u32)(rela->info & 0xffffffff);
u64 sym_value = 0;
u16 sym_shndx = 0;
if (rela_symtab && rela_strtab &&
rela_symtab->entsize >= sizeof(elf64_sym) &&
range_ok(rela_symtab->offset, rela_symtab->size, size)) {
u64 sym_entry_off = (u64)sym_idx * rela_symtab->entsize;
if (sym_entry_off + sizeof(elf64_sym) <= rela_symtab->size) {
const elf64_sym *sym = (const elf64_sym *)((const u8 *)address + rela_symtab->offset + sym_entry_off);
sym_value = sym->value;
sym_shndx = sym->shndx;
}
}
u64 S = sym_value;
if (sym_shndx > 0 && sym_shndx < 64) {
S = (u64)image + image_offset[sym_shndx] + sym_value;
}
u64 P = (u64)image + image_offset[sh->info] + rela->offset;
u64 A = rela->addend;
u64 patch = 0;
if (reloc_type == R_X86_64_64) {
patch = S + A;
} else if (reloc_type == R_X86_64_32 || reloc_type == R_X86_64_32S) {
patch = (u64)((i64)(i32)(S + A));
} else if (reloc_type == R_X86_64_PC32) {
patch = (u64)((i64)(i32)(S + A - P));
} else {
log_error("[DKM] unsupported relocation type");
log_hex64("[DKM] reloc type=", (u64)reloc_type);
return -1;
}
/* Bounds check: use the actual write width, not always 8. */
u32 reloc_width = (reloc_type == R_X86_64_64) ? 8 : 4;
if (rela->offset + reloc_width <= target->size) {
if (reloc_type == R_X86_64_32 || reloc_type == R_X86_64_32S || reloc_type == R_X86_64_PC32) {
*(u32 *)(target_base + rela->offset) = (u32)patch;
} else {
*(u64 *)(target_base + rela->offset) = patch;
}
}
}
}
const elf64_sym *desc_sym = (const elf64_sym *)symbols->driver_desc;
const elf64_sym *init_sym = (const elf64_sym *)symbols->driver_init;
const dkm_driver_desc *desc = (const dkm_driver_desc *)(image + image_offset[desc_sym->shndx] + desc_sym->value);
if (desc->magic != DKM_DRIVER_MAGIC) {
log_error("[DKM] external driver_desc magic mismatch");
return -1;
}
log_info("[DKM] external driver loaded");
log_hex64("[DKM] desc ptr=", (u64)desc);
log_hex64("[DKM] name ptr=", (u64)desc->name);
log_info(desc->name);
dkm_driver_init_fn init = (dkm_driver_init_fn)(image + image_offset[init_sym->shndx] + init_sym->value);
dkm_driver_handle handle;
handle.desc = desc;
handle.state = DKM_STATE_INITING;
handle.init_status = 0;
handle.load_stage = desc->stage;
handle.flags = desc->flags;
int result = init(dkm_get_kernel_api(), &handle);
handle.init_status = result;
if (result != 0) {
handle.state = DKM_STATE_FAILED;
log_error("[DKM] external driver init failed");
return result;
}
handle.state = DKM_STATE_ACTIVE;
log_info("[DKM] external driver active");
return 0;
}
void dkm_scan_boot_modules(void) {
struct limine_module_response *response = g_module_request.response;
if (!response) {
log_warn("[DKM] no Limine module response");
return;
}
log_info("[DKM] boot modules scan begin");
log_hex64("[DKM] boot module count=", response->module_count);
for (u64 i = 0; i < response->module_count; i++) {
struct limine_file *file = response->modules[i];
if (!file) {
log_warn("[DKM] null module entry");
continue;
}
log_info("[DKM] module path");
if (file->path) {
log_info(file->path);
}
if (file->cmdline) {
log_info(file->cmdline);
}
log_hex64("[DKM] module size=", file->size);
int status = dkm_check_elf64(file->address, file->size);
if (status == 0) {
log_info("[DKM] module ELF64 x86_64 ok");
struct dkm_symbol_scan symbols;
if (dkm_scan_symbols(file->address, file->size, &symbols) == 0) {
log_info("[DKM] loading external ELF driver");
int load_result = dkm_load_elf_rel(file->address, file->size, &symbols);
if (load_result != 0) {
log_error("[DKM] external driver load failed");
}
}
} else {
log_error("[DKM] module ELF64 rejected");
log_hex64("[DKM] elf status=", (u64)(i64)status);
}
}
log_info("[DKM] boot modules scan end");
}
Binary file not shown.
+47
View File
@@ -0,0 +1,47 @@
#include <utsm/dkm.h>
static const char *const console_early_provides[] = {
"console",
"early-log"
};
static const dkm_driver_desc console_early_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(dkm_driver_desc),
.name = "console_early",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = DKM_CLASS_CONSOLE,
.stage = 0,
.flags = DKM_F_REQUIRED | DKM_F_BOOT_MODULE | DKM_F_NO_UNLOAD | DKM_F_EARLY_LOG,
.priority = 0,
.depends = 0,
.depends_count = 0,
.provides = console_early_provides,
.provides_count = 2,
.min_kernel_abi = DKM_KERNEL_API_VERSION,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
static int console_early_init(const dkm_kernel_api *api, dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log || !api->log->info) {
return -1;
}
api->log->info("[DKM:console_early] serial console online");
return 0;
}
static int console_early_exit(dkm_driver_handle *handle) {
(void)handle;
return 0;
}
const dkm_builtin_driver dkm_builtin_console_early = {
.desc = &console_early_desc,
.init = console_early_init,
.exit = console_early_exit
};
Binary file not shown.
+67
View File
@@ -0,0 +1,67 @@
#include <utsm/dkm.h>
#include <utsm/log.h>
static int dkm_validate_desc(const dkm_driver_desc *desc) {
if (!desc) {
return -1;
}
if (desc->magic != DKM_DRIVER_MAGIC) {
return -2;
}
if (desc->abi_version != DKM_ABI_VERSION) {
return -3;
}
if (desc->desc_size < sizeof(dkm_driver_desc)) {
return -4;
}
if (!desc->name || !desc->version) {
return -5;
}
return 0;
}
void dkm_init(void) {
log_info("[DKM] init begin");
int status = dkm_load_builtin(&dkm_builtin_console_early);
if (status == 0) {
log_info("[DKM] init ok");
} else {
log_error("[DKM] init failed");
}
}
int dkm_load_builtin(const dkm_builtin_driver *driver) {
if (!driver || !driver->desc || !driver->init) {
log_error("[DKM] invalid builtin driver");
return -1;
}
int status = dkm_validate_desc(driver->desc);
if (status != 0) {
log_error("[DKM] driver_desc rejected");
return status;
}
dkm_driver_handle handle;
handle.desc = driver->desc;
handle.state = DKM_STATE_ABI_CHECKED;
handle.init_status = 0;
handle.load_stage = driver->desc->stage;
handle.flags = driver->desc->flags;
log_info("[DKM] builtin driver init begin");
log_info(driver->desc->name);
handle.state = DKM_STATE_INITING;
status = driver->init(dkm_get_kernel_api(), &handle);
handle.init_status = status;
if (status != 0) {
handle.state = DKM_STATE_FAILED;
log_error("[DKM] builtin driver init failed");
return status;
}
handle.state = DKM_STATE_ACTIVE;
log_info("[DKM] builtin driver active");
return 0;
}
Binary file not shown.
+90
View File
@@ -0,0 +1,90 @@
#include <utsm/dkm.h>
#include <utsm/log.h>
#include <utsm/idt.h>
#include <utsm/net.h>
static void dkm_api_info(const char *msg) {
log_info(msg);
}
static void dkm_api_warn(const char *msg) {
log_warn(msg);
}
static void dkm_api_error(const char *msg) {
log_error(msg);
}
static void dkm_api_panic(const char *msg) {
log_error(msg);
for (;;) {
__asm__ volatile("cli; hlt");
}
}
static const dkm_log_api g_log_api = {
.info = dkm_api_info,
.warn = dkm_api_warn,
.error = dkm_api_error,
.panic = dkm_api_panic
};
static dkm_kernel_api g_kernel_api = {
.version = DKM_KERNEL_API_VERSION,
.size = sizeof(dkm_kernel_api),
.feature_bits = 0,
.log = &g_log_api,
.mem = 0,
.utsm = 0,
.irq = 0,
.pci = 0,
.dma = 0,
.vfs = 0,
.net = 0,
.timer = 0,
.drr = 0,
.rsdp_address = 0,
.fb_address = 0,
.fb_width = 0,
.fb_height = 0,
.fb_pitch = 0,
.fb_bpp = 0,
.boot_modules_response = 0,
.irq_register = 0,
.hhdm_offset = 0,
.block = 0
};
const dkm_kernel_api *dkm_get_kernel_api(void) {
return &g_kernel_api;
}
#include "../arch/x86_64/limine.h"
extern volatile struct limine_rsdp_request g_rsdp_request;
extern volatile struct limine_framebuffer_request g_fb_request;
extern volatile struct limine_module_request g_module_request;
extern volatile struct limine_hhdm_request g_hhdm_request;
void dkm_fill_platform_info(void) {
g_kernel_api.dma = dma_get_api();
g_kernel_api.net = net_get_api();
g_kernel_api.block = block_get_api();
if (g_rsdp_request.response && g_rsdp_request.response->address) {
g_kernel_api.rsdp_address = g_rsdp_request.response->address;
}
if (g_fb_request.response && g_fb_request.response->framebuffer_count > 0) {
struct limine_framebuffer *fb = g_fb_request.response->framebuffers[0];
g_kernel_api.fb_address = fb->address;
g_kernel_api.fb_width = fb->width;
g_kernel_api.fb_height = fb->height;
g_kernel_api.fb_pitch = fb->pitch;
g_kernel_api.fb_bpp = fb->bpp;
}
if (g_module_request.response) {
g_kernel_api.boot_modules_response = g_module_request.response;
}
g_kernel_api.irq_register = (int (*)(u8,void*))((u64)irq_register);
if (g_hhdm_request.response) {
g_kernel_api.hhdm_offset = g_hhdm_request.response->offset;
}
}
Binary file not shown.
+359
View File
@@ -0,0 +1,359 @@
#include <utsm/dkm.h>
#include <utsm/log.h>
#include <utsm/types.h>
#include "../arch/x86_64/limine.h"
#define DSM_MAX_DRIVERS_PER_STAGE 8
#define DSM_MAX_STAGES 4
#define DSM_MAX_DEPENDS 4
#define DSM_MAX_PROVIDES 4
typedef struct dsm_driver_entry {
char name[32];
char path[64];
u32 class_id;
u32 required;
char depends[DSM_MAX_DEPENDS][32];
u32 depend_count;
char provides[DSM_MAX_PROVIDES][32];
u32 provide_count;
struct limine_file *boot_module;
int loaded;
} dsm_driver_entry;
typedef struct dsm_stage_entry {
u32 id;
char name[16];
u32 required;
dsm_driver_entry drivers[DSM_MAX_DRIVERS_PER_STAGE];
u32 driver_count;
} dsm_stage_entry;
static dsm_stage_entry g_stages[DSM_MAX_STAGES];
static u32 g_stage_count;
extern volatile struct limine_module_request g_module_request;
static int dsm_skip_ws(const char **p) {
while (**p == ' ' || **p == '\t' || **p == '\n' || **p == '\r') { (*p)++; }
return 0;
}
static int dsm_expect(const char **p, char c) {
dsm_skip_ws(p);
if (**p == c) { (*p)++; return 0; }
return -1;
}
static int dsm_read_string(const char **p, char *out, u32 max_len) {
dsm_skip_ws(p);
if (**p != '"') return -1;
(*p)++;
u32 i = 0;
while (**p && **p != '"' && i + 1 < max_len) {
out[i++] = **p;
(*p)++;
}
out[i] = 0;
if (**p != '"') return -1;
(*p)++;
return 0;
}
static int dsm_skip_value(const char **p) {
dsm_skip_ws(p);
if (**p == '"') {
char tmp[256];
return dsm_read_string(p, tmp, sizeof(tmp));
}
if (**p == '{') {
(*p)++;
int depth = 1;
while (depth > 0 && **p) {
if (**p == '{') depth++;
else if (**p == '}') depth--;
else if (**p == '"') { (*p)++; while (**p && **p != '"') (*p)++; if (**p) (*p)++; continue; }
if (depth > 0) (*p)++;
}
return 0;
}
if (**p == '[') {
(*p)++;
int depth = 1;
while (depth > 0 && **p) {
if (**p == '[') depth++;
else if (**p == ']') depth--;
else if (**p == '"') { (*p)++; while (**p && **p != '"') (*p)++; if (**p) (*p)++; continue; }
if (depth > 0) (*p)++;
}
return 0;
}
while (**p && **p != ',' && **p != '}' && **p != ']') (*p)++;
return 0;
}
static struct limine_file *dsm_find_boot_module(const char *path) {
struct limine_module_response *rsp = g_module_request.response;
if (!rsp) return 0;
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (f && f->path) {
const char *fp = f->path;
while (*fp == '/') fp++;
usize j = 0;
usize k = 0;
while (fp[j]) j++;
while (path[k]) k++;
if (j == k) {
int match = 1;
for (usize x = 0; x < j; x++) {
if (fp[x] != path[x]) { match = 0; break; }
}
if (match) return f;
}
}
}
return 0;
}
static int streq_static(const char *a, const char *b) {
usize i = 0;
while (a[i] && b[i]) {
if (a[i] != b[i]) return 0;
i++;
}
return a[i] == b[i];
}
static void dsm_parse_driver(const char **p, dsm_driver_entry *drv) {
drv->depend_count = 0;
drv->provide_count = 0;
drv->required = 1;
drv->boot_module = 0;
drv->loaded = 0;
drv->class_id = 0;
if (dsm_expect(p, '{') != 0) return;
while (**p && **p != '}') {
dsm_skip_ws(p);
if (**p == '}') break;
char key[32];
if (dsm_read_string(p, key, sizeof(key)) != 0) return;
dsm_expect(p, ':');
if (streq_static(key, "name")) {
dsm_read_string(p, drv->name, sizeof(drv->name));
} else if (streq_static(key, "path")) {
dsm_read_string(p, drv->path, sizeof(drv->path));
} else if (streq_static(key, "class")) {
char cls[32];
dsm_read_string(p, cls, sizeof(cls));
if (streq_static(cls, "platform")) drv->class_id = 1;
else if (streq_static(cls, "bus")) drv->class_id = 2;
else if (streq_static(cls, "interrupt")) drv->class_id = 3;
else if (streq_static(cls, "timer")) drv->class_id = 4;
else if (streq_static(cls, "console")) drv->class_id = 5;
else if (streq_static(cls, "storage")) drv->class_id = 6;
else if (streq_static(cls, "fs")) drv->class_id = 7;
else if (streq_static(cls, "fs-core")) drv->class_id = 8;
else if (streq_static(cls, "net")) drv->class_id = 9;
else if (streq_static(cls, "input")) drv->class_id = 10;
} else if (streq_static(key, "required")) {
dsm_skip_ws(p);
if (**p == 't') { drv->required = 1; (*p) += 4; }
else if (**p == 'f') { drv->required = 0; (*p) += 5; }
} else if (streq_static(key, "depends")) {
if (dsm_expect(p, '[') != 0) return;
while (**p && **p != ']') {
dsm_skip_ws(p);
if (**p == ']') break;
if (drv->depend_count < DSM_MAX_DEPENDS) {
dsm_read_string(p, drv->depends[drv->depend_count], 32);
drv->depend_count++;
} else { dsm_skip_value(p); }
dsm_skip_ws(p);
if (**p == ',') { (*p)++; continue; }
if (**p == ']') break;
}
dsm_expect(p, ']');
} else if (streq_static(key, "provides")) {
if (dsm_expect(p, '[') != 0) return;
while (**p && **p != ']') {
dsm_skip_ws(p);
if (**p == ']') break;
if (drv->provide_count < DSM_MAX_PROVIDES) {
dsm_read_string(p, drv->provides[drv->provide_count], 32);
drv->provide_count++;
} else { dsm_skip_value(p); }
dsm_skip_ws(p);
if (**p == ',') { (*p)++; continue; }
if (**p == ']') break;
}
dsm_expect(p, ']');
} else {
dsm_skip_value(p);
}
dsm_skip_ws(p);
if (**p == ',') (*p)++;
}
dsm_expect(p, '}');
}
static void dsm_parse_stage(const char **p, dsm_stage_entry *stage) {
stage->driver_count = 0;
if (dsm_expect(p, '{') != 0) return;
while (**p && **p != '}') {
dsm_skip_ws(p);
if (**p == '}') break;
char key[32];
if (dsm_read_string(p, key, sizeof(key)) != 0) return;
dsm_expect(p, ':');
if (streq_static(key, "id")) {
dsm_skip_ws(p);
u32 val = 0;
while (**p >= '0' && **p <= '9') { val = val * 10 + (u32)(**p - '0'); (*p)++; }
stage->id = val;
} else if (streq_static(key, "name")) {
dsm_read_string(p, stage->name, sizeof(stage->name));
} else if (streq_static(key, "required")) {
dsm_skip_ws(p);
if (**p == 't') { stage->required = 1; (*p) += 4; }
else if (**p == 'f') { stage->required = 0; (*p) += 5; }
} else if (streq_static(key, "drivers")) {
if (dsm_expect(p, '[') != 0) return;
while (**p && **p != ']') {
dsm_skip_ws(p);
if (**p == ']') break;
if (stage->driver_count < DSM_MAX_DRIVERS_PER_STAGE) {
dsm_parse_driver(p, &stage->drivers[stage->driver_count]);
stage->driver_count++;
} else {
dsm_skip_value(p);
}
dsm_skip_ws(p);
if (**p == ',') { (*p)++; continue; }
if (**p == ']') break;
}
dsm_expect(p, ']');
} else {
dsm_skip_value(p);
}
dsm_skip_ws(p);
if (**p == ',') (*p)++;
}
dsm_expect(p, '}');
}
static int dsm_parse_manifest(const char *text, u64 size) {
g_stage_count = 0;
const char *p = text;
const char *end = text + size;
while (p < end && *p) {
dsm_skip_ws(&p);
if (p >= end || !*p) break;
if (*p == '{' || *p == '}') { p++; continue; }
if (*p == ',' || *p == ':') { p++; continue; }
if (*p == '[' || *p == ']') { p++; continue; }
char key[32];
if (dsm_read_string(&p, key, sizeof(key)) != 0) break;
dsm_expect(&p, ':');
if (streq_static(key, "stages")) {
if (dsm_expect(&p, '[') != 0) return -1;
while (p < end && *p) {
dsm_skip_ws(&p);
if (*p == ']') { p++; break; }
if (g_stage_count < DSM_MAX_STAGES) {
dsm_parse_stage(&p, &g_stages[g_stage_count]);
g_stage_count++;
}
dsm_skip_ws(&p);
if (*p == ',') p++;
}
} else {
dsm_skip_value(&p);
}
dsm_skip_ws(&p);
if (*p == ',' || *p == '}' || *p == ']') p++;
}
return 0;
}
void dsm_load_by_manifest(void) {
struct limine_module_response *rsp = g_module_request.response;
if (!rsp) {
log_warn("[DSM] no Limine module response");
return;
}
struct limine_file *manifest_file = 0;
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (f && f->path && f->cmdline && streq_static(f->cmdline, "dkm:manifest")) {
manifest_file = f;
break;
}
}
if (!manifest_file) {
log_warn("[DSM] manifest not found in boot modules");
return;
}
log_info("[DSM] parsing manifest");
dsm_parse_manifest((const char *)manifest_file->address, manifest_file->size);
log_info("[DSM] manifest parsed");
log_hex64("[DSM] stages=", (u64)g_stage_count);
for (u32 si = 0; si < g_stage_count; si++) {
dsm_stage_entry *stage = &g_stages[si];
log_info("[DSM] stage begin");
log_info(stage->name);
log_hex64("[DSM] driver count=", stage->driver_count);
for (u32 di = 0; di < stage->driver_count; di++) {
dsm_driver_entry *drv = &stage->drivers[di];
drv->boot_module = dsm_find_boot_module(drv->path);
if (!drv->boot_module) {
log_info("[DSM] module not found");
log_info(drv->name);
if (drv->required && stage->required) {
log_error("[DSM] required module missing, abort stage");
break;
}
continue;
}
struct limine_file *f = drv->boot_module;
log_info("[DSM] loading driver");
log_info(drv->name);
if (dkm_check_elf64(f->address, f->size) != 0) {
log_error("[DSM] ELF check failed");
continue;
}
struct dkm_symbol_scan symbols;
if (dkm_scan_symbols(f->address, f->size, &symbols) != 0) {
log_error("[DSM] symbol scan failed");
continue;
}
int result = dkm_load_elf_rel(f->address, f->size, &symbols);
if (result != 0) {
log_error("[DSM] load failed");
if (drv->required && stage->required) {
log_error("[DSM] required driver failed, abort stage");
break;
}
} else {
drv->loaded = 1;
}
}
log_info("[DSM] stage end");
}
}
Binary file not shown.
+316
View File
@@ -0,0 +1,316 @@
/* drr_core.c — DRR Dedicated Recovery Root 核心实现
*
* 替换原 drr_stub.c,提供完整的:
* - Emergency Pool(独立于普通堆分配器)
* - Recovery Log(write intent/commit 追踪)
* - Checkpoint A/B 双槽(CRC 校验、原子 active slot 切换)
* - Root key 管理
* - Heartbeat
*/
#include <utsm/drr.h>
#include <utsm/log.h>
/* ---- 内部内存操作(不依赖 libc) ---- */
static void drr_memzero(void *dst, u64 n) {
u8 *d = (u8 *)dst;
while (n--) *d++ = 0;
}
static void drr_memcpy(void *dst, const void *src, u64 n) {
u8 *d = (u8 *)dst;
const u8 *s = (const u8 *)src;
while (n--) *d++ = *s++;
}
/* ---- CRC64-ECMA ---- */
static const u64 crc64_table[256] = {
0x0000000000000000ULL, 0x42F0E1EBA5EA001AULL, 0x85E1C3D753D46D34ULL, 0xC711223CF63E6D2EULL,
0x493366450E42ECDFULL, 0x0BC387AEABA8ECC5ULL, 0xCCD2A5925D9681EBULL, 0x8E224479F87C81F1ULL,
0x9266CC8A1C85D9BEULL, 0xD0962D61B96FD9A4ULL, 0x17870F5D4F51B48AULL, 0x5577EEB6EABBB490ULL,
0xDB55AACF12C73561ULL, 0x99A54B24B72D357BULL, 0x5EB4691841135855ULL, 0x1C4488F3E4F9584FULL,
0x2644C6D0383BF54AULL, 0x64B4273B9DD1F550ULL, 0xA3A505076BEF987EULL, 0xE155E4ECCE059864ULL,
0x6F77A09536791995ULL, 0x2D87417E9393198FULL, 0xEA96634265AD74A1ULL, 0xA86682A9C04774BBULL,
0xB4220A5A24BE2CF4ULL, 0xF6D2EBB181542CEEULL, 0x31C3C98D776A41C0ULL, 0x73332866D28041DAULL,
0xFD116C1F2AFCC02BULL, 0xBFE18DF48F16C031ULL, 0x78F0AFC87928AD1FULL, 0x3A004E23DCC2AD05ULL,
0x4C898D607077A834ULL, 0x0E796C8BD19DA82EULL, 0xC9684EB723A3C500ULL, 0x8B98AF5C8649C51AULL,
0x05BAEB257E3544EBULL, 0x474A0ACEDBDF44F1ULL, 0x805B28F22DE129DFULL, 0xC2ABC919880B29C5ULL,
0xDEEF41EA6CF2718AULL, 0x9C1FA001C9187190ULL, 0x5B0E823D3F261CBEULL, 0x19FE63D69ACC1CA4ULL,
0x97DC27AF62B09D55ULL, 0xD52CC644C75A9D4FULL, 0x123DE4783164F061ULL, 0x50CD0593948EF07BULL,
0x6ACD4BB0484C5D7EULL, 0x283DAA5BECA65D64ULL, 0xEF2C88671B98304AULL, 0xADDC698CBE723050ULL,
0x23FE2DF5460EB1A1ULL, 0x610ECC1EE3E4B1BBULL, 0xA61FEE2215DADC95ULL, 0xE4EF0FC9B030DC8FULL,
0xF8AB873A54C984C0ULL, 0xBA5B66D1F12384DAULL, 0x7D4A44ED071DE9F4ULL, 0x3FBAA506A2F7E9EEULL,
0xB198E17F5A8B681FULL, 0xF3680094FF616805ULL, 0x347922A8095F052BULL, 0x7689C343ACB50531ULL,
0x98131AE0E0ED2F68ULL, 0xDAE3FB0B45072F72ULL, 0x1DF2D937B339425CULL, 0x5F0238DC16D34246ULL,
0xD1207CA5EEAFC3B7ULL, 0x93D09D4E4B45C3ADULL, 0x54C1B172BD7BAE83ULL, 0x163150991891AE99ULL,
0x0A75D66AFC68F6D6ULL, 0x488537815982F6CCULL, 0x8F9415BDAFBC9BE2ULL, 0xCD64F4560A569BF8ULL,
0x4346B02FF22A1A09ULL, 0x01B651C457C01A13ULL, 0xC6A773F8A1FE773DULL, 0x8457921304147727ULL,
0xBE57DC30D8D6DA22ULL, 0xFCA73DDB7D3CDA38ULL, 0x3BB61FE78B02B716ULL, 0x7946FE0C2EE8B70CULL,
0xF764BA75D69436FDULL, 0xB5945B9E737E36E7ULL, 0x728579A285405BC9ULL, 0x3075984920AA5BD3ULL,
0x2C3110BAC453039CULL, 0x6EC1F15161B90386ULL, 0xA9D0D36D97876EA8ULL, 0xEB203286326D6EB2ULL,
0x650276FFCA11EF43ULL, 0x27F297146FFBEF59ULL, 0xE0E3B52899C58277ULL, 0xA21354C33C2F826DULL,
0xD49A9780909A875CULL, 0x966A766B35708746ULL, 0x517B5457C34EEA68ULL, 0x138BB5BC66A4EA72ULL,
0x9DA9F1C59ED86B83ULL, 0xDF59102E3B326B99ULL, 0x18483212CD0C06B7ULL, 0x5AB8D3F968E606ADULL,
0x46FC5B0A8C1F5EE2ULL, 0x040CBA4129F55EF8ULL, 0xC31D98DDDFCB33D6ULL, 0x81ED79367A2133CCULL,
0x0FCF3D4F825DB23DULL, 0x4D3FDCA427B7B227ULL, 0x8A2EFE98D189DF09ULL, 0xC8DE1F737463DF13ULL,
0xF2DE5150A8A17216ULL, 0xB02EB0BB0D4B720CULL, 0x773F9287FB751F22ULL, 0x35CF736C5E9F1F38ULL,
0xBBED3715A6E39EC9ULL, 0xF91DD6FE03099ED3ULL, 0x3E0CF4C2F537F3FDULL, 0x7CFC152950DDF3E7ULL,
0x60B89DDAB424ABA8ULL, 0x22487C3111CEABB2ULL, 0xE5595E0DE7F0C69CULL, 0xA7A9BFE6421AC686ULL,
0x298BFB9FBA664777ULL, 0x6B7B1A741F8C476DULL, 0xAC6A3848E9B22A43ULL, 0xEE9AD9A34C582A59ULL,
};
u64 drr_crc64(const void *data, u64 len) {
const u8 *p = (const u8 *)data;
u64 crc = 0xFFFFFFFFFFFFFFFFULL;
for (u64 i = 0; i < len; i++) {
crc = crc64_table[(crc ^ p[i]) & 0xFF] ^ (crc >> 8);
}
return crc ^ 0xFFFFFFFFFFFFFFFFULL;
}
/* ---- 全局 DRR 状态 ---- */
static drr_state g_drr;
/* ---- Root key(最终应从安全启动链获取) ---- */
static const u64 g_root_key[4] = {
0x4452525554534D31ULL, /* "DRRUTSM1" */
0xFEEDFACECAFEF00DULL,
0x0123456789ABCDEFULL,
0xFEDCBA9876543210ULL
};
/* ---- Emergency Pool 内部分配 ---- */
static void *pool_alloc_internal(u64 size, u64 alignment) {
u64 current = (u64)&g_drr.pool[0] + g_drr.pool_offset;
u64 aligned = utsm_align_up_u64(current, alignment);
u64 new_offset = (aligned - (u64)&g_drr.pool[0]) + size;
if (new_offset > g_drr.pool_limit) {
return NULL;
}
g_drr.pool_offset = new_offset;
return (void *)aligned;
}
void *drr_emergency_alloc(u64 size, u64 alignment) {
if (!g_drr.initialized) return NULL;
return pool_alloc_internal(size, alignment);
}
void drr_emergency_reset(void) {
if (!g_drr.initialized) return;
/* 保留已分配的子缓冲区,仅重置池偏移到子缓冲区之后 */
/* 注意:此函数仅在 recovery 路径紧急情况下使用 */
g_drr.pool_offset = 0;
/* 重新分配子缓冲区 */
drr_init();
}
/* ---- 初始化 ---- */
void drr_init(void) {
log_info("[DRR] init begin");
drr_memzero(&g_drr, sizeof(g_drr));
g_drr.pool_offset = 0;
g_drr.pool_limit = DRR_EMERGENCY_POOL_SIZE;
g_drr.root_key = g_root_key;
g_drr.recovery_generation = 1;
g_drr.heartbeat_interval = 1000;
g_drr.active_slot = 0; /* A */
/* 分配 Emergency Pool 子缓冲区 */
g_drr.stack_base = (u8 *)pool_alloc_internal(DRR_EMERGENCY_STACK_SIZE, 64);
g_drr.stack_size = DRR_EMERGENCY_STACK_SIZE;
g_drr.stack_ptr = DRR_EMERGENCY_STACK_SIZE; /* 栈从顶部向下增长 */
g_drr.log_base = (drr_log_entry *)pool_alloc_internal(DRR_RECOVERY_LOG_SIZE, 64);
g_drr.log_capacity = DRR_RECOVERY_LOG_SIZE / sizeof(drr_log_entry);
g_drr.log_count = 0;
g_drr.ckpt_meta_buf = (drr_checkpoint_meta *)pool_alloc_internal(DRR_CKPT_META_BUF_SIZE, 64);
g_drr.crash_buf = (u8 *)pool_alloc_internal(DRR_CRASH_BUF_SIZE, 64);
g_drr.crash_buf_size = DRR_CRASH_BUF_SIZE;
g_drr.meta_slab = pool_alloc_internal(DRR_META_SLAB_SIZE, 64);
g_drr.meta_slab_offset = 0;
/* 初始化 A/B slot */
drr_memzero(&g_drr.ckpt_a, sizeof(drr_checkpoint_meta));
drr_memzero(&g_drr.ckpt_b, sizeof(drr_checkpoint_meta));
g_drr.ckpt_a.magic = DRR_CKPT_MAGIC;
g_drr.ckpt_a.version = DRR_CKPT_VERSION;
g_drr.ckpt_a.active = 1;
g_drr.ckpt_b.magic = DRR_CKPT_MAGIC;
g_drr.ckpt_b.version = DRR_CKPT_VERSION;
g_drr.initialized = 1;
log_info("[DRR] init ok");
}
const u64 *drr_get_root_key(void) {
return g_drr.root_key;
}
u64 drr_recovery_generation(void) {
return g_drr.recovery_generation;
}
/* ---- Fault 报告 ---- */
void drr_report_fault(const char *reason) {
if (!g_drr.initialized) return;
log_error("[DRR] FAULT: ");
log_error(reason);
/* 记录到 crash buffer */
if (g_drr.crash_buf && g_drr.crash_buf_size > 0) {
/* 简单记录:写入 reason 的前 N 字节 */
u64 i = 0;
const char *s = reason;
while (*s && i < g_drr.crash_buf_size - 1) {
g_drr.crash_buf[i++] = (u8)*s++;
}
g_drr.crash_buf[i] = 0;
}
/* 增加 recovery generation */
g_drr.recovery_generation++;
}
/* ---- Recovery Log ---- */
void drr_log_write_intent(u32 segment_slot, u64 offset, u64 len) {
if (!g_drr.initialized || !g_drr.log_base) return;
if (g_drr.log_count >= g_drr.log_capacity) {
/* 日志满,最简单的策略:丢弃最早的条目 */
for (u32 i = 1; i < g_drr.log_count; i++) {
g_drr.log_base[i - 1] = g_drr.log_base[i];
}
g_drr.log_count--;
}
drr_log_entry *e = &g_drr.log_base[g_drr.log_count++];
e->segment_slot = segment_slot;
e->flags = DRR_LOG_FLAG_INTENT;
e->offset = offset;
e->length = len;
e->timestamp = g_drr.heartbeat_counter;
}
void drr_log_write_commit(u32 segment_slot, u64 offset, u64 len) {
if (!g_drr.initialized || !g_drr.log_base) return;
if (g_drr.log_count >= g_drr.log_capacity) {
for (u32 i = 1; i < g_drr.log_count; i++) {
g_drr.log_base[i - 1] = g_drr.log_base[i];
}
g_drr.log_count--;
}
drr_log_entry *e = &g_drr.log_base[g_drr.log_count++];
e->segment_slot = segment_slot;
e->flags = DRR_LOG_FLAG_COMMIT;
e->offset = offset;
e->length = len;
e->timestamp = g_drr.heartbeat_counter;
}
/* ---- Checkpoint ---- */
int drr_checkpoint_begin(drr_checkpoint_type type) {
if (!g_drr.initialized) return -1;
/* 选择 inactive slot */
drr_checkpoint_meta *target;
if (g_drr.active_slot == 0) {
target = &g_drr.ckpt_b;
} else {
target = &g_drr.ckpt_a;
}
target->magic = DRR_CKPT_MAGIC;
target->version = DRR_CKPT_VERSION;
target->active = 0; /* 写入时为 inactive */
target->type = type;
target->global_epoch = g_drr.recovery_generation;
target->dirty_page_count = 0;
target->mac_root = 0;
target->segment_count = 0;
target->crc = 0;
return 0;
}
int drr_checkpoint_finish(void) {
if (!g_drr.initialized) return -1;
/* 写入 inactive slot 的 CRC */
drr_checkpoint_meta *target;
if (g_drr.active_slot == 0) {
target = &g_drr.ckpt_b;
} else {
target = &g_drr.ckpt_a;
}
/* 计算 CRC(不含 crc 字段本身) */
target->crc = drr_crc64(target,
sizeof(drr_checkpoint_meta) - sizeof(u64));
/* 原子切换 active slot */
target->active = 1;
/* 旧 slot 标记 inactive */
if (g_drr.active_slot == 0) {
g_drr.ckpt_a.active = 0;
g_drr.active_slot = 1;
} else {
g_drr.ckpt_b.active = 0;
g_drr.active_slot = 0;
}
/* 增加 recovery generation */
g_drr.recovery_generation++;
/* 清空 recovery log */
g_drr.log_count = 0;
return 0;
}
int drr_checkpoint_recover(drr_checkpoint_meta *out_meta) {
if (!g_drr.initialized || !out_meta) return -1;
/* 尝试 active slot */
drr_checkpoint_meta *active = (g_drr.active_slot == 0) ?
&g_drr.ckpt_a : &g_drr.ckpt_b;
drr_checkpoint_meta *fallback = (g_drr.active_slot == 0) ?
&g_drr.ckpt_b : &g_drr.ckpt_a;
/* 验证 active slot */
if (active->magic == DRR_CKPT_MAGIC && active->active == 1) {
u64 expected_crc = active->crc;
active->crc = 0;
u64 actual_crc = drr_crc64(active,
sizeof(drr_checkpoint_meta) - sizeof(u64));
active->crc = expected_crc;
if (actual_crc == expected_crc) {
drr_memcpy(out_meta, active, sizeof(drr_checkpoint_meta));
return 0;
}
}
/* active 无效,尝试 fallback */
if (fallback->magic == DRR_CKPT_MAGIC && fallback->active == 1) {
u64 expected_crc = fallback->crc;
fallback->crc = 0;
u64 actual_crc = drr_crc64(fallback,
sizeof(drr_checkpoint_meta) - sizeof(u64));
fallback->crc = expected_crc;
if (actual_crc == expected_crc) {
drr_memcpy(out_meta, fallback, sizeof(drr_checkpoint_meta));
return 0;
}
}
/* 双槽都无效 */
return -2;
}
/* ---- Heartbeat ---- */
void drr_heartbeat_tick(void) {
if (!g_drr.initialized) return;
g_drr.heartbeat_counter++;
}
u64 drr_heartbeat_get(void) {
return g_drr.heartbeat_counter;
}
Binary file not shown.
+13
View File
@@ -0,0 +1,13 @@
#ifndef UTSM_ARENA_H
#define UTSM_ARENA_H
#include <utsm/types.h>
void arena_init(void);
void *kmem_alloc(u64 size);
void *kmem_alloc_aligned(u64 size, u64 alignment);
void *kmem_alloc_page(u64 page_count);
u64 kmem_arena_virtual_base(void);
u64 kmem_arena_virtual_end(void);
#endif
+8
View File
@@ -0,0 +1,8 @@
#ifndef UTSM_ASSERT_H
#define UTSM_ASSERT_H
#include <utsm/log.h>
#define UTSM_ASSERT(cond) do { if (!(cond)) { panic("assertion failed: " #cond); } } while (0)
#endif
+33
View File
@@ -0,0 +1,33 @@
#ifndef UTSM_BLOCK_H
#define UTSM_BLOCK_H
#include <utsm/types.h>
#define DKM_BLOCK_MAX_DEVICES 8u
typedef int (*dkm_block_read_fn)(void *ctx, u64 lba, u32 count, void *buffer);
typedef int (*dkm_block_write_fn)(void *ctx, u64 lba, u32 count, const void *buffer);
typedef struct dkm_block_device_desc {
const char *name;
u64 sector_size;
u64 sector_count;
void *ctx;
dkm_block_read_fn read;
dkm_block_write_fn write;
} dkm_block_device_desc;
typedef struct dkm_block_api {
int (*register_device)(const dkm_block_device_desc *desc);
u32 (*device_count)(void);
int (*read)(u32 index, u64 lba, u32 count, void *buffer);
int (*write)(u32 index, u64 lba, u32 count, const void *buffer);
u64 (*sector_size)(u32 index);
const char *(*device_name)(u32 index);
int (*set_write_fn)(u32 index, dkm_block_write_fn fn);
} dkm_block_api;
void block_init(void);
const dkm_block_api *block_get_api(void);
#endif
+26
View File
@@ -0,0 +1,26 @@
#ifndef UTSM_CAPABILITY_H
#define UTSM_CAPABILITY_H
#include <utsm/types.h>
#include <utsm/status.h>
#define UTSM_RIGHT_READ (1U << 0)
#define UTSM_RIGHT_WRITE (1U << 1)
#define UTSM_RIGHT_EXEC (1U << 2)
#define UTSM_RIGHT_SHARE (1U << 3)
#define UTSM_RIGHT_DMA (1U << 4)
struct utsm_segment_desc;
typedef struct {
u32 segment_slot;
u32 generation;
u32 rights;
u32 epoch;
u64 uuid_digest;
u64 auth_tag;
} utsm_capability;
int utsm_cap_validate(utsm_capability cap, u32 required_rights, u64 offset, u64 len, struct utsm_segment_desc **out_desc);
#endif
+13
View File
@@ -0,0 +1,13 @@
#ifndef UTSM_CONFIG_H
#define UTSM_CONFIG_H
#define UTSM_CACHE_LINE_SIZE 64ULL
#define UTSM_PAGE_SIZE 4096ULL
#define UTSM_MAX_SEGMENTS 1024U
#define UTSM_MAX_CAPABILITIES 256U
#define UTSM_MAX_PCKC_KEYS 8U
#define UTSM_ARENA_SIZE (16ULL * 1024ULL * 1024ULL)
#define UTSM_DIRTY_SHARD_PAGES 1024ULL
#define UTSM_KERNEL_STACK_SIZE 16384ULL
#endif
+17
View File
@@ -0,0 +1,17 @@
#ifndef UTSM_CRYPTO_H
#define UTSM_CRYPTO_H
#include <utsm/types.h>
#include <utsm/uuid.h>
struct utsm_segment_desc;
typedef struct {
u64 words[4];
} utsm_key_material;
void utsm_kdf_segment_key(uuid128_t process_uuid, uuid128_t segment_uuid, u64 key_epoch, utsm_key_material *out_key);
u64 utsm_make_tweak(u64 tweak_seed, u64 line_index, u64 key_epoch);
void utsm_crypt_line(const utsm_key_material *key, u64 tweak, const u8 *in, u8 *out);
#endif
+709
View File
@@ -0,0 +1,709 @@
/* deshab_ui.h — Deshab 视觉风格系统
*
* "Sealed Arc" 设计语言:以 UTSM 封缄内存为灵感的统一视觉体系。
*
* 核心设计隐喻:
* Arc(弧) — 封缄/解封的视觉表达,圆角、弧形边框、弧线动画
* Seal(封) — 密封容器的安全感,卡片容器、发光边缘、透明覆盖
* Flow(流) — 数据流的连续性,渐变背景、平滑过渡、流式布局
*
* 设计令牌分层:
* L0 — 原始色值(Deshab Palette)
* L1 — 语义色值(Semantic Colors,引用 L0)
* L2 — 组件令牌(Component Tokens,引用 L1)
*
* 所有 UI 组件必须通过本头文件获取视觉参数,禁止硬编码颜色/尺寸。
*/
#ifndef DESHAB_UI_H
#define DESHAB_UI_H
/* ===================================================================
* 基础类型(自包含,不依赖 utsm/types.h 以便 DSK/Shell 独立使用)
* =================================================================== */
typedef unsigned char du_u8;
typedef unsigned short du_u16;
typedef unsigned int du_u32;
typedef unsigned long long du_u64;
typedef long long du_i64;
/* ===================================================================
* L0 — Deshab 原始色板 (Deshab Palette)
*
* 色彩命名规则:{色调}_{明度}
* 格式:0xAARRGGBB(与 framebuffer 一致,小端 x86 上 BB 置低位)
* =================================================================== */
/* --- 主色调:深海蓝 (Abyss Blue) --- */
#define DP_ABYSS_900 0xFF0A1428u /* 最深:终端背景、底色 */
#define DP_ABYSS_800 0xFF0F1E38u /* 深层:暗卡片背景 */
#define DP_ABYSS_700 0xFF162848u /* 暗面:悬停态背景 */
#define DP_ABYSS_600 0xFF1E3868u /* 中暗:输入框背景 */
#define DP_ABYSS_500 0xFF284888u /* 中间:次级强调 */
#define DP_ABYSS_400 0xFF3868B0u /* 中亮:默认强调 */
#define DP_ABYSS_300 0xFF5088D0u /* 亮面:链接色 */
#define DP_ABYSS_200 0xFF78A8E8u /* 高亮:焦点指示 */
#define DP_ABYSS_100 0xFFA8CCF4u /* 最亮:浅色辅助 */
/* --- 强调色:封缄青 (Seal Cyan) — 主要操作/交互 --- */
#define DP_SEAL_900 0xFF004858u
#define DP_SEAL_700 0xFF007898u
#define DP_SEAL_500 0xFF00A8CCu /* 标准强调:按钮、选中态 */
#define DP_SEAL_300 0xFF44CCF0u /* 高亮强调:焦点环 */
#define DP_SEAL_100 0xFF99E8FFu /* 亮强调:发光边缘 */
/* --- 辅助色:弧光紫 (Arc Violet) — 次级/装饰 --- */
#define DP_ARC_900 0xFF2A1040u
#define DP_ARC_700 0xFF5A2080u
#define DP_ARC_500 0xFF8844CCu /* 装饰强调:渐变终点、图标 */
#define DP_ARC_300 0xFFB888E8u
#define DP_ARC_100 0xFFE0C8F8u
/* --- 中性色 (Neutral) --- */
#define DP_NEUTRAL_0 0xFF000000u /* 纯黑 */
#define DP_NEUTRAL_50 0xFF181820u /* 接近黑 */
#define DP_NEUTRAL_100 0xFF2A2A38u /* 暗灰 */
#define DP_NEUTRAL_200 0xFF484860u /* 中暗灰 */
#define DP_NEUTRAL_300 0xFF6A6A88u /* 中灰 */
#define DP_NEUTRAL_400 0xFF9090A8u /* 中亮灰 */
#define DP_NEUTRAL_500 0xFFB0B0C0u /* 标准灰 */
#define DP_NEUTRAL_600 0xFFD0D0DCu /* 亮灰 */
#define DP_NEUTRAL_700 0xFFE8E8F0u /* 浅灰 */
#define DP_NEUTRAL_800 0xFFF0F0F8u /* 接近白 */
#define DP_NEUTRAL_900 0xFFFFFFFFu /* 纯白 */
/* --- 语义辅助色 --- */
#define DP_SUCCESS 0xFF40C880u /* 成功:绿色 */
#define DP_WARNING 0xFFF0A030u /* 警告:琥珀色 */
#define DP_ERROR 0xFFFF4466u /* 错误:红色 */
#define DP_INFO 0xFF4499FFu /* 信息:蓝色 */
/* --- 渐变色 — DSK 加载器 / FirstInit 背景专用 --- */
#define DP_GRAD_TOP 0xFFC8E0F0u /* 淡蓝顶 */
#define DP_GRAD_MID 0xFF8888B0u /* 紫灰中 */
#define DP_GRAD_BOT 0xFF49306Fu /* 深紫底 */
/* --- 欢迎页专用 --- */
#define DP_WELCOME_FG 0xFFE8F2FCu /* 近白浅蓝(欢迎文字) */
/* ===================================================================
* L1 — 语义色值 (Semantic Colors)
*
* 暗色主题(Dark Theme)— Shell / 终端
* 亮色主题(Light Theme)— FirstInit / DSK
* =================================================================== */
/* --- 暗色主题 --- */
#define DS_DARK_BG_PRIMARY DP_ABYSS_900 /* 主背景 */
#define DS_DARK_BG_SECONDARY DP_ABYSS_800 /* 卡片/面板背景 */
#define DS_DARK_BG_TERTIARY DP_ABYSS_700 /* 悬停/输入框 */
#define DS_DARK_BG_INSET DP_ABYSS_600 /* 凹陷区域 */
#define DS_DARK_TEXT_PRIMARY DP_NEUTRAL_700 /* 主文字 */
#define DS_DARK_TEXT_SECONDARY DP_NEUTRAL_500 /* 次级文字 */
#define DS_DARK_TEXT_DIM DP_NEUTRAL_300 /* 注释/禁用 */
#define DS_DARK_TEXT_INVERT DP_ABYSS_900 /* 反色文字(亮背景上) */
#define DS_DARK_ACCENT DP_SEAL_500 /* 主强调 */
#define DS_DARK_ACCENT_LIGHT DP_SEAL_300 /* 高亮强调 */
#define DS_DARK_ACCENT_GLOW DP_SEAL_100 /* 发光 */
#define DS_DARK_DECORATIVE DP_ARC_500 /* 装饰色 */
#define DS_DARK_DECORATIVE_L DP_ARC_300 /* 浅装饰 */
#define DS_DARK_BORDER DP_ABYSS_500 /* 边框 */
#define DS_DARK_BORDER_FOCUS DP_SEAL_300 /* 焦点边框 */
#define DS_DARK_DIVIDER DP_ABYSS_600 /* 分隔线 */
#define DS_DARK_CURSOR DP_SEAL_500 /* 光标 */
#define DS_DARK_PROMPT DP_SEAL_300 /* 提示符 */
#define DS_DARK_SELECTION_BG DP_SEAL_900 /* 选中背景 */
/* --- 亮色主题 --- */
#define DS_LIGHT_BG_PRIMARY DP_NEUTRAL_900 /* 主背景(白) */
#define DS_LIGHT_BG_SECONDARY DP_NEUTRAL_700 /* 卡片背景 */
#define DS_LIGHT_BG_TERTIARY DP_NEUTRAL_600 /* 悬停 */
#define DS_LIGHT_BG_INSET DP_NEUTRAL_500 /* 输入框 */
#define DS_LIGHT_TEXT_PRIMARY DP_ABYSS_900 /* 主文字 */
#define DS_LIGHT_TEXT_SECONDARY DP_ABYSS_500 /* 次级 */
#define DS_LIGHT_TEXT_DIM DP_NEUTRAL_300 /* 注释 */
#define DS_LIGHT_TEXT_INVERT DP_NEUTRAL_900 /* 反色 */
#define DS_LIGHT_ACCENT DP_SEAL_700 /* 主强调(亮色上更深) */
#define DS_LIGHT_ACCENT_LIGHT DP_SEAL_500
#define DS_LIGHT_DECORATIVE DP_ARC_700
#define DS_LIGHT_BORDER DP_NEUTRAL_400
#define DS_LIGHT_BORDER_FOCUS DP_SEAL_500
/* ===================================================================
* 排版规范 (Typography)
* =================================================================== */
/* 字体尺寸族 */
#define DU_FONT_SIZE_XS 10u /* 辅助标注 */
#define DU_FONT_SIZE_SM 14u /* 次要说明 */
#define DU_FONT_SIZE_MD 18u /* 正文(Consolas 18px) */
#define DU_FONT_SIZE_LG 24u /* 小标题 */
#define DU_FONT_SIZE_XL 32u /* 标题 */
#define DU_FONT_SIZE_2XL 48u /* 大标题 / 欢迎文字 */
/* ASCII 位图字体参数(与 ascii_bitmaps.c 对应) */
#define DU_ASCII_CELL_W 11u
#define DU_ASCII_CELL_H 18u
#define DU_ASCII_STEP 12u /* 字符间距(含 1px gap) */
#define DU_ASCII_LINE_H 20u /* 行高(含 2px 行间距) */
/* ===================================================================
* 间距体系 (Spacing)
* =================================================================== */
#define DU_SPACE_XXS 2u
#define DU_SPACE_XS 4u
#define DU_SPACE_SM 8u
#define DU_SPACE_MD 16u
#define DU_SPACE_LG 24u
#define DU_SPACE_XL 32u
#define DU_SPACE_2XL 48u
#define DU_SPACE_3XL 64u
/* ===================================================================
* 圆角体系 (Border Radius) — "Sealed Arc" 签名元素
* =================================================================== */
#define DU_RADIUS_NONE 0u
#define DU_RADIUS_SM 4u /* 小按钮、标签 */
#define DU_RADIUS_MD 8u /* 卡片、输入框 */
#define DU_RADIUS_LG 12u /* 大卡片、面板 */
#define DU_RADIUS_XL 16u /* 模态框 */
#define DU_RADIUS_FULL 9999u /* 完全圆角(药丸形) */
/* ===================================================================
* 边框体系 (Border)
* =================================================================== */
#define DU_BORDER_THIN 1u
#define DU_BORDER_STD 2u
#define DU_BORDER_THICK 3u
/* ===================================================================
* 动画参数 (Animation)
* =================================================================== */
/* 帧延迟(busy-wait 循环次数 ≈ 毫秒级,需根据 CPU 速度校准) */
#define DU_ANIM_DELAY_SLOW 200000u /* 慢速过渡 */
#define DU_ANIM_DELAY_NORMAL 100000u /* 标准动画 */
#define DU_ANIM_DELAY_FAST 40000u /* 快速反馈 */
/* 弧线动画参数(DSK spinner 专用 — Sealed Arc Comet 设计) */
#define DU_SPINNER_RADIUS 48u
#define DU_SPINNER_THICKNESS 5u
#define DU_SPINNER_HEAD_WIDTH 40u /* 弧头宽度(度) */
#define DU_SPINNER_TAIL_LEN 220u /* 拖尾长度(度) */
#define DU_SPINNER_SPEED 4u /* 每帧旋转度数 */
#define DU_SPINNER_SPRITE 128u /* 精灵缓冲边长 */
/* 渐变动画步进 */
#define DU_FADE_STEPS 32u /* 淡入/淡出步数 */
#define DU_FADE_STEP_DELAY 8000u /* 每步延迟 */
/* ===================================================================
* 组件尺寸 (Component Sizes)
* =================================================================== */
#define DU_BUTTON_HEIGHT 36u
#define DU_INPUT_HEIGHT 32u
#define DU_CARD_PADDING_X 24u
#define DU_CARD_PADDING_Y 16u
#define DU_CARD_MIN_WIDTH 200u
#define DU_CARD_MAX_WIDTH 480u
#define DU_CURSOR_SIZE 24u /* 鼠标光标边长 */
#define DU_NOTIFICATION_H 40u
/* ===================================================================
* 渲染上下文 (Render Context)
*
* 所有绘制函数通过此上下文访问 framebuffer,避免全局状态。
* =================================================================== */
typedef struct {
du_u32 *fb; /* framebuffer 基址 */
du_u64 width; /* 像素宽 */
du_u64 height; /* 像素高 */
du_u64 pitch; /* 字节行宽 */
} du_context;
/* 初始化渲染上下文 */
static inline void du_context_init(du_context *ctx, du_u64 fb_addr,
du_u64 w, du_u64 h, du_u64 pitch) {
ctx->fb = (du_u32 *)(du_u64)fb_addr;
ctx->width = w;
ctx->height = h;
ctx->pitch = pitch;
}
/* ===================================================================
* L2 — 绘制原语 (Rendering Primitives)
* =================================================================== */
/* 颜色混合:alpha 范围 0–255 */
static inline du_u32 du_blend(du_u32 bg, du_u32 fg, du_u32 alpha) {
du_u32 na = 256 - alpha;
du_u32 r = ((bg & 0xFF) * na + (fg & 0xFF) * alpha) >> 8;
du_u32 g = (((bg >> 8) & 0xFF) * na + ((fg >> 8) & 0xFF) * alpha) >> 8;
du_u32 b = (((bg >> 16) & 0xFF) * na + ((fg >> 16) & 0xFF) * alpha) >> 8;
return 0xFF000000u | (b << 16) | (g << 8) | r;
}
/* 线性插值两色 */
static inline du_u32 du_lerp_color(du_u32 c1, du_u32 c2, du_u32 t) {
return du_blend(c1, c2, t);
}
/* 渐变背景:顶色 → 底色,按 Y 坐标插值 */
static inline du_u32 du_gradient_v(du_u32 top_color, du_u32 bot_color,
du_i64 y, du_i64 total_h) {
if (total_h <= 1) return top_color;
if (y < 0) y = 0;
if (y >= total_h) y = total_h - 1;
du_u32 alpha = (du_u32)(((du_u64)y * 255ULL) / ((du_u64)total_h - 1));
return du_blend(top_color, bot_color, alpha);
}
/* 单像素写(带边界检查) */
static inline void du_pixel(du_context *ctx, du_i64 x, du_i64 y, du_u32 color) {
if (x < 0 || (du_u64)x >= ctx->width || y < 0 || (du_u64)y >= ctx->height) return;
((du_u32 *)((du_u8 *)ctx->fb + (du_u64)y * ctx->pitch))[(du_u64)x] = color;
}
/* 读取像素(带边界检查) */
static inline du_u32 du_pixel_read(du_context *ctx, du_i64 x, du_i64 y) {
if (x < 0 || (du_u64)x >= ctx->width || y < 0 || (du_u64)y >= ctx->height) return 0;
return ((du_u32 *)((du_u8 *)ctx->fb + (du_u64)y * ctx->pitch))[(du_u64)x];
}
/* 矩形填充 */
static inline void du_fill_rect(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h, du_u32 color) {
for (du_i64 r = 0; r < h; r++) {
du_i64 yy = y + r;
if (yy < 0 || (du_u64)yy >= ctx->height) continue;
du_u32 *line = (du_u32 *)((du_u8 *)ctx->fb + (du_u64)yy * ctx->pitch);
for (du_i64 c = 0; c < w; c++) {
du_i64 xx = x + c;
if (xx < 0 || (du_u64)xx >= ctx->width) continue;
line[(du_u64)xx] = color;
}
}
}
/* 渐变矩形填充(垂直渐变) */
static inline void du_fill_rect_gradient(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h,
du_u32 top_color, du_u32 bot_color) {
for (du_i64 r = 0; r < h; r++) {
du_i64 yy = y + r;
if (yy < 0 || (du_u64)yy >= ctx->height) continue;
du_u32 color = du_gradient_v(top_color, bot_color, r, h);
du_u32 *line = (du_u32 *)((du_u8 *)ctx->fb + (du_u64)yy * ctx->pitch);
for (du_i64 c = 0; c < w; c++) {
du_i64 xx = x + c;
if (xx < 0 || (du_u64)xx >= ctx->width) continue;
line[(du_u64)xx] = color;
}
}
}
/* 全屏渐变背景 */
static inline void du_fill_bg_gradient(du_context *ctx,
du_u32 top_color, du_u32 bot_color) {
du_fill_rect_gradient(ctx, 0, 0, (du_i64)ctx->width, (du_i64)ctx->height,
top_color, bot_color);
}
/* 全屏纯色背景 */
static inline void du_fill_bg_solid(du_context *ctx, du_u32 color) {
du_fill_rect(ctx, 0, 0, (du_i64)ctx->width, (du_i64)ctx->height, color);
}
/* ===================================================================
* 圆角矩形 (Rounded Rectangle) — "Sealed Arc" 核心形状
* =================================================================== */
/* 绘制圆角矩形边框(单像素宽) */
static inline void du_rect_outline(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h,
du_u32 color, du_u32 radius) {
/* 四个角的圆弧 + 四条直线 */
du_i64 r = (du_i64)radius;
if (r > w / 2) r = w / 2;
if (r > h / 2) r = h / 2;
/* 顶线 */
for (du_i64 c = r; c < w - r; c++) {
du_pixel(ctx, x + c, y, color);
}
/* 底线 */
for (du_i64 c = r; c < w - r; c++) {
du_pixel(ctx, x + c, y + h - 1, color);
}
/* 左线 */
for (du_i64 rr = r; rr < h - r; rr++) {
du_pixel(ctx, x, y + rr, color);
}
/* 右线 */
for (du_i64 rr = r; rr < h - r; rr++) {
du_pixel(ctx, x + w - 1, y + rr, color);
}
/* 四个圆角 */
for (du_i64 dy = 0; dy <= r; dy++) {
for (du_i64 dx = 0; dx <= r; dx++) {
du_i64 d2 = dx * dx + dy * dy;
if (d2 <= r * r && d2 > (r - 1) * (r - 1)) {
/* 左上 */
du_pixel(ctx, x + r - dx, y + r - dy, color);
/* 右上 */
du_pixel(ctx, x + w - 1 - r + dx, y + r - dy, color);
/* 左下 */
du_pixel(ctx, x + r - dx, y + h - 1 - r + dy, color);
/* 右下 */
du_pixel(ctx, x + w - 1 - r + dx, y + h - 1 - r + dy, color);
}
}
}
}
/* 填充圆角矩形 */
static inline void du_fill_rounded_rect(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h,
du_u32 color, du_u32 radius) {
du_i64 r = (du_i64)radius;
if (r > w / 2) r = w / 2;
if (r > h / 2) r = h / 2;
/* 中间区域(不含角) */
du_fill_rect(ctx, x + r, y, w - 2 * r, h, color);
/* 左侧矩形 */
du_fill_rect(ctx, x, y + r, r, h - 2 * r, color);
/* 右侧矩形 */
du_fill_rect(ctx, x + w - r, y + r, r, h - 2 * r, color);
/* 四个圆角填充 */
for (du_i64 dy = 0; dy < r; dy++) {
for (du_i64 dx = 0; dx < r; dx++) {
if (dx * dx + dy * dy <= r * r) {
/* 左上 */
du_pixel(ctx, x + r - 1 - dx, y + r - 1 - dy, color);
/* 右上 */
du_pixel(ctx, x + w - r + dx, y + r - 1 - dy, color);
/* 左下 */
du_pixel(ctx, x + r - 1 - dx, y + h - r + dy, color);
/* 右下 */
du_pixel(ctx, x + w - r + dx, y + h - r + dy, color);
}
}
}
}
/* 带发光效果的圆角矩形边框(模拟 UTSM 封缄发光) */
static inline void du_rect_glow(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h,
du_u32 glow_color, du_u32 radius,
du_i64 glow_width) {
/* 从外到内逐层降低透明度 */
for (du_i64 i = glow_width; i >= 1; i--) {
du_u32 alpha = (du_u32)(40 + (glow_width - i) * 50 / glow_width);
du_u32 color = du_blend(DP_ABYSS_900, glow_color, alpha);
du_rect_outline(ctx, x - i, y - i, w + 2 * i, h + 2 * i, color, radius + (du_u32)i);
}
/* 核心边框 */
du_rect_outline(ctx, x, y, w, h, glow_color, radius);
}
/* ===================================================================
* 分隔线 (Divider)
* =================================================================== */
static inline void du_divider_h(du_context *ctx, du_i64 x, du_i64 y,
du_i64 width, du_u32 color) {
du_fill_rect(ctx, x, y, width, 1, color);
}
static inline void du_divider_v(du_context *ctx, du_i64 x, du_i64 y,
du_i64 height, du_u32 color) {
du_fill_rect(ctx, x, y, 1, height, color);
}
/* ===================================================================
* ASCII 字符渲染(需要外部提供 g_ascii 位图数组)
*
* 使用方法:包含 ascii_bitmaps.c 后调用 du_draw_char / du_draw_string
* =================================================================== */
/* ASCII 位图数组 — 由 ascii_bitmaps.c 定义(static),在包含该 .c 的编译单元内可见 */
/* 渲染单个 ASCII 字符(灰度位图 + 前景色 alpha 混合) */
static inline void du_draw_char(du_context *ctx, char ch,
du_i64 x, du_i64 y,
du_u32 fg, du_u32 bg) {
du_u32 idx = (du_u32)(ch - ' ');
if (idx > 94) idx = 0;
const du_u8 *glyph = g_ascii[idx];
du_i64 gw = g_ascii_w;
du_i64 gh = g_ascii_h;
for (du_i64 r = 0; r < gh; r++) {
du_i64 yy = y + r;
if (yy < 0 || (du_u64)yy >= ctx->height) continue;
du_u32 *line = (du_u32 *)((du_u8 *)ctx->fb + (du_u64)yy * ctx->pitch);
for (du_i64 c = 0; c < gw; c++) {
du_u8 a = glyph[r * gw + c];
if (a == 0) continue;
du_i64 xx = x + c;
if (xx < 0 || (du_u64)xx >= ctx->width) continue;
line[(du_u64)xx] = (a == 255) ? fg : du_blend(bg, fg, a);
}
}
}
/* 渲染字符串(不换行,无自动折行) */
static inline void du_draw_string(du_context *ctx, const char *s,
du_i64 x, du_i64 y,
du_u32 fg, du_u32 bg,
du_u32 step) {
du_i64 cx = x;
while (*s) {
du_draw_char(ctx, *s, cx, y, fg, bg);
cx += (du_i64)step;
s++;
}
}
/* ===================================================================
* 组件令牌 — 按钮 (Button)
* =================================================================== */
typedef struct {
du_u32 bg_normal; /* 正常背景 */
du_u32 bg_hover; /* 悬停背景 */
du_u32 bg_active; /* 按下背景 */
du_u32 fg; /* 文字色 */
du_u32 border; /* 边框色 */
du_u32 border_focus; /* 焦点边框色 */
du_u32 radius; /* 圆角半径 */
du_u32 height; /* 高度 */
du_u32 padding_x; /* 水平内边距 */
} du_button_style;
/* 暗色主题按钮样式 */
#define DU_BTN_DARK_PRIMARY { \
DS_DARK_ACCENT, DS_DARK_ACCENT_LIGHT, DP_SEAL_700, \
DP_NEUTRAL_900, DP_SEAL_300, DP_SEAL_100, \
DU_RADIUS_MD, DU_BUTTON_HEIGHT, DU_SPACE_LG \
}
#define DU_BTN_DARK_SECONDARY { \
DS_DARK_BG_TERTIARY, DS_DARK_BG_INSET, DS_DARK_BG_INSET, \
DS_DARK_TEXT_PRIMARY, DS_DARK_BORDER, DS_DARK_BORDER_FOCUS, \
DU_RADIUS_MD, DU_BUTTON_HEIGHT, DU_SPACE_LG \
}
/* ===================================================================
* 组件令牌 — 卡片 (Card)
* =================================================================== */
typedef struct {
du_u32 bg; /* 卡片背景 */
du_u32 border; /* 边框色 */
du_u32 border_focus; /* 焦点边框色 */
du_u32 shadow_color; /* 阴影色 */
du_u32 radius; /* 圆角半径 */
du_u32 padding_x; /* 水平内边距 */
du_u32 padding_y; /* 垂直内边距 */
du_u32 border_width; /* 边框宽度 */
} du_card_style;
#define DU_CARD_DARK { \
DS_DARK_BG_SECONDARY, DS_DARK_BORDER, DS_DARK_BORDER_FOCUS, \
DP_ABYSS_900, DU_RADIUS_LG, DU_CARD_PADDING_X, DU_CARD_PADDING_Y, DU_BORDER_STD \
}
#define DU_CARD_LIGHT { \
DS_LIGHT_BG_SECONDARY, DS_LIGHT_BORDER, DS_LIGHT_BORDER_FOCUS, \
DP_NEUTRAL_300, DU_RADIUS_LG, DU_CARD_PADDING_X, DU_CARD_PADDING_Y, DU_BORDER_STD \
}
/* ===================================================================
* 组件令牌 — 输入框 (Input)
* =================================================================== */
typedef struct {
du_u32 bg;
du_u32 bg_focus;
du_u32 fg;
du_u32 placeholder;
du_u32 border;
du_u32 border_focus;
du_u32 cursor;
du_u32 radius;
du_u32 height;
} du_input_style;
#define DU_INPUT_DARK { \
DS_DARK_BG_INSET, DS_DARK_BG_TERTIARY, DS_DARK_TEXT_PRIMARY, \
DS_DARK_TEXT_DIM, DS_DARK_BORDER, DS_DARK_BORDER_FOCUS, \
DS_DARK_CURSOR, DU_RADIUS_MD, DU_INPUT_HEIGHT \
}
/* ===================================================================
* 组件令牌 — 通知栏 (Notification)
* =================================================================== */
typedef enum {
DU_NOTIFY_INFO,
DU_NOTIFY_SUCCESS,
DU_NOTIFY_WARNING,
DU_NOTIFY_ERROR
} du_notify_type;
static inline du_u32 du_notify_color(du_notify_type type) {
switch (type) {
case DU_NOTIFY_SUCCESS: return DP_SUCCESS;
case DU_NOTIFY_WARNING: return DP_WARNING;
case DU_NOTIFY_ERROR: return DP_ERROR;
default: return DP_INFO;
}
}
/* ===================================================================
* 组件绘制函数 (Component Drawing)
* =================================================================== */
/* 绘制按钮 */
static inline void du_draw_button(du_context *ctx,
du_i64 x, du_i64 y, du_i64 w,
const du_button_style *style,
const char *label, int focused) {
du_u32 bg = style->bg_normal;
du_u32 border = style->border;
if (focused) {
border = style->border_focus;
}
/* 填充圆角矩形背景 */
du_fill_rounded_rect(ctx, x, y, w, (du_i64)style->height, bg, style->radius);
/* 边框 */
du_rect_outline(ctx, x, y, w, (du_i64)style->height, border, style->radius);
/* 文字居中 */
du_i64 label_len = 0;
while (label[label_len]) label_len++;
du_i64 text_w = label_len * (du_i64)DU_ASCII_STEP;
du_i64 text_x = x + (w - text_w) / 2;
du_i64 text_y = y + ((du_i64)style->height - (du_i64)DU_ASCII_CELL_H) / 2;
du_draw_string(ctx, label, text_x, text_y, style->fg, bg, DU_ASCII_STEP);
}
/* 绘制卡片 */
static inline void du_draw_card(du_context *ctx,
du_i64 x, du_i64 y, du_i64 w, du_i64 h,
const du_card_style *style, int focused) {
du_u32 border = style->border;
if (focused) {
border = style->border_focus;
/* 焦点发光效果 */
du_rect_glow(ctx, x - 2, y - 2, w + 4, h + 4,
border, style->radius + 2, 3);
}
du_fill_rounded_rect(ctx, x, y, w, h, style->bg, style->radius);
du_rect_outline(ctx, x, y, w, h, border, style->radius);
}
/* 绘制输入框 */
static inline void du_draw_input(du_context *ctx,
du_i64 x, du_i64 y, du_i64 w,
const du_input_style *style,
const char *text, int cursor_pos,
int focused) {
du_u32 bg = focused ? style->bg_focus : style->bg;
du_u32 border = focused ? style->border_focus : style->border;
du_fill_rounded_rect(ctx, x, y, w, (du_i64)style->height, bg, style->radius);
du_rect_outline(ctx, x, y, w, (du_i64)style->height, border, style->radius);
/* 文字 */
du_i64 text_x = x + (du_i64)DU_SPACE_SM;
du_i64 text_y = y + ((du_i64)style->height - (du_i64)DU_ASCII_CELL_H) / 2;
du_u32 fg = text[0] ? style->fg : style->placeholder;
du_draw_string(ctx, text, text_x, text_y, fg, bg, DU_ASCII_STEP);
/* 光标 */
if (focused && cursor_pos >= 0) {
du_i64 cx = text_x + (du_i64)cursor_pos * (du_i64)DU_ASCII_STEP;
du_fill_rect(ctx, cx, text_y, 2, (du_i64)DU_ASCII_CELL_H, style->cursor);
}
}
/* 绘制通知栏 */
static inline void du_draw_notification(du_context *ctx,
du_i64 x, du_i64 y, du_i64 w,
du_notify_type type,
const char *message) {
du_u32 accent = du_notify_color(type);
/* 半透明背景 */
du_fill_rounded_rect(ctx, x, y, w, (du_i64)DU_NOTIFICATION_H,
DP_ABYSS_800, DU_RADIUS_MD);
/* 左侧色条 */
du_fill_rect(ctx, x, y + 4, 4, (du_i64)DU_NOTIFICATION_H - 8, accent);
/* 文字 */
du_i64 text_y = y + ((du_i64)DU_NOTIFICATION_H - (du_i64)DU_ASCII_CELL_H) / 2;
du_draw_string(ctx, message, x + (du_i64)DU_SPACE_MD, text_y,
DS_DARK_TEXT_PRIMARY, DP_ABYSS_800, DU_ASCII_STEP);
}
/* 绘制进度条 */
static inline void du_draw_progress(du_context *ctx,
du_i64 x, du_i64 y, du_i64 w, du_i64 h,
du_u32 progress_0_255) {
/* 背景 */
du_fill_rounded_rect(ctx, x, y, w, h, DP_ABYSS_700, DU_RADIUS_FULL);
/* 填充 */
du_i64 fill_w = (w * (du_i64)progress_0_255) / 255;
if (fill_w > 0) {
du_fill_rounded_rect(ctx, x, y, fill_w, h, DP_SEAL_500, DU_RADIUS_FULL);
}
}
/* ===================================================================
* Spinner(加载弧) — DSK 启动加载动画
*
* 使用 "Sealed Arc Comet" 单弧彗星尾设计:
* 一个明亮的弧头 + 渐变拖尾,颜色从弧头色过渡到拖尾色。
* =================================================================== */
/* 默认弧色:[0]=弧头色(亮蓝), [1]=拖尾色(紫) */
#define DU_SPINNER_ARCS { \
DP_SEAL_300, DP_SEAL_700, DP_SEAL_500, DP_SEAL_100 \
}
/* ===================================================================
* 主题切换辅助 (Theme Switch)
* =================================================================== */
typedef enum {
DU_THEME_DARK,
DU_THEME_LIGHT
} du_theme;
/* 根据主题获取对应的背景色 */
static inline du_u32 du_theme_bg(du_theme t) {
return (t == DU_THEME_DARK) ? DS_DARK_BG_PRIMARY : DS_LIGHT_BG_PRIMARY;
}
/* 根据主题获取对应的文字色 */
static inline du_u32 du_theme_text(du_theme t) {
return (t == DU_THEME_DARK) ? DS_DARK_TEXT_PRIMARY : DS_LIGHT_TEXT_PRIMARY;
}
/* 根据主题获取对应的强调色 */
static inline du_u32 du_theme_accent(du_theme t) {
return (t == DU_THEME_DARK) ? DS_DARK_ACCENT : DS_LIGHT_ACCENT;
}
#endif /* DESHAB_UI_H */
+20
View File
@@ -0,0 +1,20 @@
#ifndef UTSM_DIRTY_H
#define UTSM_DIRTY_H
#include <utsm/types.h>
typedef struct {
u32 dirty_count;
u32 shard_id;
u64 page_base;
u64 page_count;
u64 last_checkpoint_epoch;
u64 *bitmap;
} utsm_dirty_shard;
struct utsm_segment_desc;
void utsm_dirty_init(struct utsm_segment_desc *desc, u64 page_count);
void utsm_mark_dirty(struct utsm_segment_desc *desc, u64 offset, u64 len);
#endif
+141
View File
@@ -0,0 +1,141 @@
#ifndef UTSM_DKM_H
#define UTSM_DKM_H
#include <utsm/types.h>
#include <utsm/dma.h>
#include <utsm/block.h>
#include <utsm/net.h>
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
#define DKM_KERNEL_API_VERSION 1u
#define DKM_CLASS_PLATFORM 1u
#define DKM_CLASS_BUS 2u
#define DKM_CLASS_INTERRUPT 3u
#define DKM_CLASS_TIMER 4u
#define DKM_CLASS_CONSOLE 5u
#define DKM_CLASS_STORAGE 6u
#define DKM_CLASS_FS 7u
#define DKM_CLASS_NET 8u
#define DKM_CLASS_INPUT 9u
#define DKM_CLASS_GPU 10u
#define DKM_CLASS_MISC 11u
#define DKM_F_REQUIRED (1u << 0)
#define DKM_F_BOOT_MODULE (1u << 1)
#define DKM_F_NO_UNLOAD (1u << 2)
#define DKM_F_STRONG_RECOVERY (1u << 3)
#define DKM_F_DMA_REQUIRED (1u << 4)
#define DKM_F_EARLY_LOG (1u << 5)
struct dkm_kernel_api;
struct dkm_driver_handle;
typedef struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
} dkm_driver_desc;
typedef int (*dkm_driver_init_fn)(const struct dkm_kernel_api *api, struct dkm_driver_handle *handle);
typedef int (*dkm_driver_exit_fn)(struct dkm_driver_handle *handle);
typedef struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
} dkm_log_api;
typedef struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci;
const dkm_dma_api *dma;
const void *vfs;
const dkm_net_api *net;
const void *timer;
const void *drr;
const void *rsdp_address; /* ACPI RSDP physical address */
const void *fb_address; /* framebuffer base */
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response; /* limine_module_response* */
int (*irq_register)(u8 irq, void *handler); /* kernel irq_register */
u64 hhdm_offset; /* physical → virtual */
const dkm_block_api *block; /* block provider registry */
} dkm_kernel_api;
typedef enum dkm_driver_state {
DKM_STATE_DISCOVERED = 0,
DKM_STATE_ABI_CHECKED,
DKM_STATE_INITING,
DKM_STATE_ACTIVE,
DKM_STATE_FAILED
} dkm_driver_state;
typedef struct dkm_driver_handle {
const dkm_driver_desc *desc;
dkm_driver_state state;
i32 init_status;
u32 load_stage;
u32 flags;
} dkm_driver_handle;
typedef struct dkm_builtin_driver {
const dkm_driver_desc *desc;
dkm_driver_init_fn init;
dkm_driver_exit_fn exit;
} dkm_builtin_driver;
void dkm_init(void);
int dkm_load_builtin(const dkm_builtin_driver *driver);
void dkm_scan_boot_modules(void);
void dsm_load_by_manifest(void);
void dkm_fill_platform_info(void);
const dkm_kernel_api *dkm_get_kernel_api(void);
/* exposed for manifest parser */
struct dkm_symbol_scan {
const void *driver_desc;
const void *driver_init;
const void *driver_exit;
};
int dkm_check_elf64(const void *address, u64 size);
int dkm_scan_symbols(const void *address, u64 size, struct dkm_symbol_scan *out);
int dkm_load_elf_rel(const void *address, u64 size, const struct dkm_symbol_scan *symbols);
extern const dkm_builtin_driver dkm_builtin_console_early;
#endif
+20
View File
@@ -0,0 +1,20 @@
#ifndef UTSM_DMA_H
#define UTSM_DMA_H
#include <utsm/types.h>
typedef struct dkm_dma_buffer {
void *virt;
u64 phys;
u64 size;
} dkm_dma_buffer;
typedef struct dkm_dma_api {
int (*alloc_pages)(u64 page_count, u64 alignment, u64 max_phys, dkm_dma_buffer *out);
} dkm_dma_api;
void dma_init(void);
int dma_alloc_pages(u64 page_count, u64 alignment, u64 max_phys, dkm_dma_buffer *out);
const dkm_dma_api *dma_get_api(void);
#endif
+26
View File
@@ -0,0 +1,26 @@
#ifndef UTSM_DMP_H
#define UTSM_DMP_H
#include <utsm/types.h>
typedef struct {
u64 magic;
u32 version;
u32 segment_slot;
u64 fast_base;
u64 fast_limit;
u64 fast_tweak_seed;
u64 fast_key_epoch;
u64 dirty_bitmap_base;
u64 mac_table_base;
u64 last_writer_seq;
u32 last_cpu;
u32 flags;
u64 crc;
} utsm_dmp;
struct utsm_segment_desc;
void utsm_dmp_init(utsm_dmp *dmp, struct utsm_segment_desc *desc, u32 slot);
#endif
+127
View File
@@ -0,0 +1,127 @@
#ifndef UTSM_DRR_H
#define UTSM_DRR_H
#include <utsm/types.h>
#include <utsm/config.h>
/* ===================================================================
* DRR — Dedicated Recovery Root
*
* 专用恢复根,独立于普通调度器和堆分配器。
* 负责:root key、recovery log、checkpoint A/B、Emergency Pool。
*
* 约束:
* - DRR recovery 路径禁止依赖普通堆分配器
* - 普通 OOM 不影响 DRR recovery
* - Emergency Pool 耗尽时进入 system rollback
* =================================================================== */
/* ---- Checkpoint 类型 ---- */
typedef enum {
DRR_CKPT_LIGHT = 0, /* 控制面快照 */
DRR_CKPT_DIRTY_PAGE, /* dirty ciphertext page 快照 */
DRR_CKPT_BOOT /* 启动状态 + A/B slot */
} drr_checkpoint_type;
/* ---- Recovery Log 条目 ---- */
typedef struct {
u32 segment_slot;
u32 flags; /* 0=intent, 1=commit */
u64 offset;
u64 length;
u64 timestamp; /* writer_seq snapshot */
} drr_log_entry;
#define DRR_LOG_FLAG_INTENT 0u
#define DRR_LOG_FLAG_COMMIT 1u
/* ---- Checkpoint Metadata Slot ---- */
typedef struct {
u64 magic; /* DRR_CKPT_MAGIC */
u32 version;
u32 active; /* 0=inactive, 1=active */
drr_checkpoint_type type;
u64 global_epoch;
u64 dirty_page_count;
u64 mac_root; /* MAC root hash of all sealed pages */
u64 segment_count;
u64 crc; /* CRC64 of the above */
} drr_checkpoint_meta;
#define DRR_CKPT_MAGIC 0x445252434B505421ULL /* "DRRCKPT!" */
#define DRR_CKPT_VERSION 1u
/* ---- Emergency Pool ---- */
#define DRR_EMERGENCY_POOL_SIZE (64ULL * 1024ULL) /* 64KB 独立池 */
#define DRR_EMERGENCY_STACK_SIZE 4096ULL
#define DRR_RECOVERY_LOG_SIZE 4096ULL
#define DRR_CKPT_META_BUF_SIZE 4096ULL
#define DRR_CRASH_BUF_SIZE 2048ULL
#define DRR_META_SLAB_SIZE 2048ULL
#define DRR_EMERGENCY_PAGES 4
typedef struct {
u8 pool[DRR_EMERGENCY_POOL_SIZE] __attribute__((aligned(64)));
u64 pool_offset;
u64 pool_limit;
/* 子缓冲区指针(pool 内偏移分配) */
u8 *stack_base;
u64 stack_size;
u64 stack_ptr;
drr_log_entry *log_base;
u32 log_count;
u32 log_capacity;
drr_checkpoint_meta *ckpt_meta_buf;
u8 *crash_buf;
u64 crash_buf_size;
void *meta_slab;
u64 meta_slab_offset;
/* A/B checkpoint slots */
drr_checkpoint_meta ckpt_a;
drr_checkpoint_meta ckpt_b;
u32 active_slot; /* 0=A, 1=B */
/* Root key */
const u64 *root_key;
/* Recovery generation */
u64 recovery_generation;
/* Heartbeat */
u64 heartbeat_counter;
u64 heartbeat_interval;
/* 初始化标记 */
int initialized;
} drr_state;
/* ---- 公共接口 ---- */
void drr_init(void);
const u64 *drr_get_root_key(void);
u64 drr_recovery_generation(void);
void drr_report_fault(const char *reason);
void drr_log_write_intent(u32 segment_slot, u64 offset, u64 len);
void drr_log_write_commit(u32 segment_slot, u64 offset, u64 len);
/* Checkpoint 操作 */
int drr_checkpoint_begin(drr_checkpoint_type type);
int drr_checkpoint_finish(void);
int drr_checkpoint_recover(drr_checkpoint_meta *out_meta);
/* Emergency Pool 分配 */
void *drr_emergency_alloc(u64 size, u64 alignment);
void drr_emergency_reset(void);
/* Heartbeat */
void drr_heartbeat_tick(void);
u64 drr_heartbeat_get(void);
/* CRC64 */
u64 drr_crc64(const void *data, u64 len);
#endif /* UTSM_DRR_H */
+51
View File
@@ -0,0 +1,51 @@
#ifndef UTSM_DSK_H
#define UTSM_DSK_H
#include <utsm/types.h>
#define DSK_BOOT_MAGIC 0x44534B31424F4F54ULL /* "DSK1BOOT" */
#define DSK_BOOT_ABI_VERSION 1u
#define DSK_BOOT_FLAG_FROM_UTSM (1ULL << 0)
#define DSK_BOOT_FLAG_DKM_READY (1ULL << 1)
#define DSK_BOOT_FLAG_FAT32_PATH (1ULL << 2)
typedef struct dsk_boot_context {
u64 magic;
u32 abi_version;
u32 size;
u64 flags;
u64 hhdm_offset;
u64 rsdp_address;
u64 framebuffer_address;
u64 framebuffer_width;
u64 framebuffer_height;
u64 framebuffer_pitch;
u32 framebuffer_bpp;
u32 reserved_fb;
u64 boot_modules_response;
u64 dkm_kernel_api;
u64 dkm_driver_table;
u64 dkm_driver_count;
u64 utsm_state;
u64 drr_state;
u64 memory_map;
u64 memory_map_count;
u64 memory_map_entry_size;
u64 kernel_stack_top;
u64 reserved[8];
} dsk_boot_context;
typedef void (*dsk_entry_fn)(const dsk_boot_context *context);
int dsk_load_and_jump(void);
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef UTSM_IDT_H
#define UTSM_IDT_H
#include <utsm/types.h>
void idt_init(void);
/* IRQ handler: return 1 to suppress default ACK, 0 for normal EOI */
typedef int (*irq_handler_t)(u8 irq);
int irq_register(u8 irq, irq_handler_t handler);
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef UTSM_LOG_H
#define UTSM_LOG_H
#include <utsm/types.h>
void serial_init(void);
void serial_putc(char c);
void serial_write(const char *s);
void log_info(const char *msg);
void log_warn(const char *msg);
void log_error(const char *msg);
void log_hex64(const char *prefix, u64 value);
void panic(const char *msg);
#endif
+77
View File
@@ -0,0 +1,77 @@
#ifndef UTSM_NET_H
#define UTSM_NET_H
#include <utsm/types.h>
#define DKM_NET_MAX_DEVICES 8u
#define DKM_NET_MAX_SCAN_RESULTS 32u
#define DKM_NET_SSID_MAX 32u
/* 网卡链路/能力标志。 */
#define DKM_NET_F_LINK_UP (1u << 0)
#define DKM_NET_F_TX_READY (1u << 1)
#define DKM_NET_F_RX_READY (1u << 2)
#define DKM_NET_F_WIRELESS (1u << 3)
/* WiFi 扫描结果加密类型。 */
#define DKM_NET_SEC_OPEN 0u
#define DKM_NET_SEC_WEP 1u
#define DKM_NET_SEC_WPA 2u
#define DKM_NET_SEC_WPA2 3u
#define DKM_NET_SEC_WPA3 4u
typedef int (*dkm_net_tx_fn)(void *ctx, const void *packet, u32 length);
typedef int (*dkm_net_rx_poll_fn)(void *ctx, void *buffer, u32 capacity, u32 *out_length);
/* WiFi 扫描结果(须先于回调 typedef 定义)。 */
typedef struct dkm_net_scan_result {
char ssid[DKM_NET_SSID_MAX + 1];
u8 bssid[6];
u8 channel;
i8 rssi; /* dBm,负值 */
u8 security; /* DKM_NET_SEC_* */
} dkm_net_scan_result;
/* 无线扫描回调(无线驱动填,有线驱动置 NULL)。 */
typedef int (*dkm_net_scan_start_fn)(void *ctx);
typedef int (*dkm_net_scan_count_fn)(void *ctx);
typedef int (*dkm_net_scan_result_fn)(void *ctx, u32 n, dkm_net_scan_result *out);
typedef int (*dkm_net_is_wireless_fn)(void *ctx);
typedef struct dkm_net_device_desc {
const char *name;
u8 mac[6];
u32 flags;
void *ctx;
dkm_net_tx_fn tx;
dkm_net_rx_poll_fn rx_poll;
/* 无线扩展回调(无线驱动填,有线驱动置 NULL,向后兼容)。 */
dkm_net_scan_start_fn scan_start;
dkm_net_scan_count_fn scan_count;
dkm_net_scan_result_fn scan_result;
dkm_net_is_wireless_fn is_wireless;
} dkm_net_device_desc;
typedef struct dkm_net_device_info {
const char *name;
u8 mac[6];
u32 flags;
} dkm_net_device_info;
typedef struct dkm_net_api {
int (*register_device)(const dkm_net_device_desc *desc);
u32 (*device_count)(void);
int (*device_info)(u32 index, dkm_net_device_info *out);
int (*tx)(u32 index, const void *packet, u32 length);
int (*rx_poll)(u32 index, void *buffer, u32 capacity, u32 *out_length);
/* 无线扫描接口(dispatch 到驱动回调,有线设备返回 -3 表示不支持)。 */
int (*scan_start)(u32 index);
int (*scan_count)(u32 index);
int (*scan_result)(u32 index, u32 n, dkm_net_scan_result *out);
int (*is_wireless)(u32 index);
} dkm_net_api;
void net_init(void);
const dkm_net_api *net_get_api(void);
#endif
+29
View File
@@ -0,0 +1,29 @@
#ifndef UTSM_PCKC_H
#define UTSM_PCKC_H
#include <utsm/types.h>
#include <utsm/config.h>
#include <utsm/uuid.h>
#include <utsm/crypto.h>
struct utsm_segment_desc;
typedef struct {
bool valid;
u32 segment_slot;
u64 key_epoch;
utsm_key_material key;
} utsm_pckc_entry;
typedef struct {
uuid128_t current_process_uuid;
utsm_pckc_entry entries[UTSM_MAX_PCKC_KEYS];
u64 hit_count;
u64 miss_count;
u32 next_replace;
} utsm_pckc;
void utsm_pckc_init(void);
int utsm_pckc_get_or_derive(u32 segment_slot, struct utsm_segment_desc *desc, utsm_key_material *out_key);
#endif
+79
View File
@@ -0,0 +1,79 @@
#ifndef UTSM_PROCESS_H
#define UTSM_PROCESS_H
#include <utsm/types.h>
#include <utsm/uuid.h>
#include <utsm/capability.h>
#include <utsm/config.h>
/* ---- 进程标志 ---- */
#define UTSM_PROC_F_BOOTSTRAP (1U << 0) /* 内核 bootstrap 进程 */
#define UTSM_PROC_F_KERNEL (1U << 1) /* 内核态进程 */
#define UTSM_PROC_F_ENCRYPTED (1U << 2) /* 加密堆栈/堆 */
/* ---- 进程状态 ---- */
typedef enum {
UTSM_PROC_UNUSED = 0,
UTSM_PROC_ACTIVE,
UTSM_PROC_BLOCKED,
UTSM_PROC_TERMINATED
} utsm_process_state;
/* ---- Capability Table(每进程) ---- */
typedef struct {
utsm_capability caps[UTSM_MAX_CAPABILITIES];
u32 count;
u32 generation; /* 表版本号 */
} utsm_cap_table;
/* ---- Crypto Context(每进程) ---- */
typedef struct {
u64 crypto_epoch; /* 当前加密纪元 */
u64 key_derivation_seed; /* 密钥派生种子 */
u32 pckc_hot_hint; /* PCKC 热段提示 */
u32 reserved;
} utsm_crypto_context;
/* ---- 进程上下文 ---- */
typedef struct utsm_process_context {
uuid128_t process_uuid;
u64 crypto_epoch;
u64 recovery_generation;
u32 process_slot; /* 进程表索引 */
u32 capability_count;
u32 flags;
utsm_process_state state;
/* Capability Table */
utsm_cap_table cap_table;
/* Crypto Context */
utsm_crypto_context crypto_ctx;
/* PCKC 热段提示 */
u32 hot_segment_slot;
u32 reserved;
/* DRR recovery generation */
u64 drr_recovery_gen;
} utsm_process_context;
/* ---- 进程表 ---- */
#define UTSM_MAX_PROCESSES 64
/* ---- 公共接口 ---- */
void utsm_process_init(void);
void utsm_process_create_test(utsm_process_context *process, u64 seed);
utsm_process_context *utsm_process_alloc(void);
void utsm_process_free(utsm_process_context *process);
utsm_process_context *utsm_process_get(u32 slot);
/* Capability 操作 */
int utsm_process_grant_cap(utsm_process_context *process, utsm_capability cap);
int utsm_process_revoke_cap(utsm_process_context *process, u32 cap_index);
utsm_capability *utsm_process_get_cap(utsm_process_context *process, u32 cap_index);
/* Crypto context 操作 */
void utsm_process_advance_epoch(utsm_process_context *process);
#endif /* UTSM_PROCESS_H */
+50
View File
@@ -0,0 +1,50 @@
#ifndef UTSM_SEGMENT_H
#define UTSM_SEGMENT_H
#include <utsm/types.h>
#include <utsm/uuid.h>
#include <utsm/status.h>
#include <utsm/capability.h>
#include <utsm/dirty.h>
typedef enum {
UTSM_SEG_FREE = 0,
UTSM_SEG_ACTIVE,
UTSM_SEG_CHECKPOINTING,
UTSM_SEG_SEALED,
UTSM_SEG_RECOVERING,
UTSM_SEG_POISONED,
UTSM_SEG_DESTROYED
} utsm_segment_state;
#define UTSM_SEG_F_READ (1U << 0)
#define UTSM_SEG_F_WRITE (1U << 1)
#define UTSM_SEG_F_EXEC (1U << 2)
#define UTSM_SEG_F_DMA (1U << 3)
#define UTSM_SEG_F_STRONG_RECOVERY (1U << 4)
typedef struct utsm_segment_desc {
uuid128_t segment_uuid;
uuid128_t owner_process_uuid;
u8 *cipher_base;
u64 cipher_length;
void *dmp_base;
u64 key_epoch;
u64 tweak_seed;
utsm_dirty_shard *dirty_shards;
u32 dirty_shard_count;
void *mac_table;
u32 generation;
u32 flags;
u32 state;
u32 last_cpu;
volatile u64 writer_seq;
u64 checkpoint_generation;
} utsm_segment_desc;
struct utsm_process_context;
int utsm_create_segment(struct utsm_process_context *process, u64 size, u32 flags, utsm_capability *out_cap);
utsm_segment_desc *utsm_get_segment(u32 slot);
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef UTSM_STATUS_H
#define UTSM_STATUS_H
typedef enum {
UTSM_OK = 0,
UTSM_ERR_INVALID = -1,
UTSM_ERR_NO_MEMORY = -2,
UTSM_ERR_ACCESS = -3,
UTSM_ERR_BOUNDS = -4,
UTSM_ERR_STALE_CAP = -5,
UTSM_ERR_EPOCH = -6,
UTSM_ERR_KEY_MISS = -7,
UTSM_ERR_STATE = -8,
UTSM_ERR_POISONED = -9,
UTSM_ERR_RETRY = -10
} utsm_status;
#endif
+36
View File
@@ -0,0 +1,36 @@
#ifndef UTSM_TYPES_H
#define UTSM_TYPES_H
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef signed char i8;
typedef signed short i16;
typedef signed int i32;
typedef signed long long i64;
typedef u64 usize;
typedef i64 isize;
typedef int bool;
#define true 1
#define false 0
#ifndef NULL
#define NULL ((void *)0)
#endif
#define UTSM_UNUSED(x) ((void)(x))
#define UTSM_ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0]))
static inline u64 utsm_align_up_u64(u64 value, u64 alignment) {
return (value + alignment - 1ULL) & ~(alignment - 1ULL);
}
static inline void *utsm_align_up_ptr(void *ptr, u64 alignment) {
return (void *)utsm_align_up_u64((u64)ptr, alignment);
}
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef UTSM_UTRW_H
#define UTSM_UTRW_H
#include <utsm/types.h>
#include <utsm/status.h>
#include <utsm/capability.h>
int utsm_read(utsm_capability cap, u64 offset, void *dst, u64 len);
int utsm_write(utsm_capability cap, u64 offset, const void *src, u64 len);
int utsm_slow_path(int reason);
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef UTSM_H
#define UTSM_H
#include <utsm/types.h>
#include <utsm/status.h>
#include <utsm/config.h>
#include <utsm/uuid.h>
#include <utsm/process.h>
#include <utsm/segment.h>
#include <utsm/capability.h>
#include <utsm/utrw.h>
void utsm_init(void);
int utsm_selftest_run(void);
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef UTSM_UUID_H
#define UTSM_UUID_H
#include <utsm/types.h>
typedef struct {
u64 hi;
u64 lo;
} uuid128_t;
static inline uuid128_t uuid_make_test(u64 seed) {
uuid128_t id;
id.hi = 0x5554534d00000000ULL ^ (seed * 0x9e3779b97f4a7c15ULL);
id.lo = 0x4453484200000000ULL ^ (seed + 0xd1b54a32d192ed03ULL);
return id;
}
static inline bool uuid_equal(uuid128_t a, uuid128_t b) {
return a.hi == b.hi && a.lo == b.lo;
}
#endif
+73
View File
@@ -0,0 +1,73 @@
#include <utsm/block.h>
#include <utsm/log.h>
static dkm_block_device_desc g_devices[DKM_BLOCK_MAX_DEVICES];
static u32 g_device_count;
void block_init(void) {
g_device_count = 0;
log_info("[BLOCK] registry init");
}
static int block_register_device_impl(const dkm_block_device_desc *desc) {
if (!desc || !desc->read || !desc->sector_size) return -1;
if (g_device_count >= DKM_BLOCK_MAX_DEVICES) return -2;
u32 index = g_device_count++;
g_devices[index] = *desc;
log_info("[BLOCK] device registered");
if (desc->name) log_info(desc->name);
log_hex64("[BLOCK] index=", index);
log_hex64("[BLOCK] sector_size=", desc->sector_size);
log_hex64("[BLOCK] sector_count=", desc->sector_count);
return (int)index;
}
static u32 block_device_count_impl(void) {
return g_device_count;
}
static int block_read_impl(u32 index, u64 lba, u32 count, void *buffer) {
if (index >= g_device_count || !buffer || count == 0) return -1;
dkm_block_device_desc *dev = &g_devices[index];
if (!dev->read) return -2;
return dev->read(dev->ctx, lba, count, buffer);
}
static int block_write_impl(u32 index, u64 lba, u32 count, const void *buffer) {
if (index >= g_device_count || !buffer || count == 0) return -1;
dkm_block_device_desc *dev = &g_devices[index];
if (!dev->write) return -2;
return dev->write(dev->ctx, lba, count, buffer);
}
static u64 block_sector_size_impl(u32 index) {
if (index >= g_device_count) return 0;
return g_devices[index].sector_size;
}
static const char *block_device_name_impl(u32 index) {
if (index >= g_device_count) return 0;
return g_devices[index].name;
}
static int block_set_write_fn_impl(u32 index, dkm_block_write_fn fn) {
if (index >= g_device_count) return -1;
g_devices[index].write = fn;
return 0;
}
static const dkm_block_api g_block_api = {
.register_device = block_register_device_impl,
.device_count = block_device_count_impl,
.read = block_read_impl,
.write = block_write_impl,
.sector_size = block_sector_size_impl,
.device_name = block_device_name_impl,
.set_write_fn = block_set_write_fn_impl
};
const dkm_block_api *block_get_api(void) {
return &g_block_api;
}
Binary file not shown.
+378
View File
@@ -0,0 +1,378 @@
#include <utsm/dsk.h>
#include <utsm/arena.h>
#include <utsm/dkm.h>
#include <utsm/log.h>
#include <utsm/types.h>
#include "../arch/x86_64/limine.h"
#define DSK_PATH "/system/deshab64/deshab.elf"
#define DSK_CMDLINE "dsk:main"
#define ELF_MAGIC0 0x7f
#define ELF_MAGIC1 'E'
#define ELF_MAGIC2 'L'
#define ELF_MAGIC3 'F'
#define ELFCLASS64 2
#define ELFDATA2LSB 1
#define ET_DYN 3
#define ET_EXEC 2
#define EM_X86_64 62
#define PT_LOAD 1
void *memset(void *dst, int value, usize len);
void *memcpy(void *dst, const void *src, usize len);
extern volatile struct limine_module_request g_module_request;
extern volatile struct limine_rsdp_request g_rsdp_request;
extern volatile struct limine_framebuffer_request g_fb_request;
extern volatile struct limine_hhdm_request g_hhdm_request;
typedef struct elf64_ehdr {
u8 ident[16];
u16 type;
u16 machine;
u32 version;
u64 entry;
u64 phoff;
u64 shoff;
u32 flags;
u16 ehsize;
u16 phentsize;
u16 phnum;
u16 shentsize;
u16 shnum;
u16 shstrndx;
} elf64_ehdr;
typedef struct elf64_phdr {
u32 type;
u32 flags;
u64 offset;
u64 vaddr;
u64 paddr;
u64 filesz;
u64 memsz;
u64 align;
} elf64_phdr;
/* ---- minimal FAT32 parser ---- */
typedef struct __attribute__((packed)) {
u8 jmp[3];
char oem[8];
u16 bytes_per_sector;
u8 sectors_per_cluster;
u16 reserved_sector_count;
u8 fat_count;
u16 root_entry_count;
u16 total_sectors_16;
u8 media;
u16 sectors_per_fat_16;
u16 sectors_per_track;
u16 heads;
u32 hidden_sectors;
u32 total_sectors_32;
u32 sectors_per_fat;
u16 flags;
u16 version;
u32 root_cluster;
u16 fsinfo_sector;
u16 backup_boot;
u8 reserved[12];
u8 drive;
u8 nt_flags;
u8 signature;
u32 serial;
char label[11];
char type[8];
u8 code[420];
u16 boot_sig;
} fat32_bpb;
typedef struct __attribute__((packed)) {
char name[11];
u8 attr;
u8 nt_reserved;
u8 creation_tenth;
u16 creation_time;
u16 creation_date;
u16 access_date;
u16 cluster_high;
u16 write_time;
u16 write_date;
u16 cluster_low;
u32 file_size;
} fat32_dir_entry;
static u32 fat32_read_u32(const u8 *p) {
return (u32)p[0] | ((u32)p[1] << 8) | ((u32)p[2] << 16) | ((u32)p[3] << 24);
}
static u16 fat32_read_u16(const u8 *p) {
return (u16)p[0] | ((u16)p[1] << 8);
}
static int fat32_name11_eq(const char *n, const char *s) {
for (int i = 0; i < 11; i++) {
if (n[i] != s[i]) return 0;
}
return 1;
}
/* core helpers reused from earlier loader */
static int streq(const char *a, const char *b) {
if (!a || !b) return 0;
while (*a && *b) {
if (*a != *b) return 0;
a++;
b++;
}
return *a == *b;
}
static int range_ok(u64 offset, u64 length, u64 size) {
if (offset > size) return 0;
if (length > size - offset) return 0;
return 1;
}
static struct limine_file *dsk_find_module(void) {
struct limine_module_response *rsp = g_module_request.response;
if (!rsp) return 0;
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *file = rsp->modules[i];
if (!file) continue;
if (streq(file->path, DSK_PATH) || streq(file->cmdline, DSK_CMDLINE)) {
return file;
}
}
return 0;
}
/* ---- FAT32 block-provider file reader ---- */
static u8 g_dsk_fat32_disk[65536]; /* 128-sector BPB+FAT+root dir buffer */
static u8 g_dsk_fat32_cluster[4096]; /* 8-sector cluster buffer */
/* 实机要求: 文件缓冲区足够大容纳 deshab.elf (~1.5MB) */
static u8 g_dsk_fat32_filedata[2097152]; /* 2MB file data buffer */
static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) {
const dkm_kernel_api *api = dkm_get_kernel_api();
if (!api || !api->block || !api->block->device_count) return -1;
u32 count = api->block->device_count();
if (count == 0 || api->block->sector_size(0) != 512) return -1;
/* Read first 128 sectors: BPB + FAT + root dir */
u8 *disk = g_dsk_fat32_disk;
int st = api->block->read(0, 0, 128, disk);
if (st != 0) return -1;
const fat32_bpb *bpb = (const fat32_bpb *)disk;
if (bpb->boot_sig != 0xAA55 || bpb->bytes_per_sector != 512) return -1;
u32 fat_start = bpb->reserved_sector_count * 512;
u32 data_start_sec = bpb->reserved_sector_count + (u32)bpb->fat_count * bpb->sectors_per_fat;
u32 clus = bpb->root_cluster;
u32 found_clus = 0;
u32 found_size = 0;
const char *target = "DESHAB ELF";
while (clus >= 2 && clus < 0x0FFFFFF8) {
u32 clus_lba = data_start_sec + (clus - 2) * bpb->sectors_per_cluster;
u32 cls_sec = bpb->sectors_per_cluster;
u8 *cb = g_dsk_fat32_cluster;
st = api->block->read(0, clus_lba, cls_sec, cb);
if (st != 0) return -1;
const fat32_dir_entry *dir = (const fat32_dir_entry *)cb;
for (u32 e = 0; e * 32 < cls_sec * 512; e++) {
if (dir[e].name[0] == 0) break;
if ((u8)dir[e].name[0] == 0xE5) continue;
if (dir[e].attr == 0x0F) continue;
if (dir[e].attr & 0x08) continue;
if (fat32_name11_eq(dir[e].name, target)) {
found_size = dir[e].file_size;
found_clus = fat32_read_u16((const u8 *)&dir[e].cluster_low);
break;
}
}
if (found_clus) break;
u32 fat_ent = fat_start + clus * 4;
if (fat_ent + 4 > 65536) break;
clus = fat32_read_u32(disk + fat_ent) & 0x0FFFFFFF;
}
if (!found_clus || found_size == 0) return -1;
if (found_size > sizeof(g_dsk_fat32_filedata)) return -1;
u8 *dst = g_dsk_fat32_filedata;
u32 remaining = found_size;
u32 fc = found_clus;
while (fc >= 2 && fc < 0x0FFFFFF8 && remaining > 0) {
u32 fc_lba = data_start_sec + (fc - 2) * bpb->sectors_per_cluster;
u32 fc_sec = bpb->sectors_per_cluster;
u32 fc_bytes = fc_sec * 512;
if (fc_bytes > remaining) fc_bytes = remaining;
u8 *chunk = g_dsk_fat32_cluster;
st = api->block->read(0, fc_lba, fc_sec, chunk);
if (st != 0) return -1;
for (u32 b = 0; b < fc_bytes; b++) dst[b] = chunk[b];
dst += fc_bytes;
remaining -= fc_bytes;
u32 fat_ent = fat_start + fc * 4;
if (fat_ent + 4 > 65536) { fc = 0x0FFFFFFF; break; }
fc = fat32_read_u32(disk + fat_ent) & 0x0FFFFFFF;
}
/* Copy to arena for ELF loader */
u8 *file_buf = (u8 *)kmem_alloc_aligned(found_size, 16);
if (!file_buf) return -1;
for (u32 i = 0; i < found_size; i++) file_buf[i] = g_dsk_fat32_filedata[i];
*out_addr = file_buf;
*out_size = found_size;
log_hex64("[UTSM] FAT32 file size=", found_size);
return 0;
}
/* ---- ELF checks ---- */
static int dsk_check_elf(const void *address, u64 size) {
if (!address || size < sizeof(elf64_ehdr)) return -1;
const elf64_ehdr *eh = (const elf64_ehdr *)address;
if (eh->ident[0] != ELF_MAGIC0 || eh->ident[1] != ELF_MAGIC1 ||
eh->ident[2] != ELF_MAGIC2 || eh->ident[3] != ELF_MAGIC3) return -2;
if (eh->ident[4] != ELFCLASS64 || eh->ident[5] != ELFDATA2LSB) return -3;
if (eh->machine != EM_X86_64) return -4;
if (eh->type != ET_DYN && eh->type != ET_EXEC) return -5;
if (eh->phoff == 0 || eh->phnum == 0 || eh->phentsize < sizeof(elf64_phdr)) return -6;
if (!range_ok(eh->phoff, (u64)eh->phnum * eh->phentsize, size)) return -7;
return 0;
}
static int dsk_load_elf_image(const void *address, u64 size, dsk_entry_fn *entry_out) {
const elf64_ehdr *eh = (const elf64_ehdr *)address;
const u8 *base = (const u8 *)address;
u64 min_vaddr = ~0ULL;
u64 max_vaddr = 0;
u64 max_align = 0x1000;
u32 load_count = 0;
for (u16 i = 0; i < eh->phnum; i++) {
const elf64_phdr *ph = (const elf64_phdr *)(base + eh->phoff + (u64)i * eh->phentsize);
if (ph->type != PT_LOAD) continue;
if (ph->filesz > ph->memsz) return -1;
if (!range_ok(ph->offset, ph->filesz, size)) return -2;
if (ph->vaddr < min_vaddr) min_vaddr = ph->vaddr;
if (ph->vaddr + ph->memsz > max_vaddr) max_vaddr = ph->vaddr + ph->memsz;
if (ph->align > max_align) max_align = ph->align;
load_count++;
}
if (load_count == 0 || min_vaddr == ~0ULL || max_vaddr <= min_vaddr) return -3;
if (eh->entry < min_vaddr || eh->entry >= max_vaddr) return -4;
u64 image_size = utsm_align_up_u64(max_vaddr - min_vaddr, 0x1000);
u8 *image = (u8 *)kmem_alloc_aligned(image_size, max_align);
if (!image) return -5;
memset(image, 0, image_size);
for (u16 i = 0; i < eh->phnum; i++) {
const elf64_phdr *ph = (const elf64_phdr *)(base + eh->phoff + (u64)i * eh->phentsize);
if (ph->type != PT_LOAD) continue;
u64 dst_off = ph->vaddr - min_vaddr;
if (dst_off + ph->memsz > image_size) return -6;
memcpy(image + dst_off, base + ph->offset, ph->filesz);
}
*entry_out = (dsk_entry_fn)(image + (eh->entry - min_vaddr));
log_hex64("[UTSM] DSK image base=", (u64)image);
log_hex64("[UTSM] DSK image size=", image_size);
log_hex64("[UTSM] DSK entry=", (u64)*entry_out);
return 0;
}
static void dsk_fill_boot_context(dsk_boot_context *ctx) {
memset(ctx, 0, sizeof(*ctx));
ctx->magic = DSK_BOOT_MAGIC;
ctx->abi_version = DSK_BOOT_ABI_VERSION;
ctx->size = sizeof(*ctx);
ctx->flags = DSK_BOOT_FLAG_FROM_UTSM | DSK_BOOT_FLAG_DKM_READY | DSK_BOOT_FLAG_FAT32_PATH;
if (g_hhdm_request.response) {
ctx->hhdm_offset = g_hhdm_request.response->offset;
}
if (g_rsdp_request.response) {
ctx->rsdp_address = (u64)g_rsdp_request.response->address;
}
if (g_fb_request.response && g_fb_request.response->framebuffer_count > 0) {
struct limine_framebuffer *fb = g_fb_request.response->framebuffers[0];
ctx->framebuffer_address = (u64)fb->address;
ctx->framebuffer_width = fb->width;
ctx->framebuffer_height = fb->height;
ctx->framebuffer_pitch = fb->pitch;
ctx->framebuffer_bpp = fb->bpp;
}
ctx->boot_modules_response = (u64)g_module_request.response;
ctx->dkm_kernel_api = (u64)dkm_get_kernel_api();
u64 rsp;
__asm__ volatile ("movq %%rsp, %0" : "=r"(rsp));
ctx->kernel_stack_top = rsp;
}
int dsk_load_and_jump(void) {
log_info("[UTSM] loading DSK");
log_info(DSK_PATH);
const void *data = 0;
u64 data_size = 0;
/* 1) try FAT32 block provider */
int fat32_ok = dsk_load_from_block_fat32(&data, &data_size);
if (fat32_ok == 0) {
log_info("[UTSM] DSK loaded from FAT32 block provider");
} else {
/* 2) fallback: Limine boot module */
log_info("[UTSM] FAT32 block path unavailable; trying Limine module");
struct limine_file *file = dsk_find_module();
if (!file) {
log_error("[UTSM] DSK module not found (neither FAT32 nor Limine)");
return -1;
}
data = file->address;
data_size = file->size;
log_hex64("[UTSM] DSK module size=", data_size);
}
int status = dsk_check_elf(data, data_size);
if (status != 0) {
log_error("[UTSM] DSK ELF rejected");
log_hex64("[UTSM] DSK ELF status=", (u64)(i64)status);
return status;
}
dsk_entry_fn entry = 0;
status = dsk_load_elf_image(data, data_size, &entry);
if (status != 0) {
log_error("[UTSM] DSK load failed");
log_hex64("[UTSM] DSK load status=", (u64)(i64)status);
return status;
}
dsk_boot_context *ctx = (dsk_boot_context *)kmem_alloc_aligned(sizeof(dsk_boot_context), 16);
if (!ctx) {
log_error("[UTSM] DSK context allocation failed");
return -1;
}
dsk_fill_boot_context(ctx);
log_info("[UTSM] jumping to DSK");
entry(ctx);
log_error("[UTSM] DSK returned unexpectedly");
return -1;
}
Binary file not shown.
+34
View File
@@ -0,0 +1,34 @@
#include <utsm/log.h>
static void log_line(const char *level, const char *msg) {
serial_write(level);
serial_write(" ");
serial_write(msg);
serial_write("\n");
}
void log_info(const char *msg) {
log_line("[INFO]", msg);
}
void log_warn(const char *msg) {
log_line("[WARN]", msg);
}
void log_error(const char *msg) {
log_line("[ERR ]", msg);
}
void log_hex64(const char *prefix, u64 value) {
static const char hex[] = "0123456789abcdef";
char buf[19];
buf[0] = '0';
buf[1] = 'x';
for (int i = 0; i < 16; i++) {
buf[2 + i] = hex[(value >> ((15 - i) * 4)) & 0xf];
}
buf[18] = 0;
serial_write(prefix);
serial_write(buf);
serial_write("\n");
}
Binary file not shown.
+54
View File
@@ -0,0 +1,54 @@
#include <utsm/log.h>
#include <utsm/arena.h>
#include <utsm/utsm.h>
#include <utsm/drr.h>
#include <utsm/dkm.h>
#include <utsm/idt.h>
#include <utsm/dsk.h>
#include <utsm/block.h>
#include <utsm/net.h>
void arch_halt_forever(void);
void kernel_main(void) {
serial_init();
log_info("[UTSM] boot");
idt_init();
log_info("[UTSM] arena init begin");
arena_init();
log_info("[UTSM] arena init ok");
log_info("[UTSM] dma init begin");
dma_init();
log_info("[UTSM] dma init ok");
log_info("[UTSM] net registry init begin");
net_init();
log_info("[UTSM] net registry init ok");
log_info("[UTSM] drr init begin");
drr_init();
log_info("[UTSM] drr init ok");
log_info("[UTSM] core init begin");
utsm_init();
log_info("[UTSM] init ok");
dkm_init();
dkm_fill_platform_info();
dsm_load_by_manifest();
int result = utsm_selftest_run();
if (result == 0) {
log_info("[UTSM] SELFTEST PASS");
if (dsk_load_and_jump() != 0) {
log_error("[UTSM] DSK jump failed");
}
} else {
log_error("[UTSM] SELFTEST FAIL");
}
arch_halt_forever();
}

Some files were not shown because too many files have changed in this diff Show More