diff --git a/builder.config.example b/builder.config.example new file mode 100644 index 0000000..6c61b7c --- /dev/null +++ b/builder.config.example @@ -0,0 +1,4 @@ +# +ISO_BASEDIR="/mnt/machines/iso" +# +DISK_BASEDIR="/mnt/machines/qemu-machines" diff --git a/isobuilder.sh b/isobuilder.sh index 87d6888..8f89c39 100644 --- a/isobuilder.sh +++ b/isobuilder.sh @@ -30,7 +30,7 @@ function detect_iso_arch { local iso_file="${1}" local fallback_arch="${2}" case "${iso_file@L}" in - *-amd64-*|*-x64-*) + *-amd64-*|*-x64-*|*_x64_*) echo "amd64" ;; *-arm64-*|*-aarch64-*) echo "arm64" ;; diff --git a/win11-builder-generic.sh b/win11-builder-generic.sh index c6f51a4..4d1b156 100755 --- a/win11-builder-generic.sh +++ b/win11-builder-generic.sh @@ -1,26 +1,30 @@ #!/usr/bin/env /bin/bash -declare -r TOP_BASEDIR="`pwd`" +declare -r TOP_BASEDIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)" + +# read global builder config +[[ -f "${TOP_BASEDIR}/builder.config" ]] && { + source "${TOP_BASEDIR}/builder.config" || exit $? +} # # ISO images # -declare -r ISO_BASEDIR="/mnt/machines/iso" - # Windows installation ISO #declare -r INSTALL_ISO="${ISO_BASEDIR}/Win11_25H2_English_x64_v2.iso" #declare -r INSTALL_ISO="${ISO_BASEDIR}/nano11-25H2-English-Pro-2026-03-20.iso" -declare -r INSTALL_ISO="${TOP_BASEDIR}/output/install-builder-amd64-20260601.iso" +declare -r INSTALL_ISO="${ISO_BASEDIR}/nano11-base-25H2-Pro-Eng-amd64-20260526.iso" +#declare -r INSTALL_ISO="${TOP_BASEDIR}/output/install-builder-amd64-20260601.iso" # Unattended installation add-on ISO #declare -r UNATTEND_ISO="${TOP_BASEDIR}/output/unattend.iso" +declare -r UNATTEND_CONFIG="${TOP_BASEDIR}/configs/autounattend-builder-amd64-20260604.xml" declare -r VIRTIO_ISO="${ISO_BASEDIR}/virtio-win-0.1.285.iso" # # Disk images # -declare -r DISK_BASEDIR="/mnt/machines/qemu-machines" -#declare -r DISK_IMG="${DISK_BASEDIR}/win11-builder-amd64.qcow2" +declare -r DISK_IMG="${DISK_BASEDIR}/win11-builder-amd64.qcow2" declare -r DISK_SIZE="32G" # @@ -67,11 +71,21 @@ declare -r ARM64_EFI_CODE_SIZE="64M" declare -r COMMAND="${1:-build}" shift +function has { + local val="${1}" + shift + + for x in $@; do + [[ "${x}" == "${val}" ]] && return 0 + done + return 1 +} + function detect_iso_arch { local iso_file="${1}" local fallback_arch="${2}" case "${iso_file@L}" in - *-amd64-*|*-x64-*) + *-amd64-*|*-x64-*|*_x64_*) echo "amd64" ;; *-arm64-*|*-aarch64-*) echo "arm64" ;; @@ -92,14 +106,14 @@ function detect_host_arch { # Detect host and guest architecture declare -r HOST_ARCH="$(detect_host_arch)" [[ -n "${HOST_ARCH}" ]] || { - echo "Failed to detect host arch" >&2; - exit 1; + echo "Failed to detect host arch" >&2 + exit 1 } declare -r GUEST_ARCH="$(detect_iso_arch "${INSTALL_ISO}" "${HOST_ARCH}")" [[ -n "${GUEST_ARCH}" ]] || { - echo "Failed to detect guest arch" >&2; - exit 1; + echo "Failed to detect guest arch" >&2 + exit 1 } # Setup locations @@ -201,7 +215,6 @@ function fileext_from_qemu_image_type { esac } - function expand_size { local value="${1}" [[ "${value}" =~ ^[0-9]+$ ]] && { @@ -256,7 +269,6 @@ function resize_image { do_resize_image "${img_file}" "${img_type}" "${img_cur_size}" "${img_req_size}" } - # Drivers for the WinPE early installation environment declare -r VIRTIO_WINPE_DRIVERS=( "NetKVM" @@ -265,12 +277,15 @@ declare -r VIRTIO_WINPE_DRIVERS=( "viogpudo" ) -function has { - local val="${1}"; shift - for x in $@; do - [[ "${x}" == "${val}" ]] && return 0 - done - return 1 +function guest_to_virtio_arch { + local arch="${1@L}" + case "${arch}" in + "arm64") echo "${arch@U}" ;; + "amd64") echo "${arch}" ;; + *) + echo "ERROR: Failed to determine virtio arch from '${arch}'" >&2 + return 1 ;; + esac } # @@ -294,16 +309,11 @@ function qemu_fill_unattend_fs { < "${unattend_xml}" > "${destdir}/autounattend.xml" || return $? # - local virtio_arch="${GUEST_ARCH@L}" - case "${GUEST_ARCH@L}" in - "arm64") - virtio_arch="${GUEST_ARCH@U}" ;; - "amd64") - virtio_arch="${GUEST_ARCH@L}" ;; - *) - echo "ERROR: " >&2 - return 1 ;; - esac + # Additional resources + # $OEM$\$$ -> C:\Windows + # $OEM$\$1 -> C:\ + # + mkdir -p "${destdir}/\$OEM\$/\$\$" "${destdir}/\$OEM\$/\$1" || return $? # Copy virtio drivers local virtio_iso="${3}" @@ -312,6 +322,7 @@ function qemu_fill_unattend_fs { return 1 } + local virtio_arch="$(guest_to_virtio_arch "${GUEST_ARCH}")" || return $? local virtio_drivers_list="$(7z l -slt "${virtio_iso}" | sed -ne "/^Path = [^/]\+\/w11\/${virtio_arch}\$/{ s|^Path = \([^/]\+\)/.*|\1|; p }")" [[ -n "${virtio_drivers_list}" ]] || { echo "ERROR: No drivers found in VirtIO ISO image '${virtio_iso}'" >&2 @@ -339,31 +350,36 @@ function qemu_fill_unattend_fs { function qemu_generate_unattend_iso { local destfile="${1}" - local destdir="${BASEDIR}/unattend.tmp" + local isogen_path="" + for x in "mkisofs" "genisoimage" "xorriso"; do + isogen_path="$(type -p "${x}" 2>/dev/null)" && break + done + [[ -n "${isogen_path}" ]] || { + echo "ERROR: Failed to find one of mkisofs | genisoimage | xorriso" >&2 + return 1 + } + + local destdir="${BASEDIR}/unattend.${SRANDOM:-"tmp"}" mkdir -p "${destdir}" || return $? qemu_fill_unattend_fs "${destdir}" "${2}" "${3}" || return $? - if type -p "mkisofs" &>/dev/null; then - mkisofs \ - -iso-level 3 -J -l -D -N -U -joliet-long -relaxed-filenames -rational-rock \ - -V "win11-builder-unattend" -o "${destfile}" -quiet \ - "${destdir}" || return $? - elif type -p "genisoimage" &>/dev/null; then - genisoimage \ - -iso-level 3 -J -l -D -N -U -joliet-long -allow-limited-size -relaxed-filenames -rock \ - -V "win11-builder-unattend" -o "${destfile}" -quiet \ - "${destdir}" || return $? - elif type -p "xorriso" &>/dev/null; then - echo "ERROR: xorriso support is pending" >&2 - return 1 - else - echo "ERROR: Failed to find one of mkisofs | genisofs | xorriso" >&2 - return 1 - fi + local isogen_name="$(basename "${isogen_path}")" + case "${isogen_name}" in + "mkisofs") + ${isogen_path} -iso-level 3 -J -l -D -N -U -joliet-long -relaxed-filenames -rational-rock \ + -V "win11-builder-unattend" -o "${destfile}" -quiet "${destdir}" || return $? ;; + "genisoimage") + ${isogen_path} -iso-level 3 -J -l -D -N -U -joliet-long -relaxed-filenames -rock -allow-limited-size \ + -V "win11-builder-unattend" -o "${destfile}" -quiet "${destdir}" || return $? ;; + "xorriso") + echo "ERROR: ${isogen_name} support is pending" >&2 + return 1 ;; + esac # cleanup - find "${destdir}" -delete || return $? + find "${destdir}" -delete 2>/dev/null + return 0 } function qemu_prepare_disk {