Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fffb16cdf5 |
@@ -1,40 +0,0 @@
|
||||
---
|
||||
name: Bug 报告
|
||||
about: 报告内核崩溃、驱动故障、构建失败等问题
|
||||
title: "[bug] "
|
||||
labels: bug
|
||||
---
|
||||
|
||||
## 问题描述
|
||||
|
||||
<!-- 简要描述问题 -->
|
||||
|
||||
## 复现步骤
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
## 预期行为
|
||||
|
||||
<!-- 应该发生什么 -->
|
||||
|
||||
## 实际行为
|
||||
|
||||
<!-- 实际发生了什么 -->
|
||||
|
||||
## 环境
|
||||
|
||||
- 组件:<!-- UTSM / DSK / DKM:<驱动名> / FirstInit / 构建 -->
|
||||
- 运行环境:<!-- QEMU / 真机 -->
|
||||
- QEMU 参数(如非默认):
|
||||
|
||||
## 串口日志
|
||||
|
||||
```
|
||||
<!-- 粘贴 QEMU 串口输出,至少包含崩溃点前后上下文 -->
|
||||
```
|
||||
|
||||
## 崩溃分析(如适用)
|
||||
|
||||
<!-- 三重故障 / page fault / panic 时的寄存器、栈、调用上下文 -->
|
||||
@@ -1,39 +0,0 @@
|
||||
---
|
||||
name: 功能请求
|
||||
about: 提议新驱动、新子系统或架构改进
|
||||
title: "[feat] "
|
||||
labels: enhancement
|
||||
---
|
||||
|
||||
## 功能描述
|
||||
|
||||
<!-- 简要描述提议的功能 -->
|
||||
|
||||
## 动机
|
||||
|
||||
<!-- 为什么需要这个功能,解决什么问题 -->
|
||||
|
||||
## 涉及子系统
|
||||
|
||||
- [ ] UTSM 首阶段内核
|
||||
- [ ] DSK 主内核
|
||||
- [ ] DKM 驱动
|
||||
- [ ] 内存管理
|
||||
- [ ] 文件系统 / VFS
|
||||
- [ ] 网络
|
||||
- [ ] 调度器 (SAS-R0-PCQ)
|
||||
- [ ] 恢复系统 (DRR)
|
||||
- [ ] FirstInit / 用户空间
|
||||
- [ ] 文档
|
||||
|
||||
## 设计思路
|
||||
|
||||
<!-- 描述实现方案,如有 ABI / 架构影响请重点说明 -->
|
||||
|
||||
## 路线图对应
|
||||
|
||||
<!-- 对应 docs/ROADMAP.md 中的哪个 Phase?(如适用) -->
|
||||
|
||||
## 验收标准
|
||||
|
||||
<!-- 完成后如何验证 -->
|
||||
@@ -1,52 +0,0 @@
|
||||
## 变更说明
|
||||
|
||||
<!-- 简要描述本 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 是否需要变更 -->
|
||||
@@ -1,6 +0,0 @@
|
||||
ISO/deshab.img
|
||||
*.o
|
||||
.build_tmp/
|
||||
.trae/
|
||||
docs/workbuddy-planning/
|
||||
sata_fat32_dsk.img
|
||||
@@ -1,154 +0,0 @@
|
||||
# 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 + 包解码 + 光标移动。
|
||||
@@ -1,691 +0,0 @@
|
||||
# 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 与驱动加载的整合说明。
|
||||
```
|
||||
@@ -1,298 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,617 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,358 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,798 +0,0 @@
|
||||
/* 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");
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,331 +0,0 @@
|
||||
/* 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 */
|
||||
@@ -1,462 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,309 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,347 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,251 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
$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"
|
||||
@@ -1,93 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
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 }"
|
||||
@@ -1,935 +0,0 @@
|
||||
// 编译到 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 可选
|
||||
```
|
||||
@@ -1,21 +0,0 @@
|
||||
.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.
@@ -1,5 +0,0 @@
|
||||
void arch_halt_forever(void) {
|
||||
for (;;) {
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -1,222 +0,0 @@
|
||||
#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.
@@ -1,62 +0,0 @@
|
||||
/* 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.
@@ -1,15 +0,0 @@
|
||||
#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.
@@ -1,154 +0,0 @@
|
||||
#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
|
||||
@@ -1,81 +0,0 @@
|
||||
#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.
@@ -1,29 +0,0 @@
|
||||
#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.
@@ -1,47 +0,0 @@
|
||||
#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.
@@ -1,20 +0,0 @@
|
||||
#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.
@@ -1,126 +0,0 @@
|
||||
/* 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.
@@ -1,80 +0,0 @@
|
||||
#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.
@@ -1,35 +0,0 @@
|
||||
#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.
@@ -1,19 +0,0 @@
|
||||
#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.
@@ -1,19 +0,0 @@
|
||||
#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.
@@ -1,14 +0,0 @@
|
||||
#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.
@@ -1,449 +0,0 @@
|
||||
#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.
@@ -1,47 +0,0 @@
|
||||
#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.
@@ -1,67 +0,0 @@
|
||||
#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.
@@ -1,90 +0,0 @@
|
||||
#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.
@@ -1,359 +0,0 @@
|
||||
#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.
@@ -1,316 +0,0 @@
|
||||
/* 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.
@@ -1,13 +0,0 @@
|
||||
#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
|
||||
@@ -1,8 +0,0 @@
|
||||
#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
|
||||
@@ -1,33 +0,0 @@
|
||||
#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
|
||||
@@ -1,26 +0,0 @@
|
||||
#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
|
||||
@@ -1,13 +0,0 @@
|
||||
#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
|
||||
@@ -1,17 +0,0 @@
|
||||
#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
|
||||
@@ -1,709 +0,0 @@
|
||||
/* 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 */
|
||||
@@ -1,20 +0,0 @@
|
||||
#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
|
||||
@@ -1,141 +0,0 @@
|
||||
#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
|
||||
@@ -1,20 +0,0 @@
|
||||
#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
|
||||
@@ -1,26 +0,0 @@
|
||||
#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
|
||||
@@ -1,127 +0,0 @@
|
||||
#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 */
|
||||
@@ -1,51 +0,0 @@
|
||||
#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
|
||||
@@ -1,12 +0,0 @@
|
||||
#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
|
||||
@@ -1,16 +0,0 @@
|
||||
#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
|
||||
@@ -1,77 +0,0 @@
|
||||
#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
|
||||
@@ -1,29 +0,0 @@
|
||||
#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
|
||||
@@ -1,79 +0,0 @@
|
||||
#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 */
|
||||
@@ -1,50 +0,0 @@
|
||||
#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
|
||||
@@ -1,18 +0,0 @@
|
||||
#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
|
||||
@@ -1,36 +0,0 @@
|
||||
#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
|
||||
@@ -1,12 +0,0 @@
|
||||
#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
|
||||
@@ -1,16 +0,0 @@
|
||||
#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
|
||||
@@ -1,22 +0,0 @@
|
||||
#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
|
||||
@@ -1,73 +0,0 @@
|
||||
#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.
@@ -1,378 +0,0 @@
|
||||
#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.
@@ -1,34 +0,0 @@
|
||||
#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.
@@ -1,54 +0,0 @@
|
||||
#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
Reference in New Issue
Block a user