diff options
Diffstat (limited to '')
| -rwxr-xr-x | scripts/mksystem.sh | 144 |
1 files changed, 75 insertions, 69 deletions
diff --git a/scripts/mksystem.sh b/scripts/mksystem.sh index 044c86c..053fb3b 100755 --- a/scripts/mksystem.sh +++ b/scripts/mksystem.sh | |||
| @@ -2,44 +2,49 @@ | |||
| 2 | # | 2 | # |
| 3 | # scripts/mksystem.sh — assemble the single dd-able rs-dos system image | 3 | # scripts/mksystem.sh — assemble the single dd-able rs-dos system image |
| 4 | # | 4 | # |
| 5 | # Replaces the old two-source setup (vvfat `esp/` directory for boot + | 5 | # One FAT32 image holds EVERYTHING (boot medium and data medium are the |
| 6 | # separate /tmp/disk.img for data). One FAT32 image holds EVERYTHING: | 6 | # same disk, mounted by the kernel at /disk/<UID>/): |
| 7 | # | 7 | # |
| 8 | # \bzImage kernel (rsbl requires this exact path) | 8 | # \EFI\BOOT\BOOTX64.EFI the kernel — the firmware boots it directly |
| 9 | # \initramfs.cpio.gz empty initramfs (rsbl requires it) | 9 | # \bzImage kernel copy (rsbl's expected path, real hw) |
| 10 | # \EFI\BOOT\BOOTX64.EFI boot entry: the kernel (default) or rsboot | 10 | # \initramfs.cpio.gz empty initramfs (rsbl requires the path) |
| 11 | # \bin\cli\*.efi terminal binaries (invoked by the shell) | ||
| 12 | # \bin\gui\*.efi windowed binaries (launched with no shell) | ||
| 11 | # \etc\motd.txt seed config | 13 | # \etc\motd.txt seed config |
| 12 | # \bin\cli\ \bin\gui\ binary tree (empty until Phase 2/4 migrate tools) | ||
| 13 | # \*.txt seed files (seed/) | 14 | # \*.txt seed files (seed/) |
| 14 | # | 15 | # |
| 15 | # The firmware boots from this image and the kernel mounts the same | 16 | # Freshness: an existing image is only rebuilt when a kernel/binary/seed |
| 16 | # volume at /disk/<UID>/ — boot medium and data medium are one disk. | 17 | # file is newer than it, so files written at runtime survive across |
| 18 | # boots. --force always re-creates (wipes runtime data). | ||
| 17 | # | 19 | # |
| 18 | # Usage: | 20 | # Usage: |
| 19 | # ./scripts/mksystem.sh [options] [output.img] # default /tmp/system.img | 21 | # ./scripts/mksystem.sh [options] [output.img] default: $SYSTEM_IMG |
| 20 | # | 22 | # |
| 21 | # Options: | 23 | # Options: |
| 22 | # --force rebuild even if the image exists (Makefile stamps handle | 24 | # --force rebuild even if the image is up to date |
| 23 | # normal freshness; without --force an existing image is kept, | ||
| 24 | # so user files survive across reboots) | ||
| 25 | # --size NM image size in MB (default 64) | 25 | # --size NM image size in MB (default 64) |
| 26 | # --chain \EFI\BOOT\BOOTX64.EFI = rsboot bootloader (full chain: | ||
| 27 | # firmware → rsboot → rsnix). Default is the kernel itself | ||
| 28 | # (direct: firmware → rsnix), matching the old dev loop. | ||
| 29 | # --gpt wrap the FAT volume in a GPT partition table (for dd-ing | ||
| 30 | # to real USB sticks whose firmware refuses superfloppies) | ||
| 31 | # --label NAME FAT volume label (default RSDOS) | 26 | # --label NAME FAT volume label (default RSDOS) |
| 27 | # --gpt wrap the FAT volume in a GPT partition table (for | ||
| 28 | # dd-ing to real USB sticks whose firmware refuses | ||
| 29 | # superfloppies) | ||
| 30 | # --help show this help | ||
| 31 | # | ||
| 32 | # Needs: dosfstools (mkfs.fat), mtools (mcopy/mmd), cargo (kernel+bins | ||
| 33 | # built via scripts/build.sh when missing). | ||
| 32 | # | 34 | # |
| 33 | set -euo pipefail | 35 | set -euo pipefail |
| 34 | 36 | ||
| 35 | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | 37 | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" |
| 36 | PROJECT_DIR="$(dirname "$SCRIPT_DIR")" | 38 | # Absolute self path: lib.sh cd's to the project root, so a relative $0 |
| 37 | cd "$PROJECT_DIR" | 39 | # would no longer resolve by the time --help prints the header. |
| 40 | SELF="$SCRIPT_DIR/$(basename "$0")" | ||
| 41 | |||
| 42 | # shellcheck source=lib.sh | ||
| 43 | source "$SCRIPT_DIR/lib.sh" | ||
| 38 | 44 | ||
| 39 | IMG="/tmp/system.img" | 45 | IMG="$SYSTEM_IMG" |
| 40 | SIZE_MB=64 | 46 | SIZE_MB=64 |
| 41 | FORCE=0 | 47 | FORCE=0 |
| 42 | CHAIN=0 | ||
| 43 | GPT=0 | 48 | GPT=0 |
| 44 | LABEL="RSDOS" | 49 | LABEL="RSDOS" |
| 45 | 50 | ||
| @@ -52,18 +57,15 @@ while [ $# -gt 0 ]; do | |||
| 52 | shift | 57 | shift |
| 53 | SIZE_MB="$1" | 58 | SIZE_MB="$1" |
| 54 | ;; | 59 | ;; |
| 55 | --chain) | ||
| 56 | CHAIN=1 | ||
| 57 | ;; | ||
| 58 | --gpt) | ||
| 59 | GPT=1 | ||
| 60 | ;; | ||
| 61 | --label) | 60 | --label) |
| 62 | shift | 61 | shift |
| 63 | LABEL="$1" | 62 | LABEL="$1" |
| 64 | ;; | 63 | ;; |
| 64 | --gpt) | ||
| 65 | GPT=1 | ||
| 66 | ;; | ||
| 65 | --help | -h) | 67 | --help | -h) |
| 66 | head -30 "$0" | grep "^#" | sed 's/^# \?//' | 68 | awk 'NR > 1 && /^#/ { sub(/^# ?/, ""); print; next } NR > 1 { exit }' "$SELF" |
| 67 | exit 0 | 69 | exit 0 |
| 68 | ;; | 70 | ;; |
| 69 | -*) | 71 | -*) |
| @@ -77,15 +79,9 @@ while [ $# -gt 0 ]; do | |||
| 77 | shift | 79 | shift |
| 78 | done | 80 | done |
| 79 | 81 | ||
| 80 | TARGET=x86_64-unknown-uefi | 82 | SEED_DIR="$PROJECT_DIR/seed" |
| 81 | PROFILE=release | ||
| 82 | OUT_DIR="target/$TARGET/$PROFILE" | ||
| 83 | KERNEL="$OUT_DIR/rsdos.efi" | ||
| 84 | BZIMAGE="esp/bzImage" | ||
| 85 | INITRD="esp/initramfs.cpio.gz" | ||
| 86 | BOOTLOADER="build/bootloader/BOOTX64.EFI" | ||
| 87 | 83 | ||
| 88 | # ---- checks ---- | 84 | # ---- checks --------------------------------------------------------------- |
| 89 | for cmd in mkfs.fat mcopy mmd; do | 85 | for cmd in mkfs.fat mcopy mmd; do |
| 90 | if ! command -v "$cmd" >/dev/null 2>&1; then | 86 | if ! command -v "$cmd" >/dev/null 2>&1; then |
| 91 | echo "mksystem: $cmd not found (install dosfstools + mtools)" >&2 | 87 | echo "mksystem: $cmd not found (install dosfstools + mtools)" >&2 |
| @@ -101,29 +97,26 @@ if [ "$GPT" -eq 1 ]; then | |||
| 101 | done | 97 | done |
| 102 | fi | 98 | fi |
| 103 | 99 | ||
| 104 | if [ -f "$IMG" ] && [ "$FORCE" -eq 0 ]; then | 100 | # ---- build (only when artifacts are missing; build.sh is the only cargo |
| 105 | echo "mksystem: $IMG already exists (use --force to re-create)" | 101 | # invocation, so an already-compiled tree costs nothing) -------------------- |
| 106 | exit 0 | 102 | if [ ! -f "$KERNEL" ] || ! ls "$OUT_DIR"/*.efi >/dev/null 2>&1; then |
| 103 | "$SCRIPT_DIR/build.sh" | ||
| 107 | fi | 104 | fi |
| 108 | 105 | ||
| 109 | # ---- build kernel ---- | 106 | # ---- freshness stamp ------------------------------------------------------ |
| 110 | if [ ! -f "$KERNEL" ]; then | 107 | newest="" |
| 111 | echo "mksystem: building kernel..." | 108 | for f in "$OUT_DIR"/*.efi "$SEED_DIR"/*; do |
| 112 | cargo build --release --package rsdos --target "$TARGET" | 109 | [ -f "$f" ] || continue |
| 113 | fi | 110 | if [ -z "$newest" ] || [ "$f" -nt "$newest" ]; then |
| 114 | 111 | newest="$f" | |
| 115 | # ---- build bootloader (chain mode only) ---- | 112 | fi |
| 116 | if [ "$CHAIN" -eq 1 ] && [ ! -f "$BOOTLOADER" ]; then | 113 | done |
| 117 | echo "mksystem: building bootloader..." | 114 | if [ "$FORCE" -eq 0 ] && [ -f "$IMG" ] && { [ -z "$newest" ] || [ ! "$newest" -nt "$IMG" ]; }; then |
| 118 | "$SCRIPT_DIR/build-bootloader.sh" | 115 | echo "mksystem: up to date: $IMG (use --force to re-create)" |
| 116 | exit 0 | ||
| 119 | fi | 117 | fi |
| 120 | 118 | ||
| 121 | # ---- deploy kernel artifacts to esp/ (shared with the old layout) ---- | 119 | # ---- create the FAT volume ------------------------------------------------ |
| 122 | mkdir -p esp/EFI/BOOT | ||
| 123 | cp "$KERNEL" "$BZIMAGE" | ||
| 124 | [ -f "$INITRD" ] || printf '' | gzip >"$INITRD" | ||
| 125 | |||
| 126 | # ---- create the FAT volume ---- | ||
| 127 | rm -f "$IMG" | 120 | rm -f "$IMG" |
| 128 | SIZE_BLOCKS=$((SIZE_MB * 1024)) # mkfs.fat counts 1024-byte blocks | 121 | SIZE_BLOCKS=$((SIZE_MB * 1024)) # mkfs.fat counts 1024-byte blocks |
| 129 | echo "mksystem: creating $IMG (${SIZE_MB}M FAT32, label $LABEL)" | 122 | echo "mksystem: creating $IMG (${SIZE_MB}M FAT32, label $LABEL)" |
| @@ -131,34 +124,47 @@ mkfs.fat -C -F 32 -n "$LABEL" "$IMG" "$SIZE_BLOCKS" >/dev/null | |||
| 131 | 124 | ||
| 132 | echo "mksystem: staging system tree" | 125 | echo "mksystem: staging system tree" |
| 133 | mmd -i "$IMG" ::/EFI ::/EFI/BOOT ::/etc ::/bin ::/bin/cli ::/bin/gui | 126 | mmd -i "$IMG" ::/EFI ::/EFI/BOOT ::/etc ::/bin ::/bin/cli ::/bin/gui |
| 134 | mcopy -i "$IMG" "$BZIMAGE" ::/bzImage | 127 | |
| 128 | # The firmware entry point and rsbl's kernel path are the same file. | ||
| 129 | mcopy -i "$IMG" "$KERNEL" ::/EFI/BOOT/BOOTX64.EFI | ||
| 130 | mcopy -i "$IMG" "$KERNEL" ::/bzImage | ||
| 131 | INITRD="$(mktemp -t rsdos-initrd.XXXXXX)" | ||
| 132 | trap 'rm -f "$INITRD"' EXIT | ||
| 133 | printf '' | gzip >"$INITRD" | ||
| 135 | mcopy -i "$IMG" "$INITRD" ::/initramfs.cpio.gz | 134 | mcopy -i "$IMG" "$INITRD" ::/initramfs.cpio.gz |
| 136 | if [ "$CHAIN" -eq 1 ]; then | 135 | echo " \\EFI\\BOOT\\BOOTX64.EFI \\bzImage \\initramfs.cpio.gz" |
| 137 | mcopy -i "$IMG" "$BOOTLOADER" ::/EFI/BOOT/BOOTX64.EFI | 136 | |
| 138 | echo " \\EFI\\BOOT\\BOOTX64.EFI <- rsboot (full chain)" | 137 | # External binaries: everything under bins/ was compiled into $OUT_DIR. |
| 139 | else | 138 | # Launch surface decides the directory (ADR 0006): GUI_BINS -> /bin/gui, |
| 140 | mcopy -i "$IMG" "$KERNEL" ::/EFI/BOOT/BOOTX64.EFI | 139 | # everything else -> /bin/cli. |
| 141 | echo " \\EFI\\BOOT\\BOOTX64.EFI <- kernel (direct)" | 140 | for src in "$OUT_DIR"/*.efi; do |
| 142 | fi | 141 | [ -f "$src" ] || continue |
| 143 | echo " \\bzImage \\initramfs.cpio.gz \\bin{\\cli,\\gui} \\etc" | 142 | name="$(basename "$src" .efi)" |
| 143 | [ "$name" = "rsdos" ] && continue # the kernel is not a /bin binary | ||
| 144 | case " $GUI_BINS " in | ||
| 145 | *" $name "*) kind="gui" ;; | ||
| 146 | *) kind="cli" ;; | ||
| 147 | esac | ||
| 148 | mcopy -i "$IMG" "$src" "::/bin/$kind/$name.efi" | ||
| 149 | printf ' \\bin\\%s\\%s.efi\n' "$kind" "$name" | ||
| 150 | done | ||
| 144 | 151 | ||
| 145 | # Seed files: motd lives in \etc, everything else at the volume root. | 152 | # Seed files: motd lives in \etc, everything else at the volume root. |
| 146 | SEED_DIR="$PROJECT_DIR/seed" | ||
| 147 | if [ -d "$SEED_DIR" ]; then | 153 | if [ -d "$SEED_DIR" ]; then |
| 148 | for f in "$SEED_DIR"/*; do | 154 | for f in "$SEED_DIR"/*; do |
| 149 | [ -f "$f" ] || continue | 155 | [ -f "$f" ] || continue |
| 150 | name="$(basename "$f")" | 156 | name="$(basename "$f")" |
| 151 | if [ "$name" = "motd.txt" ]; then | 157 | if [ "$name" = "motd.txt" ]; then |
| 152 | mcopy -i "$IMG" "$f" ::/etc/"$name" | 158 | mcopy -i "$IMG" "$f" ::/etc/"$name" |
| 153 | echo " \\etc\\$name" | 159 | printf ' \\etc\\%s\n' "$name" |
| 154 | else | 160 | else |
| 155 | mcopy -i "$IMG" "$f" ::/"$name" | 161 | mcopy -i "$IMG" "$f" ::/"$name" |
| 156 | echo " \\$name" | 162 | printf ' \\%s\n' "$name" |
| 157 | fi | 163 | fi |
| 158 | done | 164 | done |
| 159 | fi | 165 | fi |
| 160 | 166 | ||
| 161 | # ---- optional GPT wrapper (real-hardware dd target) ---- | 167 | # ---- optional GPT wrapper (real-hardware dd target) ----------------------- |
| 162 | if [ "$GPT" -eq 1 ]; then | 168 | if [ "$GPT" -eq 1 ]; then |
| 163 | GPT_START=2048 # 1 MiB offset (standard alignment) | 169 | GPT_START=2048 # 1 MiB offset (standard alignment) |
| 164 | GPT_IMG="$(mktemp)" | 170 | GPT_IMG="$(mktemp)" |
| @@ -179,6 +185,6 @@ fi | |||
| 179 | echo "" | 185 | echo "" |
| 180 | echo "=== Done: $IMG ===" | 186 | echo "=== Done: $IMG ===" |
| 181 | ls -lh "$IMG" | 187 | ls -lh "$IMG" |
| 182 | echo "Boot with: make run (or: make boot-image)" | 188 | echo "Boot with: ./scripts/run.sh (or: make run)" |
| 183 | [ "$GPT" -eq 0 ] && echo "USB dd tip: add --gpt for firmwares that refuse superfloppies" | 189 | [ "$GPT" -eq 0 ] && echo "USB dd tip: add --gpt for firmwares that refuse superfloppies" |
| 184 | exit 0 | 190 | exit 0 |
