moving efi code to boot
This commit is contained in:
+1
-1
@@ -91,7 +91,7 @@ behind the [arch](arch.md) boundary, and when idle, or on a panic, it **halts**
|
||||
|
||||
| Area | Code |
|
||||
|------|------|
|
||||
| Bootloader (UEFI app) | `src/efi.zig` → `BOOTX64.efi` |
|
||||
| Boot methods (one per way of booting the kernel) | `src/boot/` — `efi.zig` (UEFI) → `BOOTX64.efi` |
|
||||
| Kernel entry, panic, bring-up | `src/main.zig` |
|
||||
| Shared loader↔kernel contract (`BootInfo`, `Framebuffer`, `MemoryMap`, ABI) | `src/root.zig` |
|
||||
| Physical frame allocator | `src/pmm.zig` |
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ There are really two independent questions, and it's worth not conflating them:
|
||||
- **CPU architecture** (x86_64 vs AArch64): instructions, MMU, interrupts →
|
||||
`src/arch/<cpu>/`.
|
||||
- **Boot protocol** (UEFI vs Raspberry Pi firmware + device tree): handled
|
||||
*separately*, because loaders are their own binaries. `src/efi.zig` builds
|
||||
*separately*, because loaders are their own binaries. `src/boot/efi.zig` builds
|
||||
`BOOTX64.efi`, a distinct executable from the kernel ELF. On a Pi there is no
|
||||
separate loader at all — the firmware jumps straight into the kernel with a
|
||||
device-tree pointer, so that entry work would live in the AArch64 arch code.
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ the DTB/ACPI tells you what devices exist.
|
||||
[`MemoryMap`](memory-map.md) — the same neutral handoff `efi.zig` produces, just
|
||||
from a different source. This is where keeping boot-protocol knowledge on the
|
||||
loader side (as we did for the UEFI memory-map classification) pays off.
|
||||
- **The UEFI loader mostly carries over.** `src/efi.zig` is largely
|
||||
- **The UEFI loader mostly carries over.** `src/boot/efi.zig` is largely
|
||||
boot-*protocol* code (`std.os.uefi` protocol calls), not x86 code. Its only truly
|
||||
x86-specific bits are the ELF machine check (`.X86_64`) and the SysV calling
|
||||
convention for the kernel jump. So an `aarch64`-UEFI target (QEMU `virt` + AAVMF)
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@ that hands us a working CPU, a memory map, and a screen, and then gets out of th
|
||||
way.
|
||||
|
||||
The key thing to understand: **UEFI is not our OS, it's a stepping stone.** It
|
||||
exists to load *us*. Our `src/efi.zig` is a UEFI *application* — a normal program
|
||||
exists to load *us*. Our `src/boot/efi.zig` is a UEFI *application* — a normal program
|
||||
that the firmware runs — and its entire purpose is to gather what the kernel needs
|
||||
and then jump into the kernel.
|
||||
|
||||
@@ -23,7 +23,7 @@ Partition (ESP)** and running a file at a well-known fallback path:
|
||||
esp/EFI/BOOT/BOOTX64.efi <- the "removable media" default for x86-64
|
||||
```
|
||||
|
||||
That's exactly the layout `build.zig` assembles. It builds `src/efi.zig` for the
|
||||
That's exactly the layout `build.zig` assembles. It builds `src/boot/efi.zig` for the
|
||||
`uefi` target, installs it to `esp/EFI/BOOT/BOOTX64.efi`, and drops the kernel ELF
|
||||
at `esp/danos`. The `run-x86-64` step then points QEMU at OVMF (UEFI firmware for
|
||||
virtual machines) and presents that `esp/` directory to the guest as a FAT drive.
|
||||
@@ -174,6 +174,6 @@ power on
|
||||
```
|
||||
|
||||
Bottom line: **UEFI's job is to give us a CPU, memory, and a framebuffer, then
|
||||
disappear.** `src/efi.zig` is the thin bridge that collects those gifts into a
|
||||
disappear.** `src/boot/efi.zig` is the thin bridge that collects those gifts into a
|
||||
`BootInfo`, tears down the firmware, and jumps into the kernel — after which we're
|
||||
on our own.
|
||||
|
||||
+1
-1
@@ -106,7 +106,7 @@ There are three halt sites, and they're all the same idea:
|
||||
`arch.halt()`. A panic is unrecoverable here, so stopping the machine — rather
|
||||
than limping on with corrupted state — is the safe response.
|
||||
|
||||
3. **Bootloader failure** — in `src/efi.zig`, if `boot()` fails *before* handing
|
||||
3. **Bootloader failure** — in `src/boot/efi.zig`, if `boot()` fails *before* handing
|
||||
off to the kernel, `main` logs the error and parks the machine with the same
|
||||
loop so the message stays on screen:
|
||||
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ pub const BootInfo = extern struct {
|
||||
|
||||
## The loader side (UEFI)
|
||||
|
||||
Two functions in `src/efi.zig`, called from `exitBootServices`:
|
||||
Two functions in `src/boot/efi.zig`, called from `exitBootServices`:
|
||||
|
||||
- **`classify`** maps each UEFI descriptor to a `MemoryKind`:
|
||||
`conventional_memory` **and** `boot_services_code`/`boot_services_data → usable`;
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ argument arrives in **RCX**, not RDI.
|
||||
|
||||
danos's two binaries default to different conventions:
|
||||
|
||||
- `src/efi.zig` is built for the UEFI target, so its default C convention is
|
||||
- `src/boot/efi.zig` is built for the UEFI target, so its default C convention is
|
||||
Microsoft x64 (first argument → RCX).
|
||||
- The kernel is freestanding, so its convention is SysV (first argument → RDI).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user