feat(boot): bootstrap minimal UEFI startup and document roadmap
This commit is contained in:
parent
5fc902d56d
commit
9a71252f91
70
Makefile
Normal file
70
Makefile
Normal file
@ -0,0 +1,70 @@
|
||||
SHELL := /bin/bash
|
||||
|
||||
CC := clang
|
||||
LD := lld-link
|
||||
|
||||
BUILD_DIR := build
|
||||
EFI_DIR := $(BUILD_DIR)/image/EFI/BOOT
|
||||
BOOT_EFI := $(EFI_DIR)/BOOTX64.EFI
|
||||
BOOT_OBJ := $(BUILD_DIR)/boot/main.obj
|
||||
DEBUG_LOG := $(BUILD_DIR)/debug.log
|
||||
OVMF_CODE ?= /usr/share/OVMF/OVMF_CODE_4M.fd
|
||||
OVMF_VARS_TEMPLATE ?= /usr/share/OVMF/OVMF_VARS_4M.fd
|
||||
OVMF_VARS := $(BUILD_DIR)/OVMF_VARS.fd
|
||||
|
||||
CFLAGS := \
|
||||
-target x86_64-unknown-windows \
|
||||
-ffreestanding \
|
||||
-fshort-wchar \
|
||||
-mno-red-zone \
|
||||
-fno-stack-protector \
|
||||
-fno-builtin \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Werror \
|
||||
-Iinclude
|
||||
|
||||
LDFLAGS := \
|
||||
/subsystem:efi_application \
|
||||
/entry:efi_main \
|
||||
/nodefaultlib \
|
||||
/dll \
|
||||
/machine:x64 \
|
||||
/out:$(BOOT_EFI)
|
||||
|
||||
.PHONY: all clean run run-headless dirs
|
||||
|
||||
all: $(BOOT_EFI)
|
||||
|
||||
dirs:
|
||||
mkdir -p $(BUILD_DIR)/boot $(EFI_DIR)
|
||||
|
||||
$(BOOT_OBJ): boot/main.c include/efi.h | dirs
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BOOT_EFI): $(BOOT_OBJ) | dirs
|
||||
$(LD) $(LDFLAGS) $<
|
||||
|
||||
$(OVMF_VARS): | dirs
|
||||
cp $(OVMF_VARS_TEMPLATE) $@
|
||||
|
||||
run: $(BOOT_EFI) $(OVMF_VARS)
|
||||
qemu-system-x86_64 \
|
||||
-drive if=pflash,format=raw,readonly=on,file=$(OVMF_CODE) \
|
||||
-drive if=pflash,format=raw,file=$(OVMF_VARS) \
|
||||
-drive format=raw,file=fat:rw:$(BUILD_DIR)/image
|
||||
|
||||
run-headless: $(BOOT_EFI) $(OVMF_VARS)
|
||||
rm -f $(DEBUG_LOG)
|
||||
qemu-system-x86_64 \
|
||||
-display none \
|
||||
-nodefaults \
|
||||
-no-reboot \
|
||||
-drive if=pflash,format=raw,readonly=on,file=$(OVMF_CODE) \
|
||||
-drive if=pflash,format=raw,file=$(OVMF_VARS) \
|
||||
-drive format=raw,file=fat:rw:$(BUILD_DIR)/image \
|
||||
-debugcon file:$(DEBUG_LOG) \
|
||||
-global isa-debugcon.iobase=0xe9
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
32
boot/main.c
Normal file
32
boot/main.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include "efi.h"
|
||||
|
||||
static efi_char16_t banner_text[] = {
|
||||
'T', 'i', 'a', 'n', 'o', 'l', 'e', ' ',
|
||||
'b', 'o', 'o', 't', ' ', 's', 't', 'u',
|
||||
'b', ' ', 'l', 'o', 'a', 'd', 'e', 'd',
|
||||
'.', '\r', '\n', 0
|
||||
};
|
||||
|
||||
static inline void debug_putc(char ch) {
|
||||
__asm__ volatile("outb %0, $0xe9" : : "a"(ch));
|
||||
}
|
||||
|
||||
static void debug_puts(const char *text) {
|
||||
while (*text != '\0') {
|
||||
if (*text == '\n') {
|
||||
debug_putc('\r');
|
||||
}
|
||||
debug_putc(*text++);
|
||||
}
|
||||
}
|
||||
|
||||
efi_status EFIAPI efi_main(efi_handle image_handle, efi_system_table_t *system_table) {
|
||||
(void)image_handle;
|
||||
|
||||
system_table->con_out->output_string(system_table->con_out, banner_text);
|
||||
debug_puts("Tianole boot stub loaded.\n");
|
||||
|
||||
for (;;) {
|
||||
system_table->boot_services->stall(1000 * 1000);
|
||||
}
|
||||
}
|
||||
12
docs/agents/README.md
Normal file
12
docs/agents/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Agent 文档
|
||||
|
||||
这个目录专门放面向 AI / agent 的项目材料,不和内核设计文档混放。
|
||||
|
||||
建议内容:
|
||||
|
||||
- `session-notes/`:实现日志和阶段结论。
|
||||
- `tasks/`:适合 agent 执行的边界清晰任务。
|
||||
- `prompts/`:可复用提示词和约束。
|
||||
- `checklists/`:启动、验证、回归检查单。
|
||||
|
||||
正式架构决策仍然放在 `docs/`,然后在 agent 任务文档里引用它们。
|
||||
179
docs/roadmap.md
Normal file
179
docs/roadmap.md
Normal file
@ -0,0 +1,179 @@
|
||||
# Tianole 路线图
|
||||
|
||||
## 第 0 阶段
|
||||
|
||||
- 建立最小 `UEFI` 启动程序。
|
||||
- 在 `QEMU + OVMF` 下运行。
|
||||
- 在屏幕和 `debug.log` 中输出可见的启动标记。
|
||||
- 保证启动后常驻,便于后续调试。
|
||||
|
||||
## 第 1 阶段
|
||||
|
||||
- 把当前单体启动程序拆成 `boot/` 与 `kernel/`。
|
||||
- 定义 `boot_info` 交接结构。
|
||||
- 由 `bootloader` 加载独立 `kernel` 映像。
|
||||
- 跳转到 `kernel` 入口并建立稳定栈。
|
||||
|
||||
## 第 2 阶段
|
||||
|
||||
- 获取 `UEFI memory map`。
|
||||
- 正确执行 `ExitBootServices`。
|
||||
- 建立最小 framebuffer 控制台。
|
||||
- 开始做物理内存管理。
|
||||
|
||||
## 第 3 阶段
|
||||
|
||||
- 建立 `IDT` 和基础异常处理。
|
||||
- 增加定时器来源。
|
||||
- 开始早期 `ACPI` 解析。
|
||||
- 逐步过渡到接近 Linux 风格的 `arch/`、`mm/`、`kernel/` 边界。
|
||||
|
||||
## 总体流程
|
||||
|
||||
这个项目要按“可中断、可回坑、每一阶段都能单独验收”的方式推进。最终目标不是只在虚拟机里亮屏,而是要在这台 `UEFI x86_64` 笔记本上独立启动,并逐步具备运行本地 `git` 的能力。
|
||||
|
||||
建议的长期阶段如下:
|
||||
|
||||
### 阶段 A:启动链
|
||||
|
||||
- 跑通 `UEFI app -> bootloader -> kernel`
|
||||
- 保证 `kernel_main()` 真正开始执行
|
||||
- 保证屏幕或串口可见输出
|
||||
|
||||
完成标志:
|
||||
|
||||
- `bootloader` 成功把控制权交给独立 `kernel`
|
||||
- `kernel` 能输出第一行字并停住
|
||||
|
||||
### 阶段 B:早期内核基础
|
||||
|
||||
- 定义 `boot_info`
|
||||
- 获取 `memory map`
|
||||
- 正确执行 `ExitBootServices`
|
||||
- 建立 early console
|
||||
- 建立最小 panic / assert / log
|
||||
|
||||
完成标志:
|
||||
|
||||
- 退出 UEFI 后内核仍能稳定运行
|
||||
- 崩溃时能给出可定位信息
|
||||
|
||||
### 阶段 C:内存与异常
|
||||
|
||||
- 建立物理页分配器
|
||||
- 建立内核堆分配器
|
||||
- 建立 `GDT/IDT`
|
||||
- 处理基础异常
|
||||
- 增加定时器
|
||||
|
||||
完成标志:
|
||||
|
||||
- 能稳定分配页和堆内存
|
||||
- 关键异常能进入处理路径
|
||||
|
||||
### 阶段 D:任务模型
|
||||
|
||||
- 建立内核线程
|
||||
- 建立调度器
|
||||
- 建立上下文切换
|
||||
- 增加睡眠/唤醒与同步原语
|
||||
|
||||
完成标志:
|
||||
|
||||
- 可以同时运行多个内核线程
|
||||
- 调度由时钟驱动
|
||||
|
||||
### 阶段 E:用户态基础
|
||||
|
||||
- 建立用户地址空间
|
||||
- 增加系统调用入口
|
||||
- 增加 ELF 加载
|
||||
- 增加进程创建和等待
|
||||
|
||||
完成标志:
|
||||
|
||||
- 能加载并运行最小用户程序
|
||||
- 用户程序能调用系统调用输出
|
||||
|
||||
### 阶段 F:存储与文件系统
|
||||
|
||||
- 建立块设备层
|
||||
- 建立 `VFS`
|
||||
- 接入一个实际文件系统
|
||||
- 实现路径解析、文件读写、目录操作
|
||||
|
||||
完成标志:
|
||||
|
||||
- 能挂载文件系统
|
||||
- 能打开、读取、写入文件
|
||||
|
||||
### 阶段 G:最小用户空间
|
||||
|
||||
- 增加 `init`
|
||||
- 增加简单 shell
|
||||
- 增加基础命令
|
||||
- 补最小 `libc` 能力
|
||||
|
||||
完成标志:
|
||||
|
||||
- 启动后能进入 shell
|
||||
- 能执行几个基础程序
|
||||
|
||||
### 阶段 H:面向 git 的补齐
|
||||
|
||||
- 优先支持本地 `git`,不先碰网络
|
||||
- 补足 `git` 依赖的文件、进程、时间、路径等接口
|
||||
- 先以 `git init / status / add / commit` 为目标
|
||||
|
||||
完成标志:
|
||||
|
||||
- 能运行本地仓库的基础 `git` 操作
|
||||
|
||||
### 阶段 I:真机落地
|
||||
|
||||
- 先 `QEMU + OVMF`
|
||||
- 再 `U 盘 UEFI` 启动
|
||||
- 最后再考虑加入本机启动项
|
||||
|
||||
完成标志:
|
||||
|
||||
- 不破坏现有 `Windows 11 + Linux Mint + GRUB`
|
||||
- 能在真机上独立启动并进入系统
|
||||
|
||||
## 当前所处阶段
|
||||
|
||||
当前只完成了第 0 阶段的最小成果:
|
||||
|
||||
- `UEFI` 启动程序可构建
|
||||
- `QEMU + OVMF` 能执行它
|
||||
- 屏幕和 `debug.log` 有可见输出
|
||||
- 程序可常驻,便于调试
|
||||
|
||||
当前还没有完成:
|
||||
|
||||
- 独立 `kernel` 接管
|
||||
- `bootloader -> kernel` 交接
|
||||
- `memory map`
|
||||
- `ExitBootServices`
|
||||
- 真正的内核子系统
|
||||
|
||||
## 接下来最近三个里程碑
|
||||
|
||||
### 里程碑 1:独立 kernel 接管
|
||||
|
||||
- 让 `bootloader` 加载独立 `kernel`
|
||||
- 建立 `boot_info`
|
||||
- 跳到 `kernel_main()`
|
||||
- 由 `kernel` 自己输出第一行字
|
||||
|
||||
### 里程碑 2:退出 UEFI
|
||||
|
||||
- 获取并保存 `memory map`
|
||||
- 正确执行 `ExitBootServices`
|
||||
- `kernel` 在退出固件服务后继续稳定运行
|
||||
|
||||
### 里程碑 3:早期调试和内存基础
|
||||
|
||||
- 增加 early serial / framebuffer console
|
||||
- 建立物理页分配器
|
||||
- 建立基础异常处理
|
||||
110
include/efi.h
Normal file
110
include/efi.h
Normal file
@ -0,0 +1,110 @@
|
||||
#ifndef TIANOLE_EFI_H
|
||||
#define TIANOLE_EFI_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint64_t efi_status;
|
||||
typedef void *efi_handle;
|
||||
typedef uint16_t efi_char16_t;
|
||||
typedef uint64_t efi_uintn_t;
|
||||
|
||||
#define EFI_SUCCESS 0
|
||||
#define EFI_RESET_SHUTDOWN 2
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define EFIAPI __attribute__((ms_abi))
|
||||
#else
|
||||
#define EFIAPI
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint64_t signature;
|
||||
uint32_t revision;
|
||||
uint32_t header_size;
|
||||
uint32_t crc32;
|
||||
uint32_t reserved;
|
||||
} efi_table_header_t;
|
||||
|
||||
typedef struct efi_simple_text_output_protocol efi_simple_text_output_protocol_t;
|
||||
typedef struct efi_runtime_services efi_runtime_services_t;
|
||||
typedef struct efi_boot_services efi_boot_services_t;
|
||||
|
||||
struct efi_simple_text_output_protocol {
|
||||
void *reset;
|
||||
efi_status(EFIAPI *output_string)(
|
||||
efi_simple_text_output_protocol_t *self,
|
||||
efi_char16_t *string
|
||||
);
|
||||
};
|
||||
|
||||
struct efi_runtime_services {
|
||||
efi_table_header_t hdr;
|
||||
void *get_time;
|
||||
void *set_time;
|
||||
void *get_wakeup_time;
|
||||
void *set_wakeup_time;
|
||||
void *set_virtual_address_map;
|
||||
void *convert_pointer;
|
||||
void *get_variable;
|
||||
void *get_next_variable_name;
|
||||
void *set_variable;
|
||||
void *get_next_high_mono_count;
|
||||
void(EFIAPI *reset_system)(
|
||||
uint32_t reset_type,
|
||||
efi_status reset_status,
|
||||
efi_uintn_t data_size,
|
||||
void *reset_data
|
||||
);
|
||||
};
|
||||
|
||||
struct efi_boot_services {
|
||||
efi_table_header_t hdr;
|
||||
void *raise_tpl;
|
||||
void *restore_tpl;
|
||||
void *allocate_pages;
|
||||
void *free_pages;
|
||||
void *get_memory_map;
|
||||
void *allocate_pool;
|
||||
void *free_pool;
|
||||
void *create_event;
|
||||
void *set_timer;
|
||||
void *wait_for_event;
|
||||
void *signal_event;
|
||||
void *close_event;
|
||||
void *check_event;
|
||||
void *install_protocol_interface;
|
||||
void *reinstall_protocol_interface;
|
||||
void *uninstall_protocol_interface;
|
||||
void *handle_protocol;
|
||||
void *reserved;
|
||||
void *register_protocol_notify;
|
||||
void *locate_handle;
|
||||
void *locate_device_path;
|
||||
void *install_configuration_table;
|
||||
void *load_image;
|
||||
void *start_image;
|
||||
void *exit;
|
||||
void *unload_image;
|
||||
void *exit_boot_services;
|
||||
void *get_next_monotonic_count;
|
||||
void(EFIAPI *stall)(efi_uintn_t microseconds);
|
||||
void *set_watchdog_timer;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
efi_table_header_t hdr;
|
||||
efi_char16_t *firmware_vendor;
|
||||
uint32_t firmware_revision;
|
||||
efi_handle console_in_handle;
|
||||
void *con_in;
|
||||
efi_handle console_out_handle;
|
||||
efi_simple_text_output_protocol_t *con_out;
|
||||
efi_handle standard_error_handle;
|
||||
efi_simple_text_output_protocol_t *std_err;
|
||||
efi_runtime_services_t *runtime_services;
|
||||
efi_boot_services_t *boot_services;
|
||||
uint64_t number_of_table_entries;
|
||||
void *configuration_table;
|
||||
} efi_system_table_t;
|
||||
|
||||
#endif
|
||||
4
kernel/main.c
Normal file
4
kernel/main.c
Normal file
@ -0,0 +1,4 @@
|
||||
/*
|
||||
* Kernel code starts in the next stage.
|
||||
* The initial milestone is a verified UEFI boot path.
|
||||
*/
|
||||
5
scripts/run-qemu.sh
Executable file
5
scripts/run-qemu.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
make run
|
||||
Loading…
Reference in New Issue
Block a user