#!/bin/sh set -eu repo_root=$(CDPATH= cd -- "$(dirname "$0")/../.." && pwd) metadata_target=${METADATA_OUT:-} cleanup=0 if [ -n "${WORKDIR:-}" ]; then workdir=$WORKDIR mkdir -p "$workdir" else workdir=$(mktemp -d /tmp/fruix-phase8-bhyve-image.XXXXXX) cleanup=1 fi if [ "${KEEP_WORKDIR:-0}" -eq 1 ]; then cleanup=0 fi phase7_rootfs_dir=$workdir/phase7-rootfs phase7_rootfs_log=$workdir/phase7-rootfs.log phase7_rootfs_metadata=$workdir/phase7-rootfs-metadata.txt image_rootfs=$workdir/image-rootfs queue_file=$workdir/store-queue.txt esp_stage=$workdir/esp-stage esp_image_a=$workdir/esp-a.img esp_image_b=$workdir/esp-b.img root_image_a=$workdir/root-a.ufs root_image_b=$workdir/root-b.ufs disk_image_a=$workdir/fruix-bhyve-a.img disk_image_b=$workdir/fruix-bhyve-b.img root_makefs_a_log=$workdir/root-makefs-a.log root_makefs_b_log=$workdir/root-makefs-b.log esp_makefs_a_log=$workdir/esp-makefs-a.log esp_makefs_b_log=$workdir/esp-makefs-b.log mkimg_a_log=$workdir/mkimg-a.log mkimg_b_log=$workdir/mkimg-b.log gpart_log=$workdir/gpart-show.txt metadata_file=$workdir/phase8-bhyve-image-metadata.txt mnt_esp=$workdir/mnt-esp mnt_root=$workdir/mnt-root md_unit= cleanup_workdir() { if [ -n "$md_unit" ]; then sudo umount "$mnt_esp" >/dev/null 2>&1 || true sudo umount "$mnt_root" >/dev/null 2>&1 || true sudo mdconfig -d -u "$md_unit" >/dev/null 2>&1 || true fi if [ "$cleanup" -eq 1 ]; then rm -rf "$workdir" 2>/dev/null || sudo rm -rf "$workdir" fi } trap cleanup_workdir EXIT INT TERM copy_store_closure() { closure_path=$1 stage_root=$2 : > "$queue_file" printf '%s\n' "$closure_path" > "$queue_file" while IFS= read -r item || [ -n "$item" ]; do [ -n "$item" ] || continue staged_item=$stage_root/frx/store/$(basename "$item") if [ ! -e "$staged_item" ]; then sudo cp -a "$item" "$staged_item" if [ -f "$item/.references" ]; then while IFS= read -r ref || [ -n "$ref" ]; do [ -n "$ref" ] || continue if [ ! -e "$stage_root/frx/store/$(basename "$ref")" ]; then printf '%s\n' "$ref" >> "$queue_file" fi done < "$item/.references" fi fi done < "$queue_file" } KEEP_WORKDIR=1 WORKDIR=$phase7_rootfs_dir METADATA_OUT=$phase7_rootfs_metadata \ "$repo_root/tests/system/run-phase7-rootfs.sh" >"$phase7_rootfs_log" 2>&1 rootfs=$phase7_rootfs_dir/rootfs closure_path=$(readlink "$rootfs/run/current-system") closure_base=$(basename "$closure_path") sudo rm -rf "$image_rootfs" sudo cp -a "$rootfs" "$image_rootfs" sudo mkdir -p "$image_rootfs/frx/store" copy_store_closure "$closure_path" "$image_rootfs" rm -rf "$esp_stage" mkdir -p "$esp_stage/EFI/BOOT" sudo cp -f "$closure_path/boot/loader.efi" "$esp_stage/EFI/BOOT/BOOTX64.EFI" sudo makefs -t ffs -T 0 -B little -s 256m \ -o label=fruix-root,version=2,bsize=32768,fsize=4096,density=16384 \ "$root_image_a" "$image_rootfs" >"$root_makefs_a_log" 2>&1 sudo makefs -t ffs -T 0 -B little -s 256m \ -o label=fruix-root,version=2,bsize=32768,fsize=4096,density=16384 \ "$root_image_b" "$image_rootfs" >"$root_makefs_b_log" 2>&1 makefs -t msdos -T 0 \ -o fat_type=32 \ -o sectors_per_cluster=1 \ -o volume_label=EFISYS \ -o volume_id=305419896 \ -s 64m "$esp_image_a" "$esp_stage" >"$esp_makefs_a_log" 2>&1 makefs -t msdos -T 0 \ -o fat_type=32 \ -o sectors_per_cluster=1 \ -o volume_label=EFISYS \ -o volume_id=305419896 \ -s 64m "$esp_image_b" "$esp_stage" >"$esp_makefs_b_log" 2>&1 mkimg -s gpt -f raw -t 0 \ -p efi/efiboot:="$esp_image_a" \ -p freebsd-ufs/fruix-root:="$root_image_a" \ -o "$disk_image_a" >"$mkimg_a_log" 2>&1 mkimg -s gpt -f raw -t 0 \ -p efi/efiboot:="$esp_image_b" \ -p freebsd-ufs/fruix-root:="$root_image_b" \ -o "$disk_image_b" >"$mkimg_b_log" 2>&1 raw_sha256_a=$(sha256 -q "$disk_image_a") raw_sha256_b=$(sha256 -q "$disk_image_b") [ "$raw_sha256_a" = "$raw_sha256_b" ] || { echo "raw image reproducibility check failed" >&2 exit 1 } md=$(sudo mdconfig -a -t vnode -f "$disk_image_a") md_unit=${md#md} sudo mkdir -p "$mnt_esp" "$mnt_root" sudo gpart show -lp "/dev/$md" >"$gpart_log" esp_fstype=$(sudo fstyp "/dev/${md}p1") root_fstype=$(sudo fstyp "/dev/${md}p2") [ "$esp_fstype" = msdosfs ] || { echo "unexpected ESP filesystem: $esp_fstype" >&2; exit 1; } [ "$root_fstype" = ufs ] || { echo "unexpected root filesystem: $root_fstype" >&2; exit 1; } sudo mount -t msdosfs "/dev/${md}p1" "$mnt_esp" sudo mount -t ufs -o ro "/dev/${md}p2" "$mnt_root" [ -f "$mnt_esp/EFI/BOOT/BOOTX64.EFI" ] || { echo "missing EFI bootloader in mounted ESP" >&2 exit 1 } run_current_system_target=$(readlink "$mnt_root/run/current-system") activate_target=$(readlink "$mnt_root/activate") bin_target=$(readlink "$mnt_root/bin") boot_loader_target=$(readlink "$mnt_root/boot/loader") boot_loader_conf_target=$(readlink "$mnt_root/boot/loader.conf") rc_conf_target=$(readlink "$mnt_root/etc/rc.conf") rc_script_target=$(readlink "$mnt_root/usr/local/etc/rc.d/fruix-shepherd") [ "$run_current_system_target" = "/frx/store/$closure_base" ] || { echo "unexpected /run/current-system target: $run_current_system_target" >&2 exit 1 } [ "$activate_target" = /run/current-system/activate ] || { echo "unexpected /activate target: $activate_target" >&2 exit 1 } [ "$bin_target" = /run/current-system/profile/bin ] || { echo "unexpected /bin target: $bin_target" >&2 exit 1 } [ "$boot_loader_target" = /run/current-system/boot/loader ] || { echo "unexpected /boot/loader target: $boot_loader_target" >&2 exit 1 } [ "$boot_loader_conf_target" = /run/current-system/boot/loader.conf ] || { echo "unexpected /boot/loader.conf target: $boot_loader_conf_target" >&2 exit 1 } [ "$rc_conf_target" = /run/current-system/etc/rc.conf ] || { echo "unexpected /etc/rc.conf target: $rc_conf_target" >&2 exit 1 } [ "$rc_script_target" = /run/current-system/usr/local/etc/rc.d/fruix-shepherd ] || { echo "unexpected fruix_shepherd rc script target: $rc_script_target" >&2 exit 1 } [ -d "$mnt_root/frx/store/$closure_base" ] || { echo "closure missing from image store population" >&2 exit 1 } loader_conf_image=$mnt_root/frx/store/$closure_base/boot/loader.conf rc_conf_image=$mnt_root/frx/store/$closure_base/etc/rc.conf rc_script_image=$mnt_root/frx/store/$closure_base/usr/local/etc/rc.d/fruix-shepherd shepherd_config_image=$mnt_root/frx/store/$closure_base/shepherd/init.scm activate_image=$mnt_root/frx/store/$closure_base/activate for required in "$loader_conf_image" "$rc_conf_image" "$rc_script_image" "$shepherd_config_image" "$activate_image"; do [ -f "$required" ] || { echo "required image content missing: $required" >&2 exit 1 } done grep -F 'console="comconsole"' "$loader_conf_image" >/dev/null || { echo "loader.conf is missing the serial console setting" >&2 exit 1 } grep -F 'hostname="fruix-freebsd"' "$rc_conf_image" >/dev/null || { echo "rc.conf is missing the expected hostname" >&2 exit 1 } grep -F 'fruix_shepherd_enable="YES"' "$rc_conf_image" >/dev/null || { echo "rc.conf does not enable fruix_shepherd" >&2 exit 1 } grep -F '/var/lib/fruix/ready' "$shepherd_config_image" >/dev/null || { echo "shepherd configuration does not contain the ready marker" >&2 exit 1 } store_item_count=$(find "$mnt_root/frx/store" -mindepth 1 -maxdepth 1 | wc -l | awk '{print $1}') image_size_bytes=$(stat -f %z "$disk_image_a") cat >"$metadata_file" <