Signed-off-by: Stefan Knoblich <stkn@bitplumber.de>
This commit is contained in:
2026-08-06 13:20:22 +02:00
parent b09d3b16e2
commit 6d1873e635
3 changed files with 69 additions and 49 deletions
+4
View File
@@ -0,0 +1,4 @@
#
ISO_BASEDIR="/mnt/machines/iso"
#
DISK_BASEDIR="/mnt/machines/qemu-machines"
+1 -1
View File
@@ -30,7 +30,7 @@ function detect_iso_arch {
local iso_file="${1}" local iso_file="${1}"
local fallback_arch="${2}" local fallback_arch="${2}"
case "${iso_file@L}" in case "${iso_file@L}" in
*-amd64-*|*-x64-*) *-amd64-*|*-x64-*|*_x64_*)
echo "amd64" ;; echo "amd64" ;;
*-arm64-*|*-aarch64-*) *-arm64-*|*-aarch64-*)
echo "arm64" ;; echo "arm64" ;;
+64 -48
View File
@@ -1,26 +1,30 @@
#!/usr/bin/env /bin/bash #!/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 # ISO images
# #
declare -r ISO_BASEDIR="/mnt/machines/iso"
# Windows installation ISO # Windows installation ISO
#declare -r INSTALL_ISO="${ISO_BASEDIR}/Win11_25H2_English_x64_v2.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="${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 # Unattended installation add-on ISO
#declare -r UNATTEND_ISO="${TOP_BASEDIR}/output/unattend.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" declare -r VIRTIO_ISO="${ISO_BASEDIR}/virtio-win-0.1.285.iso"
# #
# Disk images # 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" declare -r DISK_SIZE="32G"
# #
@@ -67,11 +71,21 @@ declare -r ARM64_EFI_CODE_SIZE="64M"
declare -r COMMAND="${1:-build}" declare -r COMMAND="${1:-build}"
shift shift
function has {
local val="${1}"
shift
for x in $@; do
[[ "${x}" == "${val}" ]] && return 0
done
return 1
}
function detect_iso_arch { function detect_iso_arch {
local iso_file="${1}" local iso_file="${1}"
local fallback_arch="${2}" local fallback_arch="${2}"
case "${iso_file@L}" in case "${iso_file@L}" in
*-amd64-*|*-x64-*) *-amd64-*|*-x64-*|*_x64_*)
echo "amd64" ;; echo "amd64" ;;
*-arm64-*|*-aarch64-*) *-arm64-*|*-aarch64-*)
echo "arm64" ;; echo "arm64" ;;
@@ -92,14 +106,14 @@ function detect_host_arch {
# Detect host and guest architecture # Detect host and guest architecture
declare -r HOST_ARCH="$(detect_host_arch)" declare -r HOST_ARCH="$(detect_host_arch)"
[[ -n "${HOST_ARCH}" ]] || { [[ -n "${HOST_ARCH}" ]] || {
echo "Failed to detect host arch" >&2; echo "Failed to detect host arch" >&2
exit 1; exit 1
} }
declare -r GUEST_ARCH="$(detect_iso_arch "${INSTALL_ISO}" "${HOST_ARCH}")" declare -r GUEST_ARCH="$(detect_iso_arch "${INSTALL_ISO}" "${HOST_ARCH}")"
[[ -n "${GUEST_ARCH}" ]] || { [[ -n "${GUEST_ARCH}" ]] || {
echo "Failed to detect guest arch" >&2; echo "Failed to detect guest arch" >&2
exit 1; exit 1
} }
# Setup locations # Setup locations
@@ -201,7 +215,6 @@ function fileext_from_qemu_image_type {
esac esac
} }
function expand_size { function expand_size {
local value="${1}" local value="${1}"
[[ "${value}" =~ ^[0-9]+$ ]] && { [[ "${value}" =~ ^[0-9]+$ ]] && {
@@ -256,7 +269,6 @@ function resize_image {
do_resize_image "${img_file}" "${img_type}" "${img_cur_size}" "${img_req_size}" do_resize_image "${img_file}" "${img_type}" "${img_cur_size}" "${img_req_size}"
} }
# Drivers for the WinPE early installation environment # Drivers for the WinPE early installation environment
declare -r VIRTIO_WINPE_DRIVERS=( declare -r VIRTIO_WINPE_DRIVERS=(
"NetKVM" "NetKVM"
@@ -265,12 +277,15 @@ declare -r VIRTIO_WINPE_DRIVERS=(
"viogpudo" "viogpudo"
) )
function has { function guest_to_virtio_arch {
local val="${1}"; shift local arch="${1@L}"
for x in $@; do case "${arch}" in
[[ "${x}" == "${val}" ]] && return 0 "arm64") echo "${arch@U}" ;;
done "amd64") echo "${arch}" ;;
return 1 *)
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 $? < "${unattend_xml}" > "${destdir}/autounattend.xml" || return $?
# #
local virtio_arch="${GUEST_ARCH@L}" # Additional resources
case "${GUEST_ARCH@L}" in # $OEM$\$$ -> C:\Windows
"arm64") # $OEM$\$1 -> C:\
virtio_arch="${GUEST_ARCH@U}" ;; #
"amd64") mkdir -p "${destdir}/\$OEM\$/\$\$" "${destdir}/\$OEM\$/\$1" || return $?
virtio_arch="${GUEST_ARCH@L}" ;;
*)
echo "ERROR: " >&2
return 1 ;;
esac
# Copy virtio drivers # Copy virtio drivers
local virtio_iso="${3}" local virtio_iso="${3}"
@@ -312,6 +322,7 @@ function qemu_fill_unattend_fs {
return 1 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 }")" local virtio_drivers_list="$(7z l -slt "${virtio_iso}" | sed -ne "/^Path = [^/]\+\/w11\/${virtio_arch}\$/{ s|^Path = \([^/]\+\)/.*|\1|; p }")"
[[ -n "${virtio_drivers_list}" ]] || { [[ -n "${virtio_drivers_list}" ]] || {
echo "ERROR: No drivers found in VirtIO ISO image '${virtio_iso}'" >&2 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 { function qemu_generate_unattend_iso {
local destfile="${1}" 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 $? mkdir -p "${destdir}" || return $?
qemu_fill_unattend_fs "${destdir}" "${2}" "${3}" || return $? qemu_fill_unattend_fs "${destdir}" "${2}" "${3}" || return $?
if type -p "mkisofs" &>/dev/null; then local isogen_name="$(basename "${isogen_path}")"
mkisofs \ case "${isogen_name}" in
-iso-level 3 -J -l -D -N -U -joliet-long -relaxed-filenames -rational-rock \ "mkisofs")
-V "win11-builder-unattend" -o "${destfile}" -quiet \ ${isogen_path} -iso-level 3 -J -l -D -N -U -joliet-long -relaxed-filenames -rational-rock \
"${destdir}" || return $? -V "win11-builder-unattend" -o "${destfile}" -quiet "${destdir}" || return $? ;;
elif type -p "genisoimage" &>/dev/null; then "genisoimage")
genisoimage \ ${isogen_path} -iso-level 3 -J -l -D -N -U -joliet-long -relaxed-filenames -rock -allow-limited-size \
-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 $? ;;
-V "win11-builder-unattend" -o "${destfile}" -quiet \ "xorriso")
"${destdir}" || return $? echo "ERROR: ${isogen_name} support is pending" >&2
elif type -p "xorriso" &>/dev/null; then return 1 ;;
echo "ERROR: xorriso support is pending" >&2 esac
return 1
else
echo "ERROR: Failed to find one of mkisofs | genisofs | xorriso" >&2
return 1
fi
# cleanup # cleanup
find "${destdir}" -delete || return $? find "${destdir}" -delete 2>/dev/null
return 0
} }
function qemu_prepare_disk { function qemu_prepare_disk {