@@ -0,0 +1,4 @@
|
|||||||
|
#
|
||||||
|
ISO_BASEDIR="/mnt/machines/iso"
|
||||||
|
#
|
||||||
|
DISK_BASEDIR="/mnt/machines/qemu-machines"
|
||||||
+1
-1
@@ -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
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user