Skip to content

Commit afad75c

Browse files
author
T. Andrew Davis
committed
Update README and setup script to include mtools for disk image handling
1 parent 1632bf9 commit afad75c

2 files changed

Lines changed: 89 additions & 36 deletions

File tree

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ The system boots through an 11-phase initialization that transforms raw x86-64 h
2020
10. Syscall interface (SYSCALL/SYSRET)
2121
11. Root filesystem (HelixFS)
2222

23-
After boot, applications can spawn user processes, allocate memory, perform I/O, and communicate through syscalls. The Shell and windowed applications run directly in the kernel's event loop.
24-
23+
After boot, applications can spawn user processes, allocate memory, perform I/O, and communicate through syscalls.
2524
## Design Principles
2625

2726
- **Minimize abstraction**: Hardware is exposed. Page tables, interrupts, CPUs are visible resources.

setup-dev.sh

Lines changed: 88 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ check_rust() { has_cmd rustc && rustup target list 2>/dev/null | grep -q "
8585
check_ovmf() { get_ovmf_path &>/dev/null; }
8686
check_bootloader() { [[ -f "${ESP_DIR}/EFI/BOOT/BOOTX64.EFI" ]]; }
8787
check_qemu() { has_cmd qemu-system-x86_64; }
88-
check_disk_tools() { has_cmd qemu-img && has_cmd parted && has_cmd mkfs.vfat && has_cmd mkfs.ext4; }
88+
check_disk_tools() { has_cmd qemu-img && has_cmd parted && has_cmd mkfs.vfat && has_cmd mkfs.ext4 && has_cmd mcopy; }
8989
# Distribution checks removed - network downloader handles ISO acquisition
9090
check_disk_50g() { [[ -f "${TESTING_DIR}/test-disk-50g.img" ]]; }
9191

@@ -113,7 +113,7 @@ cmd_status() {
113113
print_check "$(has_cmd nasm && echo 1 || echo 0)" "NASM Assembler"
114114
print_check "$(check_qemu && echo 1 || echo 0)" "QEMU" "$(qemu-system-x86_64 --version 2>/dev/null | head -1 | grep -oP '\d+\.\d+\.\d+' || echo 'missing')"
115115
print_check "$(check_ovmf && echo 1 || echo 0)" "OVMF Firmware" "$(get_ovmf_path 2>/dev/null || echo 'missing')"
116-
print_check "$(check_disk_tools && echo 1 || echo 0)" "Disk Tools" "parted, mkfs.vfat, mkfs.ext4"
116+
print_check "$(check_disk_tools && echo 1 || echo 0)" "Disk Tools" "parted, mkfs.vfat, mkfs.ext4, mtools"
117117

118118
printf "\n${C_DIM}── Build ──${C_RESET}\n"
119119
print_check "$(check_bootloader && echo 1 || echo 0)" "Bootloader (BOOTX64.EFI)"
@@ -133,29 +133,29 @@ do_install_packages() {
133133

134134
case "${distro}" in
135135
arch|manjaro|endeavouros)
136-
pkgs=(base-devel nasm qemu-full ovmf parted dosfstools e2fsprogs util-linux rsync curl wget squashfs-tools cdrtools)
136+
pkgs=(base-devel nasm qemu-full ovmf parted dosfstools e2fsprogs util-linux rsync curl wget squashfs-tools cdrtools mtools)
137137
install_cmd="sudo pacman -S --needed --noconfirm"
138138
;;
139139
debian|ubuntu|pop|linuxmint|kali)
140-
pkgs=(build-essential nasm qemu-system-x86 ovmf parted dosfstools e2fsprogs util-linux rsync curl wget squashfs-tools genisoimage qemu-utils)
140+
pkgs=(build-essential nasm qemu-system-x86 ovmf parted dosfstools e2fsprogs util-linux rsync curl wget squashfs-tools genisoimage qemu-utils mtools)
141141
install_cmd="sudo apt-get install -y -qq"
142142
log_info "Updating package lists..."
143143
sudo apt-get update -qq
144144
;;
145145
fedora)
146-
pkgs=(gcc make nasm qemu-system-x86 edk2-ovmf parted dosfstools e2fsprogs util-linux rsync curl wget squashfs-tools genisoimage qemu-img)
146+
pkgs=(gcc make nasm qemu-system-x86 edk2-ovmf parted dosfstools e2fsprogs util-linux rsync curl wget squashfs-tools genisoimage qemu-img mtools)
147147
install_cmd="sudo dnf install -y -q"
148148
;;
149149
rhel|centos|almalinux|rocky)
150-
pkgs=(gcc make nasm qemu-kvm edk2-ovmf parted dosfstools e2fsprogs util-linux rsync curl wget squashfs-tools genisoimage)
150+
pkgs=(gcc make nasm qemu-kvm edk2-ovmf parted dosfstools e2fsprogs util-linux rsync curl wget squashfs-tools genisoimage mtools)
151151
install_cmd="sudo yum install -y -q"
152152
;;
153153
opensuse*|suse)
154-
pkgs=(gcc make nasm qemu-x86 qemu-ovmf-x86_64 parted dosfstools e2fsprogs util-linux rsync curl wget squashfs genisoimage)
154+
pkgs=(gcc make nasm qemu-x86 qemu-ovmf-x86_64 parted dosfstools e2fsprogs util-linux rsync curl wget squashfs genisoimage mtools)
155155
install_cmd="sudo zypper install -y"
156156
;;
157157
alpine)
158-
pkgs=(build-base nasm qemu-system-x86_64 ovmf parted dosfstools e2fsprogs util-linux rsync curl wget squashfs-tools cdrkit bash)
158+
pkgs=(build-base nasm qemu-system-x86_64 ovmf parted dosfstools e2fsprogs util-linux rsync curl wget squashfs-tools cdrkit bash mtools)
159159
install_cmd="sudo apk add"
160160
;;
161161
*)
@@ -374,6 +374,83 @@ do_create_disk() {
374374
log_success "Test disk ready (50GB sparse, will be formatted by inject)"
375375
}
376376

377+
populate_esp_image_with_mtools() {
378+
local src_dir="$1"
379+
local esp_img="$2"
380+
local -a entries=()
381+
382+
shopt -s dotglob nullglob
383+
entries=("${src_dir}"/*)
384+
shopt -u dotglob nullglob
385+
386+
[[ ${#entries[@]} -gt 0 ]] || return 0
387+
388+
mmd -i "$esp_img" ::/EFI >/dev/null 2>&1 || true
389+
mmd -i "$esp_img" ::/EFI/BOOT >/dev/null 2>&1 || true
390+
mcopy -i "$esp_img" -s "${entries[@]}" ::/ >/dev/null 2>&1
391+
}
392+
393+
populate_esp_image_with_loop_mount() {
394+
local src_dir="$1"
395+
local esp_img="$2"
396+
local mnt
397+
local loop_dev=""
398+
local attached=0
399+
local mounted=0
400+
401+
mnt=$(mktemp -d)
402+
403+
if has_cmd modprobe; then
404+
sudo modprobe loop >/dev/null 2>&1 || true
405+
fi
406+
407+
if ! loop_dev=$(sudo losetup --find --show "$esp_img" 2>/dev/null); then
408+
rmdir "$mnt"
409+
return 1
410+
fi
411+
attached=1
412+
413+
if ! sudo mount -t vfat "$loop_dev" "$mnt"; then
414+
sudo losetup -d "$loop_dev" >/dev/null 2>&1 || true
415+
rmdir "$mnt"
416+
return 1
417+
fi
418+
mounted=1
419+
420+
if ! sudo rsync -a "${src_dir}/" "$mnt/"; then
421+
(( mounted == 1 )) && sudo umount "$mnt" >/dev/null 2>&1 || true
422+
(( attached == 1 )) && sudo losetup -d "$loop_dev" >/dev/null 2>&1 || true
423+
rmdir "$mnt"
424+
return 1
425+
fi
426+
427+
sudo umount "$mnt"
428+
sudo losetup -d "$loop_dev"
429+
rmdir "$mnt"
430+
}
431+
432+
refresh_esp_image() {
433+
local esp_img="$1"
434+
local src_dir="$2"
435+
local esp_size
436+
437+
esp_size=$(du -sb "${src_dir}" | awk '{print int(($1 / 1024 / 1024) + 50)}')
438+
dd if=/dev/zero of="$esp_img" bs=1M count="$esp_size" status=none 2>/dev/null
439+
mkfs.vfat -F 32 -n ESP "$esp_img" >/dev/null 2>&1
440+
441+
if has_cmd mcopy && has_cmd mmd; then
442+
if populate_esp_image_with_mtools "$src_dir" "$esp_img"; then
443+
return 0
444+
fi
445+
log_warn "mtools copy failed; falling back to loop-mount copy"
446+
else
447+
log_info "mtools not found; using loop-mount copy for ESP image"
448+
fi
449+
450+
populate_esp_image_with_loop_mount "$src_dir" "$esp_img" \
451+
|| die "Failed to populate ESP image. Install mtools or ensure loop devices are available."
452+
}
453+
377454
do_launch_qemu() {
378455
log_step "Launching QEMU"
379456

@@ -394,16 +471,7 @@ do_launch_qemu() {
394471
local esp_img="${TESTING_DIR}/esp-temp.img"
395472
if [[ ! -f "$esp_img" ]] || [[ "${ESP_DIR}/EFI/BOOT/BOOTX64.EFI" -nt "$esp_img" ]] || [[ "${FORCE_MODE}" == "true" ]]; then
396473
log_info "Refreshing boot ESP image..."
397-
local esp_size
398-
esp_size=$(du -sb "${ESP_DIR}" | awk '{print int(($1 / 1024 / 1024) + 50)}')
399-
dd if=/dev/zero of="$esp_img" bs=1M count="$esp_size" status=none 2>/dev/null
400-
mkfs.vfat -F 32 -n ESP "$esp_img" >/dev/null 2>&1
401-
local mnt
402-
mnt=$(mktemp -d)
403-
sudo mount -o loop "$esp_img" "$mnt"
404-
sudo rsync -a "${ESP_DIR}/" "$mnt/" 2>/dev/null || true
405-
sudo umount "$mnt"
406-
rmdir "$mnt"
474+
refresh_esp_image "$esp_img" "$ESP_DIR"
407475
fi
408476
# Disk 0 (virtio): ESP FAT32 image — UEFI boots BOOTX64.EFI from here
409477
# Disk 1 (virtio): raw HelixFS image — kernel mounts this as data storage
@@ -431,14 +499,7 @@ do_launch_qemu() {
431499
local esp_img="${TESTING_DIR}/esp-temp.img"
432500
if [[ ! -f "$esp_img" ]] || [[ "${ESP_DIR}" -nt "$esp_img" ]]; then
433501
log_info "Creating ESP disk image..."
434-
local esp_size=$(du -sb "${ESP_DIR}" | awk '{print int(($1 / 1024 / 1024) + 50)}')
435-
dd if=/dev/zero of="$esp_img" bs=1M count=$esp_size status=none 2>/dev/null || true
436-
mkfs.vfat -F 32 -n ESP "$esp_img" >/dev/null 2>&1 || true
437-
local mnt=$(mktemp -d)
438-
sudo mount -o loop "$esp_img" "$mnt"
439-
sudo rsync -a "${ESP_DIR}/" "$mnt/" 2>/dev/null || true
440-
sudo umount "$mnt"
441-
rmdir "$mnt"
502+
refresh_esp_image "$esp_img" "$ESP_DIR"
442503
fi
443504
qemu-system-x86_64 \
444505
-enable-kvm \
@@ -662,14 +723,7 @@ do_launch_thinkpad() {
662723
local esp_img="${TESTING_DIR}/esp-temp.img"
663724
if [[ ! -f "$esp_img" ]] || [[ "${ESP_DIR}" -nt "$esp_img" ]]; then
664725
log_info "Creating ESP disk image..."
665-
local esp_size=$(du -sb "${ESP_DIR}" | awk '{print int(($1 / 1024 / 1024) + 50)}')
666-
dd if=/dev/zero of="$esp_img" bs=1M count=$esp_size status=none 2>/dev/null || true
667-
mkfs.vfat -F 32 -n ESP "$esp_img" >/dev/null 2>&1 || true
668-
local mnt=$(mktemp -d)
669-
sudo mount -o loop "$esp_img" "$mnt"
670-
sudo rsync -a "${ESP_DIR}/" "$mnt/" 2>/dev/null || true
671-
sudo umount "$mnt"
672-
rmdir "$mnt"
726+
refresh_esp_image "$esp_img" "$ESP_DIR"
673727
fi
674728
qemu-system-x86_64 \
675729
-enable-kvm \

0 commit comments

Comments
 (0)