Record networking and DMA development progress

Add the current OS source tree, build scripts, system image layout, and development notes covering DMA page allocation, e1000 bring-up, net API dispatch, and DHCP work in progress.
This commit is contained in:
xyou
2026-07-02 16:17:09 +08:00
parent fbc14631e3
commit f1a2a110d7
182 changed files with 16472 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
ISO/deshab.img
+154
View File
@@ -0,0 +1,154 @@
# Deshab 项目上下文
## 项目概览
Deshab 当前包含一个内核/系统实验方向,其中启动内核与主内核目标为:
```text
CODE/UTSM -> SYSTEM/boot/utsm.elf
CODE/dsk -> SYSTEM/system/deshab64/deshab.elf
```
`utsm.elf` 是当前由 bootloader 直接加载的首阶段内核,负责 UTSM、DKM 驱动加载、平台发现和早期系统服务。当前已实现两阶段 DSK 加载:优先通过 `kernel_api.block` + 内嵌 FAT32 解析从真实块设备读取 `/system/deshab64/deshab.elf`(在 SATA FAT32 盘场景已验证);无块设备时自动回退 Limine boot module 预加载。
DSK 主内核(`deshab.elf`)当前已实现:
- 内嵌 FAT32 只读解析器(256 扇区批量读取 + 内存内文件查找)
- PIE ELF loader(PT_LOAD + PT_DYNAMIC + R_X86_64_RELATIVE 重定位)
- 旋转加载动画(双缓冲精灵、顺时针、comet-tail 渐变弧)
- 首次启动检测:读取 `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, 淡蓝色背景 + 居中四色圆弧加载环(纯整数运算,无浮点依赖)
- **ahci** (stage1): PCI AHCI `8086:2922` 探测, BAR5/ABAR HHDM MMIO 映射, HBA CAP/GHC/PI/VS 与 port 枚举;已接入 `kernel_api.dma`,支持 SATA disk IDENTIFY 与 LBA0 READ 最小 DMA 路径;可向 `kernel_api.block` 注册 `ahci0` block provider;默认无 SATA 盘/ATAPI 场景会跳过命令
- **nvme** (stage1): PCI NVMe `1b36:0010` 探测, BAR0/BAR1 解析, IRQ line 读取;当前 QEMU BAR0 位于 4G 以上,MMIO register 读取等待高位 PCI MMIO 映射能力
- **bootfs** (stage1): Limine boot module 内存文件系统
- **vfs** (stage2): 挂载 bootfs, 文件查找/读取
- **devfs** (stage2): 暴露 `/dev/version`, `/dev/platform`, `/dev/fb0`, `/dev/modules`, `/dev/boot/`
- **fat32** (stage2): 只读 FAT32 BPB/FAT/目录项解析, 通过 `driver/test.fat32` 验证读取 `README.TXT`
- **ps2kbd** (stage3): PS/2 IRQ1 注册, 端口 `0x60` 扫描码读取, scan code set 1 → ASCII demo
- **e1000** (stage3): PCI `8086:10d3` 探测, BAR0 HHDM MMIO 映射, MAC 读取, IRQ 注册, 基础 link setup
- **virtio_net** (stage3): PCI virtio-net `1af4:1001` 探测, BAR 枚举, modern virtio PCI capability 枚举;暂不进行 feature negotiation / virtqueue / 收发包
当前内核平台能力:IDT 0–47 stub、异常处理、PIC remap 到 `0x20–0x2f`、IRQ handler 注册与 EOI、Limine RSDP/framebuffer/module/HHDM request。
kernel_api 已暴露能力:log, rsdp_address, fb_address/width/height/pitch/bpp, boot_modules_response, irq_register, hhdm_offset, dma.alloc_pages。
当前 manifest 中 14 个外部 `.drv` 均已替换为真实 DKM 驱动并可加载执行。
下一阶段优先路线:
1. **内存与 MMIO 基础设施**: 实现物理页分配器、页表映射接口、低位/高位 PCI MMIO 映射,解决 NVMe 4G 以上 BAR 和后续 DMA 映射问题。
2. **DMA 与块设备数据路径**: 建立 contiguous DMA buffer、cache/屏障约定、PRDT/队列内存管理,然后推进 AHCI IDENTIFY/READ 与 NVMe admin queue/identify。
3. **IRQ 后端升级**: 在现有 PIC fallback 稳定基础上扩展 IDT/vector allocator/APIC EOI/IOAPIC redirection,逐步迁移设备 IRQ,最后接入 MSI/MSI-X。
4. **网络数据路径**: 在 DMA/IRQ 完成后推进 e1000 RX/TX ring 与 virtio-net feature negotiation/virtqueue/RX-TX。
5. **VFS 与真实块设备接入**: 将 FAT32 从测试镜像迁移到 AHCI/NVMe block provider,完善挂载、读取、目录遍历和错误路径。
6. **DKM 工程化收尾**: 统一驱动本地 ABI 头、清理 warning、补充自动化 QEMU 场景(e1000/virtio-net/nvme/ahci)。
7. **FirstInit 完善**: 修复按键崩溃(fb_text 优化问题)、实现鼠标光标移动、user.conf 写盘(需 block write API)、网络配置界面。
8. **鼠标输入驱动**: 从 mouseInit stub 升级为完整 PS/2 鼠标 IRQ12 + 包解码 + 光标移动。
+691
View File
@@ -0,0 +1,691 @@
# DKM 驱动模块系统
```text
DKM = Deshab Kernel Module
DSM = Driver Startup Manager
```
DKM 是 Deshab 内核的驱动模块系统,负责在内核启动时加载 `SYSTEM/driver` 下的 ELF64 `.drv` 驱动模块,并把驱动注册到内核服务体系中。
当前实现状态:CODE/UTSM 内核已接入完整 DKM/DSM 驱动加载系统。内置 `console_early` + manifest.json 解析 + Limine boot module 预加载 + 4 stage 分阶段加载。全部 14 个外部 `.drv` 已完成 ET_REL 装载全链路:ELF64 校验、符号扫描、section 拷贝到 arena、SHT_NOBITS 清零、R_X86_64_64/32/32S/PC32 重定位、driver_desc magic 校验、外部 driver_init 调用进入 ACTIVE。当前镜像还预加载 `driver/test.fat32` 作为 FAT32 驱动测试镜像。
Linux/Windows 已编译驱动不能直接作为 DKM 驱动使用。真实驱动必须按本文件定义的 DKM ABI 编译,导出 `driver_desc`、`driver_init`、`driver_exit`,并只通过 `dkm_kernel_api` 调用内核服务。
当前真实驱动进度:14/14。
```text
stage0: timer, apic, acpi, pci
stage1: console_fb, ahci, nvme, bootfs
stage2: vfs, devfs, fat32
stage3: ps2kbd, e1000, virtio_net
```
manifest 中 14 个外部 `.drv` 均已替换为真实 DKM 驱动并可加载执行。当前 IDT/PIC/IRQ 基础设施已在内核侧实现,`apic` 已完成 APIC discovery 并保留 PIC IRQ 路由,`ahci` 已完成 PCI/ABAR/HBA/port discovery,并通过 `kernel_api.dma.alloc_pages` 接入早期低位 DMA buffer,支持 SATA disk IDENTIFY 与 LBA0 READ 最小路径;识别 SATA disk 后可向 `kernel_api.block` 注册 `ahci0` block provider。`fat32` 已优先通过 block provider 读取 FAT32 镜像,无设备或 BPB 无效时回退 boot module。`nvme` 已完成 PCI discovery 并能识别 QEMU NVMe 控制器;由于当前 QEMU BAR0 位于 4G 以上,NVMe MMIO register 读取等待高位 PCI MMIO 映射能力。`ps2kbd` 和 `e1000` 已通过 `kernel_api.irq_register` 验证 IRQ handler 注册路径。`virtio_net` 已完成 PCI discovery 和 modern virtio capability 枚举,尚未进行 feature negotiation / virtqueue / RX-TX。
下一阶段 DKM/驱动路线:
```text
P0: 物理页分配器 + 页表/MMIO 映射接口
P1: DMA buffer/屏障约定 + AHCI/NVMe block 数据路径
P2: IDT 256 vectors + vector allocator + APIC/IOAPIC/MSI IRQ backend
P3: e1000 与 virtio_net RX/TX 数据路径
P4: FAT32 接入真实 block provider,替代 test.fat32 启动镜像
P5: 驱动 ABI 公共头、warning 清理、QEMU 场景自动化
```
---
## 1. 模块目标
DKM 的目标:
```text
1. 从 SYSTEM/driver/manifest.json 读取驱动清单。
2. 按 stage 分阶段加载驱动。
3. 支持 ELF64 .drv 模块加载和重定位。
4. 提供稳定的 driver_desc ABI。
5. 通过 dkm_kernel_api 向驱动暴露内核服务。
6. 支持 stage0/stage1 boot module 早期加载。
7. 将驱动内存纳入 UTSM。
8. 将驱动状态和恢复操作纳入 DRR。
```
---
## 2. 系统目录约定
打包为 IMG 后,`SYSTEM` 是系统根目录。
```text
SYSTEM/
boot/
utsm.elf
limine.conf
driver/
manifest.json
platform/
timer.drv
apic.drv
acpi.drv
bus/
pci.drv
block/
ahci.drv
nvme.drv
fs/
bootfs.drv
vfs.drv
fat32.drv
devfs.drv
net/
e1000.drv
virtio_net.drv
input/
ps2kbd.drv
console/
console_fb.drv
```
当前驱动清单:
```text
SYSTEM/driver/manifest.json
```
---
## 3. 启动阶段
DKM 使用分阶段加载。
```text
stage0: platform
timer / apic / acpi / pci
建立平台发现、中断、总线和基础计时能力。
stage1: boot
console / block / bootfs
建立启动日志、块设备和启动文件访问能力。
stage2: filesystem
vfs / fat32 / devfs
建立完整 VFS 和可挂载文件系统。
stage3: optional
net / input / gpu
加载网络、输入、图形等非启动关键驱动。
```
规则:
```text
1. stage0/stage1 可由 bootloader 预加载为 boot module。
2. stage2/stage3 默认从 SYSTEM/driver 加载。
3. required=true 的驱动失败时进入 DRR recovery 或 panic。
4. required=false 的驱动失败时标记 FAILED 并继续启动。
```
---
## 4. driver_desc ABI
每个 `.drv` 必须导出三个符号:
```text
driver_desc
driver_init
driver_exit
```
### 4.1 常量
```c
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1
```
`0x444B4D31` 表示:
```text
DKM1
```
### 4.2 driver_desc 结构
```c
struct dkm_driver_desc {
uint32_t magic;
uint16_t abi_version;
uint16_t desc_size;
const char *name;
const char *version;
const char *vendor;
uint32_t driver_class;
uint32_t stage;
uint32_t flags;
uint32_t priority;
const char *const *depends;
uint32_t depends_count;
const char *const *provides;
uint32_t provides_count;
uint64_t min_kernel_abi;
uint64_t feature_bits;
uint64_t reserved0;
uint64_t reserved1;
};
```
### 4.3 driver_class
```text
DKM_CLASS_PLATFORM
DKM_CLASS_BUS
DKM_CLASS_INTERRUPT
DKM_CLASS_TIMER
DKM_CLASS_CONSOLE
DKM_CLASS_STORAGE
DKM_CLASS_FS
DKM_CLASS_NET
DKM_CLASS_INPUT
DKM_CLASS_GPU
DKM_CLASS_MISC
```
### 4.4 flags
```text
DKM_F_REQUIRED
当前 stage 中失败则进入 DRR recovery 或 panic。
DKM_F_BOOT_MODULE
可由 bootloader 预加载。
DKM_F_NO_UNLOAD
不允许卸载。
DKM_F_STRONG_RECOVERY
驱动 data/bss 段使用 UTSM 强恢复策略。
DKM_F_DMA_REQUIRED
驱动需要 DMA API。
DKM_F_EARLY_LOG
驱动 init 期间允许使用 early log。
```
---
## 5. 驱动入口
```c
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle);
int driver_exit(struct dkm_driver_handle *handle);
```
约定:
```text
1. driver_init 返回 0 表示成功。
2. driver_init 返回负数表示失败。
3. driver_exit 仅用于非 DKM_F_NO_UNLOAD 驱动。
4. required 驱动失败会触发 DRR recovery 或 panic。
5. optional 驱动失败会被标记为 FAILED。
```
---
## 6. kernel_api ABI
驱动默认不直接依赖任意内核符号,而是通过 `dkm_kernel_api` 调用内核服务。
```c
#define DKM_KERNEL_API_VERSION 1
struct dkm_kernel_api {
uint32_t version;
uint32_t size;
uint64_t feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
uint64_t fb_width;
uint64_t fb_height;
uint64_t fb_pitch;
uint16_t fb_bpp;
const void *boot_modules_response;
int (*irq_register)(uint8_t irq, void *handler);
uint64_t hhdm_offset;
};
```
### 6.1 log API
```c
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
```
### 6.2 memory API
```c
struct dkm_mem_api {
void *(*alloc)(uint64_t size, uint32_t flags);
void (*free)(void *ptr);
void *(*alloc_pages)(uint32_t order, uint32_t flags);
void (*free_pages)(void *ptr, uint32_t order);
void *(*mmio_map)(uint64_t phys, uint64_t size, uint32_t flags);
void (*mmio_unmap)(void *virt, uint64_t size);
};
```
### 6.3 UTSM API
```c
struct dkm_utsm_api {
int (*create_segment)(uint64_t size, uint32_t flags, struct utsm_capability *out);
int (*read)(struct utsm_capability cap, uint64_t off, void *dst, uint64_t len);
int (*write)(struct utsm_capability cap, uint64_t off, const void *src, uint64_t len);
int (*pin)(struct utsm_capability cap, uint64_t off, uint64_t len, void **window);
int (*unpin)(void *window, uint32_t flags);
};
```
### 6.4 当前平台直通能力
当前内核已通过 `dkm_kernel_api` 直接暴露早期平台信息和 IRQ/HHDM 能力:
```text
rsdp_address Limine RSDP 地址,用于 ACPI 驱动
fb_address/width/height Limine framebuffer 信息,用于 console_fb
fb_pitch/fb_bpp framebuffer 行跨度和像素格式
boot_modules_response Limine module response,用于 bootfs/fat32 测试镜像
irq_register 注册 PIC IRQ0–15 handler,用于 ps2kbd/e1000
hhdm_offset physical → virtual direct map,用于 PCI BAR MMIO
```
### 6.5 IRQ / PCI / DMA API
```c
struct dkm_irq_api {
int (*register_irq)(uint32_t vector, int (*handler)(void *ctx), void *ctx, uint32_t flags);
int (*unregister_irq)(uint32_t vector);
void (*ack)(uint32_t vector);
};
struct dkm_pci_api {
int (*scan)(int (*cb)(const struct pci_device *dev, void *ctx), void *ctx);
int (*enable_device)(const struct pci_device *dev);
uint64_t (*bar_phys)(const struct pci_device *dev, uint32_t bar);
uint64_t (*bar_size)(const struct pci_device *dev, uint32_t bar);
};
struct dkm_dma_api {
int (*alloc)(uint64_t size, uint32_t flags, struct dkm_dma_buffer *out);
void (*free)(struct dkm_dma_buffer *buf);
int (*sync_for_device)(struct dkm_dma_buffer *buf);
int (*sync_for_cpu)(struct dkm_dma_buffer *buf);
};
```
---
## 7. ELF64 .drv Loader
第一版仅支持 x86_64 ELF64 小型内核模型。
### 7.1 必须支持的 relocation
```text
R_X86_64_64
绝对 64-bit 地址重定位。
R_X86_64_RELATIVE
base + addend。
R_X86_64_GLOB_DAT
GOT 符号地址。
R_X86_64_JUMP_SLOT
PLT 函数地址。
```
### 7.2 建议支持的 relocation
```text
R_X86_64_PC32
32-bit PC-relative 调用。
R_X86_64_PLT32
PLT-relative 调用。
R_X86_64_32 / R_X86_64_32S
仅允许确认地址范围安全时使用。
```
### 7.3 第一版禁止
```text
TLS relocation
IFUNC
lazy binding
外部动态库依赖
用户态 libc 依赖
异常展开表强依赖
```
### 7.4 加载流程
```text
DKM_ELF_LOAD(path_or_boot_module)
1. 读取 ELF header。
2. 校验 ELFCLASS64 / EM_X86_64 / endian / ABI。
3. 读取 program headers 或 section headers。
4. 计算模块内存大小和对齐。
5. 通过 UTSM 创建 code/data 段。
6. 加载 PT_LOAD 或 SHF_ALLOC section。
7. 清零 .bss。
8. 解析 symbol table。
9. 解析 relocation section。
10. 解析内核导出符号和 dkm_kernel_api。
11. 执行 relocation。
12. 查找 driver_desc / driver_init / driver_exit。
13. 设置 code 段 READ|EXEC|SEALED。
14. 设置 data 段 READ|WRITE|STRONG_RECOVERY。
15. 返回 module handle。
```
---
## 8. manifest.json 格式
路径:
```text
SYSTEM/driver/manifest.json
```
顶层结构:
```json
{
"schema": "deshab.driver.manifest.v1",
"root": "SYSTEM",
"driverRoot": "SYSTEM/driver",
"format": "elf64-drv",
"abi": {},
"policy": {},
"stages": []
}
```
驱动项示例:
```json
{
"name": "pci",
"path": "driver/bus/pci.drv",
"class": "bus",
"required": true,
"depends": ["irq"],
"provides": ["pci"]
}
```
路径规则:
```text
manifest 中的 path 相对 SYSTEM 根目录。
SYSTEM/driver/manifest.json 内的 driver/bus/pci.drv 指向 SYSTEM/driver/bus/pci.drv。
stage0/stage1 驱动允许来自 boot module。
stage2/stage3 驱动默认从 SYSTEM/driver 加载。
```
---
## 9. 驱动加载状态机
正常加载:
```text
DISCOVERED
-> QUEUED
-> DEP_WAIT
-> LOADING
-> ELF_CHECKED
-> MEMORY_ALLOCATED
-> RELOCATED
-> ABI_CHECKED
-> INITING
-> ACTIVE
```
失败状态:
```text
FAILED_ELF
FAILED_RELOCATION
FAILED_DEPENDENCY
FAILED_ABI
FAILED_INIT
FAILED_REQUIRED
```
卸载状态:
```text
ACTIVE
-> QUIESCING
-> EXITING
-> UNLOADING
-> UNLOADED
```
DRR 恢复状态:
```text
ACTIVE
-> SUSPENDED_BY_DRR
-> RECOVERING
-> REINITING
-> ACTIVE
```
---
## 10. DSM 加载策略
```text
DSM_LOAD_ALL()
1. 读取 SYSTEM/driver/manifest.json。
2. 校验 schema / abi / policy。
3. 按 stage 顺序加载。
4. 每个 stage 内按 priority 排序。
5. 检查 depends 是否已由 provides 满足。
6. 未满足依赖的驱动进入 DEP_WAIT。
7. 每轮加载成功后更新 provides set。
8. 一轮后仍 DEP_WAIT 的 required 驱动进入 FAILED_REQUIRED。
9. optional 驱动失败只记录状态。
```
required 失败策略:
```text
stage0/stage1 required 失败:
DRR report_fault -> boot fallback -> panic / system rollback
stage2 required 失败:
DRR recovery -> fallback 到 bootfs 或只读模式
stage3 optional 失败:
mark FAILED -> continue boot
```
---
## 11. stage0/stage1 boot module 方案
stage0/stage1 不应依赖普通 VFS。
bootloader 应预加载:
```text
SYSTEM/driver/manifest.json
SYSTEM/driver/platform/timer.drv
SYSTEM/driver/platform/acpi.drv
SYSTEM/driver/platform/apic.drv
SYSTEM/driver/bus/pci.drv
SYSTEM/driver/console/console_fb.drv
SYSTEM/driver/fs/bootfs.drv
SYSTEM/driver/test.fat32
```
可选预加载:
```text
SYSTEM/driver/block/ahci.drv
SYSTEM/driver/block/nvme.drv
SYSTEM/driver/fs/vfs.drv
SYSTEM/driver/fs/devfs.drv
SYSTEM/driver/fs/fat32.drv
SYSTEM/driver/net/e1000.drv
SYSTEM/driver/net/virtio_net.drv
SYSTEM/driver/input/ps2kbd.drv
```
boot module 表:
```c
struct dkm_boot_module {
const char *path;
void *base;
uint64_t size;
uint32_t type;
uint32_t flags;
uint64_t checksum;
};
struct dkm_boot_module_table {
uint32_t count;
struct dkm_boot_module modules[];
};
```
查找规则:
```text
DSM_LOAD_DRIVER(path)
1. 如果 path 在 boot module table 中,直接从内存加载。
2. 否则如果 VFS 已可用,从 SYSTEM/path 加载。
3. 否则返回 BOOT_MODULE_NOT_FOUND。
```
---
## 12. 与 UTSM / DRR 的关系
### 12.1 UTSM 内存策略
```text
驱动 text:READ | EXEC | SEALED
驱动 rodata:READ | SEALED
驱动 data:READ | WRITE | STRONG_RECOVERY
驱动 bss:READ | WRITE | STRONG_RECOVERY
驱动 DMA:DMA | PINNED,必要时 CIPHERTEXT_DMA 或 NO_ENCRYPT
```
### 12.2 DRR 记录项
```text
driver name
stage
state
module memory range
provided services
recovery ops
init result
last fault
```
### 12.3 recovery ops
```c
struct dkm_driver_recovery_ops {
int (*quiesce)(void *ctx);
int (*reset)(void *ctx);
int (*reinit)(void *ctx);
int (*dump_state)(void *ctx, void *buf, uint64_t len);
};
```
DRR recovery 顺序:
```text
quiesce -> UTSM rollback -> device reset -> driver reinit -> resume
```
---
## 13. 第一版实现清单
```text
1. manifest.json parser
2. boot module table lookup
3. ELF64 header 校验
4. ELF64 section/program loading
5. relocation 处理
6. driver_desc 校验
7. kernel_api table 初始化
8. depends/provides resolver
9. staged loader
10. driver state table
11. DRR driver fault reporting
12. UTSM module memory allocation
```
---
## 14. 相关文件
```text
SYSTEM/driver/manifest.json
驱动启动清单。
RE/驱动模块ABI设计.md
DKM ABI 详细设计。
CODE/UTSM/README.md
UTSM 与驱动加载的整合说明。
```
+298
View File
@@ -0,0 +1,298 @@
/* DKM ACPI Driver - RSDP scan / RSDT parse / table enumeration
* Stage 0, optional, provides "acpi".
* Scans BIOS memory for RSDP, then walks RSDT/XSDT to list all ACPI tables.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
/* ---------------------------------------------------------------
* ACPI structures
* --------------------------------------------------------------- */
typedef struct __attribute__((packed)) {
char signature[8];
u8 checksum;
char oem_id[6];
u8 revision;
u32 rsdt_addr;
} acpi_rsdp_v1;
typedef struct __attribute__((packed)) {
/* RSDP v1 fields */
char signature[8];
u8 checksum;
char oem_id[6];
u8 revision;
u32 rsdt_addr;
/* RSDP v2+ fields */
u32 length;
u64 xsdt_addr;
u8 ext_checksum;
u8 reserved[3];
} acpi_rsdp_v2;
typedef struct __attribute__((packed)) {
char signature[4];
u32 length;
u8 revision;
u8 checksum;
char oem_id[6];
char oem_table_id[8];
u32 oem_revision;
u32 creator_id;
u32 creator_revision;
} acpi_sdt_header;
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_provides[] = { "acpi" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "acpi",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 1, /* DKM_CLASS_PLATFORM */
.stage = 0,
.flags = 0, /* optional */
.priority = 0,
.depends = NULL,
.depends_count = 0,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* Helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static u32 min_u32(u32 a, u32 b) { return a < b ? a : b; }
static int memneq(const char *a, const char *b, u32 n) {
for (u32 i = 0; i < n; i++) {
if (a[i] != b[i]) return 1;
}
return 0;
}
static u8 checksum8(const u8 *data, u32 len) {
u8 sum = 0;
for (u32 i = 0; i < len; i++) {
sum += data[i];
}
return sum;
}
static void log_hex(const char *prefix, u64 val) {
static const char hex[] = "0123456789abcdef";
char buf[32];
u32 pos = 0;
while (pos < 30) { buf[pos] = 0; pos++; }
pos = 0;
buf[pos++] = '0';
buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(val >> (i * 4)) & 0xf];
}
buf[pos] = 0;
/* manual concat via serial_write-like approach: pass prefix then buf */
g_log->info(prefix);
g_log->info(buf);
}
/* ---------------------------------------------------------------
* RSDP scan
* --------------------------------------------------------------- */
static const acpi_rsdp_v2 *acpi_find_rsdp(const void *limine_rsdp) {
/* If Limine gave us the RSDP, use it directly */
if (limine_rsdp) {
const acpi_rsdp_v2 *rsdp = (const acpi_rsdp_v2 *)limine_rsdp;
if (memneq(rsdp->signature, "RSD PTR ", 8) == 0) {
if (checksum8((const u8 *)rsdp, 20) == 0) {
return rsdp;
}
}
}
/* EBDA: extended BIOS data area, base at 0x40E */
{
u16 ebda_seg = *(const volatile u16 *)(uintptr_t)0x40E;
u64 ebda_base = (u64)ebda_seg << 4;
if (ebda_base >= 0x80000ULL && ebda_base < 0x100000ULL) {
for (u64 off = 0; off < 1024; off += 16) {
const acpi_rsdp_v2 *rsdp = (const acpi_rsdp_v2 *)(uintptr_t)(ebda_base + off);
if (off + sizeof(acpi_rsdp_v1) > 1024) break;
if (memneq(rsdp->signature, "RSD PTR ", 8) == 0) {
if (checksum8((const u8 *)rsdp, 20) == 0) {
return rsdp;
}
}
}
}
}
/* BIOS read-only area: 0x000E0000 - 0x000FFFFF */
for (u64 addr = 0x000E0000ULL; addr < 0x00100000ULL; addr += 16) {
const acpi_rsdp_v2 *rsdp = (const acpi_rsdp_v2 *)(uintptr_t)addr;
if (memneq(rsdp->signature, "RSD PTR ", 8) == 0) {
if (checksum8((const u8 *)rsdp, 20) == 0) {
return rsdp;
}
}
}
return NULL;
}
/* ---------------------------------------------------------------
* Table enumeration
* --------------------------------------------------------------- */
static void acpi_enumerate_rsdt(const acpi_sdt_header *rsdt, u32 entry_size) {
u32 entry_count = (rsdt->length - sizeof(acpi_sdt_header)) / entry_size;
const u8 *entries = (const u8 *)rsdt + sizeof(acpi_sdt_header);
g_log->info("[acpi] tables found");
for (u32 i = 0; i < entry_count; i++) {
u64 addr;
if (entry_size == 4) {
addr = (u64)((const u32 *)entries)[i];
} else {
addr = ((const u64 *)entries)[i];
}
if (addr == 0) continue;
const acpi_sdt_header *hdr = (const acpi_sdt_header *)(uintptr_t)addr;
char sig[5];
sig[0] = hdr->signature[0];
sig[1] = hdr->signature[1];
sig[2] = hdr->signature[2];
sig[3] = hdr->signature[3];
sig[4] = 0;
g_log->info("[acpi] ");
g_log->info(sig);
log_hex("[acpi] addr=", addr);
log_hex("[acpi] len =", (u64)hdr->length);
}
}
/* ---------------------------------------------------------------
* Driver entry points
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) {
return -1;
}
g_log = api->log;
g_log->info("[acpi] scanning for RSDP");
const acpi_rsdp_v2 *rsdp = acpi_find_rsdp(api->rsdp_address);
if (!rsdp) {
g_log->error("[acpi] RSDP not found");
return 0; /* optional driver, don't fail boot */
}
g_log->info("[acpi] RSDP found");
log_hex("[acpi] revision =", (u64)rsdp->revision);
g_log->info("[acpi] oem_id");
{
char oem[7];
for (int i = 0; i < 6; i++) oem[i] = rsdp->oem_id[i];
oem[6] = 0;
g_log->info(oem);
}
if (rsdp->revision >= 2 && rsdp->xsdt_addr) {
g_log->info("[acpi] using XSDT");
const acpi_sdt_header *xsdt = (const acpi_sdt_header *)(uintptr_t)rsdp->xsdt_addr;
acpi_enumerate_rsdt(xsdt, 8);
} else if (rsdp->rsdt_addr) {
g_log->info("[acpi] using RSDT");
const acpi_sdt_header *rsdt = (const acpi_sdt_header *)(uintptr_t)rsdp->rsdt_addr;
acpi_enumerate_rsdt(rsdt, 4);
} else {
g_log->warn("[acpi] no RSDT/XSDT address");
}
g_log->info("[acpi] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+645
View File
@@ -0,0 +1,645 @@
/* 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 <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_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_block_device_desc {
const char *name;
u64 sector_size;
u64 sector_count;
void *ctx;
int (*read)(void *ctx, u64 lba, u32 count, 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);
u64 (*sector_size)(u32 index);
const char *(*device_name)(u32 index);
};
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 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;
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;
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 = "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 PCI_ADDR 0xCF8
#define PCI_DATA 0xCFC
#define PCI_VENDOR_ID 0x00
#define PCI_COMMAND 0x04
#define PCI_PROG_IF 0x09
#define PCI_SUBCLASS 0x0A
#define PCI_CLASS 0x0B
#define PCI_HEADER 0x0E
#define PCI_BAR5 0x24
#define PCI_IRQ_LINE 0x3C
#define PCI_CMD_IO (1u << 0)
#define PCI_CMD_MEM (1u << 1)
#define PCI_CMD_BUSM (1u << 2)
#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_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
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 __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 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;
for (u32 i = 0; i < 100000; i++) {
cmd = g_abar[(base + PxCMD) / 4];
if (!(cmd & AHCI_CMD_CR)) break;
}
cmd &= ~AHCI_CMD_FRE;
g_abar[(base + PxCMD) / 4] = cmd;
for (u32 i = 0; i < 100000; i++) {
cmd = g_abar[(base + PxCMD) / 4];
if (!(cmd & AHCI_CMD_FR)) return 0;
}
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] = 0x25; /* 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 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_block_read(void *ctx, u64 lba, u32 count, 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_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_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;
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;
int index = api->block->register_device(&desc);
log_hex("[ahci] block provider index=", (u64)(i64)index);
} else if (identified) {
g_log->warn("[ahci] block API unavailable; provider not registered");
}
g_log->info("[ahci] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+358
View File
@@ -0,0 +1,358 @@
/* DKM APIC Driver — APIC discovery with PIC fallback
* Stage 0, required, depends on "timer", provides "irq" and "apic".
* Current kernel IRQ backend is still PIC; this driver only discovers APIC
* topology and keeps PIC routing active.
*/
#include <stdint.h>
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response;
int (*irq_register)(u8 irq, void *handler);
u64 hhdm_offset;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
static const char *const g_depends[] = { "timer" };
static const char *const g_provides[] = { "irq", "apic" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "apic",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 3, /* DKM_CLASS_INTERRUPT */
.stage = 0,
.flags = 1, /* DKM_F_REQUIRED */
.priority = 0,
.depends = g_depends,
.depends_count = 1,
.provides = g_provides,
.provides_count = 2,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
typedef struct __attribute__((packed)) {
char signature[8];
u8 checksum;
char oem_id[6];
u8 revision;
u32 rsdt_addr;
} acpi_rsdp_v1;
typedef struct __attribute__((packed)) {
char signature[8];
u8 checksum;
char oem_id[6];
u8 revision;
u32 rsdt_addr;
u32 length;
u64 xsdt_addr;
u8 ext_checksum;
u8 reserved[3];
} acpi_rsdp_v2;
typedef struct __attribute__((packed)) {
char signature[4];
u32 length;
u8 revision;
u8 checksum;
char oem_id[6];
char oem_table_id[8];
u32 oem_revision;
u32 creator_id;
u32 creator_revision;
} acpi_sdt_header;
typedef struct __attribute__((packed)) {
acpi_sdt_header hdr;
u32 lapic_addr;
u32 flags;
} acpi_madt;
struct madt_info {
u64 lapic_phys;
u32 flags;
u32 lapic_count;
u32 ioapic_count;
u32 iso_count;
};
static const struct dkm_log_api *g_log;
static int memeq(const char *a, const char *b, u32 n) {
for (u32 i = 0; i < n; i++) {
if (a[i] != b[i]) return 0;
}
return 1;
}
static u8 checksum8(const u8 *data, u32 len) {
u8 sum = 0;
for (u32 i = 0; i < len; i++) sum += data[i];
return sum;
}
static void log_hex(const char *prefix, u64 val) {
static const char hex[] = "0123456789abcdef";
char buf[19];
u32 pos = 0;
buf[pos++] = '0';
buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(val >> (i * 4)) & 0xf];
}
buf[pos] = 0;
g_log->info(prefix);
g_log->info(buf);
}
static void cpuid(u32 leaf, u32 *a, u32 *b, u32 *c, u32 *d) {
__asm__ volatile ("cpuid"
: "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d)
: "a"(leaf), "c"(0));
}
static u64 rdmsr(u32 msr) {
u32 lo;
u32 hi;
__asm__ volatile ("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
return ((u64)hi << 32) | lo;
}
static int cpu_has_lapic(void) {
u32 a, b, c, d;
cpuid(1, &a, &b, &c, &d);
(void)a;
(void)b;
(void)c;
return (d & (1u << 9)) != 0;
}
static const acpi_sdt_header *find_table_from_rsdt(const acpi_sdt_header *rsdt, const char sig[4], u32 entry_size) {
if (!rsdt || rsdt->length < sizeof(acpi_sdt_header)) return NULL;
if (checksum8((const u8 *)rsdt, rsdt->length) != 0) return NULL;
u32 count = (rsdt->length - sizeof(acpi_sdt_header)) / entry_size;
const u8 *entries = (const u8 *)rsdt + sizeof(acpi_sdt_header);
for (u32 i = 0; i < count; i++) {
u64 addr;
if (entry_size == 4) {
addr = (u64)((const u32 *)entries)[i];
} else {
addr = ((const u64 *)entries)[i];
}
if (!addr) continue;
const acpi_sdt_header *hdr = (const acpi_sdt_header *)(uintptr_t)addr;
if (hdr->length >= sizeof(acpi_sdt_header) && memeq(hdr->signature, sig, 4)) {
if (checksum8((const u8 *)hdr, hdr->length) == 0) return hdr;
}
}
return NULL;
}
static const acpi_madt *find_madt(const void *rsdp_addr) {
if (!rsdp_addr) return NULL;
const acpi_rsdp_v2 *rsdp = (const acpi_rsdp_v2 *)rsdp_addr;
if (!memeq(rsdp->signature, "RSD PTR ", 8)) return NULL;
if (checksum8((const u8 *)rsdp, 20) != 0) return NULL;
if (rsdp->revision >= 2 && rsdp->length >= sizeof(acpi_rsdp_v2) && rsdp->xsdt_addr) {
if (checksum8((const u8 *)rsdp, rsdp->length) == 0) {
const acpi_sdt_header *xsdt = (const acpi_sdt_header *)(uintptr_t)rsdp->xsdt_addr;
const acpi_sdt_header *madt = find_table_from_rsdt(xsdt, "APIC", 8);
if (madt) return (const acpi_madt *)madt;
}
}
if (rsdp->rsdt_addr) {
const acpi_sdt_header *rsdt = (const acpi_sdt_header *)(uintptr_t)(u64)rsdp->rsdt_addr;
const acpi_sdt_header *madt = find_table_from_rsdt(rsdt, "APIC", 4);
if (madt) return (const acpi_madt *)madt;
}
return NULL;
}
static void parse_madt_entries(const acpi_madt *madt, struct madt_info *info) {
const u8 *base = (const u8 *)madt;
u32 off = (u32)sizeof(acpi_madt);
while (off + 2 <= madt->hdr.length) {
const u8 *entry = base + off;
u8 type = entry[0];
u8 len = entry[1];
if (len < 2 || off + len > madt->hdr.length) {
g_log->warn("[apic] malformed MADT entry");
return;
}
if (type == 0 && len >= 8) {
u8 apic_id = entry[3];
u32 flags = *(const u32 *)(const void *)(entry + 4);
if (flags & 1u) info->lapic_count++;
log_hex("[apic] CPU LAPIC id=", apic_id);
} else if (type == 1 && len >= 12) {
u8 ioapic_id = entry[2];
u32 addr = *(const u32 *)(const void *)(entry + 4);
u32 gsi = *(const u32 *)(const void *)(entry + 8);
info->ioapic_count++;
log_hex("[apic] IOAPIC id=", ioapic_id);
log_hex("[apic] IOAPIC addr=", addr);
log_hex("[apic] IOAPIC gsi_base=", gsi);
} else if (type == 2 && len >= 10) {
u8 source = entry[3];
u32 gsi = *(const u32 *)(const void *)(entry + 4);
u16 flags = *(const u16 *)(const void *)(entry + 8);
info->iso_count++;
log_hex("[apic] ISO source=", source);
log_hex("[apic] ISO gsi=", gsi);
log_hex("[apic] ISO flags=", flags);
} else if (type == 5 && len >= 12) {
u64 override = *(const u64 *)(const void *)(entry + 4);
info->lapic_phys = override;
log_hex("[apic] LAPIC override=", override);
}
off += len;
}
}
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
g_log->info("[apic] init begin");
if (!api->irq_register) {
g_log->error("[apic] kernel irq_register missing");
return -1;
}
g_log->info("[apic] kernel IRQ backend present: PIC");
if (!cpu_has_lapic()) {
g_log->warn("[apic] CPUID local APIC not present; PIC fallback active");
g_log->info("[apic] driver ready");
return 0;
}
g_log->info("[apic] CPUID local APIC present");
u64 apic_base = rdmsr(0x1B);
u64 lapic_phys = apic_base & 0xFFFFF000ULL;
log_hex("[apic] IA32_APIC_BASE=", apic_base);
log_hex("[apic] LAPIC phys base=", lapic_phys);
if (apic_base & (1ULL << 8)) g_log->info("[apic] bootstrap processor");
if (apic_base & (1ULL << 11)) g_log->info("[apic] LAPIC enabled by firmware");
struct madt_info info;
info.lapic_phys = lapic_phys;
info.flags = 0;
info.lapic_count = 0;
info.ioapic_count = 0;
info.iso_count = 0;
const acpi_madt *madt = find_madt(api->rsdp_address);
if (madt) {
g_log->info("[apic] MADT found");
info.lapic_phys = (u64)madt->lapic_addr;
info.flags = madt->flags;
log_hex("[apic] MADT lapic_phys=", info.lapic_phys);
log_hex("[apic] MADT flags=", info.flags);
parse_madt_entries(madt, &info);
log_hex("[apic] CPU LAPIC count=", info.lapic_count);
log_hex("[apic] IOAPIC count=", info.ioapic_count);
log_hex("[apic] ISO count=", info.iso_count);
} else {
g_log->warn("[apic] MADT not found; PIC fallback active");
}
if (api->hhdm_offset && info.lapic_phys) {
volatile u32 *lapic = (volatile u32 *)(uintptr_t)(api->hhdm_offset + info.lapic_phys);
log_hex("[apic] LAPIC ID reg=", lapic[0x20 / 4]);
log_hex("[apic] LAPIC version reg=", lapic[0x30 / 4]);
log_hex("[apic] LAPIC SVR reg=", lapic[0xF0 / 4]);
} else {
g_log->warn("[apic] HHDM unavailable; skip LAPIC MMIO read");
}
g_log->info("[apic] discovery complete; PIC routing retained");
g_log->info("[apic] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+191
View File
@@ -0,0 +1,191 @@
/* DKM BootFS Driver — exposes Limine boot modules as a simple filesystem
* Stage 1, required, provides "bootfs".
* Lists all boot modules with path, size, and address.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci_api;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
/* minimal limine types matching kernel */
struct limine_file {
u64 revision;
void *address;
u64 size;
char *path;
char *cmdline;
u32 media_type;
u32 unused;
u32 tftp_ip;
u32 tftp_port;
u32 partition_index;
u32 mbr_disk_id;
u8 gpt_disk_uuid[16];
u8 gpt_part_uuid[16];
u8 part_uuid[16];
};
struct limine_module_response {
u64 revision;
u64 module_count;
struct limine_file **modules;
};
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_provides[] = { "bootfs" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "bootfs",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 7, /* DKM_CLASS_FS */
.stage = 1,
.flags = 1, /* DKM_F_REQUIRED */
.priority = 0,
.depends = NULL,
.depends_count = 0,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* Log helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static void log_hex(const char *prefix, u64 val) {
static const char hex[] = "0123456789abcdef";
char buf[19];
u32 pos = 0;
buf[pos++] = '0'; buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(val >> (i * 4)) & 0xf];
}
buf[pos] = 0;
g_log->info(prefix);
g_log->info(buf);
}
/* ---------------------------------------------------------------
* Driver entry
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
const struct limine_module_response *rsp =
(const struct limine_module_response *)api->boot_modules_response;
if (!rsp) {
g_log->error("[bootfs] no boot module response");
return -1;
}
g_log->info("[bootfs] boot module filesystem");
log_hex("[bootfs] file count=", rsp->module_count);
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (!f) continue;
g_log->info("[bootfs] ----------");
if (f->path) {
g_log->info("[bootfs] file");
g_log->info(f->path);
}
log_hex("[bootfs] size=", f->size);
log_hex("[bootfs] addr=", (u64)(uintptr_t)f->address);
if (f->cmdline) {
g_log->info("[bootfs] cmd");
g_log->info(f->cmdline);
}
}
g_log->info("[bootfs] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+259
View File
@@ -0,0 +1,259 @@
/* DKM Console Framebuffer Driver
* Stage 1, optional, provides "console".
* Light-blue background + centered circular loading animation (4-color arc ring).
*/
#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.2.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 */
static const u32 ARC[4] = { 0xFF4488CC, 0xFF2266AA, 0xFF66AAEE, 0xFF88CCFF };
/* ---------------------------------------------------------------
* Drawing helpers – all integer arithmetic, no soft-float
* --------------------------------------------------------------- */
static u64 fb_w, fb_h, fb_p;
/* double-buffer sprite for ring area (128×128 = no flicker) */
#define SPR_SIZE 128
static u32 g_sprite[SPR_SIZE * SPR_SIZE];
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;
}
}
/* alpha-blend c2 over c1, alpha 0-255 */
static u32 blend(u32 c1, u32 c2, u32 a) {
u32 na = 256 - a;
u32 r = ((c1 & 0xFF) * na + (c2 & 0xFF) * a) >> 8;
u32 g = (((c1 >> 8) & 0xFF) * na + ((c2 >> 8) & 0xFF) * a) >> 8;
u32 b = (((c1 >> 16) & 0xFF) * na + ((c2 >> 16) & 0xFF) * a) >> 8;
return 0xFF000000 | (b << 16) | (g << 8) | r;
}
/* integer sqrt – returns floor(sqrt(v)) */
static u64 isqrt(u64 v) {
u64 x = v, y = (x + 1) >> 1;
while (y < x) { x = y; y = (y + v / y) >> 1; }
return x;
}
/* approximate atan2 in degrees (0=right, CCW). dx,dy = pixel offset from center */
static i64 approx_angle(i64 dx, i64 dy) {
if (dx == 0) return dy < 0 ? 90 : 270;
i64 ax = dx < 0 ? -dx : dx;
i64 ay = dy < 0 ? -dy : dy;
i64 a;
if (ax > ay) {
a = ay * 45 / ax;
} else {
a = 90 - ax * 45 / (ay ? ay : 1);
}
/* quadrant correction */
if (dx >= 0 && dy <= 0) return a; /* Q1 */
else if (dx < 0 && dy <= 0) return 180 - a; /* Q2 */
else if (dx < 0 && dy > 0) return 180 + a; /* Q3 */
else return 360 - a; /* Q4 */
}
/* draw one arc segment: rounded caps (6° head/tail), bright mid, comet-tail fade */
static void arc_segment(u32 *fb, i64 cx, i64 cy, i64 r, i64 start, i64 sweep, u32 color, i64 thk) {
i64 ro = r + thk, ri = r - thk;
i64 ri2 = ri * ri, ro2 = (ro + 1) * (ro + 1);
i64 rnd = 6; /* rounding zone at each end, in degrees */
for (i64 dy = -ro - 1; dy <= ro + 1; dy++) {
i64 y = cy + dy;
if ((u64)y >= fb_h) continue;
u32 *line = (u32 *)((u8 *)fb + (u64)y * fb_p);
for (i64 dx = -ro - 1; dx <= ro + 1; dx++) {
i64 x = cx + dx;
if ((u64)x >= fb_w) continue;
i64 d2 = dx * dx + dy * dy;
if (d2 < ri2 - 2 || d2 > ro2 + 2) continue;
i64 ang = approx_angle(dx, dy);
i64 a = ang - start;
if (a < 0) a += 360;
if ((u64)a > (u64)sweep) continue;
/* rounded-cap fade: 0→255 over rnd°, then 255→0 over last rnd° */
u32 fade;
if ((u64)a < (u64)rnd) {
fade = (u32)(a * 255 / rnd);
} else if ((u64)a > (u64)(sweep - rnd)) {
fade = (u32)((sweep - a) * 255 / rnd);
} else {
fade = 255;
}
i64 dist = (i64)isqrt((u64)d2);
u32 effective = blend(BG, color, fade);
if (dist >= ri && dist <= ro) {
line[(u64)x] = effective;
} else if (dist >= ri - 2 && dist < ri) {
line[(u64)x] = blend(BG, effective, (u32)((dist - (ri - 2)) * 85));
} else if (dist > ro && dist <= ro + 2) {
line[(u64)x] = blend(effective, BG, (u32)((dist - ro) * 85));
}
}
}
}
/* filled disc with anti-aliased edge */
static void fill_disc(u32 *fb, i64 cx, i64 cy, i64 r, u32 color) {
i64 r2 = r * r, o2 = (r + 1) * (r + 1);
for (i64 dy = -r - 2; dy <= r + 2; dy++) {
i64 y = cy + dy;
if ((u64)y >= fb_h) continue;
u32 *line = (u32 *)((u8 *)fb + (u64)y * fb_p);
for (i64 dx = -r - 2; dx <= r + 2; dx++) {
i64 x = cx + dx;
if ((u64)x >= fb_w) continue;
i64 d2 = dx * dx + dy * dy;
if (d2 <= r2) {
line[(u64)x] = color;
} else if (d2 <= o2) {
u32 a = (u32)((o2 - d2) * 255 / (o2 - r2));
line[(u64)x] = blend(BG, color, a);
}
}
}
}
/* ---------------------------------------------------------------
* 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] boot screen");
fb_w = api->fb_width; fb_h = api->fb_height; fb_p = api->fb_pitch;
u32 *fb = (u32 *)api->fb_address;
i64 cx = (i64)fb_w / 2, cy = (i64)fb_h / 2, r = 48, thk = 4;
/* light-blue background */
fb_fill(fb, fb_p, fb_w, fb_h, BG);
/* animation: 2000 frames × 2° clockwise × ~1ms, no flicker */
i64 spr_p = SPR_SIZE * 4;
i64 scx = SPR_SIZE / 2;
i64 scy = SPR_SIZE / 2;
i64 frame = 0, base = 0;
i64 bx = cx - scx; /* screen position of sprite top-left */
i64 by = cy - scy;
while (frame < 2000) {
/* draw into sprite buffer — swap globals to sprite layout */
u64 save_w = fb_w, save_h = fb_h, save_p = fb_p;
fb_w = SPR_SIZE; fb_h = SPR_SIZE; fb_p = spr_p;
fb_fill(g_sprite, spr_p, SPR_SIZE, SPR_SIZE, BG);
arc_segment(g_sprite, scx, scy, r, base + 0, 82, ARC[0], thk);
arc_segment(g_sprite, scx, scy, r, base + 90, 82, ARC[1], thk);
arc_segment(g_sprite, scx, scy, r, base +180, 82, ARC[2], thk);
arc_segment(g_sprite, scx, scy, r, base +270, 82, ARC[3], thk);
fill_disc(g_sprite, scx, scy, r - 8, blend(BG, 0xFFD0F0FF, 80));
/* restore screen globals for blit */
fb_w = save_w; fb_h = save_h; fb_p = save_p;
/* blit sprite to screen */
for (i64 sr = 0; sr < SPR_SIZE; sr++) {
i64 sy = by + sr;
if ((u64)sy >= fb_h) continue;
u32 *dst = (u32 *)((u8 *)fb + (u64)sy * fb_p) + bx;
u32 *src = &g_sprite[sr * SPR_SIZE];
for (i64 sc = 0; sc < SPR_SIZE; sc++) {
i64 sx = bx + sc;
if ((u64)sx >= fb_w) continue;
dst[sc] = src[sc];
}
}
for (volatile u32 d = 0; d < 72000; d++) {
__asm__ volatile ("pause");
}
base -= 2;
if (base < 0) base += 360;
frame++;
}
api->log->info("[console_fb] ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+224
View File
@@ -0,0 +1,224 @@
/* DKM DevFS Driver — virtual device filesystem
* Stage 2, optional, depends on "vfs", provides "devfs".
* Exposes kernel platform info as virtual files under /dev/.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci_api;
const void *dma;
const void *vfs_api;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
struct limine_file {
u64 revision;
void *address;
u64 size;
char *path;
char *cmdline;
u8 _pad[56];
};
struct limine_module_response {
u64 revision;
u64 module_count;
struct limine_file **modules;
};
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_depends[] = { "vfs" };
static const char *const g_provides[] = { "devfs" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "devfs",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 7,
.stage = 2,
.flags = 0,
.priority = 0,
.depends = g_depends,
.depends_count = 1,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* Helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static void log_hex(const char *prefix, u64 val) {
static const char h[] = "0123456789abcdef";
char buf[19]; u32 p = 0;
buf[p++] = '0'; buf[p++] = 'x';
for (int i = 15; i >= 0; i--) buf[p++] = h[(val>>(i*4))&0xf];
buf[p] = 0;
g_log->info(prefix); g_log->info(buf);
}
/* ---------------------------------------------------------------
* Virtual file helpers
* --------------------------------------------------------------- */
static void devfs_file(const char *name, const char *content) {
g_log->info("[devfs] /dev/");
g_log->info(name);
g_log->info("[devfs] ");
g_log->info(content);
}
/* ---------------------------------------------------------------
* Driver entry
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
g_log->info("[devfs] virtual device filesystem");
/* /dev/version */
devfs_file("version", "Deshab kernel 0.1.0");
/* /dev/platform */
devfs_file("platform", "x86_64 SAS-R0");
/* /dev/fb0 */
if (api->fb_address) {
char info[64];
info[0] = 0;
/* manual number conversion for width */
{
u64 v = api->fb_width;
char tmp[24]; u32 p = 0;
if (v == 0) tmp[p++] = '0';
else { char r[24]; u32 q = 0; while (v) { r[q++] = '0' + (char)(v%10); v/=10; } while (q) tmp[p++] = r[--q]; }
tmp[p++] = 'x';
v = api->fb_height;
if (v == 0) tmp[p++] = '0';
else { char r[24]; u32 q = 0; while (v) { r[q++] = '0' + (char)(v%10); v/=10; } while (q) tmp[p++] = r[--q]; }
tmp[p++] = 'x';
v = api->fb_bpp;
if (v == 0) tmp[p++] = '0';
else { char r[24]; u32 q = 0; while (v) { r[q++] = '0' + (char)(v%10); v/=10; } while (q) tmp[p++] = r[--q]; }
tmp[p++] = ' ';
tmp[p++] = 'f';
tmp[p++] = 'b';
tmp[p++] = '0';
tmp[p] = 0;
for (u32 i = 0; i <= p; i++) info[i] = tmp[i];
}
devfs_file("fb0", info);
}
/* /dev/modules — count from boot_modules */
const struct limine_module_response *rsp =
(const struct limine_module_response *)api->boot_modules_response;
if (rsp) {
char buf[24];
buf[0] = '0'; buf[1] = 'x';
u64 v = rsp->module_count;
u32 p = 2;
if (v == 0) buf[p++] = '0';
else {
char r[18]; u32 q = 0;
while (v) { r[q++] = "0123456789abcdef"[v&0xf]; v>>=4; }
while (q) buf[p++] = r[--q];
}
buf[p] = 0;
devfs_file("modules", buf);
/* /dev/boot — list paths */
g_log->info("[devfs] /dev/boot/");
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (f && f->path) {
g_log->info("[devfs] ");
g_log->info(f->path);
}
}
}
g_log->info("[devfs] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+464
View File
@@ -0,0 +1,464 @@
/* 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 <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_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);
};
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);
};
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);
};
#define DKM_NET_F_LINK_UP (1u << 0)
#define DKM_NET_F_TX_READY (1u << 1)
#define DKM_NET_F_RX_READY (1u << 2)
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;
const struct dkm_dma_api *dma;
const void *vfs_api;
const struct dkm_net_api *net;
const void *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);
u64 hhdm_offset;
};
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_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,
};
/* PCI config ports */
#define PCI_ADDR 0xCF8
#define PCI_DATA 0xCFC
#define PCI_VENDOR_ID 0x00
#define PCI_DEVICE_ID 0x02
#define PCI_COMMAND 0x04
#define PCI_BAR0 0x10
#define PCI_IRQ_LINE 0x3C
/* 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;
static __inline__ void outl(u16 p, u32 v) { __asm__("outl %0,%1"::"a"(v),"Nd"(p)); }
static __inline__ u32 inl(u16 p) { u32 v; __asm__("inl %1,%0":"=a"(v):"Nd"(p)); return v; }
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 raw_log(const char *s) {
while (*s) {
char c = *s++;
if (c == '\n') {
for (u32 i=0;i<100000;i++) if (inb(0x3F8+5)&0x20) break;
outb(0x3F8, '\r');
}
for (u32 i=0;i<100000;i++) if (inb(0x3F8+5)&0x20) break;
outb(0x3F8, (u8)c);
}
}
static u32 pci_read(u8 bus, u8 dev, u8 func, u8 reg) {
u32 a = (1u<<31)|((u32)bus<<16)|((u32)dev<<11)|((u32)func<<8)|((u32)reg&0xFC);
outl(PCI_ADDR,a); return inl(PCI_DATA);
}
static void pci_write(u8 bus, u8 dev, u8 func, u8 reg, u32 v) {
u32 a = (1u<<31)|((u32)bus<<16)|((u32)dev<<11)|((u32)func<<8)|((u32)reg&0xFC);
outl(PCI_ADDR,a); outl(PCI_DATA,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;
for (u32 i=0;i<100000;i++) {
u32 v = g_mmio[E1000_EERD/4];
if (v & (1u<<4)) return (u16)(v >> 16);
}
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 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;
g_rx_desc[i].addr = b.phys;
g_rx_desc[i].status = 0;
}
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;
g_tx_desc[i].addr = b.phys;
g_tx_desc[i].status = E1000_TX_STA_DD;
}
raw_log("[e1000.raw] ring/buffers allocated\n");
g_mmio[E1000_RCTL/4] = 0;
g_mmio[E1000_TCTL/4] = 0;
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;
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);
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_RX_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);
raw_log("[e1000.raw] tx copied\n");
g_tx_desc[index].length = (u16)length;
g_tx_desc[index].cmd = E1000_TX_CMD_EOP | E1000_TX_CMD_IFCS | E1000_TX_CMD_RS;
g_tx_desc[index].status = 0;
g_tx_tail = (index + 1) % E1000_TX_DESC_COUNT;
g_mmio[E1000_TDT/4] = g_tx_tail;
raw_log("[e1000.raw] tx tdt written\n");
return 0;
}
static int e1000_rx_poll(void *ctx, void *buffer, u32 capacity, u32 *out_length) {
(void)ctx;
if (!g_rings_ready || !buffer || !out_length) return -1;
u32 next = (g_rx_tail + 1) % E1000_RX_DESC_COUNT;
if (!(g_rx_desc[next].status & E1000_RX_STA_DD)) return 1;
u32 len = g_rx_desc[next].length;
if (len > capacity) return -2;
copy_bytes(buffer, g_rx_buf[next], len);
*out_length = len;
g_rx_desc[next].status = 0;
g_rx_tail = next;
g_mmio[E1000_RDT/4] = g_rx_tail;
return 0;
}
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
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");
g_bar0_phys = (u64)pci_read(bus,dev,0,PCI_BAR0) & 0xFFFFFFF0ULL;
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);
for (u32 wait=0; wait<1000000; wait++) {
if (!(g_mmio[E1000_CTRL/4] & (1u << 26))) break;
}
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;
}
+307
View File
@@ -0,0 +1,307 @@
/* 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);
u64 (*sector_size)(u32 index);
const char *(*device_name)(u32 index);
};
struct dkm_kernel_api {
u32 version; u32 size; u64 feature_bits;
const struct dkm_log_api *log;
const void *mem,*utsm,*irq,*pci_api,*dma,*vfs_api,*net,*timer,*drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width,fb_height,fb_pitch; u16 fb_bpp;
const void *boot_modules_response;
int (*irq_register)(u8 irq, void *handler);
u64 hhdm_offset;
const struct dkm_block_api *block;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic; u16 abi_version; u16 desc_size;
const char *name,*version,*vendor;
u32 driver_class,stage,flags,priority;
const char *const *depends; u32 depends_count;
const char *const *provides; u32 provides_count;
u64 min_kernel_abi,feature_bits,reserved0,reserved1;
};
struct limine_file {
u64 revision; void *address; u64 size; char *path; char *cmdline; u8 _pad[56];
};
struct limine_module_response {
u64 revision; u64 module_count; struct limine_file **modules;
};
/* ---------------------------------------------------------------
* FAT32 BPB
* --------------------------------------------------------------- */
typedef struct __attribute__((packed)) {
u8 jmp[3];
char oem[8];
u16 bytes_per_sector;
u8 sectors_per_cluster;
u16 reserved_sector_count;
u8 fat_count;
u16 root_entry_count;
u16 total_sectors_16;
u8 media;
u16 sectors_per_fat_16;
u16 sectors_per_track;
u16 heads;
u32 hidden_sectors;
u32 total_sectors_32;
/* FAT32 extended */
u32 sectors_per_fat;
u16 flags;
u16 version;
u32 root_cluster;
u16 fsinfo_sector;
u16 backup_boot;
u8 reserved[12];
u8 drive;
u8 nt_flags;
u8 signature;
u32 serial;
char label[11];
char type[8];
u8 code[420];
u16 boot_sig;
} fat32_bpb;
typedef struct __attribute__((packed)) {
char name[11];
u8 attr;
u8 nt_reserved;
u8 creation_tenth;
u16 creation_time;
u16 creation_date;
u16 access_date;
u16 cluster_high;
u16 write_time;
u16 write_date;
u16 cluster_low;
u32 file_size;
} fat32_dir_entry;
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_depends[] = { "vfs", "block" };
static const char *const g_provides[] = { "fat32" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic=DKM_DRIVER_MAGIC, .abi_version=DKM_ABI_VERSION,
.desc_size=sizeof(struct dkm_driver_desc),
.name="fat32", .version="0.1.0", .vendor="Deshab",
.driver_class=7, .stage=2, .flags=0, .priority=0,
.depends=g_depends, .depends_count=2,
.provides=g_provides, .provides_count=1,
.min_kernel_abi=1,
};
/* ---------------------------------------------------------------
* Helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static u8 g_block_image[65536];
static int fat32_bpb_valid(const u8 *disk, u64 disk_size) {
if (!disk || disk_size < 512) return 0;
const fat32_bpb *bpb = (const fat32_bpb *)disk;
if (bpb->boot_sig != 0xAA55) return 0;
if (bpb->bytes_per_sector != 512) return 0;
if (bpb->sectors_per_cluster == 0) return 0;
if (bpb->reserved_sector_count == 0) return 0;
if (bpb->fat_count == 0) return 0;
if (bpb->sectors_per_fat == 0) return 0;
if (bpb->root_cluster < 2) return 0;
return 1;
}
static void log_hex(const char *p, u64 v) {
static const char h[] = "0123456789abcdef";
char b[19]; u32 i=0; b[i++]='0'; b[i++]='x';
for (int j=15;j>=0;j--) b[i++]=h[(v>>(j*4))&0xf];
b[i]=0; g_log->info(p); g_log->info(b);
}
static u32 read_u32_le(const u8 *p) {
return (u32)p[0]|((u32)p[1]<<8)|((u32)p[2]<<16)|((u32)p[3]<<24);
}
static u16 read_u16_le(const u8 *p) {
return (u16)p[0]|((u16)p[1]<<8);
}
static int strneq(const char *a, const char *b, int n) {
for (int i=0;i<n;i++) { if (a[i]!=b[i]) return 0; }
return 1;
}
static void log_name11(const char *n) {
char buf[13]; int j=0;
for (int i=0;i<8 && n[i]!=0x20 && n[i];i++) buf[j++]=n[i];
if (n[8]!=0x20 || (n[9]!=0x20 && n[9]!=0)) {
buf[j++]='.';
for (int i=8;i<11 && n[i]!=0x20 && n[i];i++) buf[j++]=n[i];
}
buf[j]=0; g_log->info(buf);
}
static const u8 *fat32_find_boot_module_image(const struct dkm_kernel_api *api, u64 *size_out) {
const struct limine_module_response *rsp =
(const struct limine_module_response *)api->boot_modules_response;
if (!rsp) return NULL;
for (u64 i=0;i<rsp->module_count;i++) {
struct limine_file *f=rsp->modules[i];
if (f&&f->cmdline&&strneq(f->cmdline,"dkm:test_fat32",13)) {
if (size_out) *size_out=f->size;
return (const u8*)f->address;
}
}
return NULL;
}
static const u8 *fat32_select_disk_image(const struct dkm_kernel_api *api, u64 *size_out) {
if (api->block && api->block->device_count && api->block->read && api->block->sector_size) {
u32 count = api->block->device_count();
log_hex("[fat32] block devices=", count);
if (count > 0 && api->block->sector_size(0) == 512) {
const char *name = api->block->device_name ? api->block->device_name(0) : NULL;
g_log->info("[fat32] trying block provider");
if (name) g_log->info(name);
int st = api->block->read(0, 0, 128, g_block_image);
log_hex("[fat32] block read status=", (u64)(i64)st);
if (st == 0 && fat32_bpb_valid(g_block_image, sizeof(g_block_image))) {
g_log->info("[fat32] using block provider image");
if (size_out) *size_out = sizeof(g_block_image);
return g_block_image;
}
g_log->warn("[fat32] block provider image is not FAT32; fallback");
}
}
u64 module_size = 0;
const u8 *module = fat32_find_boot_module_image(api, &module_size);
if (module) {
g_log->info("[fat32] using boot module image");
if (size_out) *size_out = module_size;
return module;
}
return NULL;
}
/* ---------------------------------------------------------------
* Driver entry
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api||!api->log) return -1;
g_log=api->log;
u64 disk_size = 0;
const u8 *disk = fat32_select_disk_image(api, &disk_size);
if (!disk) { g_log->warn("[fat32] no FAT32 image source"); return 0; }
if (!fat32_bpb_valid(disk, disk_size)) { g_log->warn("[fat32] invalid FAT32 BPB"); return 0; }
g_log->info("[fat32] parsing FAT32 image");
const fat32_bpb *bpb=(const fat32_bpb*)disk;
u32 bps=bpb->bytes_per_sector;
u32 spc=bpb->sectors_per_cluster;
u32 rsc=bpb->reserved_sector_count;
u32 spf=bpb->sectors_per_fat;
u32 root_clus=bpb->root_cluster;
log_hex("[fat32] bytes/sec=",bps);
log_hex("[fat32] sec/cluster=",spc);
log_hex("[fat32] fat start sec=",rsc);
log_hex("[fat32] sec/fat=",spf);
log_hex("[fat32] root cluster=",root_clus);
/* read root directory */
u32 cluster_size = bps * spc;
u32 fat_start = rsc * bps;
u32 data_start = fat_start + spf * bps;
g_log->info("[fat32] root dir entries:");
u32 clus = root_clus;
while (clus >= 2 && clus < 0x0FFFFFF8) {
u32 clus_off = data_start + (clus - 2) * cluster_size;
const fat32_dir_entry *dir = (const fat32_dir_entry *)(disk + clus_off);
for (u32 e=0; e*32 < cluster_size; e++) {
if (dir[e].name[0]==0) break;
if ((u8)dir[e].name[0]==0xE5) continue;
if (dir[e].attr==0x0F) continue; /* skip LFN */
if (dir[e].attr & 0x08) continue; /* skip volume label */
g_log->info("[fat32] ");
log_name11(dir[e].name);
log_hex("[fat32] size=",dir[e].file_size);
/* try to read README.TXT content */
if (strneq(dir[e].name,"README TXT",11)) {
u32 f_clus = read_u16_le((const u8*)&dir[e].cluster_low);
u32 f_off = data_start + (f_clus - 2)*cluster_size;
u32 f_size = dir[e].file_size;
g_log->info("[fat32] --- README.TXT content ---");
u32 n = f_size < 128 ? f_size : 128;
char line[80]; u32 lp=0;
for (u32 k=0;k<n;k++) {
u8 c = disk[f_off+k];
line[lp++]=c;
if (c=='\n'||lp>=78||k==n-1) { line[lp]=0; g_log->info("[fat32] "); g_log->info(line); lp=0; }
}
g_log->info("[fat32] --- end ---");
}
}
/* read next cluster from FAT */
u32 fat_ent_off = fat_start + clus * 4;
clus = read_u32_le(disk + fat_ent_off) & 0x0FFFFFFF;
}
g_log->info("[fat32] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle; return 0;
}
+347
View File
@@ -0,0 +1,347 @@
/* DKM NVMe Driver — PCI NVMe discovery and controller register enumeration
* Stage 1 optional storage driver, depends on "pci" and "irq", provides "block".
* This first version only discovers NVMe controllers and reads BAR0 registers;
* it does not enable queues or submit admin commands.
*/
#include <stdint.h>
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response;
int (*irq_register)(u8 irq, void *handler);
u64 hhdm_offset;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
static const char *const g_depends[] = { "pci", "irq" };
static const char *const g_provides[] = { "block" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "nvme",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 6, /* DKM_CLASS_STORAGE */
.stage = 1,
.flags = 0, /* optional */
.priority = 0,
.depends = g_depends,
.depends_count = 2,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
#define PCI_ADDR 0xCF8
#define PCI_DATA 0xCFC
#define PCI_VENDOR_ID 0x00
#define PCI_COMMAND 0x04
#define PCI_CLASS_REG 0x08
#define PCI_HEADER 0x0E
#define PCI_BAR0 0x10
#define PCI_BAR1 0x14
#define PCI_IRQ_LINE 0x3C
#define PCI_CMD_MEM (1u << 1)
#define PCI_CMD_BUSM (1u << 2)
#define NVME_CLASS_STORAGE 0x01
#define NVME_SUBCLASS_NVM 0x08
#define NVME_PROGIF_NVME 0x02
#define NVME_CAP 0x00
#define NVME_VS 0x08
#define NVME_INTMS 0x0C
#define NVME_INTMC 0x10
#define NVME_CC 0x14
#define NVME_CSTS 0x1C
#define NVME_NSSR 0x20
#define NVME_AQA 0x24
#define NVME_ASQ 0x28
#define NVME_ACQ 0x30
#define NVME_CMBLOC 0x38
#define NVME_CMBSZ 0x3C
static const struct dkm_log_api *g_log;
static volatile u8 *g_regs;
static __inline__ void outl(u16 port, u32 value) {
__asm__ volatile ("outl %0, %1" :: "a"(value), "Nd"(port));
}
static __inline__ u32 inl(u16 port) {
u32 value;
__asm__ volatile ("inl %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
static u32 pci_read(u8 bus, u8 dev, u8 func, u8 reg) {
u32 addr = (1u << 31)
| ((u32)bus << 16)
| ((u32)dev << 11)
| ((u32)func << 8)
| ((u32)reg & 0xFC);
outl(PCI_ADDR, addr);
return inl(PCI_DATA);
}
static void pci_write(u8 bus, u8 dev, u8 func, u8 reg, u32 value) {
u32 addr = (1u << 31)
| ((u32)bus << 16)
| ((u32)dev << 11)
| ((u32)func << 8)
| ((u32)reg & 0xFC);
outl(PCI_ADDR, addr);
outl(PCI_DATA, value);
}
static u32 mmio_read32(u32 off) {
return *(volatile u32 *)(void *)(g_regs + off);
}
static u64 mmio_read64(u32 off) {
u32 lo = mmio_read32(off);
u32 hi = mmio_read32(off + 4);
return ((u64)hi << 32) | lo;
}
static void log_hex(const char *prefix, u64 value) {
static const char hex[] = "0123456789abcdef";
char buf[19];
u32 pos = 0;
buf[pos++] = '0';
buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(value >> (i * 4)) & 0xf];
}
buf[pos] = 0;
g_log->info(prefix);
g_log->info(buf);
}
static int nvme_find(u8 *out_bus, u8 *out_dev, u8 *out_func) {
for (u8 bus = 0; bus < 16; bus++) {
for (u8 dev = 0; dev < 32; dev++) {
u32 vd = pci_read(bus, dev, 0, PCI_VENDOR_ID);
if ((vd & 0xffff) == 0xffff) continue;
u8 header = (u8)(pci_read(bus, dev, 0, PCI_HEADER) >> 16);
u8 func_count = (header & 0x80) ? 8 : 1;
for (u8 func = 0; func < func_count; func++) {
u32 vd2 = pci_read(bus, dev, func, PCI_VENDOR_ID);
if ((vd2 & 0xffff) == 0xffff) continue;
u32 class_reg = pci_read(bus, dev, func, PCI_CLASS_REG);
u8 prog_if = (u8)((class_reg >> 8) & 0xff);
u8 subclass = (u8)((class_reg >> 16) & 0xff);
u8 class_code = (u8)((class_reg >> 24) & 0xff);
if (class_code == NVME_CLASS_STORAGE &&
subclass == NVME_SUBCLASS_NVM &&
prog_if == NVME_PROGIF_NVME) {
*out_bus = bus;
*out_dev = dev;
*out_func = func;
return 0;
}
}
}
}
return -1;
}
static void log_nvme_version(u32 vs) {
log_hex("[nvme] version major=", (vs >> 16) & 0xffff);
log_hex("[nvme] version minor=", (vs >> 8) & 0xff);
log_hex("[nvme] version tertiary=", vs & 0xff);
}
static void log_cap_fields(u64 cap) {
log_hex("[nvme] CAP.MQES=", cap & 0xffff);
log_hex("[nvme] CAP.CQR=", (cap >> 16) & 1);
log_hex("[nvme] CAP.AMS=", (cap >> 17) & 3);
log_hex("[nvme] CAP.TO=", (cap >> 24) & 0xff);
log_hex("[nvme] CAP.DSTRD=", (cap >> 32) & 0xf);
log_hex("[nvme] CAP.NSSRS=", (cap >> 36) & 1);
log_hex("[nvme] CAP.CSS=", (cap >> 37) & 0xff);
log_hex("[nvme] CAP.MPSMIN=", (cap >> 48) & 0xf);
log_hex("[nvme] CAP.MPSMAX=", (cap >> 52) & 0xf);
}
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
g_log->info("[nvme] init begin");
u8 bus = 0;
u8 dev = 0;
u8 func = 0;
if (nvme_find(&bus, &dev, &func) != 0) {
g_log->warn("[nvme] NVMe controller not found");
g_log->info("[nvme] driver ready");
return 0;
}
g_log->info("[nvme] NVMe controller found");
log_hex("[nvme] bus=", bus);
log_hex("[nvme] dev=", dev);
log_hex("[nvme] func=", func);
u32 vd = pci_read(bus, dev, func, PCI_VENDOR_ID);
log_hex("[nvme] vendor=", vd & 0xffff);
log_hex("[nvme] device=", vd >> 16);
u32 command = pci_read(bus, dev, func, PCI_COMMAND) & 0xffff;
command |= PCI_CMD_MEM | PCI_CMD_BUSM;
pci_write(bus, dev, func, PCI_COMMAND, command);
log_hex("[nvme] PCI command=", command);
u32 bar0_lo = pci_read(bus, dev, func, PCI_BAR0);
u32 bar1_hi = pci_read(bus, dev, func, PCI_BAR1);
u64 bar_phys;
if (bar0_lo & 1u) {
g_log->warn("[nvme] BAR0 is IO space; unsupported");
g_log->info("[nvme] driver ready");
return 0;
}
if ((bar0_lo & 0x6u) == 0x4u) {
bar_phys = ((u64)bar1_hi << 32) | (u64)(bar0_lo & 0xFFFFFFF0u);
} else {
bar_phys = (u64)(bar0_lo & 0xFFFFFFF0u);
}
u32 irq_line = pci_read(bus, dev, func, PCI_IRQ_LINE) & 0xff;
log_hex("[nvme] BAR0 phys=", bar_phys);
log_hex("[nvme] PCI IRQ line=", irq_line);
if (!api->hhdm_offset || !bar_phys) {
g_log->warn("[nvme] missing HHDM or BAR0; skip MMIO enumeration");
g_log->info("[nvme] driver ready");
return 0;
}
if (bar_phys >= 0x100000000ULL) {
g_log->warn("[nvme] BAR0 is above 4G; current HHDM MMIO map cannot safely read it");
g_log->info("[nvme] discovery only; MMIO enumeration skipped");
g_log->info("[nvme] driver ready");
return 0;
}
g_regs = (volatile u8 *)(uintptr_t)(api->hhdm_offset + bar_phys);
log_hex("[nvme] HHDM offset=", api->hhdm_offset);
u64 cap = mmio_read64(NVME_CAP);
u32 vs = mmio_read32(NVME_VS);
u32 intms = mmio_read32(NVME_INTMS);
u32 intmc = mmio_read32(NVME_INTMC);
u32 cc = mmio_read32(NVME_CC);
u32 csts = mmio_read32(NVME_CSTS);
u32 nssr = mmio_read32(NVME_NSSR);
u32 aqa = mmio_read32(NVME_AQA);
u64 asq = mmio_read64(NVME_ASQ);
u64 acq = mmio_read64(NVME_ACQ);
u32 cmbloc = mmio_read32(NVME_CMBLOC);
u32 cmbsz = mmio_read32(NVME_CMBSZ);
log_hex("[nvme] CAP=", cap);
log_cap_fields(cap);
log_hex("[nvme] VS=", vs);
log_nvme_version(vs);
log_hex("[nvme] INTMS=", intms);
log_hex("[nvme] INTMC=", intmc);
log_hex("[nvme] CC=", cc);
log_hex("[nvme] CSTS=", csts);
log_hex("[nvme] NSSR=", nssr);
log_hex("[nvme] AQA=", aqa);
log_hex("[nvme] ASQ=", asq);
log_hex("[nvme] ACQ=", acq);
log_hex("[nvme] CMBLOC=", cmbloc);
log_hex("[nvme] CMBSZ=", cmbsz);
if (cc & 1u) {
g_log->warn("[nvme] controller already enabled; leaving state unchanged");
} else {
g_log->info("[nvme] controller disabled; queues not configured");
}
g_log->info("[nvme] discovery only; admin queues disabled");
g_log->info("[nvme] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+251
View File
@@ -0,0 +1,251 @@
/* DKM PCI Driver — PCI bus enumeration via config space (0xCF8/0xCFC)
* Stage 0, required, depends on "irq", provides "pci".
* No IRQ needed for enumeration. Scans all buses/devices/functions.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci_api;
const void *dma;
const void *vfs;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
/* ---------------------------------------------------------------
* PCI constants
* --------------------------------------------------------------- */
#define PCI_CFG_ADDR 0xCF8
#define PCI_CFG_DATA 0xCFC
#define PCI_VENDOR_ID 0x00
#define PCI_DEVICE_ID 0x02
#define PCI_COMMAND 0x04
#define PCI_STATUS 0x06
#define PCI_CLASS 0x0B /* class code */
#define PCI_SUBCLASS 0x0A /* subclass */
#define PCI_PROG_IF 0x09 /* prog IF */
#define PCI_HEADER_TYPE 0x0E
#define PCI_BAR0 0x10
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_depends[] = { "irq" };
static const char *const g_provides[] = { "pci" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "pci",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 2, /* DKM_CLASS_BUS */
.stage = 0,
.flags = 1, /* DKM_F_REQUIRED */
.priority = 0,
.depends = g_depends,
.depends_count = 1,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* I/O helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static __inline__ void outl(u16 port, u32 value) {
__asm__ volatile ("outl %0, %1" :: "a"(value), "Nd"(port));
}
static __inline__ u32 inl(u16 port) {
u32 value;
__asm__ volatile ("inl %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
/* ---------------------------------------------------------------
* PCI config access
* --------------------------------------------------------------- */
static u32 pci_cfg_read(u8 bus, u8 dev, u8 func, u8 reg) {
u32 addr = (u32)((1u << 31)
| ((u32)bus << 16)
| ((u32)dev << 11)
| ((u32)func << 8)
| ((u32)reg & 0xFC));
outl(PCI_CFG_ADDR, addr);
return inl(PCI_CFG_DATA);
}
static void pci_cfg_write(u8 bus, u8 dev, u8 func, u8 reg, u32 val) {
u32 addr = (u32)((1u << 31)
| ((u32)bus << 16)
| ((u32)dev << 11)
| ((u32)func << 8)
| ((u32)reg & 0xFC));
outl(PCI_CFG_ADDR, addr);
outl(PCI_CFG_DATA, val);
}
/* ---------------------------------------------------------------
* Log helpers
* --------------------------------------------------------------- */
static void log_hex(const char *prefix, u64 val) {
static const char hex[] = "0123456789abcdef";
char buf[19];
u32 pos = 0;
buf[pos++] = '0'; buf[pos++] = 'x';
for (int i = 15; i >= 0; i--) {
buf[pos++] = hex[(val >> (i * 4)) & 0xf];
}
buf[pos] = 0;
g_log->info(prefix);
g_log->info(buf);
}
static const char *pci_class_name(u8 base, u8 sub) {
switch (base) {
case 0x00: return "Legacy";
case 0x01: return "Storage";
case 0x02: return "Network";
case 0x03: return "Display";
case 0x04: return "Multimedia";
case 0x05: return "Memory";
case 0x06: return "Bridge";
case 0x07: return "SimpleComm";
case 0x08: return "BasePeriph";
case 0x09: return "Input";
case 0x0A: return "Docking";
case 0x0B: return "CPU";
case 0x0C: return "SerialBus";
case 0x0D: return "Wireless";
case 0x0E: return "IntelligentIO";
case 0x0F: return "Satellite";
case 0x10: return "Crypto";
case 0x11: return "SignalProc";
case 0x12: return "Accelerator";
default: return "Unknown";
}
(void)sub;
}
/* ---------------------------------------------------------------
* Enumeration
* --------------------------------------------------------------- */
static void pci_scan_bus(u8 bus) {
for (u8 dev = 0; dev < 32; dev++) {
u32 vid_dev = pci_cfg_read(bus, dev, 0, PCI_VENDOR_ID);
u16 vendor = (u16)(vid_dev & 0xffff);
if (vendor == 0xffff) continue;
u8 header_type = (u8)(pci_cfg_read(bus, dev, 0, PCI_HEADER_TYPE) >> 16);
int multi_func = (header_type & 0x80) != 0;
u8 func_count = multi_func ? 8 : 1;
for (u8 func = 0; func < func_count; func++) {
u32 vid_dev2 = pci_cfg_read(bus, dev, func, PCI_VENDOR_ID);
u16 vendor2 = (u16)(vid_dev2 & 0xffff);
if (vendor2 == 0xffff) continue;
u16 device = (u16)(vid_dev2 >> 16);
u32 cc = pci_cfg_read(bus, dev, func, PCI_CLASS);
u8 class_code = (u8)(cc >> 24);
u8 subclass = (u8)((cc >> 16) & 0xff);
g_log->info("[pci]");
log_hex("[pci] bus=", bus);
log_hex("[pci] dev=", dev);
log_hex("[pci] func=", func);
log_hex("[pci] vendor=", vendor2);
log_hex("[pci] device=", device);
g_log->info("[pci] class");
g_log->info(pci_class_name(class_code, subclass));
log_hex("[pci] class_hex=", class_code);
log_hex("[pci] subclass=", subclass);
}
}
}
/* ---------------------------------------------------------------
* Driver entry
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
g_log->info("[pci] scanning PCI bus");
pci_scan_bus(0);
g_log->info("[pci] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+139
View File
@@ -0,0 +1,139 @@
/* DKM PS/2 Keyboard Driver — IRQ1 scan code → ASCII
* Stage 3, optional, depends on "irq", provides "keyboard".
* Registers IRQ1 handler, translates scan codes via lookup table.
*/
#include <stdint.h>
/* DKM ABI types */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version; u32 size; u64 feature_bits;
const struct dkm_log_api *log;
const void *mem,*utsm,*irq_api,*pci_api,*dma,*vfs_api,*net,*timer,*drr;
const void *rsdp_address,*fb_address;
u64 fb_width,fb_height,fb_pitch; u16 fb_bpp;
const void *boot_modules_response;
int (*irq_register)(u8 irq, void *handler);
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic; u16 abi_version; u16 desc_size;
const char *name,*version,*vendor;
u32 driver_class,stage,flags,priority;
const char *const *depends; u32 depends_count;
const char *const *provides; u32 provides_count;
u64 min_kernel_abi,feature_bits,reserved0,reserved1;
};
/* Driver descriptor */
static const char *const g_depends[] = {"irq"};
static const char *const g_provides[] = {"keyboard"};
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic=DKM_DRIVER_MAGIC, .abi_version=DKM_ABI_VERSION,
.desc_size=sizeof(struct dkm_driver_desc),
.name="ps2kbd", .version="0.1.0", .vendor="Deshab",
.driver_class=10, .stage=3, .flags=0, .priority=0,
.depends=g_depends, .depends_count=1,
.provides=g_provides, .provides_count=1,
.min_kernel_abi=1,
};
/* Scan code set 1 → ASCII (lowercase) */
static const char sc_ascii[] = {
0,0,'1','2','3','4','5','6','7','8','9','0','-','=',0,
0,'q','w','e','r','t','y','u','i','o','p','[',']',0,
0,'a','s','d','f','g','h','j','k','l',';','\'','`',0,
'\\','z','x','c','v','b','n','m',',','.','/',0,
'*',0,' ',0
};
static const struct dkm_log_api *g_log;
static volatile int g_has_key;
static volatile u8 g_last_sc;
/* inline I/O */
static u8 inb(u16 p) { u8 v; __asm__("inb %1,%0":"=a"(v):"Nd"(p)); return v; }
static void outb(u16 p, u8 v) { __asm__("outb %0,%1"::"a"(v),"Nd"(p)); }
static void log_hex(const char *prefix, u64 v) {
static const char h[]="0123456789abcdef";
char b[19]; u32 i=0; b[i++]='0'; b[i++]='x';
for (int j=15;j>=0;j--) b[i++]=h[(v>>(j*4))&0xf];
b[i]=0; g_log->info(prefix); g_log->info(b);
}
static int kbd_handler(u8 irq) {
(void)irq;
g_last_sc = inb(0x60);
g_has_key = 1;
return 0; /* let kernel send EOI */
}
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api||!api->log) return -1;
g_log=api->log;
if (!api->irq_register) {
g_log->warn("[kbd] irq_register not available");
return 0;
}
if (api->irq_register(1, (void*)(uintptr_t)kbd_handler) != 0) {
g_log->error("[kbd] failed to register IRQ1");
return -1;
}
g_log->info("[kbd] IRQ1 registered, waiting for keypress");
g_log->info("[kbd] (boot will continue, key echo in ISR)");
/* spin briefly to show a key echo demo */
int ticks = 0;
while (ticks < 200000) {
if (g_has_key) {
u8 sc = g_last_sc;
g_has_key = 0;
if (sc < 0x80) {
/* make code */
log_hex("[kbd] sc=", sc);
if (sc < sizeof(sc_ascii) && sc_ascii[sc]) {
char buf[2] = {sc_ascii[sc], 0};
g_log->info("[kbd] key");
g_log->info(buf);
}
}
}
for (volatile int z=0;z<100;z++) {}
ticks++;
}
g_log->info("[kbd] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle; return 0;
}
+105
View File
@@ -0,0 +1,105 @@
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$Root = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $ScriptDir))
$Source = Join-Path $Root 'CODE\DKM\stub_driver\stub_driver.c'
$Manifest = Join-Path $Root 'SYSTEM\driver\manifest.json'
$SystemDriver = Join-Path $Root 'SYSTEM\driver'
$BuildDir = Join-Path $Root '.build_tmp\drivers'
function Find-Tool($Name, $ExtraNames = @()) {
$names = @($Name) + $ExtraNames
foreach ($n in $names) {
$cmd = Get-Command $n -ErrorAction SilentlyContinue
if ($cmd) { return $cmd.Source }
}
$dirs = @(
'C:\Program Files\LLVM\bin',
'C:\Program Files (x86)\LLVM\bin',
'C:\LLVM\bin',
'D:\LLVM\bin',
'D:\Program Files\LLVM\bin',
'D:\Code\LLVM\bin',
'C:\msys64\clang64\bin',
'C:\msys64\mingw64\bin',
'C:\mingw64\bin'
)
foreach ($dir in $dirs) {
foreach ($n in $names) {
$candidate = Join-Path $dir $n
if (Test-Path $candidate) { return $candidate }
if (-not $n.EndsWith('.exe')) {
$candidateExe = Join-Path $dir "$n.exe"
if (Test-Path $candidateExe) { return $candidateExe }
}
}
}
return $null
}
function Get-DriverClassValue([string]$Class) {
switch ($Class) {
'platform' { return 1 }
'bus' { return 2 }
'interrupt' { return 3 }
'timer' { return 4 }
'console' { return 5 }
'storage' { return 6 }
'fs' { return 7 }
'fs-core' { return 8 }
'net' { return 9 }
'input' { return 10 }
'gpu' { return 11 }
default { return 0 }
}
}
$clang = Find-Tool 'clang'
$lld = Find-Tool 'ld.lld'
if (-not $clang) {
throw 'clang was not found. Install LLVM/Clang.'
}
if (-not $lld) {
throw 'ld.lld was not found. Install LLVM lld.'
}
New-Item -ItemType Directory -Force -Path $BuildDir | Out-Null
$manifestData = Get-Content -Raw -LiteralPath $Manifest | ConvertFrom-Json
$count = 0
foreach ($stage in $manifestData.stages) {
foreach ($driver in $stage.drivers) {
$relative = [string]$driver.path
if (-not $relative.StartsWith('driver/')) {
throw "Unexpected driver path: $relative"
}
$destRelative = $relative.Substring('driver/'.Length).Replace('/', '\')
$dest = Join-Path $SystemDriver $destRelative
$destDir = Split-Path -Parent $dest
New-Item -ItemType Directory -Force -Path $destDir | Out-Null
$name = [string]$driver.name
$classValue = Get-DriverClassValue ([string]$driver.class)
$stageValue = [int]$stage.id
$flags = 0
if ([bool]$driver.required) { $flags = $flags -bor 1 }
if ($stageValue -le 1) { $flags = $flags -bor 2 }
$obj = Join-Path $BuildDir "$name.o"
$drv = Join-Path $BuildDir "$name.drv"
$driverNameDefine = 'DRIVER_NAME=' + $name
& $clang -target x86_64-unknown-none -std=c11 -ffreestanding -fno-stack-protector -fno-pic -fno-pie -mno-red-zone -Wall -Wextra -O2 -c $Source -o $obj "-D$driverNameDefine" "-DDRIVER_CLASS=$classValue" "-DDRIVER_STAGE=$stageValue" "-DDRIVER_FLAGS=$flags"
if ($LASTEXITCODE -ne 0) { throw "failed to compile stub driver: $name" }
& $lld -r -o $drv $obj
if ($LASTEXITCODE -ne 0) { throw "failed to link stub driver: $name" }
Copy-Item -LiteralPath $drv -Destination $dest -Force
Write-Host "[drivers] installed $relative"
$count++
}
}
Write-Host "[drivers] installed $count DKM stub drivers"
+93
View File
@@ -0,0 +1,93 @@
#include <stdint.h>
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1
#ifndef DRIVER_NAME
#define DRIVER_NAME stub
#endif
#define DKM_STRINGIFY_INNER(x) #x
#define DKM_STRINGIFY(x) DKM_STRINGIFY_INNER(x)
#define DRIVER_NAME_STRING DKM_STRINGIFY(DRIVER_NAME)
#ifndef DRIVER_CLASS
#define DRIVER_CLASS 0
#endif
#ifndef DRIVER_STAGE
#define DRIVER_STAGE 0
#endif
#ifndef DRIVER_FLAGS
#define DRIVER_FLAGS 0
#endif
#ifndef DRIVER_PRIORITY
#define DRIVER_PRIORITY 0
#endif
struct dkm_driver_desc {
uint32_t magic;
uint16_t abi_version;
uint16_t desc_size;
const char *name;
const char *version;
const char *vendor;
uint32_t driver_class;
uint32_t stage;
uint32_t flags;
uint32_t priority;
const char *const *depends;
uint32_t depends_count;
const char *const *provides;
uint32_t provides_count;
uint64_t min_kernel_abi;
uint64_t feature_bits;
uint64_t reserved0;
uint64_t reserved1;
};
struct dkm_kernel_api;
struct dkm_driver_handle;
__attribute__((visibility("default")))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = DRIVER_NAME_STRING,
.version = "0.1.0-stub",
.vendor = "Deshab",
.driver_class = DRIVER_CLASS,
.stage = DRIVER_STAGE,
.flags = DRIVER_FLAGS,
.priority = DRIVER_PRIORITY,
.depends = 0,
.depends_count = 0,
.provides = 0,
.provides_count = 0,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api, struct dkm_driver_handle *handle) {
(void)api;
(void)handle;
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+192
View File
@@ -0,0 +1,192 @@
/* DKM Timer Driver - PIT (Programmable Interval Timer)
* Stage 0 platform driver, provides "timer".
* No IDT/IRQ required - uses PIT counter polling for busy-wait delay.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types (standalone, no kernel headers)
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
/* ---------------------------------------------------------------
* PIT I/O ports
* --------------------------------------------------------------- */
#define PIT_CH0_DATA 0x40
#define PIT_CH1_DATA 0x41
#define PIT_CH2_DATA 0x42
#define PIT_CMD 0x43
/* PIT frequency: 1.193182 MHz */
#define PIT_BASE_FREQ 1193182ULL
static const char *const g_provides[] = { "timer" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "timer",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 4, /* DKM_CLASS_TIMER */
.stage = 0,
.flags = 1, /* DKM_F_REQUIRED */
.priority = 0,
.depends = NULL,
.depends_count = 0,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* Inline assembly for port I/O (works in Ring0 SAS-R0)
* --------------------------------------------------------------- */
static __inline__ void outb(u16 port, u8 value) {
__asm__ volatile ("outb %0, %1" :: "a"(value), "Nd"(port));
}
static __inline__ u8 inb(u16 port) {
u8 value;
__asm__ volatile ("inb %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
/* ---------------------------------------------------------------
* PIT operations
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static void pit_set_channel(u8 channel, u8 mode, u16 count) {
u8 cmd = (u8)((channel << 6) | (3 << 4) | (mode << 1));
outb(PIT_CMD, cmd);
outb((u16)(PIT_CH0_DATA + channel), (u8)(count & 0xff));
outb((u16)(PIT_CH0_DATA + channel), (u8)((count >> 8) & 0xff));
}
/* Read back current counter value via latch command */
static u16 pit_read_counter(void) {
u8 cmd = 0xD0; /* read-back: channel 0, latch count, no status */
outb(PIT_CMD, cmd);
u8 lo = inb(PIT_CH0_DATA);
u8 hi = inb(PIT_CH0_DATA);
return (u16)(((u16)hi << 8) | lo);
}
/* Busy-wait delay using PIT channel 0 counter.
* count: PIT divisor (1193182 = ~1 second)
* The counter counts DOWN from 'count' to 0.
* We set it to 'count', then poll until it reaches near 0.
*/
static void pit_delay(u16 count) {
pit_set_channel(0, 0, count); /* mode 0: interrupt on terminal count */
u16 prev = pit_read_counter();
u64 loops = 0;
while (1) {
u16 cur = pit_read_counter();
if (cur > prev && loops > 10) {
break; /* counter wrapped → terminal count reached */
}
prev = cur;
loops++;
}
}
/* ---------------------------------------------------------------
* Driver entry points
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) {
return -1;
}
g_log = api->log;
g_log->info("[timer] PIT driver initializing");
/* Quick calibration: set PIT to max count, measure how many
* iterations of read_counter() happen before terminal count.
*/
pit_set_channel(0, 0, 0xFFFF); /* 0xFFFF = max, ~55ms at 1.193 MHz */
u16 prev = pit_read_counter();
u64 cal_loops = 0;
while (1) {
u16 cur = pit_read_counter();
cal_loops++;
if (cur > prev && cal_loops > 5) break;
prev = cur;
}
/* Expected: PIT_BASE_FREQ / 0xFFFF ≈ 18.2 Hz, period ≈ 55 ms */
g_log->info("[timer] PIT calibration complete");
g_log->info("[timer] PIT channel 0 operational");
/* Do a quick ~100ms delay demo */
g_log->info("[timer] running 100ms busy-wait demo");
pit_delay((u16)(PIT_BASE_FREQ / 10)); /* ~0.1 sec = 119318 counts */
g_log->info("[timer] 100ms delay done");
g_log->info("[timer] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+222
View File
@@ -0,0 +1,222 @@
/* DKM VFS Driver — Virtual File System layer
* Stage 2, required, depends on "bootfs", provides "vfs".
* Mounts bootfs modules as files, implements basic open/read.
* Demo: reads and displays first 64 bytes of manifest.json.
*/
#include <stdint.h>
/* ---------------------------------------------------------------
* DKM ABI types
* --------------------------------------------------------------- */
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
#define NULL ((void *)0)
struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
};
struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const struct dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci_api;
const void *dma;
const void *vfs_api;
const void *net;
const void *timer;
const void *drr;
const void *rsdp_address;
const void *fb_address;
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response;
};
struct dkm_driver_handle;
struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
};
struct limine_file {
u64 revision;
void *address;
u64 size;
char *path;
char *cmdline;
u8 _pad[56];
};
struct limine_module_response {
u64 revision;
u64 module_count;
struct limine_file **modules;
};
/* ---------------------------------------------------------------
* Driver descriptor
* --------------------------------------------------------------- */
static const char *const g_depends[] = { "bootfs" };
static const char *const g_provides[] = { "vfs" };
__attribute__((visibility("default"), used))
const struct dkm_driver_desc driver_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(struct dkm_driver_desc),
.name = "vfs",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = 8, /* DKM_CLASS_FS_CORE */
.stage = 2,
.flags = 1,
.priority = 0,
.depends = g_depends,
.depends_count = 1,
.provides = g_provides,
.provides_count = 1,
.min_kernel_abi = 1,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
/* ---------------------------------------------------------------
* Helpers
* --------------------------------------------------------------- */
static const struct dkm_log_api *g_log;
static void log_hex(const char *prefix, u64 val) {
static const char h[] = "0123456789abcdef";
char buf[19];
u32 p = 0;
buf[p++] = '0'; buf[p++] = 'x';
for (int i = 15; i >= 0; i--) buf[p++] = h[(val >> (i*4)) & 0xf];
buf[p] = 0;
g_log->info(prefix); g_log->info(buf);
}
static u64 min64(u64 a, u64 b) { return a < b ? a : b; }
static int path_match(const char *bp, const char *mp) {
/* strip leading '/' from bootloader path */
while (*bp == '/') bp++;
u64 i = 0;
while (bp[i] && mp[i] && bp[i] == mp[i]) i++;
return bp[i] == 0 && mp[i] == 0;
}
static int str_len(const char *s) {
int l = 0; while (s[l]) l++; return l;
}
/* ---------------------------------------------------------------
* Driver entry
* --------------------------------------------------------------- */
__attribute__((visibility("default")))
int driver_init(const struct dkm_kernel_api *api,
struct dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log) return -1;
g_log = api->log;
const struct limine_module_response *rsp =
(const struct limine_module_response *)api->boot_modules_response;
if (!rsp) { g_log->error("[vfs] no modules"); return -1; }
g_log->info("[vfs] mounting bootfs as root");
log_hex("[vfs] files=", rsp->module_count);
/* list all files */
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (!f || !f->path) continue;
g_log->info("[vfs] /");
g_log->info(f->path);
}
/* ---- demo: open & read /driver/manifest.json ---- */
g_log->info("[vfs] demo: open //driver/manifest.json");
struct limine_file *target = NULL;
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (f && f->path && path_match(f->path, "driver/manifest.json")) {
target = f; break;
}
}
if (!target) {
g_log->warn("[vfs] manifest.json not found");
} else {
log_hex("[vfs] size=", target->size);
g_log->info("[vfs] content (first 64 bytes):");
/* dump first 64 bytes as hex + ascii */
u64 n = min64(64, target->size);
const u8 *data = (const u8 *)target->address;
char line[80];
for (u64 off = 0; off < n; off += 16) {
u32 pos = 0;
for (u32 j = 0; j < 16 && off + j < n; j++) {
u8 b = data[off + j];
line[pos++] = "0123456789abcdef"[b >> 4];
line[pos++] = "0123456789abcdef"[b & 0xf];
line[pos++] = ' ';
}
/* ascii */
line[pos++] = ' ';
for (u32 j = 0; j < 16 && off + j < n; j++) {
u8 c = data[off + j];
line[pos++] = (c >= 32 && c < 127) ? (char)c : '.';
}
line[pos] = 0;
g_log->info(line);
}
}
g_log->info("[vfs] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+379
View File
@@ -0,0 +1,379 @@
/* 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 <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_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);
};
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);
};
#define DKM_NET_F_LINK_UP (1u << 0)
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 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;
};
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[] = { "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
};
#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_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)
#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 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;
}
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 u8 pci_read8(u8 bus, u8 dev, u8 func, u8 reg) {
u32 v = pci_read(bus, dev, func, reg);
return (u8)((v >> ((reg & 3) * 8)) & 0xff);
}
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");
}
}
__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("[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 = 0;
netdev.rx_poll = 0;
int net_index = api->net->register_device(&netdev);
log_hex("[virtio_net] netdev register rc=", (u64)(i64)net_index);
} else {
g_log->warn("[virtio_net] net API unavailable; netdev not registered");
}
g_log->info("[virtio_net] discovery only; virtqueues disabled");
g_log->info("[virtio_net] driver ready");
return 0;
}
__attribute__((visibility("default")))
int driver_exit(struct dkm_driver_handle *handle) {
(void)handle;
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
CC := clang
LD := ld.lld
OBJCOPY := llvm-objcopy
ROOT := ../..
OUT := $(ROOT)/SYSTEM/boot/utsm.elf
CFLAGS := -target x86_64-unknown-none -std=c11 -ffreestanding -fno-builtin -fno-stack-protector -fno-pic -fno-pie -mcmodel=kernel -mno-red-zone -mno-sse -mno-sse2 -mno-mmx -msoft-float -m64 -Wall -Wextra -Iinclude -O2
ASFLAGS := -target x86_64-unknown-none -ffreestanding -fno-pic -fno-pie -mcmodel=kernel -mno-red-zone -mno-sse -mno-sse2 -mno-mmx -msoft-float -m64 -Iinclude
LDFLAGS := -nostdlib -static -z max-page-size=0x1000 -T linker.ld
C_SOURCES := $(wildcard arch/x86_64/*.c kernel/*.c runtime/*.c mm/*.c core/*.c crypto/*.c pckc/*.c utrw/*.c drr/*.c dkm/*.c test/*.c)
S_SOURCES := $(wildcard arch/x86_64/*.S)
OBJECTS := $(C_SOURCES:.c=.o) $(S_SOURCES:.S=.o)
.PHONY: all clean
all: $(OUT)
$(OUT): $(OBJECTS) linker.ld
@if not exist "$(ROOT)\SYSTEM\boot" mkdir "$(ROOT)\SYSTEM\boot"
$(LD) $(LDFLAGS) -o $@ $(OBJECTS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
%.o: %.S
$(CC) $(ASFLAGS) -c $< -o $@
clean:
powershell -NoProfile -Command "Get-ChildItem -Path . -Recurse -Filter *.o | Remove-Item -Force; if (Test-Path '$(OUT)') { Remove-Item '$(OUT)' -Force }"
+935
View File
@@ -0,0 +1,935 @@
// 编译到 SYSTEM/boot/utsm.elf
# UTSM 内核模块设计
UTSM 是当前内核架构中的封缄内存模块。
```text
UTSM = UUID-Tuned Sealed Memory
中文名:UUID 调谐封缄内存
```
UTSM 的目标是在单地址空间 Ring0 高性能内核中提供一种轻量内存语义:
```text
所有普通内存可以被直接读取,但直接读取到的是密文。
真正有效的明文读写必须经过 UTSM 读写器。
UUID 作为进程和内存段的调谐因子。
DRR 负责 root key、checkpoint、recovery log 和回滚。
```
---
## 1. 所属总架构
```text
SAS-R0-PCQ
单地址空间 Ring0 任务模型
Per-CPU O(1) 位图调度器
DRR
Dedicated Recovery Root
看门狗 / checkpoint / recovery log / A-B 回滚
UTSM
UUID-Tuned Sealed Memory
UUID 调谐封缄内存
UTRW
UTSM Tagged Reader/Writer
UTSM 带标记读写器
DMP
Descriptor Meta Page
段描述符元页
PCKC
Per-CPU Key Cache
每 CPU 密钥缓存
```
---
## 2. UTSM 核心规则
```text
1. 数据区只存连续密文。
2. UUID 不插入数据区。
3. UUID 使用 128-bit 二进制格式。
4. 每个加密段有独立 DMP。
5. 每个任务有 process_uuid 和 capability table。
6. 读写明文必须经过 UTRW。
7. 直接读取 cipher_base 只得到密文。
8. 直接写入 cipher_base 会破坏段一致性,段可被标记为 POISONED。
9. DRR 保存 root key、checkpoint、recovery log 和恢复状态。
10. 调度器只加载 crypto context,不扫描段,不破坏 O(1) 调度。
```
---
## 3. 内存布局
每个 UTSM 段由 DMP 和密文数据区组成。
```text
+-------------------------------+
| DMP: Descriptor Meta Page |
| 段描述符元页 |
+-------------------------------+
| Cipher Data Page 0 |
+-------------------------------+
| Cipher Data Page 1 |
+-------------------------------+
| Cipher Data Page 2 |
+-------------------------------+
| ... |
+-------------------------------+
```
全局区域:
```text
+--------------------------------------------------+
| Normal Encrypted Segment Region |
| 普通加密段数据区 |
+--------------------------------------------------+
| DMP Pool |
| 段描述符元页池 |
+--------------------------------------------------+
| Segment Table |
| 全局段表 |
+--------------------------------------------------+
| PCKC Area |
| Per-CPU Key Cache 区 |
+--------------------------------------------------+
| DRR Reserved Region |
| root key / checkpoint / recovery log |
+--------------------------------------------------+
```
---
## 4. 基础类型
```c
typedef struct {
uint64_t hi;
uint64_t lo;
} uuid128_t;
```
UUID 不转十进制字符串,原因:
```text
16 字节固定长度
比较快
cache 友好
适合 KDF
适合 SIMD
避免十进制解析和孔洞布局
```
---
## 5. 进程加密上下文
```c
struct utsm_process_context {
uuid128_t process_uuid;
uint64_t crypto_epoch;
uint64_t recovery_generation;
uint32_t capability_table_slot;
uint32_t capability_count;
uint32_t flags;
};
```
字段含义:
```text
process_uuid
创建任务时生成的进程 UUID。
crypto_epoch
当前密钥版本,用于重加密、回滚和 crypto erase。
recovery_generation
当前 DRR checkpoint 版本。
capability_table_slot
该任务 capability table 的位置。
capability_count
该任务拥有的段能力数量。
flags
PWC、DMA、强恢复等策略标志。
```
---
## 6. 加密段描述符
```c
struct utsm_segment_desc {
uuid128_t segment_uuid;
uuid128_t owner_process_uuid;
void *cipher_base;
uint64_t cipher_length;
void *dmp_base;
uint64_t key_epoch;
uint64_t tweak_seed;
void *dirty_bitmap;
void *mac_table;
uint32_t generation;
uint32_t flags;
uint32_t state;
uint32_t last_cpu;
uint64_t writer_seq;
uint64_t checkpoint_generation;
};
```
段状态:
```text
FREE
ACTIVE
CHECKPOINTING
SEALED
RECOVERING
POISONED
DESTROYED
```
---
## 7. DMP 段描述符元页
DMP 是热路径加速结构,替代“UUID 数字位置表”。
```c
struct utsm_dmp {
uint64_t magic;
uint32_t version;
uint32_t segment_slot;
uint64_t fast_base;
uint64_t fast_limit;
uint64_t fast_tweak_seed;
uint64_t fast_key_epoch;
uint64_t dirty_bitmap_base;
uint64_t mac_table_base;
uint64_t last_writer_seq;
uint32_t last_cpu;
uint32_t flags;
uint64_t crc;
};
```
DMP 用于:
```text
O(1) 段定位
快速边界检查
tweak 生成
Dirty Bitmap 定位
MAC Table 定位
checkpoint
recovery
```
---
## 8. Capability
任务访问段时使用 capability,而不是裸 UUID。
```c
struct utsm_capability {
uint32_t segment_slot;
uint32_t generation;
uint32_t rights;
uint32_t epoch;
uint64_t uuid_digest;
uint64_t auth_tag;
};
```
权限:
```text
READ
WRITE
EXEC
SHARE
DMA
```
热路径通过:
```text
segment_slot + generation + epoch
```
直接定位并验证段。
---
## 9. 加密规则
UTSM 不使用十进制凯撒和 UUID 孔洞,改为按 cache line 的 UUID 调谐流式加密。
```text
segment_key = KDF(
DRR_root_key,
process_uuid,
segment_uuid,
key_epoch
)
```
每 64B cache line 生成 tweak:
```text
line_index = offset / 64
tweak = hash(tweak_seed, line_index, key_epoch)
```
加密和解密:
```text
ciphertext = plaintext XOR stream(segment_key, tweak)
plaintext = ciphertext XOR stream(segment_key, tweak)
```
---
## 10. UTRW 读写器
UTRW 分三层:
```text
Level 0: Raw Access
直接读 cipher_base,得到密文。
Level 1: Fast Path
capability O(1) 定位段,PCKC 命中,无全局锁,无 trap。
Level 2: Slow Path
key miss、epoch mismatch、checkpoint、recovery、MAC fail 等异常处理。
```
### 10.1 读流程
```text
UTRW_READ(cap, offset, len, dst)
-> segment_slot 找 desc
-> generation 检查
-> rights 检查
-> epoch 检查
-> 边界检查
-> PCKC 取 key
-> 按 64B line 解密
-> 返回明文
```
### 10.2 写流程
```text
UTRW_WRITE(cap, offset, len, src)
-> segment_slot 找 desc
-> generation 检查
-> rights 检查
-> epoch 检查
-> 边界检查
-> PCKC 取 key
-> 按 64B line 加密
-> 写入 cipher data
-> 标记 dirty bitmap
-> writer_seq++
-> 按策略写 recovery log
```
部分写必须先解密旧 64B line,合并新明文后重新加密整条 line。
---
## 11. PCKC 每 CPU 密钥缓存
```c
struct utsm_pckc {
uuid128_t current_process_uuid;
uint32_t hot_segment_slot[8];
uint64_t hot_key_epoch[8];
void *key_schedule[8];
uint64_t hit_count;
uint64_t miss_count;
};
```
规则:
```text
每 CPU 一个 PCKC。
调度切换时只加载 next.crypto 指针和 hot_segment_hint。
不扫描 capability table。
不刷新全部 key。
不破坏 PCQ 的 O(1) 调度。
```
---
## 12. 与 SAS-R0-PCQ 的整合
任务结构扩展:
```c
struct task {
uint64_t tid;
uint32_t state;
uint32_t priority;
uint64_t runtime;
uint64_t time_slice;
void *stack_top;
void *entry;
struct context cpu_context;
uint32_t last_cpu;
uint64_t affinity_mask;
struct utsm_process_context *crypto;
struct utsm_capability_table *cap_table;
uint32_t hot_segment_hint;
uint32_t fault_segment_slot;
uint64_t recovery_generation;
uint64_t heartbeat_seq;
uint32_t flags;
struct task *prev;
struct task *next;
};
```
任务状态:
```text
READY
RUNNING
BLOCKED
SLEEPING
RECOVERING
FAULTED
ZOMBIE
```
---
## 13. 任务创建流程
```text
task_create(entry, priority, flags)
-> 分配 TCB
-> 生成 tid
-> 生成 process_uuid
-> 创建 utsm_process_context
-> 创建 stack segment
-> 创建 heap segment
-> 创建 ipc segment 可选
-> 生成 capability table
-> cap[0] = stack
-> cap[1] = heap
-> 初始化 CPU context
-> 通过 UTRW_WRITE 写入 start packet
-> hot_segment_hint = stack segment
-> state = READY
-> enqueue_task(current_cpu)
```
默认 capability:
```text
cap[0] = stack segment, READ | WRITE
cap[1] = heap segment, READ | WRITE
cap[2] = ipc segment, READ | WRITE | SHARE,可选
cap[3] = code segment, READ | EXEC,可选
```
---
## 14. 调度切换流程
```text
schedule()
-> old = current
-> utsm_switch_out(old)
-> next = pick_next_task()
-> utsm_switch_in(next)
-> context_switch(old, next)
```
`utsm_switch_out` 只做:
```text
标记 PWC dirty flush
保存 hot_segment_hint
更新 recovery_generation
更新 heartbeat
```
`utsm_switch_in` 只做:
```text
设置 PCKC.current_process_uuid
加载 next.crypto
检查 recovery_generation
预热 hot_segment_hint
```
禁止在调度路径中:
```text
扫描所有 segment
扫描 capability table
计算 MAC
写 checkpoint
重加密整段
```
---
## 15. Checkpoint / Rollback 协议
### 15.1 Checkpoint 类型
```text
Light Checkpoint
保存 segment table、DMP、dirty shard summary、writer_seq、key_epoch、MAC root。
Dirty Page Checkpoint
保存 dirty page 的密文副本、dirty page MAC、dirty shard、segment descriptor。
Boot Checkpoint
保存内核镜像 slot、UTSM root epoch、DRR boot status、启动阶段状态。
```
### 15.2 Dirty Shard 分片
Dirty Bitmap 不再只是一整块大 bitmap,而是拆成多个 Dirty Shard。
```c
struct utsm_dirty_shard {
uint32_t dirty_count;
uint32_t shard_id;
uint64_t page_base;
uint64_t page_count;
uint64_t last_checkpoint_epoch;
void *bitmap;
};
```
规则:
```text
1. 每个 shard 管理一段连续页范围。
2. UTRW_WRITE 标记 dirty page 时,同时更新 dirty_count。
3. checkpoint 时 dirty_count == 0 的 shard 直接跳过。
4. checkpoint 只扫描 dirty_count > 0 的 shard。
5. 每 CPU 可以维护 dirty shard list,避免全局扫描。
```
复杂度从:
```text
扫描全 dirty bitmap
```
优化为:
```text
O(number_of_dirty_shards + number_of_dirty_pages)
```
### 15.3 A/B Checkpoint Metadata 双槽
每个 checkpoint metadata 使用双槽。
```text
Checkpoint Metadata Slot A
Checkpoint Metadata Slot B
```
提交规则:
```text
当前 active = A
新 checkpoint 写 B
B 写完 metadata、dirty index、MAC root、CRC
flush
最后原子切换 active = B
旧 A 保留为 fallback
```
恢复规则:
```text
优先读取 active slot
如果 active slot CRC 错误或 generation 不完整
fallback 到另一个 slot
如果两个 slot 都损坏
进入 system rollback
```
这样可以避免 checkpoint 写一半崩溃导致旧稳定点也损坏。
### 15.4 正常 checkpoint 流程
```text
DRR 发起 checkpoint
-> checkpoint_generation++
-> 选择 inactive metadata slot
-> UTSM 遍历 dirty shard list
-> 跳过 dirty_count == 0 的 shard
-> 对 dirty shard 内的 ACTIVE 段执行 checkpoint
-> desc.state = CHECKPOINTING
-> 刷出 PWC / per-CPU dirty buffer
-> 复制 dirty ciphertext page 到 checkpoint region
-> 计算 page MAC
-> 写 segment desc snapshot
-> 写 DMP snapshot
-> 写 dirty shard summary
-> 写 checkpoint metadata CRC
-> flush checkpoint metadata
-> 原子切换 active metadata slot
-> CHECKPOINT_COMMIT
-> 清 dirty bitmap / dirty_count
-> desc.state = ACTIVE
```
### 15.5 rollback 级别
```text
Page Rollback
单页损坏,从 checkpoint slot 恢复密文页。
Segment Rollback
整段损坏,恢复 segment desc、DMP、key_epoch、dirty shard、MAC table。
System Rollback
控制面严重损坏,写 crash reason,reboot,由 bootloader 切换 last_good_slot。
```
### 15.6 DRR Emergency Pool
DRR 启动时必须预留独立紧急内存池。
```text
DRR Emergency Pool
emergency pages
recovery log buffer
checkpoint metadata buffer
DRR private stack
DRR metadata slab
crash buffer
```
规则:
```text
1. 普通 allocator 永远不能分配 Emergency Pool。
2. Emergency Pool 只供 watchdog、checkpoint、rollback、crash dump 使用。
3. 普通系统 OOM 不等于 DRR OOM。
4. recovery 路径禁止依赖普通堆分配器。
5. Emergency Pool 耗尽时直接进入 system rollback。
```
---
## 16. 启动流程
### 16.1 Bootloader 阶段
```text
1. 读取 Boot Control Block。
2. 校验 BCB CRC。
3. 选择 active_slot。
4. 如果 active_slot 失败次数超限,切换 last_good_slot。
5. 将 SYSTEM 作为打包后 IMG 内的系统根目录。
6. 加载 SYSTEM/boot/utsm.elf。
7. 加载或暴露 SYSTEM/driver/manifest.json。
8. 传入 memory map、BCB 地址、DRR reserved region 信息。
```
### 16.2 DRR 初始化
```text
1. 保留 DRR region。
2. 初始化 watchdog。
3. 建立 root key 或 root key handle。
4. 初始化 recovery log。
5. 初始化 checkpoint region。
6. 初始化 heartbeat page。
7. 初始化 DRR Emergency Pool。
8. 初始化 A/B checkpoint metadata slot。
```
### 16.3 UTSM 初始化
```text
1. 接收 DRR root key handle。
2. 初始化 global crypto epoch。
3. 初始化 segment table。
4. 初始化 DMP pool。
5. 初始化 PCKC area。
6. 初始化 dirty shard pool。
7. 初始化 dirty bitmap pool。
8. 初始化 MAC table pool。
9. 注册 UTRW fast path / slow path。
```
### 16.4 Scheduler 初始化
```text
1. 初始化 per-CPU runqueue。
2. 初始化 per-CPU heartbeat。
3. 初始化每 CPU PCKC。
4. 创建 bootstrap task。
5. 创建核心服务 task。
6. 将 task 加入 PCQ runqueue。
```
### 16.5 Driver Manifest 加载
驱动清单位于系统根目录下:
```text
SYSTEM/driver/manifest.json
```
规则:
```text
1. manifest.json 是启动驱动模块的唯一默认清单。
2. 驱动文件使用 ELF64 .drv 格式。
3. 驱动按 stage 分阶段加载。
4. required=true 的驱动失败时进入 DRR recovery 或 panic。
5. required=false 的驱动失败时标记 FAILED 并继续启动。
6. stage0/stage1 可由 bootloader 预加载为 boot module。
7. stage2/stage3 在文件系统可用后从 SYSTEM/driver 扫描加载。
```
默认阶段:
```text
stage0: platform,timer / apic / acpi / pci
stage1: boot,console / block / bootfs
stage2: filesystem,vfs / fat32 / devfs
stage3: optional,net / input / gpu
```
### 16.6 DKM 驱动 ABI 摘要
驱动模块系统:
```text
DKM = Deshab Kernel Module
DSM = Driver Startup Manager
```
每个 ELF .drv 必须导出:
```text
driver_desc
driver_init
driver_exit
```
`driver_desc` 至少描述:
```text
magic / abi_version / desc_size
name / version / vendor
driver_class / stage / flags / priority
depends / provides
min_kernel_abi / feature_bits
```
驱动入口:
```c
int driver_init(const struct dkm_kernel_api *api, struct dkm_driver_handle *handle);
int driver_exit(struct dkm_driver_handle *handle);
```
驱动默认通过 `dkm_kernel_api` 访问内核服务:
```text
log
mem
utsm
irq
pci
dma
vfs
net
timer
drr
```
ELF loader 第一版支持:
```text
必须支持:
R_X86_64_64
R_X86_64_RELATIVE
R_X86_64_GLOB_DAT
R_X86_64_JUMP_SLOT
建议支持:
R_X86_64_PC32
R_X86_64_PLT32
R_X86_64_32 / R_X86_64_32S
第一版禁止:
TLS relocation
IFUNC
lazy binding
外部动态库依赖
用户态 libc 依赖
```
驱动加载状态机:
```text
DISCOVERED
-> QUEUED
-> DEP_WAIT
-> LOADING
-> ELF_CHECKED
-> MEMORY_ALLOCATED
-> RELOCATED
-> ABI_CHECKED
-> INITING
-> ACTIVE
```
失败状态:
```text
FAILED_ELF
FAILED_RELOCATION
FAILED_DEPENDENCY
FAILED_ABI
FAILED_INIT
FAILED_REQUIRED
```
stage0/stage1 boot module 查找规则:
```text
1. 如果 path 在 boot module table 中,直接从内存加载。
2. 否则如果 VFS 已可用,从 SYSTEM/path 加载。
3. 否则返回 BOOT_MODULE_NOT_FOUND。
```
完整设计见:
```text
RE/驱动模块ABI设计.md
```
---
## 17. 错误处理
UTRW 错误状态:
```text
OK
KEY_MISS_RETRY
STALE_CAPABILITY
EPOCH_EXPIRED
OUT_OF_BOUNDS
ACCESS_DENIED
CHECKPOINT_BUSY
RECOVERING
MAC_FAILED
SEGMENT_POISONED
CORRUPTED_DESCRIPTOR
```
严重错误处理:
```text
1. 记录 task.fault_segment_slot。
2. task.state = FAULTED。
3. 从 runqueue 移除。
4. 通知 DRR。
5. DRR 决定刷新 capability、回滚 segment、kill task 或 system rollback。
```
---
## 18. UTSM v1 定稿
```text
UTSM v1 包含:
二进制 UUID
连续密文数据区
独立 DMP
全局 Segment Table
Segment Capability
Per-CPU Key Cache
UTRW 统一读写器
Dirty Shard + Dirty Bitmap
MAC Table
DRR Emergency Pool
A/B Checkpoint Metadata
DRR checkpoint / rollback 对接
SAS-R0-PCQ task 整合
加密粒度:
64B cache line
Dirty 粒度:
4KB page
Dirty 分片:
Dirty Shard,checkpoint 只扫描 dirty_count > 0 的 shard
MAC 粒度:
4KB page
Checkpoint 元数据:
A/B 双槽,CRC 校验,原子切换 active slot
大页优化:
2MB hugepage 可选
```
+21
View File
@@ -0,0 +1,21 @@
.section .text
.global _start
.type _start, @function
_start:
cli
cld
lea kernel_stack_top(%rip), %rsp
andq $-16, %rsp
call kernel_main
.hang:
cli
hlt
jmp .hang
.section .bss
.align 16
.global kernel_stack
.global kernel_stack_top
kernel_stack:
.skip 16384
kernel_stack_top:
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
void arch_halt_forever(void) {
for (;;) {
__asm__ volatile ("cli; hlt");
}
}
Binary file not shown.
+222
View File
@@ -0,0 +1,222 @@
#include <utsm/idt.h>
#include <utsm/log.h>
#include <utsm/types.h>
/* IDT gate descriptor (64-bit) */
typedef struct __attribute__((packed)) {
u16 offset_low;
u16 selector;
u8 ist;
u8 type_attr;
u16 offset_mid;
u32 offset_high;
u32 reserved;
} idt_entry;
/* IDT register */
typedef struct __attribute__((packed)) {
u16 limit;
u64 base;
} idt_ptr;
#define IDT_ENTRIES 256
static idt_entry g_idt[IDT_ENTRIES] __attribute__((aligned(16)));
#define PIC1_CMD 0x20
#define PIC1_DATA 0x21
#define PIC2_CMD 0xA0
#define PIC2_DATA 0xA1
#define ICW1_ICW4 0x01
#define ICW1_INIT 0x10
/* assembly stub declarations */
extern void isr_stub_0(void);
extern void isr_stub_1(void);
extern void isr_stub_2(void);
extern void isr_stub_3(void);
extern void isr_stub_4(void);
extern void isr_stub_5(void);
extern void isr_stub_6(void);
extern void isr_stub_7(void);
extern void isr_stub_8(void);
extern void isr_stub_9(void);
extern void isr_stub_10(void);
extern void isr_stub_11(void);
extern void isr_stub_12(void);
extern void isr_stub_13(void);
extern void isr_stub_14(void);
extern void isr_stub_15(void);
extern void isr_stub_16(void);
extern void isr_stub_17(void);
extern void isr_stub_18(void);
extern void isr_stub_19(void);
extern void isr_stub_20(void);
extern void isr_stub_21(void);
extern void isr_stub_22(void);
extern void isr_stub_23(void);
extern void isr_stub_24(void);
extern void isr_stub_25(void);
extern void isr_stub_26(void);
extern void isr_stub_27(void);
extern void isr_stub_28(void);
extern void isr_stub_29(void);
extern void isr_stub_30(void);
extern void isr_stub_31(void);
extern void isr_stub_32(void);
extern void isr_stub_33(void);
extern void isr_stub_34(void);
extern void isr_stub_35(void);
extern void isr_stub_36(void);
extern void isr_stub_37(void);
extern void isr_stub_38(void);
extern void isr_stub_39(void);
extern void isr_stub_40(void);
extern void isr_stub_41(void);
extern void isr_stub_42(void);
extern void isr_stub_43(void);
extern void isr_stub_44(void);
extern void isr_stub_45(void);
extern void isr_stub_46(void);
extern void isr_stub_47(void);
static void *g_isr_table[] = {
isr_stub_0, isr_stub_1, isr_stub_2, isr_stub_3,
isr_stub_4, isr_stub_5, isr_stub_6, isr_stub_7,
isr_stub_8, isr_stub_9, isr_stub_10, isr_stub_11,
isr_stub_12, isr_stub_13, isr_stub_14, isr_stub_15,
isr_stub_16, isr_stub_17, isr_stub_18, isr_stub_19,
isr_stub_20, isr_stub_21, isr_stub_22, isr_stub_23,
isr_stub_24, isr_stub_25, isr_stub_26, isr_stub_27,
isr_stub_28, isr_stub_29, isr_stub_30, isr_stub_31,
isr_stub_32, isr_stub_33, isr_stub_34, isr_stub_35,
isr_stub_36, isr_stub_37, isr_stub_38, isr_stub_39,
isr_stub_40, isr_stub_41, isr_stub_42, isr_stub_43,
isr_stub_44, isr_stub_45, isr_stub_46, isr_stub_47,
};
static void outb(u16 port, u8 value) {
__asm__ volatile ("outb %0, %1" :: "a"(value), "Nd"(port));
}
static u8 inb(u16 port) {
u8 value;
__asm__ volatile ("inb %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
static void io_wait(void) {
outb(0x80, 0);
}
static void pic_remap(void) {
/* save masks */
u8 m1 = inb(PIC1_DATA);
u8 m2 = inb(PIC2_DATA);
/* ICW1: start init + ICW4 */
outb(PIC1_CMD, ICW1_INIT | ICW1_ICW4);
io_wait();
outb(PIC2_CMD, ICW1_INIT | ICW1_ICW4);
io_wait();
/* ICW2: vector offsets */
outb(PIC1_DATA, 0x20); /* master: vectors 0x20-0x27 */
io_wait();
outb(PIC2_DATA, 0x28); /* slave: vectors 0x28-0x2F */
io_wait();
/* ICW3: master/slave wiring */
outb(PIC1_DATA, 0x04); /* master: IRQ2 → slave */
io_wait();
outb(PIC2_DATA, 0x02); /* slave: cascade identity */
io_wait();
/* ICW4: 8086 mode */
outb(PIC1_DATA, 0x01);
io_wait();
outb(PIC2_DATA, 0x01);
io_wait();
/* restore masks: mask all except IRQ1 (keyboard) */
outb(PIC1_DATA, 0xFD); /* 1111_1101: enable IRQ0 (timer) and IRQ1 (kb) */
outb(PIC2_DATA, 0xFF); /* mask all slave */
}
static void idt_set_entry(u8 vector, void *handler, u8 ist, u8 type) {
u64 addr = (u64)handler;
g_idt[vector].offset_low = (u16)(addr & 0xffff);
g_idt[vector].selector = 0x08; /* kernel code segment (from GDT) */
g_idt[vector].ist = ist;
g_idt[vector].type_attr = type;
g_idt[vector].offset_mid = (u16)((addr >> 16) & 0xffff);
g_idt[vector].offset_high = (u32)(addr >> 32);
g_idt[vector].reserved = 0;
}
void idt_init(void) {
log_info("[IDT] init begin");
for (u16 i = 0; i < 48; i++) {
idt_set_entry((u8)i, g_isr_table[i], 0, 0x8E); /* present, ring0, 64-bit interrupt gate */
}
/* fill unused entries with null */
for (u16 i = 48; i < IDT_ENTRIES; i++) {
idt_set_entry((u8)i, 0, 0, 0);
}
idt_ptr idtr;
idtr.limit = (u16)(sizeof(g_idt) - 1);
idtr.base = (u64)&g_idt;
__asm__ volatile ("lidt %0" :: "m"(idtr));
pic_remap();
log_info("[IDT] PIC remapped (master=0x20 slave=0x28)");
__asm__ volatile ("sti");
log_info("[IDT] interrupts enabled");
log_info("[IDT] init ok");
}
/* IRQ handler table */
static irq_handler_t g_irq_handlers[16];
int irq_register(u8 irq, irq_handler_t handler) {
if (irq >= 16) return -1;
g_irq_handlers[irq] = handler;
return 0;
}
/* Stack frame pushed by isr_common in idt.S */
typedef struct {
u64 r11, r10, r9, r8, rax, rcx, rdx, rsi, rdi;
u64 vector;
u64 error_code;
u64 rip, cs, rflags;
} isr_frame;
void idt_handler(isr_frame *frame) {
if (frame->vector < 32) {
log_error("[IDT] exception");
log_hex64("[IDT] vector=", frame->vector);
log_hex64("[IDT] err=", frame->error_code);
log_hex64("[IDT] rip=", frame->rip);
for (;;) { __asm__ volatile ("cli; hlt"); }
}
if (frame->vector >= 32 && frame->vector <= 47) {
u8 irq = (u8)(frame->vector - 0x20);
/* call registered handler */
if (irq < 16 && g_irq_handlers[irq]) {
int suppress_eoi = g_irq_handlers[irq](irq);
if (suppress_eoi) return;
}
/* send EOI */
if (frame->vector >= 0x28) {
outb(PIC2_CMD, 0x20);
}
outb(PIC1_CMD, 0x20);
}
}
Binary file not shown.
+62
View File
@@ -0,0 +1,62 @@
/* IDT assembly stubs — SAS-R0 interrupt vectors */
.section .text
.macro isr_no_err n
.global isr_stub_\n
.type isr_stub_\n, @function
isr_stub_\n:
pushq $0
pushq $\n
jmp isr_common
.endm
.macro isr_err n
.global isr_stub_\n
.type isr_stub_\n, @function
isr_stub_\n:
pushq $\n
jmp isr_common
.endm
/* Exceptions 0-31 */
isr_no_err 0; isr_no_err 1; isr_no_err 2; isr_no_err 3
isr_no_err 4; isr_no_err 5; isr_no_err 6; isr_no_err 7
isr_err 8; isr_no_err 9; isr_err 10; isr_err 11
isr_err 12; isr_err 13; isr_err 14; isr_no_err 15
isr_no_err 16; isr_err 17; isr_no_err 18; isr_no_err 19
isr_no_err 20; isr_no_err 21; isr_no_err 22; isr_no_err 23
isr_no_err 24; isr_no_err 25; isr_no_err 26; isr_no_err 27
isr_no_err 28; isr_no_err 29; isr_err 30; isr_no_err 31
/* IRQ 32-47 */
isr_no_err 32; isr_no_err 33; isr_no_err 34; isr_no_err 35
isr_no_err 36; isr_no_err 37; isr_no_err 38; isr_no_err 39
isr_no_err 40; isr_no_err 41; isr_no_err 42; isr_no_err 43
isr_no_err 44; isr_no_err 45; isr_no_err 46; isr_no_err 47
/* Common ISR */
isr_common:
pushq %rdi
pushq %rsi
pushq %rdx
pushq %rcx
pushq %rax
pushq %r8
pushq %r9
pushq %r10
pushq %r11
movq %rsp, %rdi
call idt_handler
popq %r11
popq %r10
popq %r9
popq %r8
popq %rax
popq %rcx
popq %rdx
popq %rsi
popq %rdi
addq $16, %rsp
iretq
Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
#include <utsm/types.h>
void outb(u16 port, u8 value) {
__asm__ volatile ("outb %0, %1" : : "a"(value), "Nd"(port));
}
u8 inb(u16 port) {
u8 value;
__asm__ volatile ("inb %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
void io_wait(void) {
outb(0x80, 0);
}
Binary file not shown.
+154
View File
@@ -0,0 +1,154 @@
#ifndef UTSM_LIMINE_H
#define UTSM_LIMINE_H
#include <utsm/types.h>
#define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88ULL, 0x0a82e883a194f07bULL
struct limine_hhdm_response {
u64 revision;
u64 offset;
};
struct limine_hhdm_request {
u64 id[4];
u64 revision;
struct limine_hhdm_response *response;
};
struct limine_kernel_address_response {
u64 revision;
u64 physical_base;
u64 virtual_base;
};
struct limine_kernel_address_request {
u64 id[4];
u64 revision;
struct limine_kernel_address_response *response;
};
#define LIMINE_KERNEL_ADDRESS_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x71ba76863cc55f63ULL, 0xb2644a48c516a487ULL }
struct limine_file {
u64 revision;
void *address;
u64 size;
char *path;
char *cmdline;
u32 media_type;
u32 unused;
u32 tftp_ip;
u32 tftp_port;
u32 partition_index;
u32 mbr_disk_id;
u8 gpt_disk_uuid[16];
u8 gpt_part_uuid[16];
u8 part_uuid[16];
};
struct limine_module_response {
u64 revision;
u64 module_count;
struct limine_file **modules;
};
struct limine_module_request {
u64 id[4];
u64 revision;
struct limine_module_response *response;
};
#define LIMINE_MODULE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x3e7e279702be32afULL, 0xca1c4f3bd1280ceeULL }
struct limine_rsdp_response {
u64 revision;
void *address;
};
struct limine_rsdp_request {
u64 id[4];
u64 revision;
struct limine_rsdp_response *response;
};
#define LIMINE_RSDP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0xc5e77b6b397e7b43ULL, 0x27637845accdcf3cULL }
struct limine_framebuffer {
void *address;
u64 width;
u64 height;
u64 pitch;
u16 bpp;
u8 memory_model;
u8 red_mask_size;
u8 red_mask_shift;
u8 green_mask_size;
u8 green_mask_shift;
u8 blue_mask_size;
u8 blue_mask_shift;
u8 unused[7];
u64 edid_size;
void *edid;
u64 mode_count;
struct limine_video_mode **modes;
};
struct limine_video_mode {
u64 pitch;
u64 width;
u64 height;
u16 bpp;
u8 memory_model;
u8 red_mask_size;
u8 red_mask_shift;
u8 green_mask_size;
u8 green_mask_shift;
u8 blue_mask_size;
u8 blue_mask_shift;
};
struct limine_framebuffer_response {
u64 revision;
u64 framebuffer_count;
struct limine_framebuffer **framebuffers;
};
struct limine_framebuffer_request {
u64 id[4];
u64 revision;
struct limine_framebuffer_response *response;
};
#define LIMINE_FRAMEBUFFER_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x9d5827dcd881dd75ULL, 0xa3148604f6fab11bULL }
#define LIMINE_MEMMAP_USABLE 0
#define LIMINE_MEMMAP_RESERVED 1
#define LIMINE_MEMMAP_ACPI_RECLAIMABLE 2
#define LIMINE_MEMMAP_ACPI_NVS 3
#define LIMINE_MEMMAP_BAD_MEMORY 4
#define LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 5
#define LIMINE_MEMMAP_KERNEL_AND_MODULES 6
#define LIMINE_MEMMAP_FRAMEBUFFER 7
struct limine_memmap_entry {
u64 base;
u64 length;
u64 type;
};
struct limine_memmap_response {
u64 revision;
u64 entry_count;
struct limine_memmap_entry **entries;
};
struct limine_memmap_request {
u64 id[4];
u64 revision;
struct limine_memmap_response *response;
};
#define LIMINE_MEMMAP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x67cf3d9d378a806fULL, 0xe304acdfc50c3c62ULL }
#endif
+45
View File
@@ -0,0 +1,45 @@
#include <utsm/types.h>
void outb(u16 port, u8 value);
u8 inb(u16 port);
#define COM1 0x3F8
static int serial_ready(void) {
return (inb(COM1 + 5) & 0x20) != 0;
}
static int serial_wait_ready(void) {
for (u64 spin = 0; spin < 1000000ULL; spin++) {
if (serial_ready()) {
return 1;
}
}
return 0;
}
void serial_init(void) {
outb(COM1 + 1, 0x00);
outb(COM1 + 3, 0x80);
outb(COM1 + 0, 0x03);
outb(COM1 + 1, 0x00);
outb(COM1 + 3, 0x03);
outb(COM1 + 2, 0xC7);
outb(COM1 + 4, 0x0B);
}
void serial_putc(char c) {
if (c == '\n') {
serial_putc('\r');
}
if (!serial_wait_ready()) {
return;
}
outb(COM1, (u8)c);
}
void serial_write(const char *s) {
while (*s) {
serial_putc(*s++);
}
}
Binary file not shown.
+29
View File
@@ -0,0 +1,29 @@
#include <utsm/capability.h>
#include <utsm/segment.h>
int utsm_cap_validate(utsm_capability cap, u32 required_rights, u64 offset, u64 len, utsm_segment_desc **out_desc) {
utsm_segment_desc *desc = utsm_get_segment(cap.segment_slot);
if (!desc) {
return UTSM_ERR_INVALID;
}
if (desc->state == UTSM_SEG_POISONED) {
return UTSM_ERR_POISONED;
}
if (desc->state != UTSM_SEG_ACTIVE) {
return UTSM_ERR_STATE;
}
if (desc->generation != cap.generation) {
return UTSM_ERR_STALE_CAP;
}
if ((cap.rights & required_rights) != required_rights) {
return UTSM_ERR_ACCESS;
}
if ((u32)desc->key_epoch != cap.epoch) {
return UTSM_ERR_EPOCH;
}
if (offset > desc->cipher_length || len > desc->cipher_length || offset + len > desc->cipher_length) {
return UTSM_ERR_BOUNDS;
}
*out_desc = desc;
return UTSM_OK;
}
Binary file not shown.
+47
View File
@@ -0,0 +1,47 @@
#include <utsm/dirty.h>
#include <utsm/segment.h>
#include <utsm/arena.h>
#include <utsm/config.h>
static void bitmap_set(u64 *bitmap, u64 bit) {
bitmap[bit / 64] |= 1ULL << (bit % 64);
}
static bool bitmap_test(u64 *bitmap, u64 bit) {
return (bitmap[bit / 64] & (1ULL << (bit % 64))) != 0;
}
void utsm_dirty_init(utsm_segment_desc *desc, u64 page_count) {
desc->dirty_shard_count = 1;
desc->dirty_shards = (utsm_dirty_shard *)kmem_alloc(sizeof(utsm_dirty_shard));
if (!desc->dirty_shards) {
return;
}
u64 words = (page_count + 63) / 64;
desc->dirty_shards[0].dirty_count = 0;
desc->dirty_shards[0].shard_id = 0;
desc->dirty_shards[0].page_base = 0;
desc->dirty_shards[0].page_count = page_count;
desc->dirty_shards[0].last_checkpoint_epoch = 0;
desc->dirty_shards[0].bitmap = (u64 *)kmem_alloc_aligned(words * sizeof(u64), 8);
if (desc->dirty_shards[0].bitmap) {
for (u64 i = 0; i < words; i++) {
desc->dirty_shards[0].bitmap[i] = 0;
}
}
}
void utsm_mark_dirty(utsm_segment_desc *desc, u64 offset, u64 len) {
if (!desc || !desc->dirty_shards || !desc->dirty_shards[0].bitmap || len == 0) {
return;
}
u64 first = offset / UTSM_PAGE_SIZE;
u64 last = (offset + len - 1) / UTSM_PAGE_SIZE;
utsm_dirty_shard *shard = &desc->dirty_shards[0];
for (u64 page = first; page <= last && page < shard->page_count; page++) {
if (!bitmap_test(shard->bitmap, page)) {
bitmap_set(shard->bitmap, page);
shard->dirty_count++;
}
}
}
Binary file not shown.
+20
View File
@@ -0,0 +1,20 @@
#include <utsm/dmp.h>
#include <utsm/segment.h>
#define UTSM_DMP_MAGIC 0x5554534d444d5031ULL
void utsm_dmp_init(utsm_dmp *dmp, utsm_segment_desc *desc, u32 slot) {
dmp->magic = UTSM_DMP_MAGIC;
dmp->version = 1;
dmp->segment_slot = slot;
dmp->fast_base = (u64)desc->cipher_base;
dmp->fast_limit = (u64)desc->cipher_base + desc->cipher_length;
dmp->fast_tweak_seed = desc->tweak_seed;
dmp->fast_key_epoch = desc->key_epoch;
dmp->dirty_bitmap_base = desc->dirty_shards ? (u64)desc->dirty_shards[0].bitmap : 0;
dmp->mac_table_base = (u64)desc->mac_table;
dmp->last_writer_seq = desc->writer_seq;
dmp->last_cpu = desc->last_cpu;
dmp->flags = desc->flags;
dmp->crc = dmp->magic ^ dmp->fast_base ^ dmp->fast_limit ^ dmp->fast_tweak_seed;
}
Binary file not shown.
+11
View File
@@ -0,0 +1,11 @@
#include <utsm/process.h>
#include <utsm/drr.h>
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_table_slot = 0;
process->capability_count = 0;
process->flags = 0;
}
Binary file not shown.
+80
View File
@@ -0,0 +1,80 @@
#include <utsm/segment.h>
#include <utsm/process.h>
#include <utsm/arena.h>
#include <utsm/dmp.h>
#include <utsm/config.h>
u64 utsm_next_generation(void);
static u64 digest_uuid(uuid128_t id) {
return id.hi ^ id.lo ^ (id.hi >> 32) ^ (id.lo << 17);
}
static u64 make_tweak_seed(uuid128_t process_uuid, uuid128_t segment_uuid, u64 epoch) {
return process_uuid.hi ^ process_uuid.lo ^ segment_uuid.hi ^ segment_uuid.lo ^ (epoch * 0x9e3779b97f4a7c15ULL);
}
int utsm_create_segment(utsm_process_context *process, u64 size, u32 flags, utsm_capability *out_cap) {
if (!process || !out_cap || size == 0) {
return UTSM_ERR_INVALID;
}
u32 slot = UTSM_MAX_SEGMENTS;
utsm_segment_desc *desc = NULL;
for (u32 i = 0; i < UTSM_MAX_SEGMENTS; i++) {
utsm_segment_desc *candidate = utsm_get_segment(i);
if (candidate->state == UTSM_SEG_FREE) {
slot = i;
desc = candidate;
break;
}
}
if (!desc) {
return UTSM_ERR_NO_MEMORY;
}
u64 length = utsm_align_up_u64(size, UTSM_CACHE_LINE_SIZE);
u64 pages = utsm_align_up_u64(length, UTSM_PAGE_SIZE) / UTSM_PAGE_SIZE;
u8 *cipher = (u8 *)kmem_alloc_page(pages);
utsm_dmp *dmp = (utsm_dmp *)kmem_alloc_aligned(sizeof(utsm_dmp), 64);
void *mac_table = kmem_alloc_aligned(pages * sizeof(u64), 8);
if (!cipher || !dmp || !mac_table) {
return UTSM_ERR_NO_MEMORY;
}
for (u64 i = 0; i < pages * UTSM_PAGE_SIZE; i++) {
cipher[i] = 0;
}
desc->segment_uuid = uuid_make_test(utsm_next_generation() + slot);
desc->owner_process_uuid = process->process_uuid;
desc->cipher_base = cipher;
desc->cipher_length = length;
desc->dmp_base = dmp;
desc->key_epoch = process->crypto_epoch;
desc->tweak_seed = make_tweak_seed(process->process_uuid, desc->segment_uuid, desc->key_epoch);
desc->mac_table = mac_table;
desc->generation++;
desc->flags = flags;
desc->state = UTSM_SEG_ACTIVE;
desc->last_cpu = 0;
desc->writer_seq = 0;
desc->checkpoint_generation = process->recovery_generation;
utsm_dirty_init(desc, pages);
utsm_dmp_init(dmp, desc, slot);
out_cap->segment_slot = slot;
out_cap->generation = desc->generation;
out_cap->rights = 0;
if (flags & UTSM_SEG_F_READ) out_cap->rights |= UTSM_RIGHT_READ;
if (flags & UTSM_SEG_F_WRITE) out_cap->rights |= UTSM_RIGHT_WRITE;
if (flags & UTSM_SEG_F_EXEC) out_cap->rights |= UTSM_RIGHT_EXEC;
if (flags & UTSM_SEG_F_DMA) out_cap->rights |= UTSM_RIGHT_DMA;
out_cap->epoch = (u32)desc->key_epoch;
out_cap->uuid_digest = digest_uuid(desc->segment_uuid);
out_cap->auth_tag = out_cap->uuid_digest ^ digest_uuid(process->process_uuid) ^ desc->key_epoch;
process->capability_count++;
return UTSM_OK;
}
Binary file not shown.
+32
View File
@@ -0,0 +1,32 @@
#include <utsm/utsm.h>
#include <utsm/segment.h>
#include <utsm/pckc.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_segment_desc *utsm_get_segment(u32 slot) {
if (slot >= UTSM_MAX_SEGMENTS) {
return NULL;
}
return &g_segments[slot];
}
u64 utsm_next_generation(void) {
return g_generation++;
}
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
#include <utsm/crypto.h>
#include <utsm/drr.h>
static u64 mix64(u64 x) {
x ^= x >> 30;
x *= 0xbf58476d1ce4e5b9ULL;
x ^= x >> 27;
x *= 0x94d049bb133111ebULL;
x ^= x >> 31;
return x;
}
void utsm_kdf_segment_key(uuid128_t process_uuid, uuid128_t segment_uuid, u64 key_epoch, utsm_key_material *out_key) {
const u64 *root = drr_get_root_key();
out_key->words[0] = mix64(root[0] ^ process_uuid.hi ^ segment_uuid.lo ^ key_epoch);
out_key->words[1] = mix64(root[1] ^ process_uuid.lo ^ segment_uuid.hi ^ (key_epoch << 1));
out_key->words[2] = mix64(root[2] ^ process_uuid.hi ^ segment_uuid.hi ^ (key_epoch << 7));
out_key->words[3] = mix64(root[3] ^ process_uuid.lo ^ segment_uuid.lo ^ (key_epoch << 13));
}
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
#include <utsm/crypto.h>
#include <utsm/config.h>
static u64 next_stream_word(u64 x) {
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
return x;
}
void utsm_crypt_line(const utsm_key_material *key, u64 tweak, const u8 *in, u8 *out) {
u64 state = key->words[0] ^ key->words[1] ^ key->words[2] ^ key->words[3] ^ tweak;
for (u64 i = 0; i < UTSM_CACHE_LINE_SIZE; i += 8) {
state = next_stream_word(state + i + 0xa5a5a5a5a5a5a5a5ULL);
for (u64 j = 0; j < 8; j++) {
out[i + j] = in[i + j] ^ (u8)(state >> (j * 8));
}
}
}
Binary file not shown.
+14
View File
@@ -0,0 +1,14 @@
#include <utsm/crypto.h>
static u64 mix64_tweak(u64 x) {
x ^= x >> 33;
x *= 0xff51afd7ed558ccdULL;
x ^= x >> 33;
x *= 0xc4ceb9fe1a85ec53ULL;
x ^= x >> 33;
return x;
}
u64 utsm_make_tweak(u64 tweak_seed, u64 line_index, u64 key_epoch) {
return mix64_tweak(tweak_seed ^ (line_index * 0x9e3779b97f4a7c15ULL) ^ (key_epoch << 32));
}
Binary file not shown.
+444
View File
@@ -0,0 +1,444 @@
#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];
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;
}
if (rela->offset + 8 <= target->size) {
if (reloc_type == R_X86_64_32 || reloc_type == R_X86_64_32S || reloc_type == R_X86_64_PC32) {
*(u32 *)(target_base + rela->offset) = (u32)patch;
} else {
*(u64 *)(target_base + rela->offset) = patch;
}
}
}
}
const elf64_sym *desc_sym = (const elf64_sym *)symbols->driver_desc;
const elf64_sym *init_sym = (const elf64_sym *)symbols->driver_init;
const dkm_driver_desc *desc = (const dkm_driver_desc *)(image + image_offset[desc_sym->shndx] + desc_sym->value);
if (desc->magic != DKM_DRIVER_MAGIC) {
log_error("[DKM] external driver_desc magic mismatch");
return -1;
}
log_info("[DKM] external driver loaded");
log_hex64("[DKM] desc ptr=", (u64)desc);
log_hex64("[DKM] name ptr=", (u64)desc->name);
log_info(desc->name);
dkm_driver_init_fn init = (dkm_driver_init_fn)(image + image_offset[init_sym->shndx] + init_sym->value);
dkm_driver_handle handle;
handle.desc = desc;
handle.state = DKM_STATE_INITING;
handle.init_status = 0;
handle.load_stage = desc->stage;
handle.flags = desc->flags;
int result = init(dkm_get_kernel_api(), &handle);
handle.init_status = result;
if (result != 0) {
handle.state = DKM_STATE_FAILED;
log_error("[DKM] external driver init failed");
return result;
}
handle.state = DKM_STATE_ACTIVE;
log_info("[DKM] external driver active");
return 0;
}
void dkm_scan_boot_modules(void) {
struct limine_module_response *response = g_module_request.response;
if (!response) {
log_warn("[DKM] no Limine module response");
return;
}
log_info("[DKM] boot modules scan begin");
log_hex64("[DKM] boot module count=", response->module_count);
for (u64 i = 0; i < response->module_count; i++) {
struct limine_file *file = response->modules[i];
if (!file) {
log_warn("[DKM] null module entry");
continue;
}
log_info("[DKM] module path");
if (file->path) {
log_info(file->path);
}
if (file->cmdline) {
log_info(file->cmdline);
}
log_hex64("[DKM] module size=", file->size);
int status = dkm_check_elf64(file->address, file->size);
if (status == 0) {
log_info("[DKM] module ELF64 x86_64 ok");
struct dkm_symbol_scan symbols;
if (dkm_scan_symbols(file->address, file->size, &symbols) == 0) {
log_info("[DKM] loading external ELF driver");
int load_result = dkm_load_elf_rel(file->address, file->size, &symbols);
if (load_result != 0) {
log_error("[DKM] external driver load failed");
}
}
} else {
log_error("[DKM] module ELF64 rejected");
log_hex64("[DKM] elf status=", (u64)(i64)status);
}
}
log_info("[DKM] boot modules scan end");
}
Binary file not shown.
+47
View File
@@ -0,0 +1,47 @@
#include <utsm/dkm.h>
static const char *const console_early_provides[] = {
"console",
"early-log"
};
static const dkm_driver_desc console_early_desc = {
.magic = DKM_DRIVER_MAGIC,
.abi_version = DKM_ABI_VERSION,
.desc_size = sizeof(dkm_driver_desc),
.name = "console_early",
.version = "0.1.0",
.vendor = "Deshab",
.driver_class = DKM_CLASS_CONSOLE,
.stage = 0,
.flags = DKM_F_REQUIRED | DKM_F_BOOT_MODULE | DKM_F_NO_UNLOAD | DKM_F_EARLY_LOG,
.priority = 0,
.depends = 0,
.depends_count = 0,
.provides = console_early_provides,
.provides_count = 2,
.min_kernel_abi = DKM_KERNEL_API_VERSION,
.feature_bits = 0,
.reserved0 = 0,
.reserved1 = 0
};
static int console_early_init(const dkm_kernel_api *api, dkm_driver_handle *handle) {
(void)handle;
if (!api || !api->log || !api->log->info) {
return -1;
}
api->log->info("[DKM:console_early] serial console online");
return 0;
}
static int console_early_exit(dkm_driver_handle *handle) {
(void)handle;
return 0;
}
const dkm_builtin_driver dkm_builtin_console_early = {
.desc = &console_early_desc,
.init = console_early_init,
.exit = console_early_exit
};
Binary file not shown.
+67
View File
@@ -0,0 +1,67 @@
#include <utsm/dkm.h>
#include <utsm/log.h>
static int dkm_validate_desc(const dkm_driver_desc *desc) {
if (!desc) {
return -1;
}
if (desc->magic != DKM_DRIVER_MAGIC) {
return -2;
}
if (desc->abi_version != DKM_ABI_VERSION) {
return -3;
}
if (desc->desc_size < sizeof(dkm_driver_desc)) {
return -4;
}
if (!desc->name || !desc->version) {
return -5;
}
return 0;
}
void dkm_init(void) {
log_info("[DKM] init begin");
int status = dkm_load_builtin(&dkm_builtin_console_early);
if (status == 0) {
log_info("[DKM] init ok");
} else {
log_error("[DKM] init failed");
}
}
int dkm_load_builtin(const dkm_builtin_driver *driver) {
if (!driver || !driver->desc || !driver->init) {
log_error("[DKM] invalid builtin driver");
return -1;
}
int status = dkm_validate_desc(driver->desc);
if (status != 0) {
log_error("[DKM] driver_desc rejected");
return status;
}
dkm_driver_handle handle;
handle.desc = driver->desc;
handle.state = DKM_STATE_ABI_CHECKED;
handle.init_status = 0;
handle.load_stage = driver->desc->stage;
handle.flags = driver->desc->flags;
log_info("[DKM] builtin driver init begin");
log_info(driver->desc->name);
handle.state = DKM_STATE_INITING;
status = driver->init(dkm_get_kernel_api(), &handle);
handle.init_status = status;
if (status != 0) {
handle.state = DKM_STATE_FAILED;
log_error("[DKM] builtin driver init failed");
return status;
}
handle.state = DKM_STATE_ACTIVE;
log_info("[DKM] builtin driver active");
return 0;
}
Binary file not shown.
+90
View File
@@ -0,0 +1,90 @@
#include <utsm/dkm.h>
#include <utsm/log.h>
#include <utsm/idt.h>
#include <utsm/net.h>
static void dkm_api_info(const char *msg) {
log_info(msg);
}
static void dkm_api_warn(const char *msg) {
log_warn(msg);
}
static void dkm_api_error(const char *msg) {
log_error(msg);
}
static void dkm_api_panic(const char *msg) {
log_error(msg);
for (;;) {
__asm__ volatile("cli; hlt");
}
}
static const dkm_log_api g_log_api = {
.info = dkm_api_info,
.warn = dkm_api_warn,
.error = dkm_api_error,
.panic = dkm_api_panic
};
static dkm_kernel_api g_kernel_api = {
.version = DKM_KERNEL_API_VERSION,
.size = sizeof(dkm_kernel_api),
.feature_bits = 0,
.log = &g_log_api,
.mem = 0,
.utsm = 0,
.irq = 0,
.pci = 0,
.dma = 0,
.vfs = 0,
.net = 0,
.timer = 0,
.drr = 0,
.rsdp_address = 0,
.fb_address = 0,
.fb_width = 0,
.fb_height = 0,
.fb_pitch = 0,
.fb_bpp = 0,
.boot_modules_response = 0,
.irq_register = 0,
.hhdm_offset = 0,
.block = 0
};
const dkm_kernel_api *dkm_get_kernel_api(void) {
return &g_kernel_api;
}
#include "../arch/x86_64/limine.h"
extern volatile struct limine_rsdp_request g_rsdp_request;
extern volatile struct limine_framebuffer_request g_fb_request;
extern volatile struct limine_module_request g_module_request;
extern volatile struct limine_hhdm_request g_hhdm_request;
void dkm_fill_platform_info(void) {
g_kernel_api.dma = dma_get_api();
g_kernel_api.net = net_get_api();
g_kernel_api.block = block_get_api();
if (g_rsdp_request.response && g_rsdp_request.response->address) {
g_kernel_api.rsdp_address = g_rsdp_request.response->address;
}
if (g_fb_request.response && g_fb_request.response->framebuffer_count > 0) {
struct limine_framebuffer *fb = g_fb_request.response->framebuffers[0];
g_kernel_api.fb_address = fb->address;
g_kernel_api.fb_width = fb->width;
g_kernel_api.fb_height = fb->height;
g_kernel_api.fb_pitch = fb->pitch;
g_kernel_api.fb_bpp = fb->bpp;
}
if (g_module_request.response) {
g_kernel_api.boot_modules_response = g_module_request.response;
}
g_kernel_api.irq_register = (int (*)(u8,void*))((u64)irq_register);
if (g_hhdm_request.response) {
g_kernel_api.hhdm_offset = g_hhdm_request.response->offset;
}
}
Binary file not shown.
+359
View File
@@ -0,0 +1,359 @@
#include <utsm/dkm.h>
#include <utsm/log.h>
#include <utsm/types.h>
#include "../arch/x86_64/limine.h"
#define DSM_MAX_DRIVERS_PER_STAGE 8
#define DSM_MAX_STAGES 4
#define DSM_MAX_DEPENDS 4
#define DSM_MAX_PROVIDES 4
typedef struct dsm_driver_entry {
char name[32];
char path[64];
u32 class_id;
u32 required;
char depends[DSM_MAX_DEPENDS][32];
u32 depend_count;
char provides[DSM_MAX_PROVIDES][32];
u32 provide_count;
struct limine_file *boot_module;
int loaded;
} dsm_driver_entry;
typedef struct dsm_stage_entry {
u32 id;
char name[16];
u32 required;
dsm_driver_entry drivers[DSM_MAX_DRIVERS_PER_STAGE];
u32 driver_count;
} dsm_stage_entry;
static dsm_stage_entry g_stages[DSM_MAX_STAGES];
static u32 g_stage_count;
extern volatile struct limine_module_request g_module_request;
static int dsm_skip_ws(const char **p) {
while (**p == ' ' || **p == '\t' || **p == '\n' || **p == '\r') { (*p)++; }
return 0;
}
static int dsm_expect(const char **p, char c) {
dsm_skip_ws(p);
if (**p == c) { (*p)++; return 0; }
return -1;
}
static int dsm_read_string(const char **p, char *out, u32 max_len) {
dsm_skip_ws(p);
if (**p != '"') return -1;
(*p)++;
u32 i = 0;
while (**p && **p != '"' && i + 1 < max_len) {
out[i++] = **p;
(*p)++;
}
out[i] = 0;
if (**p != '"') return -1;
(*p)++;
return 0;
}
static int dsm_skip_value(const char **p) {
dsm_skip_ws(p);
if (**p == '"') {
char tmp[256];
return dsm_read_string(p, tmp, sizeof(tmp));
}
if (**p == '{') {
(*p)++;
int depth = 1;
while (depth > 0 && **p) {
if (**p == '{') depth++;
else if (**p == '}') depth--;
else if (**p == '"') { (*p)++; while (**p && **p != '"') (*p)++; if (**p) (*p)++; continue; }
if (depth > 0) (*p)++;
}
return 0;
}
if (**p == '[') {
(*p)++;
int depth = 1;
while (depth > 0 && **p) {
if (**p == '[') depth++;
else if (**p == ']') depth--;
else if (**p == '"') { (*p)++; while (**p && **p != '"') (*p)++; if (**p) (*p)++; continue; }
if (depth > 0) (*p)++;
}
return 0;
}
while (**p && **p != ',' && **p != '}' && **p != ']') (*p)++;
return 0;
}
static struct limine_file *dsm_find_boot_module(const char *path) {
struct limine_module_response *rsp = g_module_request.response;
if (!rsp) return 0;
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (f && f->path) {
const char *fp = f->path;
while (*fp == '/') fp++;
usize j = 0;
usize k = 0;
while (fp[j]) j++;
while (path[k]) k++;
if (j == k) {
int match = 1;
for (usize x = 0; x < j; x++) {
if (fp[x] != path[x]) { match = 0; break; }
}
if (match) return f;
}
}
}
return 0;
}
static int streq_static(const char *a, const char *b) {
usize i = 0;
while (a[i] && b[i]) {
if (a[i] != b[i]) return 0;
i++;
}
return a[i] == b[i];
}
static void dsm_parse_driver(const char **p, dsm_driver_entry *drv) {
drv->depend_count = 0;
drv->provide_count = 0;
drv->required = 1;
drv->boot_module = 0;
drv->loaded = 0;
drv->class_id = 0;
if (dsm_expect(p, '{') != 0) return;
while (**p && **p != '}') {
dsm_skip_ws(p);
if (**p == '}') break;
char key[32];
if (dsm_read_string(p, key, sizeof(key)) != 0) return;
dsm_expect(p, ':');
if (streq_static(key, "name")) {
dsm_read_string(p, drv->name, sizeof(drv->name));
} else if (streq_static(key, "path")) {
dsm_read_string(p, drv->path, sizeof(drv->path));
} else if (streq_static(key, "class")) {
char cls[32];
dsm_read_string(p, cls, sizeof(cls));
if (streq_static(cls, "platform")) drv->class_id = 1;
else if (streq_static(cls, "bus")) drv->class_id = 2;
else if (streq_static(cls, "interrupt")) drv->class_id = 3;
else if (streq_static(cls, "timer")) drv->class_id = 4;
else if (streq_static(cls, "console")) drv->class_id = 5;
else if (streq_static(cls, "storage")) drv->class_id = 6;
else if (streq_static(cls, "fs")) drv->class_id = 7;
else if (streq_static(cls, "fs-core")) drv->class_id = 8;
else if (streq_static(cls, "net")) drv->class_id = 9;
else if (streq_static(cls, "input")) drv->class_id = 10;
} else if (streq_static(key, "required")) {
dsm_skip_ws(p);
if (**p == 't') { drv->required = 1; (*p) += 4; }
else if (**p == 'f') { drv->required = 0; (*p) += 5; }
} else if (streq_static(key, "depends")) {
if (dsm_expect(p, '[') != 0) return;
while (**p && **p != ']') {
dsm_skip_ws(p);
if (**p == ']') break;
if (drv->depend_count < DSM_MAX_DEPENDS) {
dsm_read_string(p, drv->depends[drv->depend_count], 32);
drv->depend_count++;
} else { dsm_skip_value(p); }
dsm_skip_ws(p);
if (**p == ',') { (*p)++; continue; }
if (**p == ']') break;
}
dsm_expect(p, ']');
} else if (streq_static(key, "provides")) {
if (dsm_expect(p, '[') != 0) return;
while (**p && **p != ']') {
dsm_skip_ws(p);
if (**p == ']') break;
if (drv->provide_count < DSM_MAX_PROVIDES) {
dsm_read_string(p, drv->provides[drv->provide_count], 32);
drv->provide_count++;
} else { dsm_skip_value(p); }
dsm_skip_ws(p);
if (**p == ',') { (*p)++; continue; }
if (**p == ']') break;
}
dsm_expect(p, ']');
} else {
dsm_skip_value(p);
}
dsm_skip_ws(p);
if (**p == ',') (*p)++;
}
dsm_expect(p, '}');
}
static void dsm_parse_stage(const char **p, dsm_stage_entry *stage) {
stage->driver_count = 0;
if (dsm_expect(p, '{') != 0) return;
while (**p && **p != '}') {
dsm_skip_ws(p);
if (**p == '}') break;
char key[32];
if (dsm_read_string(p, key, sizeof(key)) != 0) return;
dsm_expect(p, ':');
if (streq_static(key, "id")) {
dsm_skip_ws(p);
u32 val = 0;
while (**p >= '0' && **p <= '9') { val = val * 10 + (u32)(**p - '0'); (*p)++; }
stage->id = val;
} else if (streq_static(key, "name")) {
dsm_read_string(p, stage->name, sizeof(stage->name));
} else if (streq_static(key, "required")) {
dsm_skip_ws(p);
if (**p == 't') { stage->required = 1; (*p) += 4; }
else if (**p == 'f') { stage->required = 0; (*p) += 5; }
} else if (streq_static(key, "drivers")) {
if (dsm_expect(p, '[') != 0) return;
while (**p && **p != ']') {
dsm_skip_ws(p);
if (**p == ']') break;
if (stage->driver_count < DSM_MAX_DRIVERS_PER_STAGE) {
dsm_parse_driver(p, &stage->drivers[stage->driver_count]);
stage->driver_count++;
} else {
dsm_skip_value(p);
}
dsm_skip_ws(p);
if (**p == ',') { (*p)++; continue; }
if (**p == ']') break;
}
dsm_expect(p, ']');
} else {
dsm_skip_value(p);
}
dsm_skip_ws(p);
if (**p == ',') (*p)++;
}
dsm_expect(p, '}');
}
static int dsm_parse_manifest(const char *text, u64 size) {
g_stage_count = 0;
const char *p = text;
const char *end = text + size;
while (p < end && *p) {
dsm_skip_ws(&p);
if (p >= end || !*p) break;
if (*p == '{' || *p == '}') { p++; continue; }
if (*p == ',' || *p == ':') { p++; continue; }
if (*p == '[' || *p == ']') { p++; continue; }
char key[32];
if (dsm_read_string(&p, key, sizeof(key)) != 0) break;
dsm_expect(&p, ':');
if (streq_static(key, "stages")) {
if (dsm_expect(&p, '[') != 0) return -1;
while (p < end && *p) {
dsm_skip_ws(&p);
if (*p == ']') { p++; break; }
if (g_stage_count < DSM_MAX_STAGES) {
dsm_parse_stage(&p, &g_stages[g_stage_count]);
g_stage_count++;
}
dsm_skip_ws(&p);
if (*p == ',') p++;
}
} else {
dsm_skip_value(&p);
}
dsm_skip_ws(&p);
if (*p == ',' || *p == '}' || *p == ']') p++;
}
return 0;
}
void dsm_load_by_manifest(void) {
struct limine_module_response *rsp = g_module_request.response;
if (!rsp) {
log_warn("[DSM] no Limine module response");
return;
}
struct limine_file *manifest_file = 0;
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (f && f->path && f->cmdline && streq_static(f->cmdline, "dkm:manifest")) {
manifest_file = f;
break;
}
}
if (!manifest_file) {
log_warn("[DSM] manifest not found in boot modules");
return;
}
log_info("[DSM] parsing manifest");
dsm_parse_manifest((const char *)manifest_file->address, manifest_file->size);
log_info("[DSM] manifest parsed");
log_hex64("[DSM] stages=", (u64)g_stage_count);
for (u32 si = 0; si < g_stage_count; si++) {
dsm_stage_entry *stage = &g_stages[si];
log_info("[DSM] stage begin");
log_info(stage->name);
log_hex64("[DSM] driver count=", stage->driver_count);
for (u32 di = 0; di < stage->driver_count; di++) {
dsm_driver_entry *drv = &stage->drivers[di];
drv->boot_module = dsm_find_boot_module(drv->path);
if (!drv->boot_module) {
log_info("[DSM] module not found");
log_info(drv->name);
if (drv->required && stage->required) {
log_error("[DSM] required module missing, abort stage");
break;
}
continue;
}
struct limine_file *f = drv->boot_module;
log_info("[DSM] loading driver");
log_info(drv->name);
if (dkm_check_elf64(f->address, f->size) != 0) {
log_error("[DSM] ELF check failed");
continue;
}
struct dkm_symbol_scan symbols;
if (dkm_scan_symbols(f->address, f->size, &symbols) != 0) {
log_error("[DSM] symbol scan failed");
continue;
}
int result = dkm_load_elf_rel(f->address, f->size, &symbols);
if (result != 0) {
log_error("[DSM] load failed");
if (drv->required && stage->required) {
log_error("[DSM] required driver failed, abort stage");
break;
}
} else {
drv->loaded = 1;
}
}
log_info("[DSM] stage end");
}
}
Binary file not shown.
+37
View File
@@ -0,0 +1,37 @@
#include <utsm/drr.h>
#include <utsm/log.h>
static const u64 g_root_key[4] = {
0x4452525554534d31ULL,
0xfeedfacecafebeefULL,
0x0123456789abcdefULL,
0xfedcba9876543210ULL
};
void drr_stub_init(void) {
}
const u64 *drr_get_root_key(void) {
return g_root_key;
}
u64 drr_recovery_generation(void) {
return 1;
}
void drr_report_fault(const char *reason) {
log_error("[DRR] fault reported");
log_error(reason);
}
void drr_log_write_intent(u32 segment_slot, u64 offset, u64 len) {
UTSM_UNUSED(segment_slot);
UTSM_UNUSED(offset);
UTSM_UNUSED(len);
}
void drr_log_write_commit(u32 segment_slot, u64 offset, u64 len) {
UTSM_UNUSED(segment_slot);
UTSM_UNUSED(offset);
UTSM_UNUSED(len);
}
Binary file not shown.
+13
View File
@@ -0,0 +1,13 @@
#ifndef UTSM_ARENA_H
#define UTSM_ARENA_H
#include <utsm/types.h>
void arena_init(void);
void *kmem_alloc(u64 size);
void *kmem_alloc_aligned(u64 size, u64 alignment);
void *kmem_alloc_page(u64 page_count);
u64 kmem_arena_virtual_base(void);
u64 kmem_arena_virtual_end(void);
#endif
+8
View File
@@ -0,0 +1,8 @@
#ifndef UTSM_ASSERT_H
#define UTSM_ASSERT_H
#include <utsm/log.h>
#define UTSM_ASSERT(cond) do { if (!(cond)) { panic("assertion failed: " #cond); } } while (0)
#endif
+29
View File
@@ -0,0 +1,29 @@
#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 struct dkm_block_device_desc {
const char *name;
u64 sector_size;
u64 sector_count;
void *ctx;
dkm_block_read_fn read;
} 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);
u64 (*sector_size)(u32 index);
const char *(*device_name)(u32 index);
} dkm_block_api;
void block_init(void);
const dkm_block_api *block_get_api(void);
#endif
+26
View File
@@ -0,0 +1,26 @@
#ifndef UTSM_CAPABILITY_H
#define UTSM_CAPABILITY_H
#include <utsm/types.h>
#include <utsm/status.h>
#define UTSM_RIGHT_READ (1U << 0)
#define UTSM_RIGHT_WRITE (1U << 1)
#define UTSM_RIGHT_EXEC (1U << 2)
#define UTSM_RIGHT_SHARE (1U << 3)
#define UTSM_RIGHT_DMA (1U << 4)
struct utsm_segment_desc;
typedef struct {
u32 segment_slot;
u32 generation;
u32 rights;
u32 epoch;
u64 uuid_digest;
u64 auth_tag;
} utsm_capability;
int utsm_cap_validate(utsm_capability cap, u32 required_rights, u64 offset, u64 len, struct utsm_segment_desc **out_desc);
#endif
+13
View File
@@ -0,0 +1,13 @@
#ifndef UTSM_CONFIG_H
#define UTSM_CONFIG_H
#define UTSM_CACHE_LINE_SIZE 64ULL
#define UTSM_PAGE_SIZE 4096ULL
#define UTSM_MAX_SEGMENTS 1024U
#define UTSM_MAX_CAPABILITIES 256U
#define UTSM_MAX_PCKC_KEYS 8U
#define UTSM_ARENA_SIZE (16ULL * 1024ULL * 1024ULL)
#define UTSM_DIRTY_SHARD_PAGES 1024ULL
#define UTSM_KERNEL_STACK_SIZE 16384ULL
#endif
+17
View File
@@ -0,0 +1,17 @@
#ifndef UTSM_CRYPTO_H
#define UTSM_CRYPTO_H
#include <utsm/types.h>
#include <utsm/uuid.h>
struct utsm_segment_desc;
typedef struct {
u64 words[4];
} utsm_key_material;
void utsm_kdf_segment_key(uuid128_t process_uuid, uuid128_t segment_uuid, u64 key_epoch, utsm_key_material *out_key);
u64 utsm_make_tweak(u64 tweak_seed, u64 line_index, u64 key_epoch);
void utsm_crypt_line(const utsm_key_material *key, u64 tweak, const u8 *in, u8 *out);
#endif
+20
View File
@@ -0,0 +1,20 @@
#ifndef UTSM_DIRTY_H
#define UTSM_DIRTY_H
#include <utsm/types.h>
typedef struct {
u32 dirty_count;
u32 shard_id;
u64 page_base;
u64 page_count;
u64 last_checkpoint_epoch;
u64 *bitmap;
} utsm_dirty_shard;
struct utsm_segment_desc;
void utsm_dirty_init(struct utsm_segment_desc *desc, u64 page_count);
void utsm_mark_dirty(struct utsm_segment_desc *desc, u64 offset, u64 len);
#endif
+141
View File
@@ -0,0 +1,141 @@
#ifndef UTSM_DKM_H
#define UTSM_DKM_H
#include <utsm/types.h>
#include <utsm/dma.h>
#include <utsm/block.h>
#include <utsm/net.h>
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
#define DKM_KERNEL_API_VERSION 1u
#define DKM_CLASS_PLATFORM 1u
#define DKM_CLASS_BUS 2u
#define DKM_CLASS_INTERRUPT 3u
#define DKM_CLASS_TIMER 4u
#define DKM_CLASS_CONSOLE 5u
#define DKM_CLASS_STORAGE 6u
#define DKM_CLASS_FS 7u
#define DKM_CLASS_NET 8u
#define DKM_CLASS_INPUT 9u
#define DKM_CLASS_GPU 10u
#define DKM_CLASS_MISC 11u
#define DKM_F_REQUIRED (1u << 0)
#define DKM_F_BOOT_MODULE (1u << 1)
#define DKM_F_NO_UNLOAD (1u << 2)
#define DKM_F_STRONG_RECOVERY (1u << 3)
#define DKM_F_DMA_REQUIRED (1u << 4)
#define DKM_F_EARLY_LOG (1u << 5)
struct dkm_kernel_api;
struct dkm_driver_handle;
typedef struct dkm_driver_desc {
u32 magic;
u16 abi_version;
u16 desc_size;
const char *name;
const char *version;
const char *vendor;
u32 driver_class;
u32 stage;
u32 flags;
u32 priority;
const char *const *depends;
u32 depends_count;
const char *const *provides;
u32 provides_count;
u64 min_kernel_abi;
u64 feature_bits;
u64 reserved0;
u64 reserved1;
} dkm_driver_desc;
typedef int (*dkm_driver_init_fn)(const struct dkm_kernel_api *api, struct dkm_driver_handle *handle);
typedef int (*dkm_driver_exit_fn)(struct dkm_driver_handle *handle);
typedef struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
void (*error)(const char *msg);
void (*panic)(const char *msg);
} dkm_log_api;
typedef struct dkm_kernel_api {
u32 version;
u32 size;
u64 feature_bits;
const dkm_log_api *log;
const void *mem;
const void *utsm;
const void *irq;
const void *pci;
const dkm_dma_api *dma;
const void *vfs;
const dkm_net_api *net;
const void *timer;
const void *drr;
const void *rsdp_address; /* ACPI RSDP physical address */
const void *fb_address; /* framebuffer base */
u64 fb_width;
u64 fb_height;
u64 fb_pitch;
u16 fb_bpp;
const void *boot_modules_response; /* limine_module_response* */
int (*irq_register)(u8 irq, void *handler); /* kernel irq_register */
u64 hhdm_offset; /* physical → virtual */
const dkm_block_api *block; /* block provider registry */
} dkm_kernel_api;
typedef enum dkm_driver_state {
DKM_STATE_DISCOVERED = 0,
DKM_STATE_ABI_CHECKED,
DKM_STATE_INITING,
DKM_STATE_ACTIVE,
DKM_STATE_FAILED
} dkm_driver_state;
typedef struct dkm_driver_handle {
const dkm_driver_desc *desc;
dkm_driver_state state;
i32 init_status;
u32 load_stage;
u32 flags;
} dkm_driver_handle;
typedef struct dkm_builtin_driver {
const dkm_driver_desc *desc;
dkm_driver_init_fn init;
dkm_driver_exit_fn exit;
} dkm_builtin_driver;
void dkm_init(void);
int dkm_load_builtin(const dkm_builtin_driver *driver);
void dkm_scan_boot_modules(void);
void dsm_load_by_manifest(void);
void dkm_fill_platform_info(void);
const dkm_kernel_api *dkm_get_kernel_api(void);
/* exposed for manifest parser */
struct dkm_symbol_scan {
const void *driver_desc;
const void *driver_init;
const void *driver_exit;
};
int dkm_check_elf64(const void *address, u64 size);
int dkm_scan_symbols(const void *address, u64 size, struct dkm_symbol_scan *out);
int dkm_load_elf_rel(const void *address, u64 size, const struct dkm_symbol_scan *symbols);
extern const dkm_builtin_driver dkm_builtin_console_early;
#endif
+20
View File
@@ -0,0 +1,20 @@
#ifndef UTSM_DMA_H
#define UTSM_DMA_H
#include <utsm/types.h>
typedef struct dkm_dma_buffer {
void *virt;
u64 phys;
u64 size;
} dkm_dma_buffer;
typedef struct dkm_dma_api {
int (*alloc_pages)(u64 page_count, u64 alignment, u64 max_phys, dkm_dma_buffer *out);
} dkm_dma_api;
void dma_init(void);
int dma_alloc_pages(u64 page_count, u64 alignment, u64 max_phys, dkm_dma_buffer *out);
const dkm_dma_api *dma_get_api(void);
#endif
+26
View File
@@ -0,0 +1,26 @@
#ifndef UTSM_DMP_H
#define UTSM_DMP_H
#include <utsm/types.h>
typedef struct {
u64 magic;
u32 version;
u32 segment_slot;
u64 fast_base;
u64 fast_limit;
u64 fast_tweak_seed;
u64 fast_key_epoch;
u64 dirty_bitmap_base;
u64 mac_table_base;
u64 last_writer_seq;
u32 last_cpu;
u32 flags;
u64 crc;
} utsm_dmp;
struct utsm_segment_desc;
void utsm_dmp_init(utsm_dmp *dmp, struct utsm_segment_desc *desc, u32 slot);
#endif
+13
View File
@@ -0,0 +1,13 @@
#ifndef UTSM_DRR_H
#define UTSM_DRR_H
#include <utsm/types.h>
void drr_stub_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);
#endif
+51
View File
@@ -0,0 +1,51 @@
#ifndef UTSM_DSK_H
#define UTSM_DSK_H
#include <utsm/types.h>
#define DSK_BOOT_MAGIC 0x44534B31424F4F54ULL /* "DSK1BOOT" */
#define DSK_BOOT_ABI_VERSION 1u
#define DSK_BOOT_FLAG_FROM_UTSM (1ULL << 0)
#define DSK_BOOT_FLAG_DKM_READY (1ULL << 1)
#define DSK_BOOT_FLAG_FAT32_PATH (1ULL << 2)
typedef struct dsk_boot_context {
u64 magic;
u32 abi_version;
u32 size;
u64 flags;
u64 hhdm_offset;
u64 rsdp_address;
u64 framebuffer_address;
u64 framebuffer_width;
u64 framebuffer_height;
u64 framebuffer_pitch;
u32 framebuffer_bpp;
u32 reserved_fb;
u64 boot_modules_response;
u64 dkm_kernel_api;
u64 dkm_driver_table;
u64 dkm_driver_count;
u64 utsm_state;
u64 drr_state;
u64 memory_map;
u64 memory_map_count;
u64 memory_map_entry_size;
u64 kernel_stack_top;
u64 reserved[8];
} dsk_boot_context;
typedef void (*dsk_entry_fn)(const dsk_boot_context *context);
int dsk_load_and_jump(void);
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef UTSM_IDT_H
#define UTSM_IDT_H
#include <utsm/types.h>
void idt_init(void);
/* IRQ handler: return 1 to suppress default ACK, 0 for normal EOI */
typedef int (*irq_handler_t)(u8 irq);
int irq_register(u8 irq, irq_handler_t handler);
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef UTSM_LOG_H
#define UTSM_LOG_H
#include <utsm/types.h>
void serial_init(void);
void serial_putc(char c);
void serial_write(const char *s);
void log_info(const char *msg);
void log_warn(const char *msg);
void log_error(const char *msg);
void log_hex64(const char *prefix, u64 value);
void panic(const char *msg);
#endif
+42
View File
@@ -0,0 +1,42 @@
#ifndef UTSM_NET_H
#define UTSM_NET_H
#include <utsm/types.h>
#define DKM_NET_MAX_DEVICES 8u
/* 网卡链路/能力标志。 */
#define DKM_NET_F_LINK_UP (1u << 0)
#define DKM_NET_F_TX_READY (1u << 1)
#define DKM_NET_F_RX_READY (1u << 2)
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);
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;
} 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);
} dkm_net_api;
void net_init(void);
const dkm_net_api *net_get_api(void);
#endif
+29
View File
@@ -0,0 +1,29 @@
#ifndef UTSM_PCKC_H
#define UTSM_PCKC_H
#include <utsm/types.h>
#include <utsm/config.h>
#include <utsm/uuid.h>
#include <utsm/crypto.h>
struct utsm_segment_desc;
typedef struct {
bool valid;
u32 segment_slot;
u64 key_epoch;
utsm_key_material key;
} utsm_pckc_entry;
typedef struct {
uuid128_t current_process_uuid;
utsm_pckc_entry entries[UTSM_MAX_PCKC_KEYS];
u64 hit_count;
u64 miss_count;
u32 next_replace;
} utsm_pckc;
void utsm_pckc_init(void);
int utsm_pckc_get_or_derive(u32 segment_slot, struct utsm_segment_desc *desc, utsm_key_material *out_key);
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef UTSM_PROCESS_H
#define UTSM_PROCESS_H
#include <utsm/types.h>
#include <utsm/uuid.h>
typedef struct utsm_process_context {
uuid128_t process_uuid;
u64 crypto_epoch;
u64 recovery_generation;
u32 capability_table_slot;
u32 capability_count;
u32 flags;
} utsm_process_context;
void utsm_process_create_test(utsm_process_context *process, u64 seed);
#endif
+50
View File
@@ -0,0 +1,50 @@
#ifndef UTSM_SEGMENT_H
#define UTSM_SEGMENT_H
#include <utsm/types.h>
#include <utsm/uuid.h>
#include <utsm/status.h>
#include <utsm/capability.h>
#include <utsm/dirty.h>
typedef enum {
UTSM_SEG_FREE = 0,
UTSM_SEG_ACTIVE,
UTSM_SEG_CHECKPOINTING,
UTSM_SEG_SEALED,
UTSM_SEG_RECOVERING,
UTSM_SEG_POISONED,
UTSM_SEG_DESTROYED
} utsm_segment_state;
#define UTSM_SEG_F_READ (1U << 0)
#define UTSM_SEG_F_WRITE (1U << 1)
#define UTSM_SEG_F_EXEC (1U << 2)
#define UTSM_SEG_F_DMA (1U << 3)
#define UTSM_SEG_F_STRONG_RECOVERY (1U << 4)
typedef struct utsm_segment_desc {
uuid128_t segment_uuid;
uuid128_t owner_process_uuid;
u8 *cipher_base;
u64 cipher_length;
void *dmp_base;
u64 key_epoch;
u64 tweak_seed;
utsm_dirty_shard *dirty_shards;
u32 dirty_shard_count;
void *mac_table;
u32 generation;
u32 flags;
u32 state;
u32 last_cpu;
volatile u64 writer_seq;
u64 checkpoint_generation;
} utsm_segment_desc;
struct utsm_process_context;
int utsm_create_segment(struct utsm_process_context *process, u64 size, u32 flags, utsm_capability *out_cap);
utsm_segment_desc *utsm_get_segment(u32 slot);
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef UTSM_STATUS_H
#define UTSM_STATUS_H
typedef enum {
UTSM_OK = 0,
UTSM_ERR_INVALID = -1,
UTSM_ERR_NO_MEMORY = -2,
UTSM_ERR_ACCESS = -3,
UTSM_ERR_BOUNDS = -4,
UTSM_ERR_STALE_CAP = -5,
UTSM_ERR_EPOCH = -6,
UTSM_ERR_KEY_MISS = -7,
UTSM_ERR_STATE = -8,
UTSM_ERR_POISONED = -9,
UTSM_ERR_RETRY = -10
} utsm_status;
#endif
+36
View File
@@ -0,0 +1,36 @@
#ifndef UTSM_TYPES_H
#define UTSM_TYPES_H
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef signed char i8;
typedef signed short i16;
typedef signed int i32;
typedef signed long long i64;
typedef u64 usize;
typedef i64 isize;
typedef int bool;
#define true 1
#define false 0
#ifndef NULL
#define NULL ((void *)0)
#endif
#define UTSM_UNUSED(x) ((void)(x))
#define UTSM_ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0]))
static inline u64 utsm_align_up_u64(u64 value, u64 alignment) {
return (value + alignment - 1ULL) & ~(alignment - 1ULL);
}
static inline void *utsm_align_up_ptr(void *ptr, u64 alignment) {
return (void *)utsm_align_up_u64((u64)ptr, alignment);
}
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef UTSM_UTRW_H
#define UTSM_UTRW_H
#include <utsm/types.h>
#include <utsm/status.h>
#include <utsm/capability.h>
int utsm_read(utsm_capability cap, u64 offset, void *dst, u64 len);
int utsm_write(utsm_capability cap, u64 offset, const void *src, u64 len);
int utsm_slow_path(int reason);
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef UTSM_H
#define UTSM_H
#include <utsm/types.h>
#include <utsm/status.h>
#include <utsm/config.h>
#include <utsm/uuid.h>
#include <utsm/process.h>
#include <utsm/segment.h>
#include <utsm/capability.h>
#include <utsm/utrw.h>
void utsm_init(void);
int utsm_selftest_run(void);
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef UTSM_UUID_H
#define UTSM_UUID_H
#include <utsm/types.h>
typedef struct {
u64 hi;
u64 lo;
} uuid128_t;
static inline uuid128_t uuid_make_test(u64 seed) {
uuid128_t id;
id.hi = 0x5554534d00000000ULL ^ (seed * 0x9e3779b97f4a7c15ULL);
id.lo = 0x4453484200000000ULL ^ (seed + 0xd1b54a32d192ed03ULL);
return id;
}
static inline bool uuid_equal(uuid128_t a, uuid128_t b) {
return a.hi == b.hi && a.lo == b.lo;
}
#endif
+58
View File
@@ -0,0 +1,58 @@
#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 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 const dkm_block_api g_block_api = {
.register_device = block_register_device_impl,
.device_count = block_device_count_impl,
.read = block_read_impl,
.sector_size = block_sector_size_impl,
.device_name = block_device_name_impl
};
const dkm_block_api *block_get_api(void) {
return &g_block_api;
}
Binary file not shown.
+377
View File
@@ -0,0 +1,377 @@
#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 */
static u8 g_dsk_fat32_filedata[65536]; /* file data buffer */
static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) {
const dkm_kernel_api *api = dkm_get_kernel_api();
if (!api || !api->block || !api->block->device_count) return -1;
u32 count = api->block->device_count();
if (count == 0 || api->block->sector_size(0) != 512) return -1;
/* Read first 128 sectors: BPB + FAT + root dir */
u8 *disk = g_dsk_fat32_disk;
int st = api->block->read(0, 0, 128, disk);
if (st != 0) return -1;
const fat32_bpb *bpb = (const fat32_bpb *)disk;
if (bpb->boot_sig != 0xAA55 || bpb->bytes_per_sector != 512) return -1;
u32 fat_start = bpb->reserved_sector_count * 512;
u32 data_start_sec = bpb->reserved_sector_count + (u32)bpb->fat_count * bpb->sectors_per_fat;
u32 clus = bpb->root_cluster;
u32 found_clus = 0;
u32 found_size = 0;
const char *target = "DESHAB ELF";
while (clus >= 2 && clus < 0x0FFFFFF8) {
u32 clus_lba = data_start_sec + (clus - 2) * bpb->sectors_per_cluster;
u32 cls_sec = bpb->sectors_per_cluster;
u8 *cb = g_dsk_fat32_cluster;
st = api->block->read(0, clus_lba, cls_sec, cb);
if (st != 0) return -1;
const fat32_dir_entry *dir = (const fat32_dir_entry *)cb;
for (u32 e = 0; e * 32 < cls_sec * 512; e++) {
if (dir[e].name[0] == 0) break;
if ((u8)dir[e].name[0] == 0xE5) continue;
if (dir[e].attr == 0x0F) continue;
if (dir[e].attr & 0x08) continue;
if (fat32_name11_eq(dir[e].name, target)) {
found_size = dir[e].file_size;
found_clus = fat32_read_u16((const u8 *)&dir[e].cluster_low);
break;
}
}
if (found_clus) break;
u32 fat_ent = fat_start + clus * 4;
if (fat_ent + 4 > 65536) break;
clus = fat32_read_u32(disk + fat_ent) & 0x0FFFFFFF;
}
if (!found_clus || found_size == 0) return -1;
if (found_size > sizeof(g_dsk_fat32_filedata)) return -1;
u8 *dst = g_dsk_fat32_filedata;
u32 remaining = found_size;
u32 fc = found_clus;
while (fc >= 2 && fc < 0x0FFFFFF8 && remaining > 0) {
u32 fc_lba = data_start_sec + (fc - 2) * bpb->sectors_per_cluster;
u32 fc_sec = bpb->sectors_per_cluster;
u32 fc_bytes = fc_sec * 512;
if (fc_bytes > remaining) fc_bytes = remaining;
u8 *chunk = g_dsk_fat32_cluster;
st = api->block->read(0, fc_lba, fc_sec, chunk);
if (st != 0) return -1;
for (u32 b = 0; b < fc_bytes; b++) dst[b] = chunk[b];
dst += fc_bytes;
remaining -= fc_bytes;
u32 fat_ent = fat_start + fc * 4;
if (fat_ent + 4 > 65536) { fc = 0x0FFFFFFF; break; }
fc = fat32_read_u32(disk + fat_ent) & 0x0FFFFFFF;
}
/* Copy to arena for ELF loader */
u8 *file_buf = (u8 *)kmem_alloc_aligned(found_size, 16);
if (!file_buf) return -1;
for (u32 i = 0; i < found_size; i++) file_buf[i] = g_dsk_fat32_filedata[i];
*out_addr = file_buf;
*out_size = found_size;
log_hex64("[UTSM] FAT32 file size=", found_size);
return 0;
}
/* ---- ELF checks ---- */
static int dsk_check_elf(const void *address, u64 size) {
if (!address || size < sizeof(elf64_ehdr)) return -1;
const elf64_ehdr *eh = (const elf64_ehdr *)address;
if (eh->ident[0] != ELF_MAGIC0 || eh->ident[1] != ELF_MAGIC1 ||
eh->ident[2] != ELF_MAGIC2 || eh->ident[3] != ELF_MAGIC3) return -2;
if (eh->ident[4] != ELFCLASS64 || eh->ident[5] != ELFDATA2LSB) return -3;
if (eh->machine != EM_X86_64) return -4;
if (eh->type != ET_DYN && eh->type != ET_EXEC) return -5;
if (eh->phoff == 0 || eh->phnum == 0 || eh->phentsize < sizeof(elf64_phdr)) return -6;
if (!range_ok(eh->phoff, (u64)eh->phnum * eh->phentsize, size)) return -7;
return 0;
}
static int dsk_load_elf_image(const void *address, u64 size, dsk_entry_fn *entry_out) {
const elf64_ehdr *eh = (const elf64_ehdr *)address;
const u8 *base = (const u8 *)address;
u64 min_vaddr = ~0ULL;
u64 max_vaddr = 0;
u64 max_align = 0x1000;
u32 load_count = 0;
for (u16 i = 0; i < eh->phnum; i++) {
const elf64_phdr *ph = (const elf64_phdr *)(base + eh->phoff + (u64)i * eh->phentsize);
if (ph->type != PT_LOAD) continue;
if (ph->filesz > ph->memsz) return -1;
if (!range_ok(ph->offset, ph->filesz, size)) return -2;
if (ph->vaddr < min_vaddr) min_vaddr = ph->vaddr;
if (ph->vaddr + ph->memsz > max_vaddr) max_vaddr = ph->vaddr + ph->memsz;
if (ph->align > max_align) max_align = ph->align;
load_count++;
}
if (load_count == 0 || min_vaddr == ~0ULL || max_vaddr <= min_vaddr) return -3;
if (eh->entry < min_vaddr || eh->entry >= max_vaddr) return -4;
u64 image_size = utsm_align_up_u64(max_vaddr - min_vaddr, 0x1000);
u8 *image = (u8 *)kmem_alloc_aligned(image_size, max_align);
if (!image) return -5;
memset(image, 0, image_size);
for (u16 i = 0; i < eh->phnum; i++) {
const elf64_phdr *ph = (const elf64_phdr *)(base + eh->phoff + (u64)i * eh->phentsize);
if (ph->type != PT_LOAD) continue;
u64 dst_off = ph->vaddr - min_vaddr;
if (dst_off + ph->memsz > image_size) return -6;
memcpy(image + dst_off, base + ph->offset, ph->filesz);
}
*entry_out = (dsk_entry_fn)(image + (eh->entry - min_vaddr));
log_hex64("[UTSM] DSK image base=", (u64)image);
log_hex64("[UTSM] DSK image size=", image_size);
log_hex64("[UTSM] DSK entry=", (u64)*entry_out);
return 0;
}
static void dsk_fill_boot_context(dsk_boot_context *ctx) {
memset(ctx, 0, sizeof(*ctx));
ctx->magic = DSK_BOOT_MAGIC;
ctx->abi_version = DSK_BOOT_ABI_VERSION;
ctx->size = sizeof(*ctx);
ctx->flags = DSK_BOOT_FLAG_FROM_UTSM | DSK_BOOT_FLAG_DKM_READY | DSK_BOOT_FLAG_FAT32_PATH;
if (g_hhdm_request.response) {
ctx->hhdm_offset = g_hhdm_request.response->offset;
}
if (g_rsdp_request.response) {
ctx->rsdp_address = (u64)g_rsdp_request.response->address;
}
if (g_fb_request.response && g_fb_request.response->framebuffer_count > 0) {
struct limine_framebuffer *fb = g_fb_request.response->framebuffers[0];
ctx->framebuffer_address = (u64)fb->address;
ctx->framebuffer_width = fb->width;
ctx->framebuffer_height = fb->height;
ctx->framebuffer_pitch = fb->pitch;
ctx->framebuffer_bpp = fb->bpp;
}
ctx->boot_modules_response = (u64)g_module_request.response;
ctx->dkm_kernel_api = (u64)dkm_get_kernel_api();
u64 rsp;
__asm__ volatile ("movq %%rsp, %0" : "=r"(rsp));
ctx->kernel_stack_top = rsp;
}
int dsk_load_and_jump(void) {
log_info("[UTSM] loading DSK");
log_info(DSK_PATH);
const void *data = 0;
u64 data_size = 0;
/* 1) try FAT32 block provider */
int fat32_ok = dsk_load_from_block_fat32(&data, &data_size);
if (fat32_ok == 0) {
log_info("[UTSM] DSK loaded from FAT32 block provider");
} else {
/* 2) fallback: Limine boot module */
log_info("[UTSM] FAT32 block path unavailable; trying Limine module");
struct limine_file *file = dsk_find_module();
if (!file) {
log_error("[UTSM] DSK module not found (neither FAT32 nor Limine)");
return -1;
}
data = file->address;
data_size = file->size;
log_hex64("[UTSM] DSK module size=", data_size);
}
int status = dsk_check_elf(data, data_size);
if (status != 0) {
log_error("[UTSM] DSK ELF rejected");
log_hex64("[UTSM] DSK ELF status=", (u64)(i64)status);
return status;
}
dsk_entry_fn entry = 0;
status = dsk_load_elf_image(data, data_size, &entry);
if (status != 0) {
log_error("[UTSM] DSK load failed");
log_hex64("[UTSM] DSK load status=", (u64)(i64)status);
return status;
}
dsk_boot_context *ctx = (dsk_boot_context *)kmem_alloc_aligned(sizeof(dsk_boot_context), 16);
if (!ctx) {
log_error("[UTSM] DSK context allocation failed");
return -1;
}
dsk_fill_boot_context(ctx);
log_info("[UTSM] jumping to DSK");
entry(ctx);
log_error("[UTSM] DSK returned unexpectedly");
return -1;
}
Binary file not shown.
+34
View File
@@ -0,0 +1,34 @@
#include <utsm/log.h>
static void log_line(const char *level, const char *msg) {
serial_write(level);
serial_write(" ");
serial_write(msg);
serial_write("\n");
}
void log_info(const char *msg) {
log_line("[INFO]", msg);
}
void log_warn(const char *msg) {
log_line("[WARN]", msg);
}
void log_error(const char *msg) {
log_line("[ERR ]", msg);
}
void log_hex64(const char *prefix, u64 value) {
static const char hex[] = "0123456789abcdef";
char buf[19];
buf[0] = '0';
buf[1] = 'x';
for (int i = 0; i < 16; i++) {
buf[2 + i] = hex[(value >> ((15 - i) * 4)) & 0xf];
}
buf[18] = 0;
serial_write(prefix);
serial_write(buf);
serial_write("\n");
}
Binary file not shown.
+54
View File
@@ -0,0 +1,54 @@
#include <utsm/log.h>
#include <utsm/arena.h>
#include <utsm/utsm.h>
#include <utsm/drr.h>
#include <utsm/dkm.h>
#include <utsm/idt.h>
#include <utsm/dsk.h>
#include <utsm/block.h>
#include <utsm/net.h>
void arch_halt_forever(void);
void kernel_main(void) {
serial_init();
log_info("[UTSM] boot");
idt_init();
log_info("[UTSM] arena init begin");
arena_init();
log_info("[UTSM] arena init ok");
log_info("[UTSM] dma init begin");
dma_init();
log_info("[UTSM] dma init ok");
log_info("[UTSM] net registry init begin");
net_init();
log_info("[UTSM] net registry init ok");
log_info("[UTSM] drr stub init begin");
drr_stub_init();
log_info("[UTSM] drr stub 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();
}
Binary file not shown.
+73
View File
@@ -0,0 +1,73 @@
#include <utsm/net.h>
#include <utsm/log.h>
/*
* 最小 netdev 注册表:
* - 早期 DKM 驱动加载路径是单线程顺序执行,当前无需引入锁,避免在网络底座阶段扩大复杂度。
* - 后续进入多核/热插拔后,应在 register/device_info 外围加自旋锁或 RCU 风格只读快照。
*/
static dkm_net_device_desc g_net_devices[DKM_NET_MAX_DEVICES];
static u32 g_net_device_count;
void net_init(void) {
g_net_device_count = 0;
log_info("[NET] registry init");
}
static int net_register_device_impl(const dkm_net_device_desc *desc) {
if (!desc || !desc->name) return -1;
if (g_net_device_count >= DKM_NET_MAX_DEVICES) return -2;
u32 index = g_net_device_count++;
g_net_devices[index] = *desc;
log_info("[NET] device registered");
log_info(desc->name);
log_hex64("[NET] index=", index);
log_hex64("[NET] flags=", desc->flags);
return (int)index;
}
static u32 net_device_count_impl(void) {
return g_net_device_count;
}
static int net_device_info_impl(u32 index, dkm_net_device_info *out) {
if (!out) return -1;
if (index >= g_net_device_count) return -2;
const dkm_net_device_desc *dev = &g_net_devices[index];
out->name = dev->name;
for (u32 i = 0; i < 6; i++) {
out->mac[i] = dev->mac[i];
}
out->flags = dev->flags;
return 0;
}
static int net_tx_impl(u32 index, const void *packet, u32 length) {
if (index >= g_net_device_count) return -2;
const dkm_net_device_desc *dev = &g_net_devices[index];
if (!dev->tx) return -3;
log_hex64("[NET] tx dispatch fn=", (u64)dev->tx);
return dev->tx(dev->ctx, packet, length);
}
static int net_rx_poll_impl(u32 index, void *buffer, u32 capacity, u32 *out_length) {
if (index >= g_net_device_count) return -2;
const dkm_net_device_desc *dev = &g_net_devices[index];
if (!dev->rx_poll) return -3;
return dev->rx_poll(dev->ctx, buffer, capacity, out_length);
}
static const dkm_net_api g_net_api = {
.register_device = net_register_device_impl,
.device_count = net_device_count_impl,
.device_info = net_device_info_impl,
.tx = net_tx_impl,
.rx_poll = net_rx_poll_impl
};
const dkm_net_api *net_get_api(void) {
return &g_net_api;
}
Binary file not shown.
+9
View File
@@ -0,0 +1,9 @@
#include <utsm/log.h>
void arch_halt_forever(void);
void panic(const char *msg) {
log_error("[PANIC]");
log_error(msg);
arch_halt_forever();
}
Binary file not shown.
+30
View File
@@ -0,0 +1,30 @@
ENTRY(_start)
PHDRS
{
text PT_LOAD FLAGS(5); /* R-X */
rodata PT_LOAD FLAGS(4); /* R-- */
data PT_LOAD FLAGS(7); /* RWX (SAS-R0) */
}
SECTIONS
{
. = 0xffffffff80000000;
.text : ALIGN(4K) {
*(.text*)
} :text
.rodata : ALIGN(4K) {
*(.limine_requests_start*)
*(.limine_requests*)
*(.limine_requests_end*)
*(.rodata*)
} :rodata
.data : ALIGN(4K) {
*(.data*)
*(COMMON)
*(.bss*)
} :data
}

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