diff options
| author | salmonik <salmonik@tuta.io> | 2026-07-31 03:22:20 +0200 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-07-31 03:22:20 +0200 |
| commit | 0ace22d6f88692883584119c64ff010f4cee6738 (patch) | |
| tree | 6f575f9088dec8bab90943d6c23e174bca183f0a | |
| parent | restructure: rsnix kernel + shell crate + rsdos entry point (diff) | |
| download | rs-dos-0ace22d6f88692883584119c64ff010f4cee6738.tar.gz rs-dos-0ace22d6f88692883584119c64ff010f4cee6738.zip | |
fix(rsdos): organizational changes
Diffstat (limited to '')
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | .gitmodules | 3 | ||||
| -rw-r--r-- | CONTEXT.md | 2 | ||||
| -rw-r--r-- | Makefile | 56 | ||||
| m--------- | rsboot | 0 | ||||
| -rw-r--r-- | rsnix/src/interrupts.rs | 2 | ||||
| -rw-r--r-- | rsnix/src/lib.rs | 8 | ||||
| -rw-r--r-- | rsnix/src/ps2.rs | 7 | ||||
| -rwxr-xr-x | scripts/boot-image.sh | 87 | ||||
| -rwxr-xr-x | scripts/boot.sh | 100 | ||||
| -rwxr-xr-x | scripts/build-bootloader.sh | 32 | ||||
| -rwxr-xr-x | scripts/build-image.sh | 99 | ||||
| -rwxr-xr-x | scripts/debug-kernel.py (renamed from tools/debug-kernel.py) | 0 | ||||
| -rwxr-xr-x | scripts/qemu.sh (renamed from tools/qemu.sh) | 0 | ||||
| -rwxr-xr-x | tools/boot-image.sh | 62 |
15 files changed, 362 insertions, 97 deletions
| @@ -1,4 +1,5 @@ | |||
| 1 | /target | 1 | /target |
| 2 | /build | ||
| 2 | /esp/ | 3 | /esp/ |
| 3 | *.img | 4 | *.img |
| 4 | NvVars | 5 | NvVars |
diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..423167d --- /dev/null +++ b/.gitmodules | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | [submodule "rsboot"] | ||
| 2 | path = rsboot | ||
| 3 | url = https://git.2137697.xyz/RaiserSoft/rsboot.git | ||
| @@ -87,7 +87,7 @@ Single Rust crate (`x86_64-unknown-uefi` target). Module breakdown: | |||
| 87 | 87 | ||
| 88 | ## Milestone status (v0.1) | 88 | ## Milestone status (v0.1) |
| 89 | 89 | ||
| 90 | ✅ **Booting** — kernel loads via rsbl, prints banner via UEFI console | 90 | ✅ **Booting** — kernel loads via rsbl, prints banner via UEFI console (verified on real hardware) |
| 91 | ✅ **ExitBootServices** — memory map captured via static `.bss` buffer | 91 | ✅ **ExitBootServices** — memory map captured via static `.bss` buffer |
| 92 | (see `docs/adr/0001-static-buffer-for-memory-map.md`) | 92 | (see `docs/adr/0001-static-buffer-for-memory-map.md`) |
| 93 | ✅ **Serial** — UART 16550 at COM1, 115200 8N1 | 93 | ✅ **Serial** — UART 16550 at COM1, 115200 8N1 |
| @@ -11,7 +11,7 @@ export BOOTLOADER=rsboot/rsboot.efi | |||
| 11 | export OVMF=/usr/share/edk2/x64/OVMF.4m.fd | 11 | export OVMF=/usr/share/edk2/x64/OVMF.4m.fd |
| 12 | export BOOT_EFI=$(ESP_DIR)/EFI/BOOT/BOOTX64.EFI | 12 | export BOOT_EFI=$(ESP_DIR)/EFI/BOOT/BOOTX64.EFI |
| 13 | 13 | ||
| 14 | .PHONY: all run run-gui clean image debug release fmt | 14 | .PHONY: all run run-gui clean image debug release fmt bootloader boot-image |
| 15 | 15 | ||
| 16 | # ---- Build --------------------------------------------------------------- | 16 | # ---- Build --------------------------------------------------------------- |
| 17 | 17 | ||
| @@ -75,23 +75,24 @@ debug: all | |||
| 75 | -display none \ | 75 | -display none \ |
| 76 | -s -S | 76 | -s -S |
| 77 | 77 | ||
| 78 | # Boot from a raw disk image (created by tools/boot-image.sh) | 78 | # Boot from a raw disk image (delegates to boot-image.sh which builds the |
| 79 | # full chain if the image doesn't exist yet) | ||
| 79 | run-image: all | 80 | run-image: all |
| 80 | qemu-system-x86_64 \ | 81 | ./scripts/boot-image.sh rs-dos.img |
| 81 | -bios $(OVMF) \ | ||
| 82 | -drive file=$(IMG),format=raw,if=none,id=hd \ | ||
| 83 | -device ide-hd,drive=hd \ | ||
| 84 | -serial stdio \ | ||
| 85 | -m 256M \ | ||
| 86 | -machine q35 \ | ||
| 87 | -cpu qemu64 \ | ||
| 88 | -no-reboot \ | ||
| 89 | -display none | ||
| 90 | 82 | ||
| 91 | # ---- Disk image ---------------------------------------------------------- | 83 | # ---- Full boot chain ----------------------------------------------------- |
| 92 | 84 | ||
| 85 | # Build bootloader only (rsboot submodule) | ||
| 86 | bootloader: | ||
| 87 | ./scripts/build-bootloader.sh | ||
| 88 | |||
| 89 | # Build the full boot chain disk image (kernel + bootloader) | ||
| 93 | image: all | 90 | image: all |
| 94 | ./tools/boot-image.sh rs-dos.img | 91 | ./scripts/build-image.sh rs-dos.img |
| 92 | |||
| 93 | # Boot the full chain disk image (builds it first if needed) | ||
| 94 | boot-image: all | ||
| 95 | ./scripts/boot-image.sh rs-dos.img | ||
| 95 | 96 | ||
| 96 | # ---- Utilities ----------------------------------------------------------- | 97 | # ---- Utilities ----------------------------------------------------------- |
| 97 | 98 | ||
| @@ -105,16 +106,21 @@ clean: | |||
| 105 | help: | 106 | help: |
| 106 | @echo "rs-dos — Make targets" | 107 | @echo "rs-dos — Make targets" |
| 107 | @echo "" | 108 | @echo "" |
| 108 | @echo " make build kernel + ESP (default)" | 109 | @echo " make build kernel + ESP (default)" |
| 109 | @echo " make release build with --release (smaller binary)" | 110 | @echo " make release build with --release (smaller binary)" |
| 110 | @echo " make image create bootable USB image (rs-dos.img)" | 111 | @echo " make bootloader build rsboot from source" |
| 111 | @echo " make run QEMU serial console (no graphics)" | 112 | @echo " make image build full chain disk image (bootloader + kernel)" |
| 112 | @echo " make run-gui QEMU with graphical window (GOP/PS2)" | 113 | @echo " make boot-image build + boot full chain via QEMU" |
| 113 | @echo " make debug QEMU + GDB stub on :1234" | 114 | @echo " make run QEMU serial console (direct boot, no bootloader)" |
| 114 | @echo " make clean remove build artifacts" | 115 | @echo " make run-gui QEMU with graphical window (GOP/PS2)" |
| 115 | @echo " make fmt format Rust source" | 116 | @echo " make debug QEMU + GDB stub on :1234" |
| 117 | @echo " make clean remove build artifacts" | ||
| 118 | @echo " make fmt format Rust source" | ||
| 116 | @echo "" | 119 | @echo "" |
| 117 | @echo "Scripts:" | 120 | @echo "Scripts:" |
| 118 | @echo " ./tools/qemu.sh flexible QEMU launcher" | 121 | @echo " ./scripts/boot.sh quick direct boot (dev loop)" |
| 119 | @echo " ./tools/boot-image.sh create bootable disk image" | 122 | @echo " ./scripts/boot-image.sh boot full chain (builds if needed)" |
| 120 | @echo " ./tools/debug-kernel.py GDB plugin (attach after 'make debug')" | 123 | @echo " ./scripts/build-image.sh build full chain disk image" |
| 124 | @echo " ./scripts/build-bootloader.sh build rsboot from source" | ||
| 125 | @echo " ./scripts/qemu.sh flexible QEMU launcher" | ||
| 126 | @echo " ./scripts/debug-kernel.py GDB plugin (attach after 'make debug')" | ||
diff --git a/rsboot b/rsboot new file mode 160000 | |||
| Subproject 1963a0a6d7398a426d0701f90a5bc796e32899a | |||
diff --git a/rsnix/src/interrupts.rs b/rsnix/src/interrupts.rs index 8f2acd7..66dc59f 100644 --- a/rsnix/src/interrupts.rs +++ b/rsnix/src/interrupts.rs | |||
| @@ -362,7 +362,7 @@ pub fn init() { | |||
| 362 | 362 | ||
| 363 | // Build the IDTR pseudo-descriptor. | 363 | // Build the IDTR pseudo-descriptor. |
| 364 | IDTR = [ | 364 | IDTR = [ |
| 365 | ((256u16 * 16 - 1)), // limit = 256*16 - 1 | 365 | (256u16 * 16 - 1), // limit = 256*16 - 1 |
| 366 | idt_ptr as u16, // base lo | 366 | idt_ptr as u16, // base lo |
| 367 | (idt_ptr as u64 >> 16) as u16, // base mid | 367 | (idt_ptr as u64 >> 16) as u16, // base mid |
| 368 | (idt_ptr as u64 >> 32) as u16, // base hi | 368 | (idt_ptr as u64 >> 32) as u16, // base hi |
diff --git a/rsnix/src/lib.rs b/rsnix/src/lib.rs index 6c7fb3c..0bc0cb9 100644 --- a/rsnix/src/lib.rs +++ b/rsnix/src/lib.rs | |||
| @@ -2,10 +2,10 @@ | |||
| 2 | 2 | ||
| 3 | extern crate alloc; | 3 | extern crate alloc; |
| 4 | 4 | ||
| 5 | pub mod uefi; | ||
| 6 | pub mod serial; | ||
| 7 | pub mod gop; | ||
| 8 | pub mod font; | 5 | pub mod font; |
| 9 | pub mod ps2; | 6 | pub mod gop; |
| 10 | pub mod interrupts; | 7 | pub mod interrupts; |
| 11 | pub mod memory; | 8 | pub mod memory; |
| 9 | pub mod ps2; | ||
| 10 | pub mod serial; | ||
| 11 | pub mod uefi; | ||
diff --git a/rsnix/src/ps2.rs b/rsnix/src/ps2.rs index b83a4e0..477d146 100644 --- a/rsnix/src/ps2.rs +++ b/rsnix/src/ps2.rs | |||
| @@ -346,10 +346,9 @@ fn update_modifiers(scancode: u8, pressed: bool, e0: bool) { | |||
| 346 | (0x1D, true) => set_mod(state, MOD_RCTRL, pressed), | 346 | (0x1D, true) => set_mod(state, MOD_RCTRL, pressed), |
| 347 | (0x38, false) => set_mod(state, MOD_LALT, pressed), | 347 | (0x38, false) => set_mod(state, MOD_LALT, pressed), |
| 348 | (0x38, true) => set_mod(state, MOD_RALT, pressed), | 348 | (0x38, true) => set_mod(state, MOD_RALT, pressed), |
| 349 | (0x3A, false) | 349 | (0x3A, false) if pressed => { |
| 350 | if pressed => { | 350 | state.modifiers ^= MOD_CAPS; |
| 351 | state.modifiers ^= MOD_CAPS; | 351 | } |
| 352 | } | ||
| 353 | _ => {} | 352 | _ => {} |
| 354 | } | 353 | } |
| 355 | } | 354 | } |
diff --git a/scripts/boot-image.sh b/scripts/boot-image.sh new file mode 100755 index 0000000..913e5cb --- /dev/null +++ b/scripts/boot-image.sh | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | #!/usr/bin/env bash | ||
| 2 | # | ||
| 3 | # scripts/boot-image.sh — boot rs-dos full chain disk image in QEMU | ||
| 4 | # | ||
| 5 | # Builds the image first if needed, then boots with UEFI firmware through | ||
| 6 | # the real boot chain: firmware → rsboot → rsnix kernel. | ||
| 7 | # | ||
| 8 | # Usage: | ||
| 9 | # ./scripts/boot-image.sh [--gui] [--debug] [--mem 512M] [--smp 2] | ||
| 10 | # | ||
| 11 | # Keybindings: | ||
| 12 | # Ctrl-A X — quit | ||
| 13 | # Ctrl-A C — QEMU monitor | ||
| 14 | # | ||
| 15 | # Environment: | ||
| 16 | # OVMF path to OVMF firmware (default: /usr/share/edk2/x64/OVMF.4m.fd) | ||
| 17 | # MEM memory size (default: 256M) | ||
| 18 | # SMP CPU count (default: 1) | ||
| 19 | # | ||
| 20 | set -euo pipefail | ||
| 21 | |||
| 22 | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | ||
| 23 | PROJECT_DIR="$(dirname "$SCRIPT_DIR")" | ||
| 24 | |||
| 25 | cd "$PROJECT_DIR" | ||
| 26 | |||
| 27 | IMAGE="rs-dos.img" | ||
| 28 | |||
| 29 | # ---- config ---- | ||
| 30 | OVMF="${OVMF:-/usr/share/edk2/x64/OVMF.4m.fd}" | ||
| 31 | MEM="${MEM:-256M}" | ||
| 32 | SMP="${SMP:-1}" | ||
| 33 | GUI="" | ||
| 34 | DEBUG="" | ||
| 35 | |||
| 36 | # ---- args ---- | ||
| 37 | while [ $# -gt 0 ]; do | ||
| 38 | case "$1" in | ||
| 39 | --gui | -g) GUI="-vga std" ;; | ||
| 40 | --debug | -d) DEBUG="-s -S" ;; | ||
| 41 | --mem) | ||
| 42 | shift | ||
| 43 | MEM="$1" | ||
| 44 | ;; | ||
| 45 | --smp) | ||
| 46 | shift | ||
| 47 | SMP="$1" | ||
| 48 | ;; | ||
| 49 | --help | -h) | ||
| 50 | head -20 "$0" | grep "^#" | sed 's/^# //' | ||
| 51 | exit 0 | ||
| 52 | ;; | ||
| 53 | *) | ||
| 54 | echo "unknown: $1" | ||
| 55 | exit 1 | ||
| 56 | ;; | ||
| 57 | esac | ||
| 58 | shift | ||
| 59 | done | ||
| 60 | |||
| 61 | # ---- build image if missing ---- | ||
| 62 | if [ ! -f "$IMAGE" ]; then | ||
| 63 | echo "Image not found, building..." | ||
| 64 | "$SCRIPT_DIR/build-image.sh" | ||
| 65 | fi | ||
| 66 | |||
| 67 | # ---- boot ---- | ||
| 68 | echo "" | ||
| 69 | echo "=== Booting (full chain: firmware → rsboot → rsnix) ===" | ||
| 70 | echo " image: $IMAGE" | ||
| 71 | echo " ovmf: $OVMF" | ||
| 72 | echo " mem: $MEM smp: $SMP" | ||
| 73 | echo " gui: $([ -n "$GUI" ] && echo yes || echo no)" | ||
| 74 | echo " gdb: $([ -n "$DEBUG" ] && echo ':1234' || echo off)" | ||
| 75 | echo "" | ||
| 76 | |||
| 77 | exec qemu-system-x86_64 \ | ||
| 78 | -bios "$OVMF" \ | ||
| 79 | -drive file="$IMAGE",format=raw,if=none,id=hd \ | ||
| 80 | -device ide-hd,drive=hd \ | ||
| 81 | -serial stdio \ | ||
| 82 | -m "$MEM" \ | ||
| 83 | -machine q35 \ | ||
| 84 | -cpu qemu64 \ | ||
| 85 | -no-reboot \ | ||
| 86 | -smp "$SMP" \ | ||
| 87 | $GUI $DEBUG | ||
diff --git a/scripts/boot.sh b/scripts/boot.sh new file mode 100755 index 0000000..1e3f739 --- /dev/null +++ b/scripts/boot.sh | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | #!/usr/bin/env bash | ||
| 2 | # | ||
| 3 | # scripts/boot.sh — quick direct boot in QEMU (dev loop) | ||
| 4 | # | ||
| 5 | # Fastest iteration: boots the kernel directly as BOOTX64.EFI via QEMU's | ||
| 6 | # FAT driver, skipping the bootloader entirely. | ||
| 7 | # | ||
| 8 | # Usage: | ||
| 9 | # ./scripts/boot.sh [--gui] [--debug] [--release] [--mem 512M] [--smp 2] | ||
| 10 | # | ||
| 11 | # Boot chain: firmware → rsnix (direct) | ||
| 12 | # Full chain: use ./scripts/boot-image.sh (firmware → rsboot → rsnix) | ||
| 13 | # | ||
| 14 | # Keybindings: | ||
| 15 | # Ctrl-A X — quit | ||
| 16 | # Ctrl-A C — QEMU monitor | ||
| 17 | # | ||
| 18 | # Environment: | ||
| 19 | # OVMF path to OVMF firmware (default: /usr/share/edk2/x64/OVMF.4m.fd) | ||
| 20 | # MEM memory size (default: 256M) | ||
| 21 | # SMP CPU count (default: 1) | ||
| 22 | # | ||
| 23 | set -euo pipefail | ||
| 24 | |||
| 25 | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | ||
| 26 | PROJECT_DIR="$(dirname "$SCRIPT_DIR")" | ||
| 27 | |||
| 28 | cd "$PROJECT_DIR" | ||
| 29 | |||
| 30 | ESP_DIR="$PROJECT_DIR/esp" | ||
| 31 | |||
| 32 | # ---- config ---- | ||
| 33 | OVMF="${OVMF:-/usr/share/edk2/x64/OVMF.4m.fd}" | ||
| 34 | MEM="${MEM:-256M}" | ||
| 35 | SMP="${SMP:-1}" | ||
| 36 | PROFILE="debug" | ||
| 37 | CARGO_FLAGS="" | ||
| 38 | GUI="" | ||
| 39 | DEBUG="" | ||
| 40 | |||
| 41 | # ---- args ---- | ||
| 42 | while [ $# -gt 0 ]; do | ||
| 43 | case "$1" in | ||
| 44 | --gui | -g) GUI="-vga std" ;; | ||
| 45 | --debug | -d) DEBUG="-s -S" ;; | ||
| 46 | --release | -r) | ||
| 47 | PROFILE="release" | ||
| 48 | CARGO_FLAGS="--release" | ||
| 49 | ;; | ||
| 50 | --mem) | ||
| 51 | shift | ||
| 52 | MEM="$1" | ||
| 53 | ;; | ||
| 54 | --smp) | ||
| 55 | shift | ||
| 56 | SMP="$1" | ||
| 57 | ;; | ||
| 58 | --help | -h) | ||
| 59 | head -20 "$0" | grep "^#" | sed 's/^# //' | ||
| 60 | exit 0 | ||
| 61 | ;; | ||
| 62 | *) | ||
| 63 | echo "unknown: $1" | ||
| 64 | exit 1 | ||
| 65 | ;; | ||
| 66 | esac | ||
| 67 | shift | ||
| 68 | done | ||
| 69 | |||
| 70 | OUT_DIR="target/x86_64-unknown-uefi/$PROFILE" | ||
| 71 | KERNEL="$OUT_DIR/rsdos.efi" | ||
| 72 | |||
| 73 | # ---- build ---- | ||
| 74 | echo "=== Building kernel ($PROFILE) ===" | ||
| 75 | cargo build --package rsdos --target x86_64-unknown-uefi $CARGO_FLAGS | ||
| 76 | |||
| 77 | # ---- deploy ---- | ||
| 78 | mkdir -p "$ESP_DIR/EFI/BOOT" | ||
| 79 | cp "$KERNEL" "$ESP_DIR/EFI/BOOT/BOOTX64.EFI" | ||
| 80 | echo " kernel: $(ls -lh "$KERNEL" | awk '{print $5}')" | ||
| 81 | |||
| 82 | # ---- boot ---- | ||
| 83 | echo "" | ||
| 84 | echo "=== Booting (direct: firmware → rsnix) ===" | ||
| 85 | echo " ovmf: $OVMF" | ||
| 86 | echo " mem: $MEM smp: $SMP" | ||
| 87 | echo " gui: $([ -n "$GUI" ] && echo yes || echo no)" | ||
| 88 | echo " gdb: $([ -n "$DEBUG" ] && echo ':1234' || echo off)" | ||
| 89 | echo "" | ||
| 90 | |||
| 91 | exec qemu-system-x86_64 \ | ||
| 92 | -bios "$OVMF" \ | ||
| 93 | -drive file=fat:rw:"$ESP_DIR",format=raw \ | ||
| 94 | -serial stdio \ | ||
| 95 | -m "$MEM" \ | ||
| 96 | -machine q35 \ | ||
| 97 | -cpu qemu64 \ | ||
| 98 | -no-reboot \ | ||
| 99 | -smp "$SMP" \ | ||
| 100 | $GUI $DEBUG | ||
diff --git a/scripts/build-bootloader.sh b/scripts/build-bootloader.sh new file mode 100755 index 0000000..9a96cfe --- /dev/null +++ b/scripts/build-bootloader.sh | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | #!/usr/bin/env bash | ||
| 2 | # | ||
| 3 | # scripts/build-bootloader.sh — build rsboot (UEFI bootloader) | ||
| 4 | # | ||
| 5 | # rsboot is a git submodule at rsboot/. This builds it and places | ||
| 6 | # BOOTX64.EFI into build/bootloader/. | ||
| 7 | # | ||
| 8 | # Usage: | ||
| 9 | # ./scripts/build-bootloader.sh | ||
| 10 | # | ||
| 11 | # Output: | ||
| 12 | # build/bootloader/BOOTX64.EFI | ||
| 13 | # | ||
| 14 | set -euo pipefail | ||
| 15 | |||
| 16 | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | ||
| 17 | PROJECT_DIR="$(dirname "$SCRIPT_DIR")" | ||
| 18 | BUILD_DIR="$PROJECT_DIR/build" | ||
| 19 | BOOTLOADER_DIR="$BUILD_DIR/bootloader" | ||
| 20 | |||
| 21 | echo "=== Building rsboot (UEFI bootloader) ===" | ||
| 22 | |||
| 23 | # Ensure submodule is checked out | ||
| 24 | git submodule update --init "$PROJECT_DIR/rsboot" | ||
| 25 | |||
| 26 | cd "$PROJECT_DIR/rsboot" | ||
| 27 | make clean 2>/dev/null || true | ||
| 28 | make -j"$(nproc)" 2>&1 | sed 's/^/ /' | ||
| 29 | |||
| 30 | echo "" | ||
| 31 | echo "=== rsboot build complete ===" | ||
| 32 | ls -lh "$BOOTLOADER_DIR/BOOTX64.EFI" | ||
diff --git a/scripts/build-image.sh b/scripts/build-image.sh new file mode 100755 index 0000000..02672ad --- /dev/null +++ b/scripts/build-image.sh | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | #!/usr/bin/env bash | ||
| 2 | # | ||
| 3 | # scripts/build-image.sh — assemble a bootable rs-dos disk image (UEFI/GPT) | ||
| 4 | # | ||
| 5 | # Layout: | ||
| 6 | # Partition 1: ESP (FAT32) — rsboot bootloader + kernel | ||
| 7 | # | ||
| 8 | # Output: | ||
| 9 | # rs-dos.img (or custom path) — bootable raw disk image for UEFI | ||
| 10 | # | ||
| 11 | # Usage: | ||
| 12 | # ./scripts/build-image.sh [output.img] | ||
| 13 | # | ||
| 14 | set -euo pipefail | ||
| 15 | |||
| 16 | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | ||
| 17 | PROJECT_DIR="$(dirname "$SCRIPT_DIR")" | ||
| 18 | |||
| 19 | cd "$PROJECT_DIR" | ||
| 20 | |||
| 21 | BUILD_DIR="$PROJECT_DIR/build" | ||
| 22 | ESP_DIR="$PROJECT_DIR/esp" | ||
| 23 | |||
| 24 | IMAGE="${1:-$PROJECT_DIR/rs-dos.img}" | ||
| 25 | TARGET=x86_64-unknown-uefi | ||
| 26 | PROFILE=debug | ||
| 27 | OUT_DIR="target/${TARGET}/${PROFILE}" | ||
| 28 | |||
| 29 | BOOTLOADER="$BUILD_DIR/bootloader/BOOTX64.EFI" | ||
| 30 | KERNEL="$OUT_DIR/rsdos.efi" | ||
| 31 | BZIMAGE="$ESP_DIR/bzImage" | ||
| 32 | INITRD="$ESP_DIR/initramfs.cpio.gz" | ||
| 33 | BOOT_EFI="$ESP_DIR/EFI/BOOT/BOOTX64.EFI" | ||
| 34 | |||
| 35 | ESP_START=2048 # 1 MiB offset (standard alignment) | ||
| 36 | ESP_SIZE_MB=64 | ||
| 37 | |||
| 38 | IMAGE_SIZE_MB=$((ESP_SIZE_MB + 2)) # ESP + GPT gap + backup | ||
| 39 | |||
| 40 | # ---- checks ---- | ||
| 41 | for cmd in sfdisk mkfs.vfat mcopy truncate dd; do | ||
| 42 | if ! command -v "$cmd" &>/dev/null; then | ||
| 43 | echo "Error: $cmd not found" | ||
| 44 | exit 1 | ||
| 45 | fi | ||
| 46 | done | ||
| 47 | |||
| 48 | # ---- build kernel ---- | ||
| 49 | echo "[1/4] Building kernel..." | ||
| 50 | cargo build --package rsdos --target x86_64-unknown-uefi ${CARGO_FLAGS:-} | ||
| 51 | |||
| 52 | # ---- build bootloader ---- | ||
| 53 | echo "[2/4] Building bootloader..." | ||
| 54 | if [ ! -f "$BOOTLOADER" ]; then | ||
| 55 | "$SCRIPT_DIR/build-bootloader.sh" | ||
| 56 | fi | ||
| 57 | |||
| 58 | # ---- assemble ESP ---- | ||
| 59 | echo "[3/4] Assembling ESP..." | ||
| 60 | mkdir -p "$ESP_DIR/EFI/BOOT" | ||
| 61 | cp "$KERNEL" "$BZIMAGE" | ||
| 62 | cp "$BOOTLOADER" "$BOOT_EFI" | ||
| 63 | if [ ! -f "$INITRD" ]; then | ||
| 64 | printf '' | gzip >"$INITRD" | ||
| 65 | fi | ||
| 66 | |||
| 67 | # ---- create disk image ---- | ||
| 68 | echo "[4/4] Writing disk image..." | ||
| 69 | rm -f "$IMAGE" | ||
| 70 | truncate -s "${IMAGE_SIZE_MB}M" "$IMAGE" | ||
| 71 | |||
| 72 | # GPT partition table: single EFI System partition | ||
| 73 | sfdisk --quiet "$IMAGE" <<EOF | ||
| 74 | label: gpt | ||
| 75 | type=U, start=$ESP_START, size=+ | ||
| 76 | EOF | ||
| 77 | |||
| 78 | # Build FAT32 image with ESP contents | ||
| 79 | ESP_IMG=$(mktemp) | ||
| 80 | truncate -s "${ESP_SIZE_MB}M" "$ESP_IMG" | ||
| 81 | mkfs.vfat -F 32 -n "RS-DOS" "$ESP_IMG" >/dev/null 2>&1 | ||
| 82 | |||
| 83 | # Copy files into FAT | ||
| 84 | mmd -i "$ESP_IMG" ::/EFI 2>/dev/null || true | ||
| 85 | mmd -i "$ESP_IMG" ::/EFI/BOOT 2>/dev/null || true | ||
| 86 | mcopy -i "$ESP_IMG" "$BOOT_EFI" ::/EFI/BOOT/BOOTX64.EFI | ||
| 87 | mcopy -i "$ESP_IMG" "$BZIMAGE" ::/bzImage 2>/dev/null || true | ||
| 88 | mcopy -i "$ESP_IMG" "$INITRD" ::/initramfs.cpio.gz 2>/dev/null || true | ||
| 89 | |||
| 90 | # Inject FAT into image at partition offset | ||
| 91 | dd if="$ESP_IMG" of="$IMAGE" bs=512 seek="$ESP_START" conv=notrunc 2>/dev/null | ||
| 92 | rm -f "$ESP_IMG" | ||
| 93 | |||
| 94 | echo "" | ||
| 95 | echo "=== Done: $IMAGE ===" | ||
| 96 | ls -lh "$IMAGE" | ||
| 97 | echo "" | ||
| 98 | echo "Boot with: ./scripts/boot-image.sh" | ||
| 99 | echo "USB: sudo dd if=$IMAGE of=/dev/sdX bs=4M status=progress" | ||
diff --git a/tools/debug-kernel.py b/scripts/debug-kernel.py index c794ad6..c794ad6 100755 --- a/tools/debug-kernel.py +++ b/scripts/debug-kernel.py | |||
diff --git a/tools/qemu.sh b/scripts/qemu.sh index b75bed4..b75bed4 100755 --- a/tools/qemu.sh +++ b/scripts/qemu.sh | |||
diff --git a/tools/boot-image.sh b/tools/boot-image.sh deleted file mode 100755 index 2592afa..0000000 --- a/tools/boot-image.sh +++ /dev/null | |||
| @@ -1,62 +0,0 @@ | |||
| 1 | #!/usr/bin/env bash | ||
| 2 | # ============================================================================= | ||
| 3 | # tools/boot-image.sh — Create a bootable disk image from the ESP directory | ||
| 4 | # | ||
| 5 | # Produces a raw disk image (bootable via UEFI) for dd-ing to a USB stick | ||
| 6 | # or attaching to QEMU as a hard disk. | ||
| 7 | # | ||
| 8 | # Usage: | ||
| 9 | # ./tools/boot-image.sh [output.img] | ||
| 10 | # | ||
| 11 | # Default output: raisernics.img | ||
| 12 | # ============================================================================= | ||
| 13 | set -euo pipefail | ||
| 14 | |||
| 15 | SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" | ||
| 16 | cd "$SCRIPT_DIR" | ||
| 17 | |||
| 18 | OUTPUT="${1:-raisernics.img}" | ||
| 19 | ESP_DIR="${ESP_DIR:-esp}" | ||
| 20 | MBR_SZ=1 # 1 MB reserved at start for GPT/pmbr | ||
| 21 | SECTOR_SZ=512 | ||
| 22 | |||
| 23 | # Rebuild ESP if stale | ||
| 24 | make all | ||
| 25 | |||
| 26 | if [ ! -d "$ESP_DIR" ]; then | ||
| 27 | echo "ERROR: ESP directory '$ESP_DIR' not found. Run 'make all' first." | ||
| 28 | exit 1 | ||
| 29 | fi | ||
| 30 | |||
| 31 | # Calculate required size: ESP contents + MBR gap + some slack | ||
| 32 | ESP_SIZE_MB=$(du -sm "$ESP_DIR" 2>/dev/null | cut -f1 || echo 1) | ||
| 33 | TOTAL_MB=$((ESP_SIZE_MB + MBR_SZ + 1)) # +1 MB slack | ||
| 34 | |||
| 35 | echo "Creating ${TOTAL_MB} MB disk image: ${OUTPUT}" | ||
| 36 | |||
| 37 | # Create empty image with MBR gap | ||
| 38 | dd if=/dev/zero of="$OUTPUT" bs=1M count="$TOTAL_MB" status=none 2>/dev/null | ||
| 39 | |||
| 40 | # Partition table: single GPT partition, type EFI System (C12A7328-F81F-11D2-BA4B-00A0C93EC93B) | ||
| 41 | sgdisk --clear \ | ||
| 42 | --new=1:${MBR_SZ}M:0 \ | ||
| 43 | --typecode=1:C12A7328-F81F-11D2-BA4B-00A0C93EC93B \ | ||
| 44 | --change-name=1:"raisernics" \ | ||
| 45 | "$OUTPUT" >/dev/null | ||
| 46 | |||
| 47 | # Find partition offset | ||
| 48 | PART_START=$(sgdisk --info=1 "$OUTPUT" 2>/dev/null | grep "Partition start sector" | awk '{print $NF}') | ||
| 49 | if [ -z "$PART_START" ]; then | ||
| 50 | PART_START=$((MBR_SZ * 1024 * 1024 / SECTOR_SZ)) | ||
| 51 | fi | ||
| 52 | |||
| 53 | # Format as FAT32 | ||
| 54 | mformat -i "$OUTPUT"@$((PART_START * SECTOR_SZ)) -h 32 -s 32 -t "$((TOTAL_MB * 2))" >/dev/null 2>&1 || true | ||
| 55 | |||
| 56 | # Copy the ESP contents onto the partition | ||
| 57 | mcopy -i "$OUTPUT"@$((PART_START * SECTOR_SZ)) -s "$ESP_DIR"/* ::/ 2>/dev/null | ||
| 58 | |||
| 59 | echo " -> ${OUTPUT} ($(ls -lh "$OUTPUT" | awk '{print $5}'))" | ||
| 60 | echo "" | ||
| 61 | echo "To write to USB: sudo dd if=${OUTPUT} of=/dev/sdX bs=4M status=progress" | ||
| 62 | echo "To test with QEMU: qemu-system-x86_64 -bios <OVMF> -drive file=${OUTPUT},format=raw" | ||
