system: validate UEFI installer ISO boot path
This commit is contained in:
@@ -100,6 +100,6 @@ Commit:
|
||||
|
||||
Per `docs/PLAN_4.md`, the next planned step is:
|
||||
|
||||
- **Phase 18.3** — produce a bootable UEFI installer ISO
|
||||
- **Phase 19.1** — define and document the canonical Fruix deployment workflow for rebuild, image generation, installation, and rollback
|
||||
|
||||
That should build on the now-validated installer environment rather than replacing it.
|
||||
Phase 18.3 is now complete: Fruix can build, boot, install from, and validate a bootable UEFI installer ISO on FreeBSD.
|
||||
|
||||
@@ -52,12 +52,16 @@ Instead it uses a small UEFI El Torito boot image plus an in-memory installer ro
|
||||
3. the ISO root also contains `/boot/root.img`
|
||||
4. `loader.conf` on the ISO is augmented with:
|
||||
- `mdroot_load="YES"`
|
||||
- `mdroot_type="md_image"`
|
||||
- `mdroot_type="mfs_root"`
|
||||
- `mdroot_name="/boot/root.img"`
|
||||
- `rootdev="ufs:/dev/md0"`
|
||||
- `vfs.root.mountfrom="ufs:/dev/md0"`
|
||||
- `vfs.root.mountfrom.options="rw"`
|
||||
|
||||
A practical loader detail surfaced during validation:
|
||||
|
||||
- setting `rootdev` or `currdev` to `md0:` in the ISO loader path is wrong for this loader configuration and caused an early EFI-loader crash before kernel handoff
|
||||
- the reliable ISO path is to let loader keep its current device on the CD media, preload `/boot/root.img`, and pass only `vfs.root.mountfrom=ufs:/dev/md0`
|
||||
|
||||
This preserves the existing Fruix installer environment semantics while avoiding the need to make the whole installer operate directly from a read-only ISO root.
|
||||
|
||||
### Installer root image contents
|
||||
@@ -66,7 +70,7 @@ This preserves the existing Fruix installer environment semantics while avoiding
|
||||
|
||||
- installer closure
|
||||
- target closure
|
||||
- target store closure
|
||||
- target runtime store closure needed for installation/boot
|
||||
- staged target rootfs under `/var/lib/fruix/installer/target-rootfs`
|
||||
- installer plan and state files under `/var/lib/fruix/installer`
|
||||
- installer helper scripts:
|
||||
@@ -86,7 +90,7 @@ While exercising the refactored split modules, two issues surfaced and were fixe
|
||||
- this constant was accidentally omitted when `modules/fruix/system/freebsd.scm` was split
|
||||
- the missing definition was restored in `modules/fruix/system/freebsd/build.scm`
|
||||
|
||||
## Current validation status
|
||||
## Validation
|
||||
|
||||
### Completed smoke validation
|
||||
|
||||
@@ -119,21 +123,83 @@ installer_closure_path=/tmp/...-fruix-system-fruix-freebsd-installer
|
||||
target_closure_path=/tmp/...-fruix-system-fruix-freebsd
|
||||
```
|
||||
|
||||
### Validation harness added
|
||||
### End-to-end harness validation
|
||||
|
||||
Added:
|
||||
|
||||
- `tests/system/run-phase18-installer-iso.sh`
|
||||
|
||||
This harness is intended to validate the full Phase 18.3 flow:
|
||||
This harness validates the full Phase 18.3 flow:
|
||||
|
||||
1. build installer ISO
|
||||
2. boot it under QEMU/UEFI/TCG
|
||||
3. install onto a second disk from inside the booted ISO environment
|
||||
3. install onto a target disk from inside the booted ISO environment
|
||||
4. boot the installed target
|
||||
|
||||
## Status
|
||||
Passing validation:
|
||||
|
||||
Phase 18.3 implementation is now in place, with successful build-smoke validation and a dedicated end-to-end harness added.
|
||||
- `PASS phase18-installer-iso`
|
||||
|
||||
The remaining step is full end-to-end boot/install validation of the ISO path under QEMU/UEFI/TCG and, if practical, the broader validated virtualization path.
|
||||
Validated result summary:
|
||||
|
||||
```text
|
||||
installer_iso_store_path=/frx/store/...-fruix-installer-iso-fruix-freebsd-installer
|
||||
installer_iso_image=/frx/store/...-fruix-installer-iso-fruix-freebsd-installer/installer.iso
|
||||
installer_boot_efi_image=/frx/store/...-fruix-installer-iso-fruix-freebsd-installer/efiboot.img
|
||||
installer_root_image=/frx/store/...-fruix-installer-iso-fruix-freebsd-installer/root.img
|
||||
install_target_device=/dev/vtbd0
|
||||
freebsd_source_kind=git
|
||||
freebsd_source_ref=stable/15
|
||||
freebsd_source_commit=332708a606f6bf0841c1d4a74c0d067f5640fe89
|
||||
materialized_source_store=/frx/store/459499e0eb29f4c73ad455060dd2502d21fb56f205c0a676831cf723b3a0c378-freebsd-source-stable15-installer-iso-target-source
|
||||
installer_state=done
|
||||
installer_sshd_status=running
|
||||
target_esp_fstype=msdosfs
|
||||
target_root_fstype=ufs
|
||||
target_shepherd_status=running
|
||||
target_sshd_status=running
|
||||
installer_iso_boot=ok
|
||||
installer_iso_install=ok
|
||||
installed_target_boot=ok
|
||||
```
|
||||
|
||||
Notable ISO-specific validation detail:
|
||||
|
||||
- unlike the disk-image-style installer environment from Phase 18.2, the ISO boots from `cd0`, so the target virtio disk appears as:
|
||||
- `/dev/vtbd0`
|
||||
- the earlier installer-environment default:
|
||||
- `/dev/vtbd1`
|
||||
remains correct for the disk-image installer, but not for the ISO path
|
||||
|
||||
The harness verified all of the following:
|
||||
|
||||
1. `fruix system installer-iso` produces a bootable ISO artifact in `/frx/store`
|
||||
2. the ISO boots successfully under QEMU/UEFI/TCG
|
||||
3. the booted installer ISO environment becomes reachable over SSH
|
||||
4. `/run/current-system` inside the installer ISO points at the installer closure
|
||||
5. the installer rc.d job reaches:
|
||||
- `state=done`
|
||||
6. the installer log records:
|
||||
- `fruix-installer:done`
|
||||
7. the installed target disk contains:
|
||||
- GPT partitioning
|
||||
- EFI filesystem: `msdosfs`
|
||||
- root filesystem: `ufs`
|
||||
- `EFI/BOOT/BOOTX64.EFI`
|
||||
- `/var/lib/fruix/install.scm`
|
||||
8. the installed target then boots successfully as its own Fruix system under QEMU/UEFI/TCG
|
||||
9. after target boot:
|
||||
- `/run/current-system` points at the target closure
|
||||
- shepherd is running
|
||||
- `sshd` is running
|
||||
- activation completed successfully
|
||||
|
||||
## Result
|
||||
|
||||
Phase 18.3 is complete.
|
||||
|
||||
Fruix now has a validated bootable UEFI installer ISO on FreeBSD that can:
|
||||
|
||||
- boot into a Fruix-managed installer environment from ISO media
|
||||
- perform the non-interactive installation flow onto a target disk
|
||||
- and boot the installed target successfully
|
||||
|
||||
@@ -464,7 +464,7 @@
|
||||
|
||||
(define* (operating-system-installer-iso-spec os
|
||||
#:key
|
||||
(install-target-device "/dev/vtbd1")
|
||||
(install-target-device "/dev/vtbd0")
|
||||
(installer-host-name (string-append (operating-system-host-name os)
|
||||
"-installer"))
|
||||
(root-size #f)
|
||||
@@ -494,7 +494,7 @@
|
||||
(define image-builder-version "2")
|
||||
(define install-builder-version "1")
|
||||
(define installer-image-builder-version "1")
|
||||
(define installer-iso-builder-version "1")
|
||||
(define installer-iso-builder-version "2")
|
||||
|
||||
(define (operating-system-install-metadata-object install-spec closure-path store-items)
|
||||
`((install-version . ,install-builder-version)
|
||||
@@ -1091,14 +1091,21 @@
|
||||
(substring sanitized 0 32)
|
||||
sanitized)))
|
||||
|
||||
(define (source-store-item? item)
|
||||
(string-contains (path-basename item) "-freebsd-source-"))
|
||||
|
||||
(define (runtime-store-items items)
|
||||
(filter (lambda (item)
|
||||
(not (source-store-item? item)))
|
||||
items))
|
||||
|
||||
(define (write-installer-iso-loader-conf source-path destination)
|
||||
(let* ((mode (stat:perms (stat source-path)))
|
||||
(base (call-with-input-file source-path get-string-all))
|
||||
(extra (string-append
|
||||
"mdroot_load=\"YES\"\n"
|
||||
"mdroot_type=\"md_image\"\n"
|
||||
"mdroot_type=\"mfs_root\"\n"
|
||||
"mdroot_name=\"/boot/root.img\"\n"
|
||||
"rootdev=\"ufs:/dev/md0\"\n"
|
||||
"vfs.root.mountfrom=\"ufs:/dev/md0\"\n"
|
||||
"vfs.root.mountfrom.options=\"rw\"\n")))
|
||||
(write-file destination
|
||||
@@ -1110,6 +1117,14 @@
|
||||
extra))
|
||||
(chmod destination mode)))
|
||||
|
||||
(define (rewrite-installer-iso-fstab image-rootfs installer-closure-path)
|
||||
(let ((fstab-path (string-append image-rootfs "/frx/store/"
|
||||
(path-basename installer-closure-path)
|
||||
"/etc/fstab")))
|
||||
(rewrite-text-file fstab-path
|
||||
'(("/dev/gpt/fruix-installer-root\t/\tufs"
|
||||
. "/dev/md0\t/\tufs")))))
|
||||
|
||||
(define* (make-ufs-image output-path source-root label #:key size)
|
||||
(apply run-command
|
||||
(append (list "makefs" "-t" "ffs" "-T" "0" "-B" "little")
|
||||
@@ -1167,7 +1182,7 @@
|
||||
(guile-prefix "/tmp/guile-freebsd-validate-install")
|
||||
(guile-extra-prefix "/tmp/guile-gnutls-freebsd-validate-install")
|
||||
(shepherd-prefix "/tmp/shepherd-freebsd-validate-install")
|
||||
(install-target-device "/dev/vtbd1")
|
||||
(install-target-device "/dev/vtbd0")
|
||||
(root-size #f)
|
||||
(installer-host-name (string-append (operating-system-host-name os)
|
||||
"-installer"))
|
||||
@@ -1191,9 +1206,11 @@
|
||||
#:shepherd-prefix shepherd-prefix))
|
||||
(target-closure-path (assoc-ref target-closure 'closure-path))
|
||||
(installer-closure-path (assoc-ref installer-closure 'closure-path))
|
||||
(target-store-items (store-reference-closure (list target-closure-path)))
|
||||
(installer-store-items (store-reference-closure (list installer-closure-path)))
|
||||
(combined-store-items (delete-duplicates (append installer-store-items target-store-items)))
|
||||
(target-closure-store-items (store-reference-closure (list target-closure-path)))
|
||||
(target-runtime-store-items (runtime-store-items target-closure-store-items))
|
||||
(installer-store-items (runtime-store-items
|
||||
(store-reference-closure (list installer-closure-path))))
|
||||
(combined-store-items (delete-duplicates (append installer-store-items target-runtime-store-items)))
|
||||
(sanitized-iso-volume-label (sanitize-iso-volume-label iso-volume-label))
|
||||
(installer-iso-spec (operating-system-installer-iso-spec os
|
||||
#:install-target-device install-target-device
|
||||
@@ -1207,7 +1224,7 @@
|
||||
(target-install-spec (assoc-ref installer-iso-spec 'target-install))
|
||||
(install-metadata (operating-system-install-metadata-object target-install-spec
|
||||
target-closure-path
|
||||
target-store-items))
|
||||
target-closure-store-items))
|
||||
(installer-plan-directory "/var/lib/fruix/installer")
|
||||
(installer-state-path (string-append installer-plan-directory "/state"))
|
||||
(installer-log-path "/var/log/fruix-installer.log")
|
||||
@@ -1223,7 +1240,7 @@
|
||||
"\ncombined-store-items=\n"
|
||||
(string-join combined-store-items "\n")
|
||||
"\ntarget-store-items=\n"
|
||||
(string-join target-store-items "\n")
|
||||
(string-join target-closure-store-items "\n")
|
||||
"\ninstall-metadata=\n"
|
||||
(object->string install-metadata)
|
||||
"\n"))
|
||||
@@ -1257,7 +1274,7 @@
|
||||
(copy-tree-contents target-rootfs (string-append plan-root "/target-rootfs"))
|
||||
(copy-store-items-into-rootfs image-rootfs store-dir combined-store-items)
|
||||
(write-file (string-append plan-root "/store-items")
|
||||
(string-append (string-join (map path-basename target-store-items) "\n") "\n"))
|
||||
(string-append (string-join (map path-basename target-runtime-store-items) "\n") "\n"))
|
||||
(write-file (string-append plan-root "/install.scm")
|
||||
(object->string install-metadata))
|
||||
(copy-regular-file (string-append target-closure-path "/boot/loader.efi")
|
||||
@@ -1276,6 +1293,7 @@
|
||||
(render-installer-rc-script installer-plan-directory))
|
||||
(chmod (string-append image-rootfs "/usr/local/libexec/fruix-installer-run") #o555)
|
||||
(chmod (string-append image-rootfs "/usr/local/etc/rc.d/fruix-installer") #o555)
|
||||
(rewrite-installer-iso-fstab image-rootfs installer-closure-path)
|
||||
(make-ufs-image temp-root image-rootfs installer-root-partition-label #:size root-size)
|
||||
(populate-installer-iso-boot-tree installer-closure-path iso-root temp-root)
|
||||
(make-efi-boot-image (resolved-path (string-append installer-closure-path "/boot/loader.efi")) temp-esp)
|
||||
@@ -1334,5 +1352,5 @@
|
||||
(host-base-provenance-file . ,(assoc-ref target-closure 'host-base-provenance-file))
|
||||
(store-layout-file . ,(assoc-ref target-closure 'store-layout-file))
|
||||
(store-items . ,combined-store-items)
|
||||
(target-store-items . ,target-store-items)
|
||||
(target-store-items . ,target-closure-store-items)
|
||||
(installer-store-items . ,installer-store-items))))
|
||||
|
||||
@@ -635,7 +635,7 @@ Common options:\n\
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:install-target-device (or install-target-device "/dev/vtbd1")
|
||||
#:install-target-device (or install-target-device "/dev/vtbd0")
|
||||
#:root-size root-size)))
|
||||
((string=? action "install")
|
||||
(unless target
|
||||
|
||||
@@ -9,7 +9,7 @@ system_name=${SYSTEM_NAME:-phase18-target-operating-system}
|
||||
store_dir=${STORE_DIR:-/frx/store}
|
||||
installer_root_size=${INSTALLER_ROOT_SIZE:-}
|
||||
target_disk_capacity=${TARGET_DISK_CAPACITY:-12g}
|
||||
install_target_device=${INSTALL_TARGET_DEVICE:-/dev/vtbd1}
|
||||
install_target_device=${INSTALL_TARGET_DEVICE:-/dev/vtbd0}
|
||||
qemu_smp=${QEMU_SMP:-2}
|
||||
installer_memory=${INSTALLER_MEMORY:-6144}
|
||||
installer_ssh_port=${INSTALLER_SSH_PORT:-10027}
|
||||
|
||||
Reference in New Issue
Block a user