mirror of
https://github.com/dockur/windows.git
synced 2026-08-03 12:37:20 +01:00
feat: Improve image detection and answer file generation (#1940)
This commit is contained in:
+131
-83
@@ -235,25 +235,131 @@ validateDomainName() {
|
||||
return 0
|
||||
}
|
||||
|
||||
generateEvalXML() {
|
||||
|
||||
# Evaluation templates are generated from their normal counterpart so
|
||||
# both variants remain identical except for evaluation-specific selectors.
|
||||
|
||||
local id="$1"
|
||||
local detected_index="${2:-}"
|
||||
local source="/run/assets/${id::-5}.xml"
|
||||
local target="/run/assets/$id.xml"
|
||||
local index="$detected_index" tmp
|
||||
|
||||
[[ "${id,,}" == *"-eval" ]] || return 1
|
||||
[ -s "$source" ] || return 1
|
||||
|
||||
if [ -n "$index" ] && [[ ! "$index" =~ ^[1-9][0-9]*$ ]]; then
|
||||
error "Invalid evaluation image index: $index"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! tmp=$(mktemp -p /run/assets ".${id}.XXXXXX"); then
|
||||
error "Failed to create a temporary evaluation answer file!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! sed \
|
||||
-e '/<ProductKey>.*<\/ProductKey>/d' \
|
||||
-e '/<ProductKey>/,/<\/ProductKey>/d' \
|
||||
"$source" > "$tmp"; then
|
||||
rm -f "$tmp"
|
||||
error "Failed to generate evaluation answer file from $source!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -n "$detected_index" ]; then
|
||||
|
||||
# A WIM index was detected, so replace any selector inherited from
|
||||
# the normal template with the exact index from the ISO image.
|
||||
if ! sed -i \
|
||||
-e '/<InstallFrom>.*<\/InstallFrom>/d' \
|
||||
-e '/<InstallFrom>/,/<\/InstallFrom>/d' \
|
||||
"$tmp"; then
|
||||
rm -f "$tmp"
|
||||
error "Failed to replace evaluation image selector!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
# No WIM was inspected, so retain the known defaults for download routes.
|
||||
case "${id,,}" in
|
||||
*"-ltsc-eval" ) index="1" ;;
|
||||
*"-iot-eval" ) index="2" ;;
|
||||
esac
|
||||
|
||||
fi
|
||||
|
||||
if [ -n "$index" ] && ! grep -q '<InstallFrom>' "$tmp"; then
|
||||
if ! sed -i \
|
||||
'0,/<InstallTo>/{ /<InstallTo>/i\
|
||||
<InstallFrom>\
|
||||
<MetaData wcm:action="add">\
|
||||
<Key>/IMAGE/INDEX</Key>\
|
||||
<Value>'"$index"'</Value>\
|
||||
</MetaData>\
|
||||
</InstallFrom>
|
||||
}' "$tmp"; then
|
||||
rm -f "$tmp"
|
||||
error "Failed to select evaluation image index $index!"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! xmllint --nonet --noout "$tmp"; then
|
||||
rm -f "$tmp"
|
||||
error "Generated evaluation answer file is invalid!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! chmod 644 "$tmp" || ! mv -f "$tmp" "$target"; then
|
||||
rm -f "$tmp"
|
||||
error "Failed to create evaluation answer file: $target"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
setXML() {
|
||||
|
||||
local file="/custom.xml"
|
||||
local file
|
||||
local index="${2:-}"
|
||||
local custom_files=(
|
||||
"/custom.xml"
|
||||
"$STORAGE/custom.xml"
|
||||
"/run/assets/custom.xml"
|
||||
)
|
||||
|
||||
CUSTOM_XML=""
|
||||
|
||||
if [ -d "$file" ]; then
|
||||
error "The bind $file maps to a file that does not exist!" && exit 67
|
||||
if [ -d "${custom_files[0]}" ]; then
|
||||
error "The bind ${custom_files[0]} maps to a file that does not exist!"
|
||||
exit 67
|
||||
fi
|
||||
|
||||
[ ! -f "$file" ] || [ ! -s "$file" ] && file="$STORAGE/custom.xml"
|
||||
[ ! -f "$file" ] || [ ! -s "$file" ] && file="/run/assets/custom.xml"
|
||||
[ ! -f "$file" ] || [ ! -s "$file" ] && file="$1"
|
||||
[ ! -f "$file" ] || [ ! -s "$file" ] && file="/run/assets/$DETECTED.xml"
|
||||
[ ! -f "$file" ] || [ ! -s "$file" ] && return 1
|
||||
for file in "${custom_files[@]}"; do
|
||||
if [ -f "$file" ] && [ -s "$file" ]; then
|
||||
CUSTOM_XML="Y"
|
||||
XML="$file"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
case "$file" in
|
||||
"/custom.xml" | "$STORAGE/custom.xml" ) CUSTOM_XML="Y" ;;
|
||||
esac
|
||||
file="$1"
|
||||
|
||||
if [[ "${DETECTED,,}" == *"-eval" ]]; then
|
||||
if [ ! -f "$file" ] || [ ! -s "$file" ]; then
|
||||
generateEvalXML "$DETECTED" "$index" || return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "$file" ] || [ ! -s "$file" ]; then
|
||||
file="/run/assets/$DETECTED.xml"
|
||||
fi
|
||||
|
||||
[ -f "$file" ] && [ -s "$file" ] || return 1
|
||||
|
||||
XML="$file"
|
||||
return 0
|
||||
@@ -262,15 +368,14 @@ setXML() {
|
||||
updateDomain() {
|
||||
|
||||
local asset="$1"
|
||||
local domain account auth pass pw
|
||||
local domain account auth pass
|
||||
local cred_domain ou arch tmp result
|
||||
|
||||
domain=$(escapeXML "$2") || return 1
|
||||
account=$(escapeXML "$3") || return 1
|
||||
auth=$(escapeXML "$4") || return 1
|
||||
pass=$(escapeXML "$5") || return 1
|
||||
pw="$6"
|
||||
ou=$(escapeXML "$7") || return 1
|
||||
ou=$(escapeXML "$6") || return 1
|
||||
|
||||
arch=$(sed -n -E \
|
||||
'0,/processorArchitecture="/s/.*processorArchitecture="([^"]+)".*/\1/p' \
|
||||
@@ -291,7 +396,7 @@ updateDomain() {
|
||||
|
||||
if ! DOMAIN_XML="$domain" ACCOUNT_XML="$account" \
|
||||
AUTH_XML="$auth" PASS_XML="$pass" \
|
||||
CRED_DOMAIN="$cred_domain" PW="$pw" OU_XML="$ou" \
|
||||
CRED_DOMAIN="$cred_domain" OU_XML="$ou" \
|
||||
ARCH_XML="$arch" \
|
||||
awk '
|
||||
/<settings[^>]*pass="specialize"[^>]*>/ { section = "specialize" }
|
||||
@@ -326,11 +431,18 @@ updateDomain() {
|
||||
|
||||
section == "oobeSystem" && in_autologon &&
|
||||
/^[[:space:]]*<Value>.*<\/Value>[[:space:]]*$/ {
|
||||
print " <Value>" ENVIRON["PW"] "</Value>"
|
||||
print " <Value>" ENVIRON["PASS_XML"] "</Value>"
|
||||
password_added = 1
|
||||
next
|
||||
}
|
||||
|
||||
section == "oobeSystem" && in_autologon &&
|
||||
/^[[:space:]]*<PlainText([[:space:]/>])/ {
|
||||
print " <PlainText>true</PlainText>"
|
||||
plaintext_added = 1
|
||||
next
|
||||
}
|
||||
|
||||
section == "specialize" && !join_added &&
|
||||
/^[[:space:]]*<\/settings>[[:space:]]*$/ {
|
||||
print " <component name=\"Microsoft-Windows-UnattendedJoin\" processorArchitecture=\"" ENVIRON["ARCH_XML"] "\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n" \
|
||||
@@ -362,7 +474,7 @@ updateDomain() {
|
||||
section == "oobeSystem" && /<\/UserAccounts>/ { in_accounts = 0 }
|
||||
/^[[:space:]]*<\/settings>[[:space:]]*$/ { section = "" }
|
||||
|
||||
END { exit !(join_added && accounts_added && autologon_added && password_added) }
|
||||
END { exit !(join_added && accounts_added && autologon_added && password_added && plaintext_added) }
|
||||
' "$asset" > "$result" ||
|
||||
! mv -f "$result" "$asset"; then
|
||||
|
||||
@@ -558,10 +670,8 @@ updateXML() {
|
||||
|
||||
if [ -n "$domain" ]; then
|
||||
|
||||
pw=$(printf '%s' "${PASSWORD}Password" | iconv -f utf-8 -t utf-16le | base64 -w 0) || return 1
|
||||
|
||||
if ! updateDomain "$asset" "$domain" "$user" \
|
||||
"$auth_user" "$PASSWORD" "$pw" "$DOMAIN_OU"; then
|
||||
"$auth_user" "$PASSWORD" "$DOMAIN_OU"; then
|
||||
error "Failed to add domain configuration to answer file!"
|
||||
return 1
|
||||
fi
|
||||
@@ -724,68 +834,6 @@ validateLegacyUsername() {
|
||||
return 0
|
||||
}
|
||||
|
||||
detectLegacy() {
|
||||
|
||||
local dir="$1"
|
||||
local find
|
||||
|
||||
[[ "${PLATFORM,,}" != "x64" ]] && return 1
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type d -iname WIN95 -print -quit)
|
||||
[ -n "$find" ] && DETECTED="win95" && return 0
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type d -iname WIN98 -print -quit)
|
||||
[ -n "$find" ] && DETECTED="win98" && return 0
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type d -iname WIN9X -print -quit)
|
||||
[ -n "$find" ] && DETECTED="win9x" && return 0
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_W.40 -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_S.40 -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_TS.40 -print -quit)
|
||||
[ -n "$find" ] && DETECTED="winnt4" && return 0
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_NT.5 -print -quit)
|
||||
|
||||
if [ -n "$find" ]; then
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_IA.5 -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_ID.5 -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_IP.5 -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_IS.5 -print -quit)
|
||||
[ -n "$find" ] && DETECTED="win2k" && return 0
|
||||
|
||||
fi
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -iname WIN51 -print -quit)
|
||||
|
||||
if [ -n "$find" ]; then
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AP -print -quit)
|
||||
[ -n "$find" ] && DETECTED="winxpx64" && return 0
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IC -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IP -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname setupxp.htm -print -quit)
|
||||
[ -n "$find" ] && DETECTED="winxpx86" && return 0
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IS -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IA -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IB -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51ID -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IL -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AA -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AD -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AS -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51MA -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51MD -print -quit)
|
||||
[ -n "$find" ] && DETECTED="win2003r2" && return 0
|
||||
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
legacyInstall() {
|
||||
|
||||
local pid=""
|
||||
@@ -1266,8 +1314,8 @@ legacyPrepare() {
|
||||
local image="$tmp/eltorito_img1_bios.img"
|
||||
|
||||
ETFS="boot.img"
|
||||
[ -f "$dir/$ETFS" ] && [ -s "$dir/$ETFS" ] && return 0
|
||||
|
||||
[ -s "$dir/$ETFS" ] && return 0
|
||||
rm -f "$dir/$ETFS" || return 1
|
||||
rm -rf "$tmp" || return 1
|
||||
|
||||
|
||||
+58
-55
@@ -30,7 +30,6 @@ WIDTH=$(strip "$WIDTH")
|
||||
HEIGHT=$(strip "$HEIGHT")
|
||||
DOMAIN=$(strip "$DOMAIN")
|
||||
REGION=$(strip "$REGION")
|
||||
COMMAND=$(strip "$COMMAND")
|
||||
EDITION=$(strip "$EDITION")
|
||||
KEYBOARD=$(strip "$KEYBOARD")
|
||||
LANGUAGE=$(strip "$LANGUAGE")
|
||||
@@ -39,6 +38,7 @@ DOMAIN_OU=$(strip "$DOMAIN_OU")
|
||||
WORKGROUP=$(strip "$WORKGROUP")
|
||||
|
||||
MIRRORS=3
|
||||
SUGGEST=""
|
||||
|
||||
parseVersion() {
|
||||
|
||||
@@ -54,11 +54,11 @@ parseVersion() {
|
||||
;;
|
||||
"11l" | "11ltsc" | "ltsc11" | "win11l" | "win11-ltsc" | "win11x64-ltsc" )
|
||||
VERSION="win11x64-enterprise-ltsc-eval"
|
||||
[ -z "$DETECTED" ] && DETECTED="win11x64-ltsc"
|
||||
SUGGEST="win11x64-ltsc"
|
||||
;;
|
||||
"11i" | "11iot" | "iot11" | "win11i" | "win11-iot" | "win11x64-iot" )
|
||||
VERSION="win11x64-enterprise-iot-eval"
|
||||
[ -z "$DETECTED" ] && DETECTED="win11x64-iot"
|
||||
SUGGEST="win11x64-iot"
|
||||
;;
|
||||
"10" | "10p" | "win10" | "pro10" | "win10p" | "windows10" | "windows 10" )
|
||||
VERSION="win10x64"
|
||||
@@ -68,11 +68,11 @@ parseVersion() {
|
||||
;;
|
||||
"10l" | "10ltsc" | "ltsc10" | "win10l" | "win10-ltsc" | "win10x64-ltsc" )
|
||||
VERSION="win10x64-enterprise-ltsc-eval"
|
||||
[ -z "$DETECTED" ] && DETECTED="win10x64-ltsc"
|
||||
SUGGEST="win10x64-ltsc"
|
||||
;;
|
||||
"10i" | "10iot" | "iot10" | "win10i" | "win10-iot" | "win10x64-iot" )
|
||||
VERSION="win10x64-enterprise-iot-eval"
|
||||
[ -z "$DETECTED" ] && DETECTED="win10x64-iot"
|
||||
SUGGEST="win10x64-iot"
|
||||
;;
|
||||
"8" | "8p" | "81" | "81p" | "pro8" | "8.1" | "win8" | "win8p" | "win81" | "win81p" | "windows 8" )
|
||||
VERSION="win81x64"
|
||||
@@ -82,7 +82,7 @@ parseVersion() {
|
||||
;;
|
||||
"7" | "win7" | "windows7" | "windows 7" )
|
||||
VERSION="win7x64"
|
||||
[ -z "$DETECTED" ] && DETECTED="win7x64-ultimate"
|
||||
SUGGEST="win7x64-ultimate"
|
||||
;;
|
||||
"7u" | "win7u" | "windows7u" | "windows 7u" )
|
||||
VERSION="win7x64-ultimate"
|
||||
@@ -92,7 +92,7 @@ parseVersion() {
|
||||
;;
|
||||
"7x86" | "win7x86" | "win732" | "windows7x86" )
|
||||
VERSION="win7x86"
|
||||
[ -z "$DETECTED" ] && DETECTED="win7x86-ultimate"
|
||||
SUGGEST="win7x86-ultimate"
|
||||
;;
|
||||
"7ux86" | "7u32" | "win7x86-ultimate" )
|
||||
VERSION="win7x86-ultimate"
|
||||
@@ -102,7 +102,7 @@ parseVersion() {
|
||||
;;
|
||||
"vista" | "vs" | "6" | "winvista" | "windowsvista" | "windows vista" )
|
||||
VERSION="winvistax64"
|
||||
[ -z "$DETECTED" ] && DETECTED="winvistax64-ultimate"
|
||||
SUGGEST="winvistax64-ultimate"
|
||||
;;
|
||||
"vistu" | "vu" | "6u" | "winvistu" )
|
||||
VERSION="winvistax64-ultimate"
|
||||
@@ -112,7 +112,7 @@ parseVersion() {
|
||||
;;
|
||||
"vistax86" | "vista32" | "6x86" | "winvistax86" | "windowsvistax86" )
|
||||
VERSION="winvistax86"
|
||||
[ -z "$DETECTED" ] && DETECTED="winvistax86-ultimate"
|
||||
SUGGEST="winvistax86-ultimate"
|
||||
;;
|
||||
"vux86" | "vu32" | "winvistax86-ultimate" )
|
||||
VERSION="winvistax86-ultimate"
|
||||
@@ -155,22 +155,30 @@ parseVersion() {
|
||||
;;
|
||||
"nano11" | "nano 11" )
|
||||
VERSION="nano11"
|
||||
[ -z "$DETECTED" ] && DETECTED="win11x64"
|
||||
;;
|
||||
"core11" | "core 11" )
|
||||
VERSION="core11"
|
||||
[ -z "$DETECTED" ] && DETECTED="win11x64"
|
||||
;;
|
||||
"tiny11" | "tiny 11" )
|
||||
VERSION="tiny11"
|
||||
[ -z "$DETECTED" ] && DETECTED="win11x64"
|
||||
;;
|
||||
"tiny10" | "tiny 10" )
|
||||
VERSION="tiny10"
|
||||
[ -z "$DETECTED" ] && DETECTED="win10x64-ltsc"
|
||||
SUGGEST="win10x64-ltsc"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$SUGGEST" ]; then
|
||||
case "${VERSION,,}" in
|
||||
*"-enterprise-ltsc-eval" )
|
||||
SUGGEST="${VERSION%-enterprise-ltsc-eval}-ltsc" ;;
|
||||
*"-enterprise-iot-eval" )
|
||||
SUGGEST="${VERSION%-enterprise-iot-eval}-iot" ;;
|
||||
*"-eval" )
|
||||
SUGGEST="${VERSION%-eval}" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -459,6 +467,7 @@ printVariant() {
|
||||
|
||||
local id="$1"
|
||||
local desc="$2"
|
||||
local show_eval="${3:-N}"
|
||||
|
||||
desc=$(printVersion "$id" "$desc") || return 1
|
||||
|
||||
@@ -474,6 +483,10 @@ printVariant() {
|
||||
;;
|
||||
esac
|
||||
|
||||
if enabled "$show_eval" && [[ "${id,,}" == *"-eval" ]]; then
|
||||
desc+=" (Evaluation)"
|
||||
fi
|
||||
|
||||
echo "$desc"
|
||||
return 0
|
||||
}
|
||||
@@ -482,8 +495,8 @@ printEdition() {
|
||||
|
||||
local id="$1"
|
||||
local desc="$2"
|
||||
local result=""
|
||||
local edition=""
|
||||
local show_eval="${3:-N}"
|
||||
local result="" edition=""
|
||||
|
||||
result=$(printVersion "$id" "x")
|
||||
[[ "$result" == "x" ]] && echo "$desc" && return 0
|
||||
@@ -498,7 +511,7 @@ printEdition() {
|
||||
*"-ultimate" )
|
||||
edition="Ultimate"
|
||||
;;
|
||||
*"-enterprise" )
|
||||
*"-enterprise" | *"-enterprise-eval" )
|
||||
edition="Enterprise"
|
||||
;;
|
||||
*"-education" )
|
||||
@@ -513,9 +526,6 @@ printEdition() {
|
||||
*"-ltsc" | *"-ltsc-eval" )
|
||||
edition="Enterprise LTSC"
|
||||
;;
|
||||
*"-enterprise-eval" )
|
||||
edition="Enterprise (Evaluation)"
|
||||
;;
|
||||
"win7"* )
|
||||
edition="Professional"
|
||||
;;
|
||||
@@ -539,6 +549,10 @@ printEdition() {
|
||||
|
||||
[ -n "$edition" ] && result+=" $edition"
|
||||
|
||||
if enabled "$show_eval" && [[ "${id,,}" == *"-eval" ]]; then
|
||||
result+=" (Evaluation)"
|
||||
fi
|
||||
|
||||
echo "$result"
|
||||
return 0
|
||||
}
|
||||
@@ -669,40 +683,40 @@ getVersion() {
|
||||
local id
|
||||
local name="$1"
|
||||
local arch="$2"
|
||||
local evaluation=""
|
||||
|
||||
id=$(fromName "$name" "$arch")
|
||||
[[ "${name,,}" == *"evaluation"* ]] && evaluation="-eval"
|
||||
|
||||
case "${id,,}" in
|
||||
"win7"* | "winvista"* )
|
||||
case "${name,,}" in
|
||||
*" home"* ) id="$id-home" ;;
|
||||
*" starter"* ) id="$id-starter" ;;
|
||||
*" ultimate"* ) id="$id-ultimate" ;;
|
||||
*" enterprise evaluation"* ) id="$id-enterprise-eval" ;;
|
||||
*" enterprise"* ) id="$id-enterprise" ;;
|
||||
esac
|
||||
case "${name,,}" in
|
||||
*" home"* ) id="$id-home" ;;
|
||||
*" starter"* ) id="$id-starter" ;;
|
||||
*" ultimate"* ) id="$id-ultimate" ;;
|
||||
*" enterprise"* ) id="$id-enterprise$evaluation" ;;
|
||||
esac
|
||||
;;
|
||||
"win8"* )
|
||||
case "${name,,}" in
|
||||
*" enterprise evaluation"* ) id="$id-enterprise-eval" ;;
|
||||
*" enterprise"* ) id="$id-enterprise" ;;
|
||||
esac
|
||||
case "${name,,}" in
|
||||
*" enterprise"* ) id="$id-enterprise$evaluation" ;;
|
||||
esac
|
||||
;;
|
||||
"win10"* | "win11"* )
|
||||
case "${name,,}" in
|
||||
*" iot"* ) id="$id-iot" ;;
|
||||
*" ltsc"* ) id="$id-ltsc" ;;
|
||||
*" home"* ) id="$id-home" ;;
|
||||
*" education"* ) id="$id-education" ;;
|
||||
*" enterprise evaluation"* ) id="$id-enterprise-eval" ;;
|
||||
*" enterprise"* ) id="$id-enterprise" ;;
|
||||
esac
|
||||
case "${name,,}" in
|
||||
*" iot"* ) id="$id-iot$evaluation" ;;
|
||||
*" ltsc"* ) id="$id-ltsc$evaluation" ;;
|
||||
*" home"* ) id="$id-home" ;;
|
||||
*" education"* ) id="$id-education" ;;
|
||||
*" enterprise"* ) id="$id-enterprise$evaluation" ;;
|
||||
esac
|
||||
;;
|
||||
"win2025"* | "win2022"* | "win2019"* | "win2016"* | "win2012"* | "win2008"* | "win2003"* )
|
||||
case "${name,,}" in
|
||||
*" evaluation"* ) id="$id-eval" ;;
|
||||
*"hyper-v server"* ) id="$id-hv" ;;
|
||||
esac
|
||||
"win2025"* | "win2022"* | "win2019"* | "win2016"* | \
|
||||
"win2012"* | "win2008"* | "win2003"* )
|
||||
case "${name,,}" in
|
||||
*"hyper-v server"* ) id="$id-hv" ;;
|
||||
*"evaluation"* ) id="$id-eval" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -710,17 +724,6 @@ getVersion() {
|
||||
return 0
|
||||
}
|
||||
|
||||
switchEdition() {
|
||||
|
||||
local id="$1"
|
||||
|
||||
if [[ "${id,,}" == *"-eval" ]]; then
|
||||
[ -z "$DETECTED" ] && DETECTED="${id::-5}"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
getMido() {
|
||||
|
||||
local id="$1"
|
||||
@@ -798,7 +801,7 @@ getMido() {
|
||||
sum="6612b5b1f53e845aacdf96e974bb119a3d9b4dcb5b82e65804ab7e534dc7b4d5"
|
||||
url="https://download.microsoft.com/download/6/2/A/62A76ABB-9990-4EFC-A4FE-C7D698DAEB96/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_SERVER_EVAL_EN-US-IR3_SSS_X64FREE_EN-US_DV9.ISO"
|
||||
;;
|
||||
"win2008r2" )
|
||||
"win2008r2" | "win2008r2-eval" )
|
||||
size=3166840832
|
||||
sum="30832ad76ccfa4ce48ccb936edefe02079d42fb1da32201bf9e3a880c8ed6312"
|
||||
url="https://download.microsoft.com/download/4/1/D/41DEA7E0-B30D-4012-A1E3-F24DC03BA1BB/7601.17514.101119-1850_x64fre_server_eval_en-us-GRMSXEVAL_EN_DVD.iso"
|
||||
|
||||
@@ -15,6 +15,7 @@ cd /run
|
||||
. define.sh # Define versions
|
||||
. mido.sh # Download Windows
|
||||
. answer.sh # Setup answer files
|
||||
. image.sh # Detect image files
|
||||
. install.sh # Run installation
|
||||
. disk.sh # Initialize disks
|
||||
. display.sh # Initialize graphics
|
||||
|
||||
+522
@@ -0,0 +1,522 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
getPlatform() {
|
||||
|
||||
local xml="$1"
|
||||
local tag="ARCH"
|
||||
local platform="x64"
|
||||
local arch
|
||||
|
||||
arch=$(sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$xml")
|
||||
|
||||
case "${arch,,}" in
|
||||
"0" ) platform="x86" ;;
|
||||
"9" ) platform="x64" ;;
|
||||
"12" ) platform="arm64" ;;
|
||||
esac
|
||||
|
||||
echo "$platform"
|
||||
return 0
|
||||
}
|
||||
|
||||
checkPlatform() {
|
||||
|
||||
local xml="$1"
|
||||
local platform compat
|
||||
|
||||
platform=$(getPlatform "$xml")
|
||||
|
||||
case "${platform,,}" in
|
||||
"x86" ) compat="x64" ;;
|
||||
"x64" ) compat="$platform" ;;
|
||||
"arm64" ) compat="$platform" ;;
|
||||
* ) compat="${PLATFORM,,}" ;;
|
||||
esac
|
||||
|
||||
[[ "${compat,,}" == "${PLATFORM,,}" ]] && return 0
|
||||
|
||||
error "You cannot boot ${platform^^} images on a $PLATFORM CPU!"
|
||||
return 1
|
||||
}
|
||||
|
||||
hasVersion() {
|
||||
|
||||
local wanted="$1"
|
||||
shift
|
||||
|
||||
local actual expected_id selected_id file source
|
||||
local i
|
||||
|
||||
local -a actuals=("$@")
|
||||
local -a expected=("$wanted")
|
||||
local -a selected=("$wanted")
|
||||
|
||||
# Treat normal and Evaluation variants of the same edition as compatible.
|
||||
# The exact requested variant is always checked first.
|
||||
if [[ "${wanted,,}" == *"-eval" ]]; then
|
||||
expected+=("${wanted%-eval}")
|
||||
selected+=("${wanted%-eval}")
|
||||
else
|
||||
expected+=("$wanted-eval")
|
||||
selected+=("$wanted-eval")
|
||||
fi
|
||||
|
||||
for (( i=0; i<${#expected[@]}; i++ )); do
|
||||
|
||||
expected_id="${expected[$i]}"
|
||||
selected_id="${selected[$i]}"
|
||||
|
||||
for actual in "${actuals[@]}"; do
|
||||
[[ "${actual,,}" == "${expected_id,,}" ]] || continue
|
||||
|
||||
file="/run/assets/$selected_id.xml"
|
||||
|
||||
if [ -s "$file" ]; then
|
||||
echo "$selected_id"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "${selected_id,,}" == *"-eval" ]]; then
|
||||
source="/run/assets/${selected_id%-eval}.xml"
|
||||
|
||||
if [ -s "$source" ]; then
|
||||
echo "$selected_id"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Client editions without a dedicated template can use the generic
|
||||
# template. updateImage() makes that copy edition-neutral.
|
||||
case "${selected_id,,}" in
|
||||
"win7"* | "win8"* | "win10"* | "win11"* | "winvista"* )
|
||||
file="/run/assets/${selected_id%%-*}.xml"
|
||||
|
||||
if [ -s "$file" ]; then
|
||||
echo "$selected_id"
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
selectVersion() {
|
||||
|
||||
local tag="$1"
|
||||
local xml="$2"
|
||||
local platform="$3"
|
||||
local suggested="${4:-}"
|
||||
|
||||
local name id base prefer match suffix actual
|
||||
local tried=""
|
||||
|
||||
local -a versions=()
|
||||
local -a bases=()
|
||||
local -a priorities=(
|
||||
"-enterprise"
|
||||
"-ultimate"
|
||||
""
|
||||
"-iot"
|
||||
"-ltsc"
|
||||
"-education"
|
||||
"-home"
|
||||
"-starter"
|
||||
"-hv"
|
||||
)
|
||||
|
||||
while IFS= read -r name; do
|
||||
[[ "$name" == *"Operating System"* ]] && continue
|
||||
[ -z "$name" ] && continue
|
||||
|
||||
base=$(fromName "$name" "$platform")
|
||||
id=$(getVersion "$name" "$platform")
|
||||
|
||||
if [ -z "$base" ] || [ -z "$id" ]; then
|
||||
warn "Unknown ${tag,,}: '$name'"
|
||||
continue
|
||||
fi
|
||||
|
||||
versions+=("$id")
|
||||
bases+=("$base")
|
||||
done < <(
|
||||
sed -n \
|
||||
"/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" \
|
||||
<<< "$xml"
|
||||
)
|
||||
|
||||
[ "${#versions[@]}" -eq 0 ] && return 0
|
||||
|
||||
if [ -n "$EDITION" ]; then
|
||||
|
||||
for base in "${bases[@]}"; do
|
||||
[[ "${base,,}" == win20* ]] && continue
|
||||
|
||||
tried="Y"
|
||||
|
||||
case "${EDITION,,}" in
|
||||
"pro" | "professional" | "business" )
|
||||
prefer="$base"
|
||||
;;
|
||||
* )
|
||||
prefer="$base-${EDITION,,}"
|
||||
;;
|
||||
esac
|
||||
|
||||
if match=$(hasVersion "$prefer" "${versions[@]}"); then
|
||||
echo "$match"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$tried" ]; then
|
||||
warn "Edition '$EDITION' is not supported by this image, using automatic selection instead."
|
||||
fi
|
||||
fi
|
||||
|
||||
# For reused automatic media, prefer the edition selected by parseVersion()
|
||||
# when that edition is actually present in the image. An explicit EDITION
|
||||
# remains authoritative because it is handled above.
|
||||
if [ -n "$suggested" ]; then
|
||||
if match=$(hasVersion "$suggested" "${versions[@]}"); then
|
||||
echo "$match"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Preserve the existing preference for Enterprise, Ultimate, and the
|
||||
# normal Pro/Professional/Business edition. The remaining entries provide
|
||||
# deterministic selection when those editions are absent.
|
||||
for suffix in "${priorities[@]}"; do
|
||||
for base in "${bases[@]}"; do
|
||||
prefer="$base$suffix"
|
||||
|
||||
# Automatic selection must prefer an edition that is actually present.
|
||||
for actual in "${versions[@]}"; do
|
||||
[[ "${actual%-eval}" == "${prefer%-eval}" ]] || continue
|
||||
|
||||
if match=$(hasVersion "$prefer" "${versions[@]}"); then
|
||||
echo "$match"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
# Future or unusual edition that getVersion() recognizes but which is not
|
||||
# included in the priority list: use the first recognized WIM image.
|
||||
echo "${versions[0]}"
|
||||
return 0
|
||||
}
|
||||
|
||||
detectVersion() {
|
||||
|
||||
local xml="$1"
|
||||
local suggested="${2:-}"
|
||||
local id platform
|
||||
|
||||
platform=$(getPlatform "$xml")
|
||||
id=$(selectVersion "DISPLAYNAME" "$xml" "$platform" "$suggested")
|
||||
[ -z "$id" ] &&
|
||||
id=$(selectVersion "PRODUCTNAME" "$xml" "$platform" "$suggested")
|
||||
[ -z "$id" ] &&
|
||||
id=$(selectVersion "NAME" "$xml" "$platform" "$suggested")
|
||||
|
||||
echo "$id"
|
||||
return 0
|
||||
}
|
||||
|
||||
getImageIndex() {
|
||||
|
||||
local xml="$1"
|
||||
local wanted="$2"
|
||||
local platform tag index name id
|
||||
|
||||
local -a matches=()
|
||||
|
||||
[ -z "$wanted" ] && return 1
|
||||
|
||||
platform=$(getPlatform "$xml")
|
||||
|
||||
for tag in DISPLAYNAME PRODUCTNAME NAME; do
|
||||
|
||||
matches=()
|
||||
|
||||
while IFS=$'\t' read -r index name; do
|
||||
[ -n "$index" ] || continue
|
||||
[[ "$name" == *"Operating System"* ]] && continue
|
||||
[ -z "$name" ] && continue
|
||||
|
||||
id=$(getVersion "$name" "$platform")
|
||||
[[ "${id,,}" == "${wanted,,}" ]] || continue
|
||||
|
||||
matches+=("$index")
|
||||
done < <(
|
||||
awk -v tag="$tag" '
|
||||
/<IMAGE INDEX="/ {
|
||||
image_index = $0
|
||||
sub(/^.*<IMAGE INDEX="/, "", image_index)
|
||||
sub(/".*$/, "", image_index)
|
||||
}
|
||||
|
||||
image_index != "" && $0 ~ "<" tag ">" {
|
||||
value = $0
|
||||
sub("^.*<" tag ">", "", value)
|
||||
sub("</" tag ">.*$", "", value)
|
||||
print image_index "\t" value
|
||||
}
|
||||
|
||||
/<\/IMAGE>/ {
|
||||
image_index = ""
|
||||
}
|
||||
' <<< "$xml"
|
||||
)
|
||||
|
||||
case "${#matches[@]}" in
|
||||
0 )
|
||||
continue
|
||||
;;
|
||||
1 )
|
||||
echo "${matches[0]}"
|
||||
return 0
|
||||
;;
|
||||
* )
|
||||
# Several WIM entries collapse to the same internal version ID,
|
||||
# so selecting one of their indexes would be arbitrary.
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
detectLanguage() {
|
||||
|
||||
local xml="$1"
|
||||
local lang=""
|
||||
|
||||
if [[ "$xml" == *"LANGUAGE><DEFAULT>"* ]]; then
|
||||
lang="${xml#*LANGUAGE><DEFAULT>}"
|
||||
lang="${lang%%<*}"
|
||||
else
|
||||
if [[ "$xml" == *"FALLBACK><DEFAULT>"* ]]; then
|
||||
lang="${xml#*FALLBACK><DEFAULT>}"
|
||||
lang="${lang%%<*}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$lang" ]; then
|
||||
warn "Language could not be detected from ISO!" && return 0
|
||||
fi
|
||||
|
||||
local culture
|
||||
culture=$(getLanguage "$lang" "culture")
|
||||
[ -n "$culture" ] && LANGUAGE="$lang" && return 0
|
||||
|
||||
warn "Invalid language detected: \"$lang\""
|
||||
return 0
|
||||
}
|
||||
|
||||
skipVersion() {
|
||||
|
||||
local id="$1"
|
||||
|
||||
case "${id,,}" in
|
||||
"win9"* | "winxp"* | "win2k"* | "win2003"* )
|
||||
return 0 ;;
|
||||
esac
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
detectLegacy() {
|
||||
|
||||
local dir="$1"
|
||||
local find
|
||||
|
||||
[[ "${PLATFORM,,}" != "x64" ]] && return 1
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type d -iname WIN95 -print -quit)
|
||||
[ -n "$find" ] && DETECTED="win95" && return 0
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type d -iname WIN98 -print -quit)
|
||||
[ -n "$find" ] && DETECTED="win98" && return 0
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type d -iname WIN9X -print -quit)
|
||||
[ -n "$find" ] && DETECTED="win9x" && return 0
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_W.40 -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_S.40 -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_TS.40 -print -quit)
|
||||
[ -n "$find" ] && DETECTED="winnt4" && return 0
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_NT.5 -print -quit)
|
||||
|
||||
if [ -n "$find" ]; then
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_IA.5 -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_ID.5 -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_IP.5 -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname CDROM_IS.5 -print -quit)
|
||||
[ -n "$find" ] && DETECTED="win2k" && return 0
|
||||
|
||||
fi
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -iname WIN51 -print -quit)
|
||||
|
||||
if [ -n "$find" ]; then
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AP -print -quit)
|
||||
[ -n "$find" ] && DETECTED="winxpx64" && return 0
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IC -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IP -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname setupxp.htm -print -quit)
|
||||
[ -n "$find" ] && DETECTED="winxpx86" && return 0
|
||||
|
||||
find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IS -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IA -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IB -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51ID -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51IL -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AA -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AD -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51AS -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51MA -print -quit)
|
||||
[ -z "$find" ] && find=$(find "$dir" -maxdepth 1 -type f -iname WIN51MD -print -quit)
|
||||
[ -n "$find" ] && DETECTED="win2003r2" && return 0
|
||||
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
detectImage() {
|
||||
|
||||
local dir="$1"
|
||||
local version="$2"
|
||||
local desc msg language
|
||||
local file source
|
||||
|
||||
XML=""
|
||||
|
||||
# For normal download routes, avoid inspecting install.wim when the route
|
||||
# already maps directly to an available answer file. Routes such as Tiny10
|
||||
# and Tiny11 have no corresponding answer file, so their actual Windows
|
||||
# edition will be detected from the downloaded image instead.
|
||||
if [ -z "$DETECTED" ] && [ -z "$CUSTOM" ] &&
|
||||
[ -z "${REUSED_ISO:-}" ] && [[ "${version,,}" != "http"* ]]; then
|
||||
|
||||
file="/run/assets/$version.xml"
|
||||
|
||||
if [ -s "$file" ]; then
|
||||
DETECTED="$version"
|
||||
elif [[ "${version,,}" == *"-eval" ]]; then
|
||||
source="/run/assets/${version%-eval}.xml"
|
||||
[ -s "$source" ] && DETECTED="$version"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if [ -n "$DETECTED" ]; then
|
||||
|
||||
skipVersion "${DETECTED,,}" && return 0
|
||||
|
||||
if ! setXML "" && ! enabled "$MANUAL"; then
|
||||
MANUAL="Y"
|
||||
desc=$(printEdition "$DETECTED" "this version")
|
||||
warn "the answer file for $desc was not found ($DETECTED.xml), $FB."
|
||||
fi
|
||||
|
||||
return 0
|
||||
fi
|
||||
|
||||
info "Detecting version from ISO image..."
|
||||
|
||||
if detectLegacy "$dir"; then
|
||||
desc=$(printEdition "$DETECTED" "$DETECTED" "Y")
|
||||
info "Detected: $desc"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local src wim info index suggested
|
||||
src=$(find "$dir" -maxdepth 1 -type d -iname sources -print -quit)
|
||||
|
||||
if [ ! -d "$src" ]; then
|
||||
warn "failed to locate 'sources' folder in ISO image, $FB"
|
||||
return 1
|
||||
fi
|
||||
|
||||
wim=$(find "$src" -maxdepth 1 -type f \
|
||||
\( -iname install.wim -or -iname install.esd \) -print -quit)
|
||||
|
||||
if [ ! -f "$wim" ]; then
|
||||
warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! info=$(wimlib-imagex info -xml "$wim" |
|
||||
iconv -f UTF-16LE -t UTF-8); then
|
||||
warn "failed to read Windows image information, $FB"
|
||||
return 1
|
||||
fi
|
||||
|
||||
checkPlatform "$info" || exit 67
|
||||
|
||||
suggested=""
|
||||
|
||||
if [ -z "$CUSTOM" ] && [ -n "${REUSED_ISO:-}" ]; then
|
||||
suggested="${SUGGEST:-}"
|
||||
fi
|
||||
|
||||
DETECTED=$(detectVersion "$info" "$suggested")
|
||||
|
||||
if [ -z "$DETECTED" ]; then
|
||||
msg="Failed to determine Windows version from image"
|
||||
|
||||
if setXML "" || enabled "$MANUAL"; then
|
||||
info "${msg}!"
|
||||
else
|
||||
MANUAL="Y"
|
||||
warn "${msg}, $FB."
|
||||
fi
|
||||
|
||||
return 0
|
||||
fi
|
||||
|
||||
index=$(getImageIndex "$info" "$DETECTED") || index=""
|
||||
desc=$(printEdition "$DETECTED" "$DETECTED" "Y")
|
||||
|
||||
detectLanguage "$info"
|
||||
|
||||
if [[ "${LANGUAGE,,}" != "en" && "${LANGUAGE,,}" != "en-"* ]]; then
|
||||
language=$(getLanguage "$LANGUAGE" "desc")
|
||||
desc+=" ($language)"
|
||||
fi
|
||||
|
||||
info "Detected: $desc"
|
||||
setXML "" "$index" && return 0
|
||||
|
||||
if [[ "$DETECTED" == "win81x86"* ||
|
||||
"$DETECTED" == "win10x86"* ]]; then
|
||||
error "The 32-bit version of $desc is not supported!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
msg="the answer file for $desc was not found ($DETECTED.xml)"
|
||||
local fallback="/run/assets/${DETECTED%%-*}.xml"
|
||||
|
||||
if setXML "$fallback" || enabled "$MANUAL"; then
|
||||
! enabled "$MANUAL" && warn "${msg}."
|
||||
else
|
||||
MANUAL="Y"
|
||||
warn "${msg}, $FB."
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
+19
-263
@@ -218,6 +218,18 @@ startInstall() {
|
||||
|
||||
BOOT="$STORAGE/$file"
|
||||
|
||||
REUSED_ISO=""
|
||||
[ -s "$BOOT" ] && REUSED_ISO="Y"
|
||||
|
||||
# Use the suggested answer file for a new automatic download. When an
|
||||
# existing ISO is reused, leave DETECTED empty so its actual image can
|
||||
# be inspected instead.
|
||||
if [ -n "$DETECTED" ]; then
|
||||
DETECTED_ORG="Y"
|
||||
elif [ -z "$REUSED_ISO" ]; then
|
||||
DETECTED="$SUGGEST"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
TMP="$STORAGE/tmp"
|
||||
@@ -677,265 +689,6 @@ extractImage() {
|
||||
return 0
|
||||
}
|
||||
|
||||
getPlatform() {
|
||||
|
||||
local xml="$1"
|
||||
local tag="ARCH"
|
||||
local platform="x64"
|
||||
local arch
|
||||
|
||||
arch=$(sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$xml")
|
||||
|
||||
case "${arch,,}" in
|
||||
"0" ) platform="x86" ;;
|
||||
"9" ) platform="x64" ;;
|
||||
"12" ) platform="arm64" ;;
|
||||
esac
|
||||
|
||||
echo "$platform"
|
||||
return 0
|
||||
}
|
||||
|
||||
checkPlatform() {
|
||||
|
||||
local xml="$1"
|
||||
local platform compat
|
||||
|
||||
platform=$(getPlatform "$xml")
|
||||
|
||||
case "${platform,,}" in
|
||||
"x86" ) compat="x64" ;;
|
||||
"x64" ) compat="$platform" ;;
|
||||
"arm64" ) compat="$platform" ;;
|
||||
* ) compat="${PLATFORM,,}" ;;
|
||||
esac
|
||||
|
||||
[[ "${compat,,}" == "${PLATFORM,,}" ]] && return 0
|
||||
|
||||
error "You cannot boot ${platform^^} images on a $PLATFORM CPU!"
|
||||
return 1
|
||||
}
|
||||
|
||||
hasVersion() {
|
||||
|
||||
local id="$1"
|
||||
local tag="$2"
|
||||
local xml="$3"
|
||||
local edition alternate=""
|
||||
|
||||
[ ! -f "/run/assets/$id.xml" ] && return 1
|
||||
|
||||
edition=$(printEdition "$id" "")
|
||||
[ -z "$edition" ] && return 1
|
||||
|
||||
[[ "${xml,,}" == *"<${tag,,}>${edition,,}</${tag,,}>"* ]] && return 0
|
||||
|
||||
case "${id,,}" in
|
||||
*"-iot" | *"-iot-eval" )
|
||||
alternate="${id/-iot/-ltsc}" ;;
|
||||
*"-ltsc" | *"-ltsc-eval" )
|
||||
alternate="${id/-ltsc/-iot}" ;;
|
||||
* ) return 1 ;;
|
||||
esac
|
||||
|
||||
edition=$(printEdition "$alternate" "")
|
||||
[ -z "$edition" ] && return 1
|
||||
|
||||
[[ "${xml,,}" == *"<${tag,,}>${edition,,}</${tag,,}>"* ]] && return 0
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
selectVersion() {
|
||||
|
||||
local tag="$1"
|
||||
local xml="$2"
|
||||
local platform="$3"
|
||||
local id name prefer
|
||||
|
||||
name=$(sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$xml")
|
||||
[[ "$name" == *"Operating System"* ]] && name=""
|
||||
[ -z "$name" ] && return 0
|
||||
|
||||
id=$(fromName "$name" "$platform")
|
||||
[ -z "$id" ] && warn "Unknown ${tag,,}: '$name'" && return 0
|
||||
|
||||
if [ -n "$EDITION" ] && [[ "$id" != win20* ]]; then
|
||||
case "${EDITION,,}" in
|
||||
"pro" | "professional" | "business" ) prefer="$id" ;;
|
||||
* ) prefer="$id-${EDITION,,}" ;;
|
||||
esac
|
||||
|
||||
if hasVersion "$prefer" "$tag" "$xml"; then
|
||||
echo "$prefer"
|
||||
return 0
|
||||
fi
|
||||
|
||||
warn "Edition '$EDITION' is not supported by this image, using automatic selection instead."
|
||||
fi
|
||||
|
||||
prefer="$id-enterprise"
|
||||
hasVersion "$prefer" "$tag" "$xml" && echo "$prefer" && return 0
|
||||
|
||||
prefer="$id-ultimate"
|
||||
hasVersion "$prefer" "$tag" "$xml" && echo "$prefer" && return 0
|
||||
|
||||
prefer="$id"
|
||||
hasVersion "$prefer" "$tag" "$xml" && echo "$prefer" && return 0
|
||||
|
||||
prefer=$(getVersion "$name" "$platform")
|
||||
|
||||
echo "$prefer"
|
||||
return 0
|
||||
}
|
||||
|
||||
detectVersion() {
|
||||
|
||||
local xml="$1"
|
||||
local id platform
|
||||
|
||||
platform=$(getPlatform "$xml")
|
||||
id=$(selectVersion "DISPLAYNAME" "$xml" "$platform")
|
||||
[ -z "$id" ] && id=$(selectVersion "PRODUCTNAME" "$xml" "$platform")
|
||||
[ -z "$id" ] && id=$(selectVersion "NAME" "$xml" "$platform")
|
||||
|
||||
echo "$id"
|
||||
return 0
|
||||
}
|
||||
|
||||
detectLanguage() {
|
||||
|
||||
local xml="$1"
|
||||
local lang=""
|
||||
|
||||
if [[ "$xml" == *"LANGUAGE><DEFAULT>"* ]]; then
|
||||
lang="${xml#*LANGUAGE><DEFAULT>}"
|
||||
lang="${lang%%<*}"
|
||||
else
|
||||
if [[ "$xml" == *"FALLBACK><DEFAULT>"* ]]; then
|
||||
lang="${xml#*FALLBACK><DEFAULT>}"
|
||||
lang="${lang%%<*}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$lang" ]; then
|
||||
warn "Language could not be detected from ISO!" && return 0
|
||||
fi
|
||||
|
||||
local culture
|
||||
culture=$(getLanguage "$lang" "culture")
|
||||
[ -n "$culture" ] && LANGUAGE="$lang" && return 0
|
||||
|
||||
warn "Invalid language detected: \"$lang\""
|
||||
return 0
|
||||
}
|
||||
|
||||
skipVersion() {
|
||||
|
||||
local id="$1"
|
||||
|
||||
case "${id,,}" in
|
||||
"win9"* | "winxp"* | "win2k"* | "win2003"* )
|
||||
return 0 ;;
|
||||
esac
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
detectImage() {
|
||||
|
||||
local dir="$1"
|
||||
local version="$2"
|
||||
local desc msg language
|
||||
|
||||
XML=""
|
||||
|
||||
if [ -z "$DETECTED" ] && [ -z "$CUSTOM" ]; then
|
||||
[[ "${version,,}" != "http"* ]] && DETECTED="$version"
|
||||
fi
|
||||
|
||||
if [ -n "$DETECTED" ]; then
|
||||
|
||||
skipVersion "${DETECTED,,}" && return 0
|
||||
|
||||
if ! setXML "" && ! enabled "$MANUAL"; then
|
||||
MANUAL="Y"
|
||||
desc=$(printEdition "$DETECTED" "this version")
|
||||
warn "the answer file for $desc was not found ($DETECTED.xml), $FB."
|
||||
fi
|
||||
|
||||
return 0
|
||||
fi
|
||||
|
||||
info "Detecting version from ISO image..."
|
||||
|
||||
if detectLegacy "$dir"; then
|
||||
desc=$(printEdition "$DETECTED" "$DETECTED")
|
||||
info "Detected: $desc"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local src wim info
|
||||
src=$(find "$dir" -maxdepth 1 -type d -iname sources -print -quit)
|
||||
|
||||
if [ ! -d "$src" ]; then
|
||||
warn "failed to locate 'sources' folder in ISO image, $FB" && return 1
|
||||
fi
|
||||
|
||||
wim=$(find "$src" -maxdepth 1 -type f \( -iname install.wim -or -iname install.esd \) -print -quit)
|
||||
|
||||
if [ ! -f "$wim" ]; then
|
||||
warn "failed to locate 'install.wim' or 'install.esd' in ISO image, $FB" && return 1
|
||||
fi
|
||||
|
||||
if ! info=$(wimlib-imagex info -xml "$wim" | iconv -f UTF-16LE -t UTF-8); then
|
||||
warn "failed to read Windows image information, $FB"
|
||||
return 1
|
||||
fi
|
||||
|
||||
checkPlatform "$info" || exit 67
|
||||
|
||||
DETECTED=$(detectVersion "$info")
|
||||
|
||||
if [ -z "$DETECTED" ]; then
|
||||
msg="Failed to determine Windows version from image"
|
||||
if setXML "" || enabled "$MANUAL"; then
|
||||
info "${msg}!"
|
||||
else
|
||||
MANUAL="Y"
|
||||
warn "${msg}, $FB."
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
desc=$(printEdition "$DETECTED" "$DETECTED")
|
||||
detectLanguage "$info"
|
||||
|
||||
if [[ "${LANGUAGE,,}" != "en" && "${LANGUAGE,,}" != "en-"* ]]; then
|
||||
language=$(getLanguage "$LANGUAGE" "desc")
|
||||
desc+=" ($language)"
|
||||
fi
|
||||
|
||||
info "Detected: $desc"
|
||||
setXML "" && return 0
|
||||
|
||||
if [[ "$DETECTED" == "win81x86"* || "$DETECTED" == "win10x86"* ]]; then
|
||||
error "The 32-bit version of $desc is not supported!" && return 1
|
||||
fi
|
||||
|
||||
msg="the answer file for $desc was not found ($DETECTED.xml)"
|
||||
local fallback="/run/assets/${DETECTED%%-*}.xml"
|
||||
|
||||
if setXML "$fallback" || enabled "$MANUAL"; then
|
||||
! enabled "$MANUAL" && warn "${msg}."
|
||||
else
|
||||
MANUAL="Y"
|
||||
warn "${msg}, $FB."
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
setMachine() {
|
||||
|
||||
local id="$1"
|
||||
@@ -1005,10 +758,13 @@ prepareImage() {
|
||||
|
||||
if [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then
|
||||
|
||||
[ -f "$dir/$ETFS" ] && [ -f "$dir/$EFISYS" ] && return 0
|
||||
|
||||
[ -f "$dir/$ETFS" ] && [ -s "$dir/$ETFS" ] &&
|
||||
[ -f "$dir/$EFISYS" ] && [ -s "$dir/$EFISYS" ] && return 0
|
||||
|
||||
missing=$(basename "$dir/$EFISYS")
|
||||
[ ! -f "$dir/$ETFS" ] && missing=$(basename "$dir/$ETFS")
|
||||
if [ ! -f "$dir/$ETFS" ] || [ ! -s "$dir/$ETFS" ]; then
|
||||
missing=$(basename "$dir/$ETFS")
|
||||
fi
|
||||
|
||||
error "Failed to locate file \"${missing,,}\" in ISO image!"
|
||||
return 1
|
||||
@@ -1369,7 +1125,7 @@ buildImage() {
|
||||
|
||||
[ -z "$LABEL" ] && LABEL="Windows"
|
||||
|
||||
if [ ! -f "$dir/$ETFS" ]; then
|
||||
if [ ! -f "$dir/$ETFS" ] || [ ! -s "$dir/$ETFS" ]; then
|
||||
error "Failed to locate file \"$ETFS\" in ISO image!" && return 1
|
||||
fi
|
||||
|
||||
|
||||
+133
-33
@@ -68,7 +68,7 @@ curlRequest() {
|
||||
if (( rc != 0 )); then
|
||||
|
||||
reason=$(sed -nE 's/^curl: \([0-9]+\) //p' "$log" | tail -n 1)
|
||||
|
||||
|
||||
rm -f "$log"
|
||||
handleCurlError "$rc" "$server" "$reason"
|
||||
|
||||
@@ -124,10 +124,6 @@ downloadWindows() {
|
||||
fi
|
||||
|
||||
# Get product edition ID for latest release of given Windows version
|
||||
# Product edition ID: This specifies both the Windows release (e.g. 22H2) and edition ("multi-edition" is default, either Home/Pro/Edu/etc., we select "Pro" in the answer files) in one number
|
||||
# This is the *only* request we make that Fido doesn't. Fido manually maintains a list of all the Windows release/edition product edition IDs in its script (see: $WindowsVersions array). This is helpful for downloading older releases (e.g. Windows 10 1909, 21H1, etc.) but we always want to get the newest release which is why we get this value dynamically
|
||||
# Also, keeping a "$WindowsVersions" array like Fido does would be way too much of a maintenance burden
|
||||
# Remove "Accept" header that curl sends by default
|
||||
enabled "$DEBUG" && echo "Parsing download page: ${url}"
|
||||
|
||||
curlRequest page "Microsoft" "$agent" \
|
||||
@@ -415,29 +411,99 @@ downloadWindowsEval() {
|
||||
return 0
|
||||
}
|
||||
|
||||
getMidoDetected() {
|
||||
|
||||
# Return the answer-file identity for the Microsoft source that actually
|
||||
# succeeded without changing the global DETECTED value.
|
||||
|
||||
local version="${1,,}"
|
||||
local source="${2,,}"
|
||||
local current="$3"
|
||||
local default="$version"
|
||||
local detected
|
||||
|
||||
[ -z "$source" ] && source="$version"
|
||||
|
||||
# Preserve a DETECTED value that existed before SUGGEST was assigned.
|
||||
if enabled "${DETECTED_ORG:-}"; then
|
||||
echo "$current"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Derive the normal answer-file identity from the requested download route.
|
||||
case "$default" in
|
||||
*"-enterprise-ltsc-eval" )
|
||||
default="${default%-enterprise-ltsc-eval}-ltsc"
|
||||
;;
|
||||
*"-enterprise-iot-eval" )
|
||||
default="${default%-enterprise-iot-eval}-iot"
|
||||
;;
|
||||
*"-eval" )
|
||||
default="${default%-eval}"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Preserve a genuinely different DETECTED override.
|
||||
if [ -n "$current" ] && [[ "${current,,}" != "$default" ]]; then
|
||||
echo "$current"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Select the answer-file identity for the source that actually succeeded.
|
||||
case "$source" in
|
||||
*"-enterprise-ltsc-eval" )
|
||||
detected="${source%-enterprise-ltsc-eval}-ltsc-eval"
|
||||
;;
|
||||
*"-enterprise-iot-eval" )
|
||||
detected="${source%-enterprise-iot-eval}-iot"
|
||||
;;
|
||||
*"-eval" )
|
||||
detected="$source"
|
||||
;;
|
||||
* )
|
||||
detected="${current:-$default}"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$detected"
|
||||
return 0
|
||||
}
|
||||
|
||||
downloadWindowsLtsc() {
|
||||
|
||||
local id="$1"
|
||||
local lang="$2"
|
||||
local desc="$3"
|
||||
local alternate=""
|
||||
local alternate_desc=""
|
||||
|
||||
case "${id,,}" in
|
||||
"win11${PLATFORM,,}-enterprise-iot-eval" )
|
||||
alternate="win11${PLATFORM,,}-enterprise-ltsc-eval" ;;
|
||||
alternate="win11${PLATFORM,,}-enterprise-ltsc-eval"
|
||||
;;
|
||||
"win11${PLATFORM,,}-enterprise-ltsc-eval" )
|
||||
alternate="win11${PLATFORM,,}-enterprise-iot-eval" ;;
|
||||
* ) error "Invalid VERSION specified, value \"$id\" is not recognized!"
|
||||
return 1 ;;
|
||||
alternate="win11${PLATFORM,,}-enterprise-iot-eval"
|
||||
;;
|
||||
* )
|
||||
error "Invalid VERSION specified, value \"$id\" is not recognized!"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if downloadWindowsEval "$id" "$lang" "$desc" > /dev/null 2>&1; then
|
||||
MIDO_SOURCE="$id"
|
||||
return 0
|
||||
fi
|
||||
|
||||
info "Primary download source failed, trying the alternate LTSC source..."
|
||||
alternate_desc=$(printEdition "$alternate" "$alternate" "Y")
|
||||
|
||||
downloadWindowsEval "$alternate" "$lang" "$desc" && return 0
|
||||
info "Primary download source failed, trying $alternate_desc instead..."
|
||||
|
||||
if downloadWindowsEval "$alternate" "$lang" "$alternate_desc"; then
|
||||
MIDO_SOURCE="$alternate"
|
||||
warn "the requested $desc was unavailable, using $alternate_desc instead."
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
@@ -447,19 +513,24 @@ getWindows() {
|
||||
local version="$1"
|
||||
local lang="$2"
|
||||
local desc="$3"
|
||||
|
||||
local language edition
|
||||
|
||||
MIDO_SOURCE=""
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
edition=$(printEdition "$version" "$desc")
|
||||
edition=$(printEdition "$version" "$desc" "Y")
|
||||
|
||||
local msg="Requesting $desc from the Microsoft servers..."
|
||||
info "$msg" && html "$msg"
|
||||
|
||||
case "${version,,}" in
|
||||
"win2008r2" | "win81${PLATFORM,,}"* | "win10${PLATFORM,,}-enterprise"* )
|
||||
"win2008r2"* | \
|
||||
"win81${PLATFORM,,}"* | \
|
||||
"win10${PLATFORM,,}-enterprise"* | \
|
||||
"win11${PLATFORM,,}-enterprise-iot-eval" )
|
||||
if [[ "${lang,,}" != "en" && "${lang,,}" != "en-"* ]]; then
|
||||
error "No download in the $language language available for $edition!"
|
||||
MIDO_URL="" && return 1
|
||||
MIDO_URL=""
|
||||
return 1
|
||||
fi ;;
|
||||
esac
|
||||
|
||||
@@ -469,32 +540,57 @@ getWindows() {
|
||||
* )
|
||||
if [[ "${PLATFORM,,}" != "x64" ]]; then
|
||||
error "No download for the ${PLATFORM^^} platform available for $edition!"
|
||||
MIDO_URL="" && return 1
|
||||
MIDO_URL=""
|
||||
return 1
|
||||
fi ;;
|
||||
esac
|
||||
|
||||
case "${version,,}" in
|
||||
"win11${PLATFORM,,}" )
|
||||
downloadWindows "$version" "$lang" "$edition" && return 0
|
||||
;;
|
||||
|
||||
if downloadWindows "$version" "$lang" "$edition"; then
|
||||
MIDO_SOURCE="$version"
|
||||
return 0
|
||||
fi ;;
|
||||
|
||||
"win11${PLATFORM,,}-enterprise-iot-eval" | \
|
||||
"win11${PLATFORM,,}-enterprise-ltsc-eval" )
|
||||
|
||||
downloadWindowsLtsc "$version" "$lang" "$edition" && return 0
|
||||
;;
|
||||
|
||||
"win11${PLATFORM,,}-enterprise"* )
|
||||
downloadWindowsEval "$version" "$lang" "$edition" && return 0
|
||||
|
||||
if downloadWindowsEval "$version" "$lang" "$edition"; then
|
||||
MIDO_SOURCE="$version"
|
||||
return 0
|
||||
fi ;;
|
||||
|
||||
"win2025-eval" | "win2022-eval" | "win2019-eval" | \
|
||||
"win2019-hv" | "win2016-eval" | "win2012r2-eval" )
|
||||
|
||||
if downloadWindowsEval "$version" "$lang" "$edition"; then
|
||||
MIDO_SOURCE="$version"
|
||||
return 0
|
||||
fi ;;
|
||||
|
||||
"win2008r2"*| "win81${PLATFORM,,}"* | "win10${PLATFORM,,}-enterprise"* ) ;;
|
||||
|
||||
* )
|
||||
error "Invalid VERSION specified, value \"$version\" is not recognized!"
|
||||
return 1
|
||||
;;
|
||||
"win2025-eval" | "win2022-eval" | "win2019-eval" | "win2019-hv" | "win2016-eval" | "win2012r2-eval" )
|
||||
downloadWindowsEval "$version" "$lang" "$edition" && return 0
|
||||
;;
|
||||
"win2008r2" | "win81${PLATFORM,,}"* | "win10${PLATFORM,,}-enterprise"* )
|
||||
;;
|
||||
* ) error "Invalid VERSION specified, value \"$version\" is not recognized!" ;;
|
||||
esac
|
||||
|
||||
MIDO_URL=$(getMido "$version" "$lang" "")
|
||||
[ -z "$MIDO_URL" ] && return 1
|
||||
|
||||
if [[ "${version,,}" == "win2008r2"* ]]; then
|
||||
MIDO_SOURCE="win2008r2-eval"
|
||||
return 0
|
||||
fi
|
||||
|
||||
MIDO_SOURCE="$version"
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -668,7 +764,7 @@ getESD() {
|
||||
|
||||
fi
|
||||
|
||||
if [ ! -s "$dir/$xmlFile" ]; then
|
||||
if [ ! -f "$dir/$xmlFile" ] || [ ! -s "$dir/$xmlFile" ]; then
|
||||
error "Failed to find $xmlFile in $file!"
|
||||
return 1
|
||||
fi
|
||||
@@ -682,7 +778,7 @@ getESD() {
|
||||
result=$(xmllint --nonet --xpath "${query}" "$dir/$xmlFile" 2>/dev/null || true)
|
||||
|
||||
if [ -z "$result" ]; then
|
||||
desc=$(printEdition "$version" "$desc")
|
||||
desc=$(printEdition "$version" "$desc" "Y")
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
error "No download link available for $desc!"
|
||||
return 1
|
||||
@@ -697,7 +793,7 @@ getESD() {
|
||||
result=$(xmllint --nonet --xpath "//File[LanguageCode=\"${culture,,}\"]" "$dir/$filterFile" 2>/dev/null || true)
|
||||
|
||||
if [ -z "$result" ]; then
|
||||
desc=$(printEdition "$version" "$desc")
|
||||
desc=$(printEdition "$version" "$desc" "Y")
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
error "No download in the $language language available for $desc!"
|
||||
return 1
|
||||
@@ -899,6 +995,7 @@ downloadImage() {
|
||||
local tried="n"
|
||||
local success="n"
|
||||
local seconds="5"
|
||||
local detected="$DETECTED"
|
||||
local url sum size base desc language i
|
||||
|
||||
if [[ "${version,,}" == "http"* ]]; then
|
||||
@@ -915,14 +1012,14 @@ downloadImage() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
desc=$(printVariant "$version" "")
|
||||
desc=$(printVariant "$version" "" "Y")
|
||||
|
||||
if [[ "${lang,,}" != "en" && "${lang,,}" != "en-"* ]]; then
|
||||
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
|
||||
if ! validVersion "$version" "$lang"; then
|
||||
desc=$(printEdition "$version" "$desc")
|
||||
desc=$(printEdition "$version" "$desc" "Y")
|
||||
desc+=" in $language"
|
||||
|
||||
fallbackEnglish "$iso" "$version" "$lang" "$desc" && return 0
|
||||
@@ -946,6 +1043,7 @@ downloadImage() {
|
||||
|
||||
if [[ "$success" == "y" ]]; then
|
||||
|
||||
detected=$(getMidoDetected "$version" "$MIDO_SOURCE" "$DETECTED")
|
||||
url=$(getMido "$version" "$lang" "")
|
||||
|
||||
sum=""
|
||||
@@ -957,13 +1055,15 @@ downloadImage() {
|
||||
sum=$(getMido "$version" "$lang" "sum")
|
||||
fi
|
||||
|
||||
tryDownload "$iso" "$MIDO_URL" "$sum" "$size" "$lang" "$desc" "$seconds" && return 0
|
||||
if tryDownload "$iso" "$MIDO_URL" "$sum" "$size" "$lang" "$desc" "$seconds"; then
|
||||
# Commit the candidate only after the image was downloaded and verified.
|
||||
DETECTED="$detected"
|
||||
return 0
|
||||
fi
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
switchEdition "$version"
|
||||
|
||||
if isESD "$version" "$lang"; then
|
||||
|
||||
if [[ "$tried" != "n" ]]; then
|
||||
|
||||
Reference in New Issue
Block a user