feat: Added editions and mirrors (#95)

This commit is contained in:
Kroese 2024-04-30 23:33:00 +02:00 committed by GitHub
parent 5768ae5c2a
commit 9d2f095054
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 431 additions and 172 deletions

View file

@ -1,5 +1,5 @@
FROM scratch FROM scratch
COPY --from=qemux/qemu-arm:1.15 / / COPY --from=qemux/qemu-arm:1.16 / /
ARG DEBCONF_NOWARNINGS "yes" ARG DEBCONF_NOWARNINGS "yes"
ARG DEBIAN_FRONTEND "noninteractive" ARG DEBIAN_FRONTEND "noninteractive"

View file

@ -80,10 +80,10 @@ docker run -it --rm --name windows -p 8006:8006 --device=/dev/kvm --cap-add NET_
Select from the values below: Select from the values below:
| **Value** | **Description** | **Platform** | **Source** | **Size** | | **Value** | **Version** | **Platform** | **Size** |
|---|---|---|---|---| |---|---|---|---|
| `win11` | Windows 11 Pro | ARM64 | Microsoft | 4.6 GB | | `win11` | Windows 11 Pro | ARM64 | 4.6 GB |
| `win10` | Windows 10 Pro | ARM64 | Microsoft | 3.9 GB | | `win10` | Windows 10 Pro | ARM64 | 3.9 GB |
To install x86 or x64 versions of Windows use [dockur/windows](https://github.com/dockur/windows/). To install x86 or x64 versions of Windows use [dockur/windows](https://github.com/dockur/windows/).

147
src/define.sh Normal file
View file

@ -0,0 +1,147 @@
#!/usr/bin/env bash
set -Eeuo pipefail
: "${MANUAL:=""}"
: "${VERSION:=""}"
: "${DETECTED:=""}"
: "${PLATFORM:="ARM64"}"
parseVersion() {
[ -z "$VERSION" ] && VERSION="win11"
if [[ "${VERSION}" == \"*\" || "${VERSION}" == \'*\' ]]; then
VERSION="${VERSION:1:-1}"
fi
case "${VERSION,,}" in
"11" | "win11" | "windows11" | "windows 11")
VERSION="win11${PLATFORM,,}"
;;
"10" | "win10" | "windows10" | "windows 10")
VERSION="win10${PLATFORM,,}"
;;
esac
return 0
}
printVersion() {
local id="$1"
local desc="$2"
[[ "$id" == "win10"* ]] && desc="Windows 10"
[[ "$id" == "win11"* ]] && desc="Windows 11"
[ -z "$desc" ] && desc="Windows"
echo "$desc for ${PLATFORM}"
return 0
}
getName() {
local file="$1"
local desc="$2"
[[ "${file,,}" == "win11"* ]] && desc="Windows 11"
[[ "${file,,}" == "win10"* ]] && desc="Windows 10"
[[ "${file,,}" == *"windows11"* ]] && desc="Windows 11"
[[ "${file,,}" == *"windows10"* ]] && desc="Windows 10"
[[ "${file,,}" == *"windows_11"* ]] && desc="Windows 11"
[[ "${file,,}" == *"windows_10"* ]] && desc="Windows 10"
[[ "${file,,}" == *"windows 11"* ]] && desc="Windows 11"
[[ "${file,,}" == *"windows 10"* ]] && desc="Windows 10"
[ -z "$desc" ] && desc="Windows"
echo "$desc for ${PLATFORM}"
return 0
}
getVersion() {
local name="$1"
local detected=""
[[ "${name,,}" == *"windows 11"* ]] && detected="win11${PLATFORM,,}"
[[ "${name,,}" == *"windows 10"* ]] && detected="win10${PLATFORM,,}"
echo "$detected"
return 0
}
isESD() {
local id="$1"
case "${id,,}" in
"win11${PLATFORM,,}")
return 0
;;
"win10${PLATFORM,,}")
return 0
;;
esac
return 1
}
getLink() {
# Fallbacks for users who cannot connect to the Microsoft servers
local id="$1"
local url=""
local host="https://dl.bobpony.com"
case "${id,,}" in
"win11${PLATFORM,,}")
url="$host/windows/11/en-us_windows_11_23h2_${PLATFORM,,}.iso"
;;
"win10${PLATFORM,,}")
url="$host/windows/10/en-us_windows_10_22h2_${PLATFORM,,}.iso"
;;
esac
echo "$url"
return 0
}
secondLink() {
# Fallbacks for users who cannot connect to the Microsoft servers
local id="$1"
local url=""
local host="https://drive.massgrave.dev"
case "${id,,}" in
"win11${PLATFORM,,}")
url="$host/SW_DVD9_Win_Pro_11_23H2.2_Arm64_English_Pro_Ent_EDU_N_MLF_X23-68023.ISO"
;;
"win10${PLATFORM,,}")
url="$host/SW_DVD9_Win_Pro_10_22H2.15_Arm64_English_Pro_Ent_EDU_N_MLF_X23-67223.ISO"
;;
esac
echo "$url"
return 0
}
validVersion() {
local id="$1"
local url
isESD "$id" && return 0
url=$(getLink "$id")
[ -n "$url" ] && return 0
url=$(secondLink "$id")
[ -n "$url" ] && return 0
return 1
}

View file

@ -9,6 +9,7 @@ SUPPORT="https://github.com/dockur/windows-arm"
cd /run cd /run
. reset.sh # Initialize system . reset.sh # Initialize system
. define.sh # Define versions
. install.sh # Run installation . install.sh # Run installation
. disk.sh # Initialize disks . disk.sh # Initialize disks
. display.sh # Initialize graphics . display.sh # Initialize graphics
@ -28,8 +29,8 @@ info "Booting ${APP}${BOOT_DESC}..."
(( rc != 0 )) && error "$(<"$QEMU_LOG")" && exit 15 (( rc != 0 )) && error "$(<"$QEMU_LOG")" && exit 15
terminal terminal
( sleep 10; boot ) &
tail -fn +0 "$QEMU_LOG" 2>/dev/null & tail -fn +0 "$QEMU_LOG" 2>/dev/null &
( sleep 10; [ ! -f "$QEMU_END" ] && info "Windows started succesfully, visit http://localhost:8006/ to view the screen..." ) &
cat "$QEMU_TERM" 2> /dev/null | tee "$QEMU_PTY" & cat "$QEMU_TERM" 2> /dev/null | tee "$QEMU_PTY" &
wait $! || : wait $! || :

View file

@ -1,85 +1,13 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -Eeuo pipefail set -Eeuo pipefail
: "${MANUAL:=""}"
: "${VERSION:=""}"
: "${DETECTED:=""}"
[ -z "$VERSION" ] && VERSION="win11arm64"
if [[ "${VERSION}" == \"*\" || "${VERSION}" == \'*\' ]]; then
VERSION="${VERSION:1:-1}"
fi
[[ "${VERSION,,}" == "11" ]] && VERSION="win11arm64"
[[ "${VERSION,,}" == "win11" ]] && VERSION="win11arm64"
[[ "${VERSION,,}" == "10" ]] && VERSION="win10arm64"
[[ "${VERSION,,}" == "win10" ]] && VERSION="win10arm64"
CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname windows.iso -printf "%f\n" | head -n 1)
[ -z "$CUSTOM" ] && CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.iso -printf "%f\n" | head -n 1)
[ -z "$CUSTOM" ] && CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname boot.iso -printf "%f\n" | head -n 1)
[ -z "$CUSTOM" ] && CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.img -printf "%f\n" | head -n 1)
if [ -z "$CUSTOM" ] && [[ "${VERSION,,}" != "http"* ]]; then
FN="${VERSION/\/storage\//}"
[[ "$FN" == "."* ]] && FN="${FN:1}"
CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname "$FN" -printf "%f\n" | head -n 1)
fi
ESD_URL="" ESD_URL=""
PLATFORM="ARM64"
TMP="$STORAGE/tmp" TMP="$STORAGE/tmp"
DIR="$TMP/unpack" DIR="$TMP/unpack"
FB="falling back to manual installation!" FB="falling back to manual installation!"
ETFS="boot/etfsboot.com" ETFS="boot/etfsboot.com"
EFISYS="efi/microsoft/boot/efisys_noprompt.bin" EFISYS="efi/microsoft/boot/efisys_noprompt.bin"
printVersion() {
local id="$1"
local desc="$2"
[[ "$id" == "win10"* ]] && desc="Windows 10 for ARM"
[[ "$id" == "win11"* ]] && desc="Windows 11 for ARM"
[ -z "$desc" ] && desc="Windows for ARM"
echo "$desc"
return 0
}
getName() {
local file="$1"
local desc="$2"
[[ "${file,,}" == "win11"* ]] && desc="Windows 11 for ARM"
[[ "${file,,}" == "win10"* ]] && desc="Windows 10 for ARM"
[[ "${file,,}" == *"windows11"* ]] && desc="Windows 11 for ARM"
[[ "${file,,}" == *"windows10"* ]] && desc="Windows 10 for ARM"
[[ "${file,,}" == *"windows_11"* ]] && desc="Windows 11 for ARM"
[[ "${file,,}" == *"windows_10"* ]] && desc="Windows 10 for ARM"
[ -z "$desc" ] && desc="Windows for ARM"
echo "$desc"
return 0
}
getVersion() {
local name="$1"
local detected=""
[[ "${name,,}" == *"windows 11"* ]] && detected="win11arm64"
[[ "${name,,}" == *"windows 10"* ]] && detected="win10arm64"
echo "$detected"
return 0
}
hasDisk() { hasDisk() {
[ -b "${DEVICE:-}" ] && return 0 [ -b "${DEVICE:-}" ] && return 0
@ -106,19 +34,39 @@ finishInstall() {
local aborted="$2" local aborted="$2"
if [ ! -s "$iso" ] || [ ! -f "$iso" ]; then if [ ! -s "$iso" ] || [ ! -f "$iso" ]; then
error "Failed to find ISO: $iso" && return 1 error "Failed to find ISO file: $iso" && return 1
fi fi
if [ -w "$iso" ] && [[ "$aborted" != [Yy1]* ]]; then if [ -w "$iso" ] && [[ "$aborted" != [Yy1]* ]]; then
# Mark ISO as prepared via magic byte # Mark ISO as prepared via magic byte
if ! printf '\x16' | dd of="$iso" bs=1 seek=0 count=1 conv=notrunc status=none; then if ! printf '\x16' | dd of="$iso" bs=1 seek=0 count=1 conv=notrunc status=none; then
error "Failed to set magic byte!" && return 1 error "Failed to set magic byte in ISO file: $iso" && return 1
fi fi
fi fi
rm -f "$STORAGE/windows.boot" rm -f "$STORAGE/windows.ver"
cp /run/version "$STORAGE/windows.ver"
rm -f "$STORAGE/windows.old" rm -f "$STORAGE/windows.old"
rm -f "$STORAGE/windows.boot"
rm -f "$STORAGE/windows.mode"
cp /run/version "$STORAGE/windows.ver"
if [[ "${PLATFORM,,}" == "x64" ]]; then
if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then
echo "$BOOT_MODE" > "$STORAGE/windows.mode"
if [[ "${MACHINE,,}" != "q35" ]]; then
echo "$MACHINE" > "$STORAGE/windows.old"
fi
else
# Enable secure boot + TPM on manual installs as Win11 requires
if [[ "$MANUAL" == [Yy1]* ]] || [[ "$aborted" == [Yy1]* ]]; then
if [[ "${DETECTED,,}" == "win11"* ]]; then
BOOT_MODE="windows_secure"
echo "$BOOT_MODE" > "$STORAGE/windows.mode"
fi
fi
fi
fi
rm -rf "$TMP" rm -rf "$TMP"
return 0 return 0
@ -130,7 +78,7 @@ abortInstall() {
if [[ "$iso" != "$STORAGE/$BASE" ]]; then if [[ "$iso" != "$STORAGE/$BASE" ]]; then
if ! mv -f "$iso" "$STORAGE/$BASE"; then if ! mv -f "$iso" "$STORAGE/$BASE"; then
error "Failed to move ISO: $iso" && return 1 error "Failed to move ISO file: $iso" && return 1
fi fi
fi fi
@ -154,18 +102,14 @@ startInstall() {
CUSTOM="" CUSTOM=""
if [[ "${VERSION,,}" == "http"* ]]; then if [[ "${VERSION,,}" != "http"* ]]; then
EXTERNAL="Y"
else
EXTERNAL="N" EXTERNAL="N"
fi
if [[ "$EXTERNAL" != [Yy1]* ]]; then
BASE="$VERSION.iso" BASE="$VERSION.iso"
else else
EXTERNAL="Y"
BASE=$(basename "${VERSION%%\?*}") BASE=$(basename "${VERSION%%\?*}")
: "${BASE//+/ }"; printf -v BASE '%b' "${_//%/\\x}" : "${BASE//+/ }"; printf -v BASE '%b' "${_//%/\\x}"
BASE=$(echo "$BASE" | sed -e 's/[^A-Za-z0-9._-]/_/g') BASE=$(echo "$BASE" | sed -e 's/[^A-Za-z0-9._-]/_/g')
@ -173,9 +117,13 @@ startInstall() {
fi fi
fi fi
if [[ "${PLATFORM,,}" == "x64" ]]; then
! migrateFiles "$BASE" "$VERSION" && error "Migration failed!" && exit 57
fi
if skipInstall; then if skipInstall; then
[ ! -f "$STORAGE/$BASE" ] && BASE="" [ ! -f "$STORAGE/$BASE" ] && BASE=""
VGA="virtio-gpu" [[ "${PLATFORM,,}" == "arm64" ]] && VGA="virtio-gpu"
return 1 return 1
fi fi
@ -204,11 +152,7 @@ startInstall() {
if [ ! -f "$STORAGE/$CUSTOM" ]; then if [ ! -f "$STORAGE/$CUSTOM" ]; then
CUSTOM="" CUSTOM=""
if [[ "$EXTERNAL" == [Yy1]* ]]; then
ISO="$TMP/$BASE" ISO="$TMP/$BASE"
else
ISO="$TMP/$VERSION.esd"
fi
else else
ISO="$STORAGE/$CUSTOM" ISO="$STORAGE/$CUSTOM"
fi fi
@ -216,12 +160,29 @@ startInstall() {
return 0 return 0
} }
detectCustom() {
CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname windows.iso -printf "%f\n" | head -n 1)
[ -z "$CUSTOM" ] && CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.iso -printf "%f\n" | head -n 1)
[ -z "$CUSTOM" ] && CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname boot.iso -printf "%f\n" | head -n 1)
[ -z "$CUSTOM" ] && CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.img -printf "%f\n" | head -n 1)
if [ -z "$CUSTOM" ] && [[ "${VERSION,,}" != "http"* ]]; then
FN="${VERSION/\/storage\//}"
[[ "$FN" == "."* ]] && FN="${FN:1}"
CUSTOM=$(find "$STORAGE" -maxdepth 1 -type f -iname "$FN" -printf "%f\n" | head -n 1)
fi
return 0
}
getESD() { getESD() {
local dir="$1" local dir="$1"
local version="$2"
local winCatalog size local winCatalog size
case "${VERSION,,}" in case "${version,,}" in
"win11${PLATFORM,,}") "win11${PLATFORM,,}")
winCatalog="https://go.microsoft.com/fwlink?linkid=2156292" winCatalog="https://go.microsoft.com/fwlink?linkid=2156292"
;; ;;
@ -229,7 +190,7 @@ getESD() {
winCatalog="https://go.microsoft.com/fwlink/?LinkId=841361" winCatalog="https://go.microsoft.com/fwlink/?LinkId=841361"
;; ;;
*) *)
error "Invalid version specified: $VERSION" && return 1 error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1
;; ;;
esac esac
@ -240,41 +201,44 @@ getESD() {
mkdir -p "$dir" mkdir -p "$dir"
local wFile="catalog.cab" local wFile="catalog.cab"
local xFile="products.xml"
local eFile="esd_edition.xml"
local fFile="products_filter.xml"
{ wget "$winCatalog" -O "$dir/$wFile" -q --no-check-certificate; rc=$?; } || : { wget "$winCatalog" -O "$dir/$wFile" -q; rc=$?; } || :
(( rc != 0 )) && error "Failed to download $winCatalog , reason: $rc" && return 1 (( rc != 0 )) && error "Failed to download $winCatalog , reason: $rc" && return 1
cd "$dir" cd "$dir"
if ! cabextract "$wFile" > /dev/null; then if ! cabextract "$wFile" > /dev/null; then
cd /run cd /run
error "Failed to extract CAB file!" && return 1 error "Failed to extract $wFile!" && return 1
fi fi
cd /run cd /run
if [ ! -s "$dir/products.xml" ]; then if [ ! -s "$dir/$xFile" ]; then
error "Failed to find products.xml!" && return 1 error "Failed to find $xFile in $wFile!" && return 1
fi fi
local esdLang="en-us" local esdLang="en-us"
local editionName="Professional" local editionName="Professional"
local edQuery='//File[Architecture="'${PLATFORM}'"][Edition="'${editionName}'"]' local edQuery='//File[Architecture="'${PLATFORM}'"][Edition="'${editionName}'"]'
echo -e '<Catalog>' > "${dir}/products_filter.xml" echo -e '<Catalog>' > "$dir/$fFile"
xmllint --nonet --xpath "${edQuery}" "${dir}/products.xml" >> "${dir}/products_filter.xml" 2>/dev/null xmllint --nonet --xpath "${edQuery}" "$dir/$xFile" >> "$dir/$fFile" 2>/dev/null
echo -e '</Catalog>'>> "${dir}/products_filter.xml" echo -e '</Catalog>'>> "$dir/$fFile"
xmllint --nonet --xpath '//File[LanguageCode="'${esdLang}'"]' "${dir}/products_filter.xml" >"${dir}/esd_edition.xml" xmllint --nonet --xpath '//File[LanguageCode="'${esdLang}'"]' "$dir/$fFile" >"$dir/$eFile"
size=$(stat -c%s "${dir}/esd_edition.xml") size=$(stat -c%s "$dir/$eFile")
if ((size<20)); then if ((size<20)); then
error "Failed to find Windows product!" && return 1 error "Failed to find Windows product in $eFile!" && return 1
fi fi
ESD_URL=$(xmllint --nonet --xpath '//FilePath' "${dir}/esd_edition.xml" | sed -E -e 's/<[\/]?FilePath>//g') ESD_URL=$(xmllint --nonet --xpath '//FilePath' "$dir/$eFile" | sed -E -e 's/<[\/]?FilePath>//g')
if [ -z "$ESD_URL" ]; then if [ -z "$ESD_URL" ]; then
error "Failed to find ESD URL!" && return 1 error "Failed to find ESD URL in $eFile!" && return 1
fi fi
rm -rf "$dir" rm -rf "$dir"
@ -286,7 +250,7 @@ downloadFile() {
local iso="$1" local iso="$1"
local url="$2" local url="$2"
local desc="$3" local desc="$3"
local rc progress local rc progress domain
rm -f "$iso" rm -f "$iso"
@ -298,10 +262,15 @@ downloadFile() {
fi fi
local msg="Downloading $desc..." local msg="Downloading $desc..."
domain=$(echo "$url" | awk -F/ '{print $3}')
domain=$(expr "$domain" : '.*\.\(.*\..*\)')
[[ "${domain,,}" != *"microsoft.com" ]] && msg="Downloading $desc from $domain..."
info "$msg" && html "$msg" info "$msg" && html "$msg"
/run/progress.sh "$iso" "Downloading $desc ([P])..." & /run/progress.sh "$iso" "Downloading $desc ([P])..." &
{ wget "$url" -O "$iso" -q --no-check-certificate --show-progress "$progress"; rc=$?; } || : { wget "$url" -O "$iso" -q --show-progress "$progress"; rc=$?; } || :
fKill "progress.sh" fKill "progress.sh"
@ -320,57 +289,78 @@ downloadFile() {
downloadImage() { downloadImage() {
local iso="$1" local iso="$1"
local url="$2" local version="$2"
local rc desc local tried="n"
local url desc
if [[ "$EXTERNAL" != [Yy1]* ]]; then if [[ "${version,,}" == "http"* ]]; then
desc=$(printVersion "$VERSION" "Windows for ARM")
else
desc=$(getName "$BASE" "$BASE") desc=$(getName "$BASE" "$BASE")
downloadFile "$iso" "$version" "$desc" && return 0
return 1
fi fi
if [[ "$EXTERNAL" != [Yy1]* ]]; then if ! validVersion "$version"; then
error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1
fi
if ! getESD "$TMP/esd"; then if [[ "${PLATFORM,,}" == "x64" ]]; then
url="" desc=$(printVersion "$version" "Windows")
else else
url="$ESD_URL" desc=$(printVersion "$version" "Windows for ${PLATFORM}")
fi
if [[ "${PLATFORM,,}" == "x64" ]]; then
if isMido "$version"; then
tried="y"
doMido "$iso" "$version" "$desc" && return 0
fi
switchEdition "$version"
fi
if isESD "$version"; then
if [[ "$tried" != "n" ]]; then
info "Failed to download $desc using Mido, will try a diferent method now..."
fi
tried="y"
if getESD "$TMP/esd" "$version"; then
ISO="$TMP/$version.esd"
downloadFile "$ISO" "$ESD_URL" "$desc" && return 0
ISO="$TMP/$BASE"
fi fi
fi fi
url=$(getLink "$version")
if [ -n "$url" ]; then if [ -n "$url" ]; then
downloadFile "$iso" "$url" "$desc" && return 0
if [[ "$tried" != "n" ]]; then
info "Failed to download $desc from Microsoft, will try another mirror now..."
fi fi
[[ "$EXTERNAL" == [Yy1]* ]] && return 1 tried="y"
case "${VERSION,,}" in
"win11${PLATFORM,,}")
url="https://dl.bobpony.com/windows/11/en-us_windows_11_23h2_${PLATFORM,,}.iso"
;;
"win10${PLATFORM,,}")
url="https://dl.bobpony.com/windows/10/en-us_windows_10_22h2_${PLATFORM,,}.iso"
;;
*)
return 1
;;
esac
info "Failed to download $desc from Microsoft, will try another mirror now..."
rm -rf "$TMP"
mkdir -p "$TMP"
ISO="$TMP/$BASE"
iso="$ISO"
downloadFile "$iso" "$url" "$desc" && return 0 downloadFile "$iso" "$url" "$desc" && return 0
fi
url=$(secondLink "$version")
if [ -n "$url" ]; then
if [[ "$tried" != "n" ]]; then
info "Failed to download $desc, will try another mirror now..."
fi
tried="y"
downloadFile "$iso" "$url" "$desc" && return 0
fi
return 1 return 1
} }
@ -378,9 +368,10 @@ extractESD() {
local iso="$1" local iso="$1"
local dir="$2" local dir="$2"
local version="$3"
local desc="$4"
local size size_gb space space_gb desc local size size_gb space space_gb desc
desc=$(printVersion "$VERSION" "Windows for ARM")
local msg="Extracting $desc bootdisk..." local msg="Extracting $desc bootdisk..."
info "$msg" && html "$msg" info "$msg" && html "$msg"
@ -405,7 +396,7 @@ extractESD() {
wimlib-imagex apply "$iso" 1 "${dir}" --quiet 2>/dev/null || { wimlib-imagex apply "$iso" 1 "${dir}" --quiet 2>/dev/null || {
retVal=$? retVal=$?
error "Extracting bootdisk failed" && return $retVal error "Extracting $desc bootdisk failed" && return $retVal
} }
local bootWimFile="${dir}/sources/boot.wim" local bootWimFile="${dir}/sources/boot.wim"
@ -432,7 +423,7 @@ extractESD() {
local edition imageIndex imageEdition local edition imageIndex imageEdition
case "${VERSION,,}" in case "${version,,}" in
"win11${PLATFORM,,}") "win11${PLATFORM,,}")
edition="11 pro" edition="11 pro"
;; ;;
@ -440,7 +431,7 @@ extractESD() {
edition="10 pro" edition="10 pro"
;; ;;
*) *)
error "Invalid version specified: $VERSION" && return 1 error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1
;; ;;
esac esac
@ -449,7 +440,7 @@ extractESD() {
[[ "${imageEdition,,}" != *"$edition"* ]] && continue [[ "${imageEdition,,}" != *"$edition"* ]] && continue
wimlib-imagex export "${iso}" ${imageIndex} "${installWimFile}" --compress=LZMS --chunk-size 128K --quiet || { wimlib-imagex export "${iso}" ${imageIndex} "${installWimFile}" --compress=LZMS --chunk-size 128K --quiet || {
retVal=$? retVal=$?
error "Addition of ${imageIndex} to the image failed" && return $retVal error "Addition of ${imageIndex} to the $desc image failed" && return $retVal
} }
return 0 return 0
done done
@ -461,16 +452,17 @@ extractImage() {
local iso="$1" local iso="$1"
local dir="$2" local dir="$2"
local version="$3"
local desc="downloaded ISO" local desc="downloaded ISO"
local size size_gb space space_gb local size size_gb space space_gb
if [[ "${iso,,}" == *".esd" ]]; then if [[ "$EXTERNAL" != [Yy1]* ]] && [ -z "$CUSTOM" ]; then
extractESD "$iso" "$dir" && return 0 desc=$(printVersion "$version" "downloaded ISO")
return 1
fi fi
if [[ "$EXTERNAL" != [Yy1]* ]] && [ -z "$CUSTOM" ]; then if [[ "${iso,,}" == *".esd" ]]; then
desc=$(printVersion "$VERSION" "downloaded ISO") extractESD "$iso" "$dir" "$version" "$desc" && return 0
return 1
fi fi
local msg="Extracting $desc image..." local msg="Extracting $desc image..."
@ -505,6 +497,7 @@ extractImage() {
detectImage() { detectImage() {
XML="" XML=""
local dsc
local dir="$1" local dir="$1"
if [ -n "$CUSTOM" ]; then if [ -n "$CUSTOM" ]; then
@ -524,10 +517,9 @@ detectImage() {
if [[ "${DETECTED,,}" != "winxp"* ]]; then if [[ "${DETECTED,,}" != "winxp"* ]]; then
local dsc
dsc=$(printVersion "$DETECTED" "$DETECTED") dsc=$(printVersion "$DETECTED" "$DETECTED")
warn "got $dsc, but no matching XML file exists, $FB." warn "got $dsc, but no matching file called $DETECTED.xml exists, $FB."
fi fi
return 0 return 0
@ -535,10 +527,24 @@ detectImage() {
info "Detecting Windows version from ISO image..." info "Detecting Windows version from ISO image..."
if [[ "${PLATFORM,,}" == "x64" ]]; then
if [ -f "$dir/WIN51" ] || [ -f "$dir/SETUPXP.HTM" ]; then
if [ -d "$dir/AMD64" ]; then
DETECTED="winxpx64"
else
DETECTED="winxpx86"
fi
dsc=$(printVersion "$DETECTED" "$DETECTED")
info "Detected: $dsc"
return 0
fi
fi
local src loc tag result name name2 desc local src loc tag result name name2 desc
src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1) src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1)
if [ ! -d "$src" ]; then if [ ! -d "$src" ]; then
[[ "${PLATFORM,,}" == "x64" ]] && BOOT_MODE="windows_legacy"
warn "failed to locate 'sources' folder in ISO image, $FB" && return 1 warn "failed to locate 'sources' folder in ISO image, $FB" && return 1
fi fi
@ -546,6 +552,7 @@ detectImage() {
[ ! -f "$loc" ] && loc=$(find "$src" -maxdepth 1 -type f -iname install.esd | head -n 1) [ ! -f "$loc" ] && loc=$(find "$src" -maxdepth 1 -type f -iname install.esd | head -n 1)
if [ ! -f "$loc" ]; then if [ ! -f "$loc" ]; then
[[ "${PLATFORM,,}" == "x64" ]] && BOOT_MODE="windows_legacy"
warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB" && return 1 warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB" && return 1
fi fi
@ -573,7 +580,7 @@ detectImage() {
[[ "$MANUAL" != [Yy1]* ]] && XML="$DETECTED.xml" [[ "$MANUAL" != [Yy1]* ]] && XML="$DETECTED.xml"
info "Detected: $desc" info "Detected: $desc"
else else
warn "detected $desc, but no matching XML file exists, $FB." warn "detected $desc, but no matching file called $DETECTED.xml exists, $FB."
fi fi
return 0 return 0
@ -584,17 +591,37 @@ prepareImage() {
local iso="$1" local iso="$1"
local dir="$2" local dir="$2"
if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then
if [[ "${DETECTED,,}" != "winxp"* ]] && [[ "${DETECTED,,}" != "win2008"* ]]; then
if [[ "${DETECTED,,}" != "winvista"* ]] && [[ "${DETECTED,,}" != "win7"* ]]; then
if [ -f "$dir/$ETFS" ] && [ -f "$dir/$EFISYS" ]; then if [ -f "$dir/$ETFS" ] && [ -f "$dir/$EFISYS" ]; then
return 0 return 0
fi fi
if [ ! -f "$dir/$ETFS" ]; then if [ ! -f "$dir/$ETFS" ]; then
warn "failed to locate file 'etfsboot.com' in ISO image!" warn "failed to locate file 'etfsboot.com' in ISO image, falling back to legacy boot!"
else else
warn "failed to locate file 'efisys_noprompt.bin' in ISO image!" warn "failed to locate file 'efisys_noprompt.bin' in ISO image, falling back to legacy boot!"
fi fi
return 1 fi
fi
fi
[[ "${PLATFORM,,}" == "arm64" ]] && return 1
if [[ "${DETECTED,,}" == "winxp"* ]]; then
if ! prepareXP "$iso" "$dir"; then
error "Failed to prepare Windows XP ISO!" && return 1
fi
else
if ! prepareLegacy "$iso" "$dir"; then
error "Failed to prepare Windows ISO!" && return 1
fi
fi
return 0
} }
updateImage() { updateImage() {
@ -602,7 +629,7 @@ updateImage() {
local iso="$1" local iso="$1"
local dir="$2" local dir="$2"
local asset="/run/assets/$3" local asset="/run/assets/$3"
local path src loc index result local path src loc xml index result
[ ! -s "$asset" ] || [ ! -f "$asset" ] && return 0 [ ! -s "$asset" ] || [ ! -f "$asset" ] && return 0
@ -612,6 +639,7 @@ updateImage() {
src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1) src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1)
if [ ! -d "$src" ]; then if [ ! -d "$src" ]; then
[[ "${PLATFORM,,}" == "x64" ]] && BOOT_MODE="windows_legacy"
warn "failed to locate 'sources' folder in ISO image, $FB" && return 1 warn "failed to locate 'sources' folder in ISO image, $FB" && return 1
fi fi
@ -619,10 +647,12 @@ updateImage() {
[ ! -f "$loc" ] && loc=$(find "$src" -maxdepth 1 -type f -iname boot.esd | head -n 1) [ ! -f "$loc" ] && loc=$(find "$src" -maxdepth 1 -type f -iname boot.esd | head -n 1)
if [ ! -f "$loc" ]; then if [ ! -f "$loc" ]; then
[[ "${PLATFORM,,}" == "x64" ]] && BOOT_MODE="windows_legacy"
warn "failed to locate 'boot.wim' or 'boot.esd' in ISO image, $FB" && return 1 warn "failed to locate 'boot.wim' or 'boot.esd' in ISO image, $FB" && return 1
fi fi
info "Adding XML file for automatic installation..." xml=$(basename "$asset")
info "Adding $xml for automatic installation..."
index="1" index="1"
result=$(wimlib-imagex info -xml "$loc" | tr -d '\000') result=$(wimlib-imagex info -xml "$loc" | tr -d '\000')
@ -632,7 +662,7 @@ updateImage() {
fi fi
if ! wimlib-imagex update "$loc" "$index" --command "add $asset /autounattend.xml" > /dev/null; then if ! wimlib-imagex update "$loc" "$index" --command "add $asset /autounattend.xml" > /dev/null; then
warn "failed to add XML to ISO image, $FB" && return 1 warn "failed to add $xml to ISO image, $FB" && return 1
fi fi
return 0 return 0
@ -670,6 +700,7 @@ copyOEM() {
buildImage() { buildImage() {
local dir="$1" local dir="$1"
local failed="N"
local cat="BOOT.CAT" local cat="BOOT.CAT"
local label="${BASE%.*}" local label="${BASE%.*}"
local log="/run/shm/iso.log" local log="/run/shm/iso.log"
@ -693,8 +724,33 @@ buildImage() {
error "Not enough free space in $STORAGE, have $space_gb GB available but need at least $size_gb GB." && return 1 error "Not enough free space in $STORAGE, have $space_gb GB available but need at least $size_gb GB." && return 1
fi fi
if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then
if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 4 -J -l -D -N -joliet-long -relaxed-filenames -V "$label" \ if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 4 -J -l -D -N -joliet-long -relaxed-filenames -V "$label" \
-udf -boot-info-table -eltorito-alt-boot -eltorito-boot "$EFISYS" -no-emul-boot -allow-limited-size -quiet "$dir" 2> "$log"; then -udf -boot-info-table -eltorito-alt-boot -eltorito-boot "$EFISYS" -no-emul-boot -allow-limited-size -quiet "$dir" 2> "$log"; then
failed="Y"
fi
else
if [[ "${DETECTED,,}" != "winxp"* ]]; then
if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -c "$cat" -iso-level 2 -J -l -D -N -joliet-long -relaxed-filenames -V "$label" \
-udf -allow-limited-size -quiet "$dir" 2> "$log"; then
failed="Y"
fi
else
if ! genisoimage -o "$out" -b "$ETFS" -no-emul-boot -boot-load-seg 1984 -boot-load-size 4 -c "$cat" -iso-level 2 -J -l -D -N -joliet-long \
-relaxed-filenames -V "$label" -quiet "$dir" 2> "$log"; then
failed="Y"
fi
fi
fi
if [[ "$failed" != "N" ]]; then
[ -s "$log" ] && echo "$(<"$log")" [ -s "$log" ] && echo "$(<"$log")"
error "Failed to build image!" && return 1 error "Failed to build image!" && return 1
fi fi
@ -715,18 +771,58 @@ buildImage() {
bootWindows() { bootWindows() {
rm -rf "$TMP"
if [ -s "$STORAGE/windows.mode" ] && [ -f "$STORAGE/windows.mode" ]; then if [ -s "$STORAGE/windows.mode" ] && [ -f "$STORAGE/windows.mode" ]; then
BOOT_MODE=$(<"$STORAGE/windows.mode") BOOT_MODE=$(<"$STORAGE/windows.mode")
rm -rf "$TMP" if [ -s "$STORAGE/windows.old" ] && [ -f "$STORAGE/windows.old" ]; then
[[ "${PLATFORM,,}" == "x64" ]] && MACHINE=$(<"$STORAGE/windows.old")
fi
return 0 return 0
fi fi
rm -rf "$TMP" # Migrations
[[ "${PLATFORM,,}" != "x64" ]] && return 0
if [ -f "$STORAGE/windows.old" ]; then
MACHINE=$(<"$STORAGE/windows.old")
[ -z "$MACHINE" ] && MACHINE="q35"
BOOT_MODE="windows_legacy"
echo "$BOOT_MODE" > "$STORAGE/windows.mode"
return 0
fi
local creation="1.10"
local minimal="2.14"
if [ -f "$STORAGE/windows.ver" ]; then
creation=$(<"$STORAGE/windows.ver")
[[ "${creation}" != *"."* ]] && creation="$minimal"
fi
# Force secure boot on installs created prior to v2.14
if (( $(echo "$creation < $minimal" | bc -l) )); then
if [[ "${BOOT_MODE,,}" == "windows" ]]; then
BOOT_MODE="windows_secure"
echo "$BOOT_MODE" > "$STORAGE/windows.mode"
if [ -f "$STORAGE/windows.rom" ] && [ ! -f "$STORAGE/$BOOT_MODE.rom" ]; then
mv "$STORAGE/windows.rom" "$STORAGE/$BOOT_MODE.rom"
fi
if [ -f "$STORAGE/windows.vars" ] && [ ! -f "$STORAGE/$BOOT_MODE.vars" ]; then
mv "$STORAGE/windows.vars" "$STORAGE/$BOOT_MODE.vars"
fi
fi
fi
return 0 return 0
} }
###################################### ######################################
! parseVersion && exit 58
! detectCustom && exit 59
if ! startInstall; then if ! startInstall; then
bootWindows && return 0 bootWindows && return 0
exit 68 exit 68
@ -734,13 +830,13 @@ fi
if [ ! -s "$ISO" ] || [ ! -f "$ISO" ]; then if [ ! -s "$ISO" ] || [ ! -f "$ISO" ]; then
if ! downloadImage "$ISO" "$VERSION"; then if ! downloadImage "$ISO" "$VERSION"; then
rm -f "$ISO" rm -f "$ISO" 2> /dev/null || true
exit 61 exit 61
fi fi
fi fi
if ! extractImage "$ISO" "$DIR"; then if ! extractImage "$ISO" "$DIR" "$VERSION"; then
rm -f "$ISO" rm -f "$ISO" 2> /dev/null || true
exit 62 exit 62
fi fi

View file

@ -23,6 +23,21 @@ _trap() {
done done
} }
boot() {
[ -f "$QEMU_END" ] && return 0
if [ -s "$QEMU_PTY" ]; then
if grep -iq " hard" "$QEMU_PTY"; then
info "Windows started succesfully, visit http://localhost:8006/ to view the screen..."
return 0
fi
fi
error "Timeout while waiting for QEMU to boot the machine!"
return 0
}
ready() { ready() {
[ -f "$STORAGE/windows.boot" ] && return 0 [ -f "$STORAGE/windows.boot" ] && return 0