diff --git a/README.md b/README.md index 09d82f4..065d6ca 100644 --- a/README.md +++ b/README.md @@ -1,230 +1,72 @@ # Tianole -新的起点。这个仓库现在不保留旧实现,先把目标机器、开发环境、技术路线和最小步骤固定下来,避免再次在错误方向上堆代码。 +Tianole 是一个面向 `UEFI x86_64` 机器的自制操作系统项目。 -## 当前结论 +当前目标不是一次性做“大而全”的系统,而是按 Linux 风格的分层思路,逐步把启动链、内核基础设施、用户态和文件系统建立起来,最终能在真机上安全启动,并逐步具备运行本地 `git` 的能力。 -- 语言:第一版用 `C` -- 架构:`x86_64` -- 启动方式:`UEFI` -- 主开发环境:`WSL2` -- 日常验证:先 `QEMU + OVMF` -- 真机验证:先 `U 盘 UEFI` 启动 -- 最终目标:在自己的笔记本上以独立启动项或可控方式启动,不先破坏现有 `Windows 11 + Linux Mint + GRUB` +## 当前状态 -## 为什么现在不用旧代码 +- 已跑通 `QEMU + OVMF` 下的最小 `UEFI` 启动链 +- 已拆分为 `bootloader + kernel` +- `bootloader` 已能加载独立 `kernel.elf` +- `kernel_main()` 已能实际执行 -旧实现的问题不是“有几个 bug”,而是路线已经和目标真机错位: - -- 旧项目是 `32位 + Multiboot + GRUB + qemu-system-i386` -- 你的目标机器是现代 `UEFI + GPT + x86_64` -- 旧项目已经铺到任务、FAT16、ATA PIO、用户态切换,但底座仍是老 PC 路线 -- 继续修补会持续消耗精力在错误底座上 - -所以现在直接重开,比在旧代码上修修补补更省。 - -## 这台机器已经确认的信息 - -- 当前日期环境:`2026-05-08` -- 机器:`LENOVO 21HX` -- CPU:`13th Gen Intel Core i5-13500H` -- 核心/线程:`12` 核 `16` 线程 -- 内存:`16 GB` -- 显卡:`Intel Iris Xe Graphics` -- 磁盘:`1 TB NVMe SSD` -- 固件模式:`UEFI` -- 分区表:`GPT` -- BIOS 版本:`LBCN26WW` -- BIOS 日期:`2024-08-23` -- 当前系统状态:你现在在 `Windows 11`,机器上同时有 `Linux Mint` -- 启动情况:GRUB 由 `Mint` 管理,你现在只是从该多启动环境进入了 Windows -- 额外观察:系统报告 `HypervisorPresent = True` -- 未确认项:`Secure Boot` 状态未成功读出,后续真机启动自制 OS 时必须单独检查 - -## 这些信息意味着什么 - -- 不要走 `BIOS + MBR + 16位 boot sector` 教程路线 -- 不要再把 `32位` 当主线 -- 第一阶段不要碰真实 GPU 驱动,先用 `UEFI GOP framebuffer` -- 第一阶段不要碰真实 `NVMe` 驱动 -- 第一阶段不要急着做复杂用户态 -- 真机阶段不要一开始去改现有 `GRUB` 或覆盖 EFI 启动链 - -## 为什么现在选 C,不选 Rust - -你的条件是: - -- 想长期做 -- 但会断断续续 -- 目标是最后装到自己的真机 -- 设计思路参考 Linux - -在这个组合下,`C + x86_64 + UEFI` 的阻力最低。 - -原因: - -- 回坑成本低 -- Linux 资料、历史实现、底层文档更贴近 C -- 你要适配的核心问题是 `UEFI / GPT / framebuffer / 内存管理 / 中断`,不是语言特性 -- Rust 不是不能做,但更容易把精力花在 `no_std`、启动框架和抽象边界上 - -结论: - -- 第一版内核主体:`C` -- 少量汇编:只保留最必要的入口和极少数底层切换 -- 以后如果需要,再局部引入 Rust - -## 为什么用 WSL2 - -主开发环境建议: - -- `WSL2 + Ubuntu` - -原因: - -- `gcc/clang` -- `make` -- `nasm` -- `lld` -- `objdump/readelf` -- `qemu` -- `mtools` -- `ovmf` - -这套工具在 Linux 环境里更顺,资料也基本默认 Linux。 - -Windows 仍然保留这些职责: - -- 日常文件管理 -- 处理下载 -- 需要时管理 U 盘 -- 重启进入 BIOS/启动菜单 -- 真机测试前的辅助操作 - -长期工作流: - -1. 在 `WSL2` 中写代码、编译、跑 `QEMU` -2. 需要更底层的镜像/介质实验时,可以切去 `Mint` -3. 真机验证优先走 `U 盘 UEFI` 启动 -4. 系统稳定后,再决定是否集成进本机磁盘启动项 - -## 目标路线 - -第一阶段只做最小系统: - -1. `UEFI` 启动成功 -2. 获取内存映射 -3. 初始化 `framebuffer` -4. 屏幕输出 -5. 建立基础页表 -6. 基础中断框架 -7. 一个极简内核循环 - -这一阶段完成后,再考虑: - -1. 物理内存分配器 -2. 简单堆分配 -3. 键盘输入 -4. 简单 shell -5. ELF 加载 -6. 用户态 -7. 文件系统 - -## WSL2 中建议的基础环境 - -以 Ubuntu 为例: - -```bash -sudo apt update -sudo apt install -y \ - build-essential \ - clang \ - lld \ - nasm \ - make \ - cmake \ - qemu-system-x86 \ - ovmf \ - mtools \ - dosfstools \ - gdisk \ - xorriso \ - gdb \ - python3 -``` - -可选检查: - -```bash -gcc --version -clang --version -ld.lld --version -nasm -v -qemu-system-x86_64 --version -``` - -## 新仓库的起步步骤 - -切到 `WSL` 后,建议按这个顺序开始: - -1. 在 `WSL` 中打开这个仓库 -2. 保持仓库目标单纯,只做 `C + UEFI + x86_64` -3. 先搭最小目录结构 -4. 先让一个最小 `UEFI` 程序在 `QEMU + OVMF` 下跑起来 -5. 再把它拆成 `bootloader / kernel` 或直接决定最小加载方案 -6. 先证明启动链可控,再扩内核 - -## 建议的最小目录结构 - -第一版建议从非常小的结构开始: +## 当前目录 ```text tianole/ - README.md - .gitignore + AGENTS.md Makefile - boot/ - kernel/ + arch/ + docs/ include/ + kernel/ scripts/ - build/ ``` -先不要一开始就拆出: +当前还没有直接复制 Linux 的完整目录树,但已经开始按接近 Linux 的方式分层: -- `fs/` -- `drivers/` -- `mm/` -- `userland/` -- `lib/` +- `arch/`:架构相关代码 +- `kernel/`:通用内核主体逐步放这里 +- `include/tianole/`:项目自有共享接口 +- `docs/`:正式设计和路线图 -等真正需要时再拆,不要先造目录架子。 +## 开发顺序 -## 真机测试原则 +当前建议的实现顺序是: -你这台机器是 `Windows 11 + Linux Mint` 双系统,并且已有 `GRUB` 启动环境,所以真机测试要克制: +1. 启动链 +2. 早期调试输出 +3. 内存与异常基础 +4. 执行流与调度 +5. 用户态入口 +6. 文件系统与存储 +7. shell / 工具 +8. 面向 `git` 的补齐 +9. 真机落地 -1. 第一阶段只在 `QEMU + OVMF` 验证 -2. 第二阶段只从 `U 盘` 启动 -3. 第三阶段再考虑新增 UEFI 启动项 -4. 不要一开始改当前磁盘上的 `GRUB` 配置 -5. 不要一开始尝试覆盖现有 EFI 分区中的关键文件 +更细的阶段说明见: -## 当前最重要的技术边界 +- [docs/roadmap.md](//wsl.localhost/Ubuntu/home/indole/tianole/docs/roadmap.md) -- 做现代 PC,不做老式 BIOS 教程项目 -- 先做可启动、可显示、可调试 -- 先不要做“看起来很完整”的模块铺设 -- 先把启动链做对,再谈进程、文件系统、用户态 -- 任何新代码都要服务于真机 `UEFI x86_64` 目标 +## 构建与运行 -## 下一步 +在 WSL2 / Ubuntu 中: -切到 `WSL` 后,下一步不是继续讨论语言,而是直接开始搭最小骨架: +```bash +make +make run +``` -1. 建立 `Makefile` -2. 建立最小 `boot/` 与 `kernel/` -3. 跑通 `QEMU + OVMF` -4. 在屏幕上输出一行可见文本 +无界面调试: -做到这一步后,再继续扩展。 +```bash +make run-headless +cat build/debug.log +``` + +## 文档 + +- 路线图:[docs/roadmap.md](//wsl.localhost/Ubuntu/home/indole/tianole/docs/roadmap.md) +- 本机环境与真机启动约束:[docs/host-machine.md](//wsl.localhost/Ubuntu/home/indole/tianole/docs/host-machine.md) +- agent 入口:[AGENTS.md](//wsl.localhost/Ubuntu/home/indole/tianole/AGENTS.md) diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c index bbe5ab1..82f229b 100644 --- a/arch/x86/boot/main.c +++ b/arch/x86/boot/main.c @@ -49,6 +49,27 @@ static void mem_zero(void *dst, uint64_t size) { } } +void *memset(void *dst, int value, __SIZE_TYPE__ size) { + uint8_t *out = (uint8_t *)dst; + __SIZE_TYPE__ i; + + for (i = 0; i < size; ++i) { + out[i] = (uint8_t)value; + } + + return dst; +} + +static void debug_put_hex64(uint64_t value) { + static const char digits[] = "0123456789abcdef"; + int shift; + + debug_puts("0x"); + for (shift = 60; shift >= 0; shift -= 4) { + debug_putc(digits[(value >> shift) & 0xf]); + } +} + static efi_status open_root( efi_handle image_handle, efi_system_table_t *system_table, @@ -222,6 +243,63 @@ static efi_status load_kernel_image( return EFI_SUCCESS; } +static efi_status fetch_memory_map( + efi_system_table_t *system_table, + tianole_boot_info_t *boot_info +) { + tianole_efi_memory_descriptor_t *memory_map; + efi_uintn_t memory_map_size; + efi_uintn_t map_key; + efi_uintn_t descriptor_size; + uint32_t descriptor_version; + efi_status status; + + memory_map_size = 0; + map_key = 0; + descriptor_size = 0; + descriptor_version = 0; + status = system_table->boot_services->get_memory_map( + &memory_map_size, + 0, + &map_key, + &descriptor_size, + &descriptor_version + ); + if (status != EFI_BUFFER_TOO_SMALL) { + return status; + } + + memory_map_size += descriptor_size * 8; + status = system_table->boot_services->allocate_pool( + EFI_LOADER_DATA, + memory_map_size, + (void **)&memory_map + ); + if (status != EFI_SUCCESS) { + return status; + } + + status = system_table->boot_services->get_memory_map( + &memory_map_size, + memory_map, + &map_key, + &descriptor_size, + &descriptor_version + ); + if (status != EFI_SUCCESS) { + system_table->boot_services->free_pool(memory_map); + return status; + } + + boot_info->memory_map = (uint64_t)(uintptr_t)memory_map; + boot_info->memory_map_size = memory_map_size; + boot_info->memory_map_key = map_key; + boot_info->memory_descriptor_size = descriptor_size; + boot_info->memory_descriptor_version = descriptor_version; + + return EFI_SUCCESS; +} + efi_status EFIAPI efi_main(efi_handle image_handle, efi_system_table_t *system_table) { efi_file_protocol_t *root; void *kernel_image; @@ -255,6 +333,19 @@ efi_status EFIAPI efi_main(efi_handle image_handle, efi_system_table_t *system_t return status; } + status = fetch_memory_map(system_table, &boot_info); + if (status != EFI_SUCCESS) { + debug_puts("failed: fetch memory map\n"); + return status; + } + + debug_puts("memory_map descriptors_size="); + debug_put_hex64(boot_info.memory_descriptor_size); + debug_puts("\n"); + debug_puts("memory_map size="); + debug_put_hex64(boot_info.memory_map_size); + debug_puts("\n"); + debug_puts("jumping to kernel entry\n"); kernel_entry(&boot_info); diff --git a/arch/x86/include/efi.h b/arch/x86/include/efi.h index 5bf97ca..39ba455 100644 --- a/arch/x86/include/efi.h +++ b/arch/x86/include/efi.h @@ -141,13 +141,19 @@ struct efi_boot_services { efi_physical_address_t *memory ); void *free_pages; - void *get_memory_map; + efi_status(EFIAPI *get_memory_map)( + efi_uintn_t *memory_map_size, + void *memory_map, + efi_uintn_t *map_key, + efi_uintn_t *descriptor_size, + uint32_t *descriptor_version + ); efi_status(EFIAPI *allocate_pool)( int pool_type, efi_uintn_t size, void **buffer ); - void *free_pool; + efi_status(EFIAPI *free_pool)(void *buffer); void *create_event; void *set_timer; void *wait_for_event; diff --git a/docs/host-machine.md b/docs/host-machine.md new file mode 100644 index 0000000..fffddcd --- /dev/null +++ b/docs/host-machine.md @@ -0,0 +1,75 @@ +# 本机环境与真机启动约束 + +这个文档记录 Tianole 未来在本机落地时必须考虑的环境信息。它不属于 README 首页内容,但对后续真机启动、U 盘验证、启动项接入很重要。 + +## 机器信息 + +- 日期环境:`2026-05-08` +- 机器:`LENOVO 21HX` +- CPU:`13th Gen Intel Core i5-13500H` +- 核心 / 线程:`12` 核 `16` 线程 +- 内存:`16 GB` +- 显卡:`Intel Iris Xe Graphics` +- 磁盘:`1 TB NVMe SSD` + +## 固件与启动环境 + +- 固件模式:`UEFI` +- 分区表:`GPT` +- BIOS 版本:`LBCN26WW` +- BIOS 日期:`2024-08-23` +- 当前系统状态:本机有 `Windows 11` 与 `Linux Mint` +- 启动情况:当前多启动由 `Mint` 的 `GRUB` 管理 +- 额外观察:系统报告 `HypervisorPresent = True` +- 未确认项:`Secure Boot` 状态仍需单独确认 + +## 这些信息意味着什么 + +- 不走 `BIOS + MBR + 16-bit boot sector` 路线 +- 不把 `32-bit` 作为主线 +- 第一阶段不碰真实 GPU 驱动,先依赖 `UEFI GOP framebuffer` +- 第一阶段不碰真实 `NVMe` 驱动 +- 真机阶段不应一开始改写现有 `GRUB` +- 真机阶段不应一开始覆盖现有 EFI 分区中的关键文件 + +## 真机验证原则 + +1. 第一阶段只在 `QEMU + OVMF` 下验证 +2. 第二阶段优先用 `U 盘 UEFI` 启动验证 +3. 第三阶段再考虑新增本机 UEFI 启动项 +4. 在系统稳定前,不改写现有系统磁盘启动链 + +## 开发环境 + +主开发环境建议: + +- `WSL2 + Ubuntu` + +推荐工具: + +```bash +sudo apt update +sudo apt install -y \ + build-essential \ + clang \ + lld \ + nasm \ + make \ + cmake \ + qemu-system-x86 \ + ovmf \ + mtools \ + dosfstools \ + gdisk \ + xorriso \ + gdb \ + python3 +``` + +Windows 侧主要承担: + +- 日常文件管理 +- 下载与资料整理 +- U 盘管理 +- BIOS / 启动菜单辅助操作 +- 真机测试前准备 diff --git a/docs/roadmap.md b/docs/roadmap.md index ba4179c..fb7bd6b 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,77 +1,57 @@ # Tianole 路线图 -## 第 0 阶段 +## 总原则 -- 建立最小 `UEFI` 启动程序。 -- 在 `QEMU + OVMF` 下运行。 -- 在屏幕和 `debug.log` 中输出可见的启动标记。 -- 保证启动后常驻,便于后续调试。 +这个项目按“可中断、可回坑、每一阶段都能单独验收”的方式推进。 -## 第 1 阶段 +目标不是只在虚拟机里亮屏,而是: -- 把当前单体启动程序拆成 `boot/` 与 `kernel/`。 -- 定义 `boot_info` 交接结构。 -- 由 `bootloader` 加载独立 `kernel` 映像。 -- 跳转到 `kernel` 入口并建立稳定栈。 +- 在 `UEFI x86_64` 真机上独立启动 +- 逐步具备完整内核基础设施 +- 逐步具备运行本地 `git` 的能力 -## 第 2 阶段 +这里参考 Linux 的是分层思路和演进顺序,不是照搬早期 Linux 的启动方式或目录树。 -- 获取 `UEFI memory map`。 -- 正确执行 `ExitBootServices`。 -- 建立最小 framebuffer 控制台。 -- 开始做物理内存管理。 +## 推荐开发顺序 -## 第 3 阶段 - -- 建立 `IDT` 和基础异常处理。 -- 增加定时器来源。 -- 开始早期 `ACPI` 解析。 -- 逐步过渡到接近 Linux 风格的 `arch/`、`mm/`、`kernel/` 边界。 - -## 总体流程 - -这个项目要按“可中断、可回坑、每一阶段都能单独验收”的方式推进。最终目标不是只在虚拟机里亮屏,而是要在这台 `UEFI x86_64` 笔记本上独立启动,并逐步具备运行本地 `git` 的能力。 - -建议的长期阶段如下: - -### 阶段 A:启动链 +### 1. 启动链 - 跑通 `UEFI app -> bootloader -> kernel` - 保证 `kernel_main()` 真正开始执行 -- 保证屏幕或串口可见输出 +- 保证最小可见输出 完成标志: - `bootloader` 成功把控制权交给独立 `kernel` - `kernel` 能输出第一行字并停住 -### 阶段 B:早期内核基础 +### 2. 早期调试输出 -- 定义 `boot_info` -- 获取 `memory map` -- 正确执行 `ExitBootServices` -- 建立 early console -- 建立最小 panic / assert / log +- 保留当前 `debug` 输出路径 +- 增加 early serial log +- 为后续脱离固件后的调试做准备 完成标志: -- 退出 UEFI 后内核仍能稳定运行 -- 崩溃时能给出可定位信息 +- 内核在更早阶段也能稳定输出日志 -### 阶段 C:内存与异常 +### 3. 内存与异常基础 -- 建立物理页分配器 -- 建立内核堆分配器 +- 获取 `UEFI memory map` +- 正确执行 `ExitBootServices` - 建立 `GDT/IDT` -- 处理基础异常 +- 增加基础异常处理 +- 建立物理页分配器 +- 建立内核堆 - 增加定时器 完成标志: -- 能稳定分配页和堆内存 +- 退出 UEFI 后内核仍稳定运行 - 关键异常能进入处理路径 +- 内核能稳定分配页和堆内存 -### 阶段 D:任务模型 +### 4. 执行流与调度 - 建立内核线程 - 建立调度器 @@ -83,11 +63,11 @@ - 可以同时运行多个内核线程 - 调度由时钟驱动 -### 阶段 E:用户态基础 +### 5. 用户态入口 - 建立用户地址空间 - 增加系统调用入口 -- 增加 ELF 加载 +- 增加 ELF 用户程序加载 - 增加进程创建和等待 完成标志: @@ -95,7 +75,7 @@ - 能加载并运行最小用户程序 - 用户程序能调用系统调用输出 -### 阶段 F:存储与文件系统 +### 6. 文件系统与存储 - 建立块设备层 - 建立 `VFS` @@ -107,7 +87,7 @@ - 能挂载文件系统 - 能打开、读取、写入文件 -### 阶段 G:最小用户空间 +### 7. shell 与基础工具 - 增加 `init` - 增加简单 shell @@ -119,9 +99,10 @@ - 启动后能进入 shell - 能执行几个基础程序 -### 阶段 H:面向 git 的补齐 +### 8. 面向 git 的补齐 -- 优先支持本地 `git`,不先碰网络 +- 优先支持本地 `git` +- 不先碰网络协议栈 - 补足 `git` 依赖的文件、进程、时间、路径等接口 - 先以 `git init / status / add / commit` 为目标 @@ -129,7 +110,7 @@ - 能运行本地仓库的基础 `git` 操作 -### 阶段 I:真机落地 +### 9. 真机落地 - 先 `QEMU + OVMF` - 再 `U 盘 UEFI` 启动 @@ -137,31 +118,25 @@ 完成标志: -- 不破坏现有 `Windows 11 + Linux Mint + GRUB` +- 不破坏现有本机启动链 - 能在真机上独立启动并进入系统 -## 当前所处阶段 +## 当前进度 -当前只完成了第 0 阶段的最小成果: +当前已经完成: -- `UEFI` 启动程序可构建 -- `QEMU + OVMF` 能执行它 -- 屏幕和 `debug.log` 有可见输出 -- 程序可常驻,便于调试 - -当前已经开始进入第 1 阶段: - -- 代码结构已经为 `bootloader -> kernel` 交接预留边界 -- `boot_info` 已经作为项目自有交接结构存在 -- `arch/x86/` 已经承载当前架构专用启动代码 +- 最小 `UEFI` 启动链 +- `bootloader + kernel` 拆分 +- 独立 `kernel.elf` 加载 +- `kernel_main()` 实际执行 +- `memory map` 已通过 `boot_info` 传递,并能在 kernel 中统计描述符与可用页数 当前还没有完成: -- 独立 `kernel` 接管 -- `bootloader -> kernel` 交接 -- `memory map` - `ExitBootServices` -- 真正的内核子系统 +- early serial log +- framebuffer console +- 真正的内存管理和异常子系统 ## 当前代码组织原则 @@ -177,25 +152,23 @@ - `UEFI` 相关定义留在 `arch/x86/` - 通用交接结构放在 `include/tianole/` -- 以后新增架构时,优先新增新的 `arch//`,而不是改写通用代码 +- 以后新增架构时,优先新增新的 `arch//` -## 接下来最近三个里程碑 +## 最近里程碑 -### 里程碑 1:独立 kernel 接管 +### 里程碑 1:退出 UEFI 前的最后准备 -- 让 `bootloader` 加载独立 `kernel` -- 建立 `boot_info` -- 跳到 `kernel_main()` -- 由 `kernel` 自己输出第一行字 +- 获取并保存完整 `memory map` +- 扩展 `boot_info` +- 建立 early serial log ### 里程碑 2:退出 UEFI -- 获取并保存 `memory map` - 正确执行 `ExitBootServices` - `kernel` 在退出固件服务后继续稳定运行 -### 里程碑 3:早期调试和内存基础 +### 里程碑 3:早期内核基础设施 -- 增加 early serial / framebuffer console +- 增加 framebuffer console - 建立物理页分配器 - 建立基础异常处理 diff --git a/include/tianole/boot_info.h b/include/tianole/boot_info.h index aa5e892..32aaa23 100644 --- a/include/tianole/boot_info.h +++ b/include/tianole/boot_info.h @@ -3,6 +3,17 @@ #include +#define TIANOLE_EFI_MEMORY_TYPE_CONVENTIONAL 7u + +typedef struct { + uint32_t type; + uint32_t pad; + uint64_t physical_start; + uint64_t virtual_start; + uint64_t number_of_pages; + uint64_t attribute; +} tianole_efi_memory_descriptor_t; + /* * Boot-time handoff data owned by Tianole rather than by a specific * firmware or architecture API. Fields can grow over time while the @@ -11,6 +22,12 @@ typedef struct { uint32_t version; uint32_t boot_flags; + uint64_t memory_map; + uint64_t memory_map_size; + uint64_t memory_map_key; + uint64_t memory_descriptor_size; + uint32_t memory_descriptor_version; + uint32_t reserved0; } tianole_boot_info_t; #define TIANOLE_BOOT_INFO_VERSION 1u diff --git a/kernel/main.c b/kernel/main.c index 32a6c4e..b29468a 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -15,6 +15,54 @@ static void debug_puts(const char *text) { } } +static void debug_put_u64_decimal(uint64_t value) { + char digits[20]; + uint32_t index = 0; + + if (value == 0) { + debug_putc('0'); + return; + } + + while (value != 0) { + digits[index++] = (char)('0' + (value % 10)); + value /= 10; + } + + while (index != 0) { + debug_putc(digits[--index]); + } +} + +static void log_memory_map_summary(const tianole_boot_info_t *boot_info) { + uint64_t offset; + uint64_t descriptors = 0; + uint64_t conventional_pages = 0; + + if (boot_info == 0 || boot_info->memory_map == 0 || boot_info->memory_descriptor_size == 0) { + debug_puts("memory map metadata missing\n"); + return; + } + + for (offset = 0; offset + sizeof(tianole_efi_memory_descriptor_t) <= boot_info->memory_map_size; + offset += boot_info->memory_descriptor_size) { + const tianole_efi_memory_descriptor_t *descriptor = + (const tianole_efi_memory_descriptor_t *)(uintptr_t)(boot_info->memory_map + offset); + + descriptors++; + if (descriptor->type == TIANOLE_EFI_MEMORY_TYPE_CONVENTIONAL) { + conventional_pages += descriptor->number_of_pages; + } + } + + debug_puts("memory map descriptors="); + debug_put_u64_decimal(descriptors); + debug_puts("\n"); + debug_puts("conventional memory pages="); + debug_put_u64_decimal(conventional_pages); + debug_puts("\n"); +} + void kernel_main(const tianole_boot_info_t *boot_info) { debug_puts("kernel_main entered\n"); if (boot_info != 0 && boot_info->version == TIANOLE_BOOT_INFO_VERSION) { @@ -27,6 +75,8 @@ void kernel_main(const tianole_boot_info_t *boot_info) { debug_puts("boot services still active\n"); } + log_memory_map_summary(boot_info); + for (;;) { __asm__ volatile("hlt"); }