Make zig-out a FHS image, and the boot volume
`zig build` now installs into a FHS-shaped zig-out that *is* the danos filesystem and the boot volume — no more zig-out/bin or a separate esp/: zig-out/EFI/BOOT/BOOTX64.efi (firmware entry; UEFI fixes this path) zig-out/boot/initial-ramdisk.img zig-out/system/kernel (the kernel binary) zig-out/system/services/init vfs zig-out/system/drivers/hpet bus Binaries land at their addressed, leaf-collapsed paths per the sub-project resolution rule (system/services/init/init.zig -> system/services/init); vfs, hpet, and bus are installed to their FHS homes too, so the image is complete even though at boot they arrive inside the initial-ramdisk. The bootloader (boot/efi.zig) now loads each artifact from its FHS path (system\kernel, system\services\init, boot\initial-ramdisk.img); run-x86-64 mounts zig-out directly; the QEMU test harness assembles its ESP from the FHS zig-out. Also renames system/kernel/main.zig -> kernel.zig so the kernel follows the name/name.zig convention (kernel/ = ring-0 code, services/ = ring-3 OS services). Documents the resolution rule in the repository-layout section (README + coding standard). Suite 35/35 plus host tests green.
This commit is contained in:
@@ -30,8 +30,10 @@ channels. See [`docs/`](docs/README.md) for how each piece works.
|
|||||||
zig build
|
zig build
|
||||||
```
|
```
|
||||||
|
|
||||||
Produces the UEFI bootloader (`zig-out/bin/BOOTX64.efi`) and the kernel ELF
|
Produces a FHS-shaped `zig-out/` that *is* the danos filesystem and the boot volume:
|
||||||
(`zig-out/bin/kernel`).
|
the UEFI bootloader at `zig-out/EFI/BOOT/BOOTX64.efi`, the kernel at
|
||||||
|
`zig-out/system/kernel`, init at `zig-out/system/services/init`, drivers under
|
||||||
|
`zig-out/system/drivers/`, and the initial-ramdisk at `zig-out/boot/`.
|
||||||
|
|
||||||
## Run
|
## Run
|
||||||
|
|
||||||
|
|||||||
+10
-8
@@ -7,16 +7,18 @@ const GraphicsOutput = uefi.protocol.GraphicsOutput;
|
|||||||
const EdidActive = uefi.protocol.edid.Active;
|
const EdidActive = uefi.protocol.edid.Active;
|
||||||
const MemoryMapSlice = uefi.tables.MemoryMapSlice;
|
const MemoryMapSlice = uefi.tables.MemoryMapSlice;
|
||||||
|
|
||||||
/// Name of the kernel ELF on the boot volume (installed to the ESP root by
|
// The boot volume is the FHS-shaped zig-out (see build.zig / docs/README.md), so the
|
||||||
/// build.zig). UEFI wants a UTF-16, null-terminated path.
|
// loader reads each artifact from its addressed FHS path. UEFI paths use backslashes;
|
||||||
const kernel_file_name = std.unicode.utf8ToUtf16LeStringLiteral("kernel");
|
// the FAT driver walks the components itself, so no per-directory dance is needed.
|
||||||
|
|
||||||
/// Path of the init program on the boot volume (UEFI paths use backslashes;
|
/// The kernel image: /system/kernel.
|
||||||
/// the FAT driver walks the components itself, so no directory dance needed).
|
const kernel_file_name = std.unicode.utf8ToUtf16LeStringLiteral("system\\kernel");
|
||||||
const init_file_name = std.unicode.utf8ToUtf16LeStringLiteral("sbin\\init");
|
|
||||||
|
|
||||||
/// Path of the initial_ramdisk image on the boot volume (the VFS server + drivers).
|
/// The init program: /system/services/init.
|
||||||
const initial_ramdisk_file_name = std.unicode.utf8ToUtf16LeStringLiteral("initial-ramdisk.img");
|
const init_file_name = std.unicode.utf8ToUtf16LeStringLiteral("system\\services\\init");
|
||||||
|
|
||||||
|
/// The initial-ramdisk (the VFS server + drivers), in /boot.
|
||||||
|
const initial_ramdisk_file_name = std.unicode.utf8ToUtf16LeStringLiteral("boot\\initial-ramdisk.img");
|
||||||
|
|
||||||
/// Physical page size, and the sentinel UEFI uses to seek to end-of-file.
|
/// Physical page size, and the sentinel UEFI uses to seek to end-of-file.
|
||||||
const page_size = 4096;
|
const page_size = 4096;
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
.name = "kernel",
|
.name = "kernel",
|
||||||
.root_module = b.createModule(.{
|
.root_module = b.createModule(.{
|
||||||
.root_source_file = b.path("system/kernel/main.zig"),
|
.root_source_file = b.path("system/kernel/kernel.zig"),
|
||||||
.target = kernel_target,
|
.target = kernel_target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.code_model = .kernel, // kernel runs in the top 2 GiB (higher half)
|
.code_model = .kernel, // kernel runs in the top 2 GiB (higher half)
|
||||||
@@ -233,14 +233,21 @@ pub fn build(b: *std.Build) void {
|
|||||||
// (.text at 1 MiB), which the loader allocates and copies into.
|
// (.text at 1 MiB), which the loader allocates and copies into.
|
||||||
exe.image_base = 0xFFFFFFFF80100000;
|
exe.image_base = 0xFFFFFFFF80100000;
|
||||||
|
|
||||||
b.installArtifact(exe);
|
// Everything installs into a FHS-shaped zig-out: it IS the danos filesystem *and*
|
||||||
|
// the boot volume. Each binary lands at its addressed, leaf-collapsed path — the
|
||||||
|
// kernel at zig-out/system/kernel (from system/kernel/kernel.zig), init at
|
||||||
|
// zig-out/system/services/init, and so on (see docs/README.md). The bootloader
|
||||||
|
// then loads these FHS paths off the volume.
|
||||||
|
const kernel_install = b.addInstallArtifact(exe, .{ .dest_dir = .{ .override = .{ .custom = "system" } } });
|
||||||
|
b.getInstallStep().dependOn(&kernel_install.step);
|
||||||
|
|
||||||
// --- /sbin/init: the first user-space program ---
|
// --- init: the first user-space program (a system service) ---
|
||||||
// Built by the shared user-binary recipe (see addUserBinary): freestanding,
|
// Built by the shared user-binary recipe (see addUserBinary): freestanding,
|
||||||
// linked into the kernel's user region against the `runtime` runtime library, and
|
// linked into the kernel's user region against the `runtime` runtime library, and
|
||||||
// started in ring 3 by the kernel's user-ELF loader.
|
// started in ring 3 by the kernel's user-ELF loader.
|
||||||
const init_exe = addUserBinary(b, kernel_target, runtime_module, posix_module, "init", "system/services/init/init.zig");
|
const init_exe = addUserBinary(b, kernel_target, runtime_module, posix_module, "init", "system/services/init/init.zig");
|
||||||
b.installArtifact(init_exe);
|
const init_install = b.addInstallArtifact(init_exe, .{ .dest_dir = .{ .override = .{ .custom = "system/services" } } });
|
||||||
|
b.getInstallStep().dependOn(&init_install.step);
|
||||||
|
|
||||||
// --- initial_ramdisk: a bundle of extra user binaries (VFS server + drivers) ---
|
// --- initial_ramdisk: a bundle of extra user binaries (VFS server + drivers) ---
|
||||||
// Each is built by the same user-binary recipe, then packed into one image by
|
// Each is built by the same user-binary recipe, then packed into one image by
|
||||||
@@ -266,9 +273,19 @@ pub fn build(b: *std.Build) void {
|
|||||||
mk_run.addArg("bus");
|
mk_run.addArg("bus");
|
||||||
mk_run.addFileArg(bus_exe.getEmittedBin());
|
mk_run.addFileArg(bus_exe.getEmittedBin());
|
||||||
|
|
||||||
// Install the image to zig-out/bin (so the QEMU test harness picks it up like
|
// Also install the packed binaries to their FHS homes, so zig-out is a true image
|
||||||
// the other binaries). The run-x86-64 ESP install is added below.
|
// of the filesystem — even though at boot they arrive inside the initial-ramdisk.
|
||||||
const initial_ramdisk_install = b.addInstallFile(initial_ramdisk_img, "bin/initial-ramdisk.img");
|
for ([_]struct { *std.Build.Step.Compile, []const u8 }{
|
||||||
|
.{ vfs_exe, "system/services" },
|
||||||
|
.{ hpet_exe, "system/drivers" },
|
||||||
|
.{ bus_exe, "system/drivers" },
|
||||||
|
}) |entry| {
|
||||||
|
const step = b.addInstallArtifact(entry[0], .{ .dest_dir = .{ .override = .{ .custom = entry[1] } } });
|
||||||
|
b.getInstallStep().dependOn(&step.step);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The initial-ramdisk itself installs to /boot (with the loaders).
|
||||||
|
const initial_ramdisk_install = b.addInstallFile(initial_ramdisk_img, "boot/initial-ramdisk.img");
|
||||||
b.getInstallStep().dependOn(&initial_ramdisk_install.step);
|
b.getInstallStep().dependOn(&initial_ramdisk_install.step);
|
||||||
|
|
||||||
// Boot methods live in boot/, one per way of getting the kernel running.
|
// Boot methods live in boot/, one per way of getting the kernel running.
|
||||||
@@ -289,7 +306,10 @@ pub fn build(b: *std.Build) void {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
b.installArtifact(efiexe);
|
// UEFI firmware requires the removable-media loader at exactly \EFI\BOOT\BOOTX64.efi,
|
||||||
|
// so that path is fixed by the firmware (it is /boot's EFI stub, conceptually).
|
||||||
|
const efi_install = b.addInstallArtifact(efiexe, .{ .dest_dir = .{ .override = .{ .custom = "EFI/BOOT" } } });
|
||||||
|
b.getInstallStep().dependOn(&efi_install.step);
|
||||||
|
|
||||||
// --- run-x86-64: boot the x86-64 kernel in QEMU via UEFI/OVMF ---
|
// --- run-x86-64: boot the x86-64 kernel in QEMU via UEFI/OVMF ---
|
||||||
// Firmware lives in different places per OS/distro, so probe the known
|
// Firmware lives in different places per OS/distro, so probe the known
|
||||||
@@ -320,21 +340,8 @@ pub fn build(b: *std.Build) void {
|
|||||||
"/usr/local/share/qemu/edk2-i386-vars.fd", // macOS Homebrew (Intel)
|
"/usr/local/share/qemu/edk2-i386-vars.fd", // macOS Homebrew (Intel)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Assemble an EFI System Partition layout: esp/EFI/BOOT/BOOTX64.efi
|
// The FHS zig-out (installed above) *is* the boot volume — no separate ESP to
|
||||||
const efi_install = b.addInstallArtifact(efiexe, .{
|
// assemble. QEMU presents it to the guest as a FAT drive below.
|
||||||
.dest_dir = .{ .override = .{ .custom = "esp/EFI/BOOT" } },
|
|
||||||
});
|
|
||||||
// The bootloader loads the kernel by name from the volume root, so drop the
|
|
||||||
// kernel ELF at esp/kernel.
|
|
||||||
const kernel_install = b.addInstallArtifact(exe, .{
|
|
||||||
.dest_dir = .{ .override = .{ .custom = "esp" } },
|
|
||||||
});
|
|
||||||
// The bootloader loads init from sbin/init on the same volume.
|
|
||||||
const init_install = b.addInstallArtifact(init_exe, .{
|
|
||||||
.dest_dir = .{ .override = .{ .custom = "esp/sbin" } },
|
|
||||||
});
|
|
||||||
// ...and the initial_ramdisk (VFS server + drivers) from the volume root.
|
|
||||||
const initial_ramdisk_esp_install = b.addInstallFile(initial_ramdisk_img, "esp/initial-ramdisk.img");
|
|
||||||
|
|
||||||
// The firmware needs to write NVRAM, so give it a writable copy of the vars.
|
// The firmware needs to write NVRAM, so give it a writable copy of the vars.
|
||||||
const vars_copy = b.addSystemCommand(&.{ "cp", "-f", ovmf_vars });
|
const vars_copy = b.addSystemCommand(&.{ "cp", "-f", ovmf_vars });
|
||||||
@@ -351,10 +358,10 @@ pub fn build(b: *std.Build) void {
|
|||||||
});
|
});
|
||||||
run_efi.addArg("-drive");
|
run_efi.addArg("-drive");
|
||||||
run_efi.addPrefixedFileArg("if=pflash,format=raw,file=", vars_out);
|
run_efi.addPrefixedFileArg("if=pflash,format=raw,file=", vars_out);
|
||||||
// Present the ESP directory to the guest as a FAT drive.
|
// Present the FHS zig-out to the guest as a FAT drive — it is the boot volume.
|
||||||
run_efi.addArgs(&.{
|
run_efi.addArgs(&.{
|
||||||
"-drive",
|
"-drive",
|
||||||
b.fmt("format=raw,file=fat:rw:{s}/esp", .{b.install_path}),
|
b.fmt("format=raw,file=fat:rw:{s}", .{b.install_path}),
|
||||||
"-net",
|
"-net",
|
||||||
"none",
|
"none",
|
||||||
// Emulated display advertising 1280x720 as its native (EDID preferred)
|
// Emulated display advertising 1280x720 as its native (EDID preferred)
|
||||||
@@ -369,10 +376,8 @@ pub fn build(b: *std.Build) void {
|
|||||||
// timestamped file under zig-out, so each run leaves its own log behind.
|
// timestamped file under zig-out, so each run leaves its own log behind.
|
||||||
const serial_log = b.fmt("{s}/run-x86-64-serial0-{s}.log", .{ b.install_path, timestamp(b) });
|
const serial_log = b.fmt("{s}/run-x86-64-serial0-{s}.log", .{ b.install_path, timestamp(b) });
|
||||||
run_efi.addArgs(&.{ "-serial", b.fmt("file:{s}", .{serial_log}) });
|
run_efi.addArgs(&.{ "-serial", b.fmt("file:{s}", .{serial_log}) });
|
||||||
run_efi.step.dependOn(&efi_install.step);
|
// The whole FHS zig-out must be installed before we mount it.
|
||||||
run_efi.step.dependOn(&kernel_install.step);
|
run_efi.step.dependOn(b.getInstallStep());
|
||||||
run_efi.step.dependOn(&init_install.step);
|
|
||||||
run_efi.step.dependOn(&initial_ramdisk_esp_install.step);
|
|
||||||
|
|
||||||
const run_efi_step = b.step("run-x86-64", "Boot the x86-64 kernel in QEMU (UEFI/OVMF); serial0 is logged to zig-out/run-x86-64-serial0-<timestamp>.log");
|
const run_efi_step = b.step("run-x86-64", "Boot the x86-64 kernel in QEMU (UEFI/OVMF); serial0 is logged to zig-out/run-x86-64-serial0-<timestamp>.log");
|
||||||
run_efi_step.dependOn(&run_efi.step);
|
run_efi_step.dependOn(&run_efi.step);
|
||||||
|
|||||||
+20
-1
@@ -125,6 +125,25 @@ reach it *by module name*, never by a path into its files. The source tree delib
|
|||||||
what you see under `system/` in the source is what a running danos represents under
|
what you see under `system/` in the source is what a running danos represents under
|
||||||
`/system`.
|
`/system`.
|
||||||
|
|
||||||
|
**A sub-project is addressed by its directory; its entry point repeats the directory's
|
||||||
|
name.** `system/services/init/` contains `init.zig` (its root), and produces a binary
|
||||||
|
addressed as **`system/services/init`** — the repeated leaf resolves away:
|
||||||
|
|
||||||
|
| Source (root file) | Addressed as (module / binary / FHS path) |
|
||||||
|
|----------------------------------------|--------------------------------------------|
|
||||||
|
| `system/services/init/init.zig` | `system/services/init` → `/system/services/init` |
|
||||||
|
| `system/drivers/hpet/hpet.zig` | `system/drivers/hpet` → `/system/drivers/hpet` |
|
||||||
|
| `library/runtime/runtime.zig` | `library/runtime` (the `runtime` module) |
|
||||||
|
|
||||||
|
In **source**, a sub-project is a directory so it can hold many files — the entry is
|
||||||
|
`init/init.zig`, beside it `vfs/vfs-test.zig`, `vfs/protocol.zig`, and so on. When
|
||||||
|
**addressed or installed**, that collapses to the single canonical path: the `init`
|
||||||
|
binary installs to `/system/services/init` (a file at that path), not
|
||||||
|
`/system/services/init/init`. The repeated leaf exists only in source; the directory is
|
||||||
|
the identity, the entry file is its implementation. (Same idea as a Go package being its
|
||||||
|
directory, or a macOS `.app` bundle addressed by the bundle, not the executable within.)
|
||||||
|
A sub-project's extra files are reached through the module, never as separate paths.
|
||||||
|
|
||||||
```
|
```
|
||||||
system/ → /system danos's own internals (the self-representation)
|
system/ → /system danos's own internals (the self-representation)
|
||||||
danos.zig the kernel↔user ABI contract (the `danos` module)
|
danos.zig the kernel↔user ABI contract (the `danos` module)
|
||||||
@@ -157,7 +176,7 @@ appears in the private-ABI path.
|
|||||||
| Area | Code |
|
| Area | Code |
|
||||||
|------|------|
|
|------|------|
|
||||||
| Boot methods (one per way of booting the kernel) | `boot/` — `efi.zig` (UEFI) → `BOOTX64.efi` |
|
| Boot methods (one per way of booting the kernel) | `boot/` — `efi.zig` (UEFI) → `BOOTX64.efi` |
|
||||||
| Kernel entry, panic, bring-up | `system/kernel/main.zig` |
|
| Kernel entry, panic, bring-up | `system/kernel/kernel.zig` |
|
||||||
| Shared loader↔kernel contract (`BootInfo`, `Framebuffer`, `MemoryMap`, `Syscall`, ABI) | `system/danos.zig` |
|
| Shared loader↔kernel contract (`BootInfo`, `Framebuffer`, `MemoryMap`, `Syscall`, ABI) | `system/danos.zig` |
|
||||||
| Physical frame allocator | `system/kernel/pmm.zig` |
|
| Physical frame allocator | `system/kernel/pmm.zig` |
|
||||||
| Kernel heap (`std.mem.Allocator`) | `system/kernel/heap.zig` |
|
| Kernel heap (`std.mem.Allocator`) | `system/kernel/heap.zig` |
|
||||||
|
|||||||
@@ -137,6 +137,11 @@ single word or acronym needs no hyphen: `scheduler.zig`, `paging.zig`, `apic.zig
|
|||||||
`idt.zig`. (The module *alias* a file is imported under still follows the code
|
`idt.zig`. (The module *alias* a file is imported under still follows the code
|
||||||
conventions above — `snake_case` — because it's an identifier, not a filename.)
|
conventions above — `snake_case` — because it's an identifier, not a filename.)
|
||||||
|
|
||||||
|
**A sub-project's entry point repeats its directory's name** — `init/init.zig`,
|
||||||
|
`runtime/runtime.zig`, `hpet/hpet.zig` — and the sub-project is addressed by the
|
||||||
|
*directory* (`system/services/init`, `library/runtime`), with the repeated leaf
|
||||||
|
resolving away. See the repository-layout section of [README.md](README.md).
|
||||||
|
|
||||||
## Why acronyms are the line
|
## Why acronyms are the line
|
||||||
|
|
||||||
Because an acronym has no letters to restore. `MMIO` doesn't become "memory mapped
|
Because an acronym has no letters to restore. `MMIO` doesn't become "memory mapped
|
||||||
|
|||||||
+12
-9
@@ -20,14 +20,17 @@ UEFI boots by looking for a FAT-formatted partition called the **EFI System
|
|||||||
Partition (ESP)** and running a file at a well-known fallback path:
|
Partition (ESP)** and running a file at a well-known fallback path:
|
||||||
|
|
||||||
```
|
```
|
||||||
esp/EFI/BOOT/BOOTX64.efi <- the "removable media" default for x86-64
|
EFI/BOOT/BOOTX64.efi <- the "removable media" default for x86-64
|
||||||
```
|
```
|
||||||
|
|
||||||
That's exactly the layout `build.zig` assembles. It builds `boot/efi.zig` for the
|
The boot volume is the **FHS-shaped `zig-out`** itself (see the repository-layout note
|
||||||
`uefi` target, installs it to `esp/EFI/BOOT/BOOTX64.efi`, and drops the kernel ELF
|
in [README.md](README.md)): `build.zig` installs `boot/efi.zig` (built for the `uefi`
|
||||||
at `esp/kernel`. The `run-x86-64` step then points QEMU at OVMF (UEFI firmware for
|
target) to `zig-out/EFI/BOOT/BOOTX64.efi` — the one path UEFI firmware fixes — and lays
|
||||||
virtual machines) and presents that `esp/` directory to the guest as a FAT drive.
|
the rest out by FHS path: the kernel at `zig-out/system/kernel`, init at
|
||||||
The firmware finds `BOOTX64.efi` and runs it — that's our `main()`.
|
`zig-out/system/services/init`, the initial-ramdisk at `zig-out/boot/`. The
|
||||||
|
`run-x86-64` step points QEMU at OVMF (UEFI firmware for virtual machines) and presents
|
||||||
|
`zig-out` to the guest as a FAT drive. The firmware finds `BOOTX64.efi` and runs it —
|
||||||
|
that's our `main()`, which then loads the kernel and init from their FHS paths.
|
||||||
|
|
||||||
## Boot services: the firmware's API
|
## Boot services: the firmware's API
|
||||||
|
|
||||||
@@ -164,13 +167,13 @@ the loader writes are the bytes the kernel reads.
|
|||||||
```
|
```
|
||||||
power on
|
power on
|
||||||
-> UEFI firmware initialises hardware
|
-> UEFI firmware initialises hardware
|
||||||
-> finds esp/EFI/BOOT/BOOTX64.efi, runs it (our efi.zig main)
|
-> finds EFI/BOOT/BOOTX64.efi on the FHS volume, runs it (our efi.zig main)
|
||||||
-> grab boot services
|
-> grab boot services
|
||||||
-> queryFramebuffer (via GOP: EDID native res, setMode, describe fb)
|
-> queryFramebuffer (via GOP: EDID native res, setMode, describe fb)
|
||||||
-> loadKernel (read danos ELF, load PT_LOAD segments to 0x100000)
|
-> loadKernel (read system/kernel ELF, load PT_LOAD segments to 0x100000)
|
||||||
-> exitBootServices (retry until the memory-map key holds)
|
-> exitBootServices (retry until the memory-map key holds)
|
||||||
-> jump to e_entry, boot_info pointer in RDI
|
-> jump to e_entry, boot_info pointer in RDI
|
||||||
-> kernel _start (system/kernel/main.zig: framebuffer console, then halt)
|
-> kernel _start (system/kernel/kernel.zig: framebuffer console, then halt)
|
||||||
```
|
```
|
||||||
|
|
||||||
Bottom line: **UEFI's job is to give us a CPU, memory, and a framebuffer, then
|
Bottom line: **UEFI's job is to give us a CPU, memory, and a framebuffer, then
|
||||||
|
|||||||
+1
-1
@@ -83,7 +83,7 @@ treats the call:
|
|||||||
signature for a kernel entry point — the bootloader jumps in and nothing ever
|
signature for a kernel entry point — the bootloader jumps in and nothing ever
|
||||||
jumps back out.
|
jumps back out.
|
||||||
|
|
||||||
You can see the chain in `system/kernel/main.zig`: `_start` is `noreturn`, it calls
|
You can see the chain in `system/kernel/kernel.zig`: `_start` is `noreturn`, it calls
|
||||||
`kmain` which is `noreturn`, which ends by calling `arch.halt()` which is
|
`kmain` which is `noreturn`, which ends by calling `arch.halt()` which is
|
||||||
`noreturn`. The "never returns" property is threaded all the way down.
|
`noreturn`. The "never returns" property is threaded all the way down.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
//! Shared definitions that form the contract between a bootloader
|
//! Shared definitions that form the contract between a bootloader
|
||||||
//! (boot/, e.g. efi.zig built as BOOTX64.efi) and the kernel (system/kernel/main.zig).
|
//! (boot/, e.g. efi.zig built as BOOTX64.efi) and the kernel (system/kernel/kernel.zig).
|
||||||
//!
|
//!
|
||||||
//! Both binaries import this as the "danos" module, so the handoff layout is
|
//! Both binaries import this as the "danos" module, so the handoff layout is
|
||||||
//! defined in exactly one place.
|
//! defined in exactly one place.
|
||||||
|
|||||||
+16
-11
@@ -55,11 +55,14 @@ ARCHES = {
|
|||||||
"/opt/homebrew/share/qemu/edk2-i386-vars.fd", # macOS Homebrew (Apple Silicon)
|
"/opt/homebrew/share/qemu/edk2-i386-vars.fd", # macOS Homebrew (Apple Silicon)
|
||||||
"/usr/local/share/qemu/edk2-i386-vars.fd", # macOS Homebrew (Intel)
|
"/usr/local/share/qemu/edk2-i386-vars.fd", # macOS Homebrew (Intel)
|
||||||
],
|
],
|
||||||
"efi_app": ("EFI/BOOT/BOOTX64.efi", "BOOTX64.efi"), # (dest in ESP, name in zig-out/bin)
|
# zig-out is a FHS-shaped image and the boot volume; the harness copies the
|
||||||
"kernel": ("kernel", "kernel"),
|
# boot-critical files from their FHS paths into a fresh ESP with the same
|
||||||
# Further files shipped on the ESP: the init user program and the initial_ramdisk
|
# layout. (dest in ESP, source path under zig-out) — identical here.
|
||||||
# (VFS server + drivers), both copied from zig-out/bin.
|
"efi_app": ("EFI/BOOT/BOOTX64.efi", "EFI/BOOT/BOOTX64.efi"),
|
||||||
"extra": [("sbin/init", "init"), ("initial-ramdisk.img", "initial-ramdisk.img")],
|
"kernel": ("system/kernel", "system/kernel"),
|
||||||
|
# The init user program and the initial-ramdisk (VFS server + drivers).
|
||||||
|
"extra": [("system/services/init", "system/services/init"),
|
||||||
|
("boot/initial-ramdisk.img", "boot/initial-ramdisk.img")],
|
||||||
# Built as a function so we can splice in per-run paths.
|
# Built as a function so we can splice in per-run paths.
|
||||||
"qemu_args": lambda a, esp, vars_fd, serial: [
|
"qemu_args": lambda a, esp, vars_fd, serial: [
|
||||||
"-machine", "q35", "-m", "128M",
|
"-machine", "q35", "-m", "128M",
|
||||||
@@ -237,14 +240,16 @@ def make_esp(arch):
|
|||||||
esp = os.path.join(WORK, "esp")
|
esp = os.path.join(WORK, "esp")
|
||||||
if os.path.exists(esp):
|
if os.path.exists(esp):
|
||||||
shutil.rmtree(esp)
|
shutil.rmtree(esp)
|
||||||
efi_dest, efi_name = arch["efi_app"]
|
efi_dest, efi_src = arch["efi_app"]
|
||||||
kern_dest, kern_name = arch["kernel"]
|
kern_dest, kern_src = arch["kernel"]
|
||||||
|
fhs = os.path.join(REPO, "zig-out") # zig-out is the FHS image
|
||||||
os.makedirs(os.path.join(esp, os.path.dirname(efi_dest)), exist_ok=True)
|
os.makedirs(os.path.join(esp, os.path.dirname(efi_dest)), exist_ok=True)
|
||||||
shutil.copy(os.path.join(REPO, "zig-out", "bin", efi_name), os.path.join(esp, efi_dest))
|
os.makedirs(os.path.join(esp, os.path.dirname(kern_dest)), exist_ok=True)
|
||||||
shutil.copy(os.path.join(REPO, "zig-out", "bin", kern_name), os.path.join(esp, kern_dest))
|
shutil.copy(os.path.join(fhs, efi_src), os.path.join(esp, efi_dest))
|
||||||
for dest, name in arch.get("extra", []):
|
shutil.copy(os.path.join(fhs, kern_src), os.path.join(esp, kern_dest))
|
||||||
|
for dest, src in arch.get("extra", []):
|
||||||
os.makedirs(os.path.join(esp, os.path.dirname(dest)), exist_ok=True)
|
os.makedirs(os.path.join(esp, os.path.dirname(dest)), exist_ok=True)
|
||||||
shutil.copy(os.path.join(REPO, "zig-out", "bin", name), os.path.join(esp, dest))
|
shutil.copy(os.path.join(fhs, src), os.path.join(esp, dest))
|
||||||
return esp
|
return esp
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user