feat: Improved installation (#483)

This commit is contained in:
Kroese 2024-05-10 18:21:41 +02:00 committed by GitHub
parent 5a000c1f9e
commit f7986f57ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 199 additions and 94 deletions

View File

@ -984,7 +984,7 @@ migrateFiles() {
[[ "${version,,}" == "win7${PLATFORM,,}" ]] && file="en_windows_7_enterprise_with_sp1_${PLATFORM,,}_dvd_u_677651.iso" [[ "${version,,}" == "win7${PLATFORM,,}" ]] && file="en_windows_7_enterprise_with_sp1_${PLATFORM,,}_dvd_u_677651.iso"
[ ! -f "$STORAGE/$file" ] && return 0 [ ! -f "$STORAGE/$file" ] && return 0
! mv "$STORAGE/$file" "$base" && return 1 ! mv -f "$STORAGE/$file" "$base" && return 1
return 0 return 0
} }
@ -1199,15 +1199,17 @@ prepareLegacy() {
local iso="$1" local iso="$1"
local dir="$2" local dir="$2"
local file="$dir/boot.img"
ETFS="boot.img" ETFS=$(basename "$file")
rm -f "$dir/$ETFS" [ -f "$file" ] && [ -s "$file" ] && return 0
rm -f "$file"
local len offset local len offset
len=$(isoinfo -d -i "$iso" | grep "Nsect " | grep -o "[^ ]*$") len=$(isoinfo -d -i "$iso" | grep "Nsect " | grep -o "[^ ]*$")
offset=$(isoinfo -d -i "$iso" | grep "Bootoff " | grep -o "[^ ]*$") offset=$(isoinfo -d -i "$iso" | grep "Bootoff " | grep -o "[^ ]*$")
dd "if=$iso" "of=$dir/$ETFS" bs=2048 "count=$len" "skip=$offset" status=none && return 0 dd "if=$iso" "of=$file" bs=2048 "count=$len" "skip=$offset" status=none && return 0
return 1 return 1
} }

View File

@ -31,7 +31,7 @@ skipInstall() {
startInstall() { startInstall() {
html "Starting Windows..." html "Starting $APP..."
if [ -n "$CUSTOM" ]; then if [ -n "$CUSTOM" ]; then
@ -59,23 +59,37 @@ startInstall() {
if [ -f "$ISO" ] && [ -s "$ISO" ]; then if [ -f "$ISO" ] && [ -s "$ISO" ]; then
# Check if the ISO was already processed by our script
local magic local magic
local byte="16" local auto="16"
[[ "$MANUAL" == [Yy1]* ]] && byte="17" local manual="17"
local byte="$auto"
[[ "$MANUAL" == [Yy1]* ]] && byte="$manual"
# Check if the ISO was already processed by our script
magic=$(dd if="$ISO" seek=0 bs=1 count=1 status=none | tr -d '\000') magic=$(dd if="$ISO" seek=0 bs=1 count=1 status=none | tr -d '\000')
magic="$(printf '%s' "$magic" | od -A n -t x1 -v | tr -d ' \n')" magic="$(printf '%s' "$magic" | od -A n -t x1 -v | tr -d ' \n')"
[[ "$magic" == "$byte" ]] && return 1 if [[ "$magic" == "$byte" ]]; then
if [ -z "$CUSTOM" ] || [ -n "$ORIGINAL" ]; then
return 1
fi
fi
fi fi
rm -rf "$TMP"
mkdir -p "$TMP"
if [ -z "$CUSTOM" ]; then if [ -z "$CUSTOM" ]; then
BOOT="$ISO" BOOT="$ISO"
ISO=$(basename "$ISO") ISO=$(basename "$ISO")
ISO="$TMP/$ISO" ISO="$TMP/$ISO"
if [ -f "$BOOT" ] && [ -s "$BOOT" ]; then
mv -f "$BOOT" "$ISO"
fi
else else
if [ -n "$ORIGINAL" ]; then if [ -n "$ORIGINAL" ]; then
@ -91,8 +105,6 @@ startInstall() {
fi fi
rm -f "$BOOT" rm -f "$BOOT"
rm -rf "$TMP"
mkdir -p "$TMP"
return 0 return 0
} }
@ -118,7 +130,7 @@ finishInstall() {
rm -f "$STORAGE/windows.boot" rm -f "$STORAGE/windows.boot"
rm -f "$STORAGE/windows.mode" rm -f "$STORAGE/windows.mode"
cp /run/version "$STORAGE/windows.ver" cp -f /run/version "$STORAGE/windows.ver"
if [[ "${PLATFORM,,}" == "x64" ]]; then if [[ "${PLATFORM,,}" == "x64" ]]; then
if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then
@ -174,19 +186,18 @@ detectCustom() {
base="${VERSION/\/storage\//}" base="${VERSION/\/storage\//}"
[[ "$base" == "."* ]] && base="${file:1}" [[ "$base" == "."* ]] && base="${file:1}"
[[ "$base" == *"/"* ]] && base="" [[ "$base" == *"/"* ]] && base=""
[ -n "$base" ] && file=$(find "$STORAGE" -maxdepth 1 -type f -iname "$base" -printf "%f\n" | head -n 1) [ -n "$base" ] && file=$(find "$STORAGE" -maxdepth 1 -type f -iname "$base" | head -n 1)
fi fi
[ -z "$file" ] && file=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.iso -printf "%f\n" | head -n 1) [ -z "$file" ] && file=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.iso | head -n 1)
[ -z "$file" ] && file=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.img -printf "%f\n" | head -n 1) [ -z "$file" ] && file=$(find "$STORAGE" -maxdepth 1 -type f -iname custom.img | head -n 1)
[ -n "$file" ] && file="$STORAGE/$file"
base="/custom.iso" base="/custom.iso"
[ -f "$base" ] && [ -s "$base" ] && file="$base" [ -f "$base" ] && [ -s "$base" ] && file="$base"
[ -z "$file" ] && return 0 if [ ! -f "$file" ] || [ ! -s "$file" ]; then
[ ! -f "$file" ] && return 0 return 0
[ ! -s "$file" ] && return 0 fi
size="$(stat -c%s "$file")" size="$(stat -c%s "$file")"
[ -z "$size" ] || [[ "$size" == "0" ]] && return 0 [ -z "$size" ] || [[ "$size" == "0" ]] && return 0
@ -197,8 +208,8 @@ detectCustom() {
CUSTOM="$base" CUSTOM="$base"
ORIGINAL="$file" ORIGINAL="$file"
else else
CUSTOM="$file"
rm -f "$base" rm -f "$base"
CUSTOM="$file"
fi fi
return 0 return 0
@ -499,20 +510,20 @@ extractESD() {
fi fi
local esdImageCount local esdImageCount
esdImageCount=$(wimlib-imagex info "${iso}" | awk '/Image Count:/ {print $3}') esdImageCount=$(wimlib-imagex info "$iso" | awk '/Image Count:/ {print $3}')
wimlib-imagex apply "$iso" 1 "${dir}" --quiet 2>/dev/null || { wimlib-imagex apply "$iso" 1 "$dir" --quiet 2>/dev/null || {
retVal=$? retVal=$?
error "Extracting $desc bootdisk failed" && return $retVal error "Extracting $desc bootdisk failed" && return $retVal
} }
local bootWimFile="${dir}/sources/boot.wim" local bootWimFile="$dir/sources/boot.wim"
local installWimFile="${dir}/sources/install.wim" local installWimFile="$dir/sources/install.wim"
local msg="Extracting $desc environment..." local msg="Extracting $desc environment..."
info "$msg" && html "$msg" info "$msg" && html "$msg"
wimlib-imagex export "${iso}" 2 "${bootWimFile}" --compress=LZX --chunk-size 32K --quiet || { wimlib-imagex export "$iso" 2 "$bootWimFile" --compress=LZX --chunk-size 32K --quiet || {
retVal=$? retVal=$?
error "Adding WinPE failed" && return ${retVal} error "Adding WinPE failed" && return ${retVal}
} }
@ -520,7 +531,7 @@ extractESD() {
local msg="Extracting $desc setup..." local msg="Extracting $desc setup..."
info "$msg" && html "$msg" info "$msg" && html "$msg"
wimlib-imagex export "${iso}" 3 "$bootWimFile" --compress=LZX --chunk-size 32K --boot --quiet || { wimlib-imagex export "$iso" 3 "$bootWimFile" --compress=LZX --chunk-size 32K --boot --quiet || {
retVal=$? retVal=$?
error "Adding Windows Setup failed" && return ${retVal} error "Adding Windows Setup failed" && return ${retVal}
} }
@ -542,11 +553,11 @@ extractESD() {
fi fi
for (( imageIndex=4; imageIndex<=esdImageCount; imageIndex++ )); do for (( imageIndex=4; imageIndex<=esdImageCount; imageIndex++ )); do
imageEdition=$(wimlib-imagex info "${iso}" ${imageIndex} | grep '^Description:' | sed 's/Description:[ \t]*//') imageEdition=$(wimlib-imagex info "$iso" ${imageIndex} | grep '^Description:' | sed 's/Description:[ \t]*//')
[[ "${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 $desc image failed" && return $retVal error "Addition of $imageIndex to the $desc image failed" && return $retVal
} }
return 0 return 0
done done
@ -606,22 +617,50 @@ extractImage() {
setXML() { setXML() {
[[ "$MANUAL" == [Yy1]* ]] && return 0
local file="/custom.xml" local file="/custom.xml"
[ -f "$file" ] && [ -s "$file" ] && XML="$file" && return 0 [ ! -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
file="$STORAGE/custom.xml" XML="$file"
[ -f "$file" ] && [ -s "$file" ] && XML="$file" && return 0 return 0
}
file="/run/assets/custom.xml" getPlatform() {
[ -f "$file" ] && [ -s "$file" ] && XML="$file" && return 0
file="$1" local xml="$1"
[ -z "$file" ] && file="/run/assets/$DETECTED.xml" local tag="ARCH"
[ -f "$file" ] && [ -s "$file" ] && XML="$file" && return 0 local platform="x64"
local arch
return 1 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
}
hasVersion() {
local id="$1"
local tag="$2"
local xml="$3"
local edition
[ ! -f "/run/assets/$id.xml" ] && return 1
edition=$(printEdition "$id" "")
[ -z "$edition" ] && return 1
[[ "${xml,,}" != *"<${tag,,}>${edition,,}</${tag,,}>"* ]] && return 1
return 0
} }
selectVersion() { selectVersion() {
@ -629,7 +668,7 @@ selectVersion() {
local tag="$1" local tag="$1"
local xml="$2" local xml="$2"
local platform="$3" local platform="$3"
local id find name prefer local id name prefer
name=$(sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$xml") name=$(sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$xml")
[[ "$name" == *"Operating System"* ]] && name="" [[ "$name" == *"Operating System"* ]] && name=""
@ -639,22 +678,13 @@ selectVersion() {
[ -z "$id" ] && warn "Unknown ${tag,,}: '$name'" && return 0 [ -z "$id" ] && warn "Unknown ${tag,,}: '$name'" && return 0
prefer="$id-enterprise" prefer="$id-enterprise"
[ -f "/run/assets/$prefer.xml" ] && find=$(printEdition "$prefer" "") || find="" hasVersion "$prefer" "$tag" "$xml" && echo "$prefer" && return 0
if [ -n "$find" ] && [[ "${xml,,}" == *"<${tag,,}>${find,,}</${tag,,}>"* ]]; then
echo "$prefer" && return 0
fi
prefer="$id-ultimate" prefer="$id-ultimate"
[ -f "/run/assets/$prefer.xml" ] && find=$(printEdition "$prefer" "") || find="" hasVersion "$prefer" "$tag" "$xml" && echo "$prefer" && return 0
if [ -n "$find" ] && [[ "${xml,,}" == *"<${tag,,}>${find,,}</${tag,,}>"* ]]; then
echo "$prefer" && return 0
fi
prefer="$id" prefer="$id"
[ -f "/run/assets/$prefer.xml" ] && find=$(printEdition "$prefer" "") || find="" hasVersion "$prefer" "$tag" "$xml" && echo "$prefer" && return 0
if [ -n "$find" ] && [[ "${xml,,}" == *"<${tag,,}>${find,,}</${tag,,}>"* ]]; then
echo "$prefer" && return 0
fi
prefer=$(getVersion "$name" "$platform") prefer=$(getVersion "$name" "$platform")
@ -662,32 +692,37 @@ selectVersion() {
return 0 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
}
detectVersion() { detectVersion() {
local xml="$1" local xml="$1"
local id arch local id platform
local tag="ARCH"
local platform="x64"
local compat="$platform"
arch=$(sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$xml")
case "${arch,,}" in
"0" ) platform="x86"; compat="x64" ;;
"9" ) platform="x64"; compat="$platform" ;;
"12" )platform="arm64"; compat="$platform" ;;
esac
if [[ "${compat,,}" != "${PLATFORM,,}" ]]; then
error "You cannot boot ${platform^^} images on a $PLATFORM cpu!"
exit 67
fi
platform=$(getPlatform "$xml")
id=$(selectVersion "DISPLAYNAME" "$xml" "$platform") id=$(selectVersion "DISPLAYNAME" "$xml" "$platform")
[ -z "$id" ] && id=$(selectVersion "PRODUCTNAME" "$xml" "$platform") [ -z "$id" ] && id=$(selectVersion "PRODUCTNAME" "$xml" "$platform")
[ -z "$id" ] && id=$(selectVersion "NAME" "$xml" "$platform") [ -z "$id" ] && id=$(selectVersion "NAME" "$xml" "$platform")
[ -n "$id" ] && [[ "${id,,}" != *"unknown"* ]] && echo "$id" && return 0
echo "$id"
return 0 return 0
} }
@ -707,10 +742,12 @@ detectImage() {
[[ "${DETECTED,,}" == "winxp"* ]] && return 0 [[ "${DETECTED,,}" == "winxp"* ]] && return 0
setXML "" && return 0 if ! setXML "" && [[ "$MANUAL" != [Yy1]* ]]; then
MANUAL="Y"
desc=$(printEdition "$DETECTED" "this version") desc=$(printEdition "$DETECTED" "this version")
warn "the answer file for $desc was not found ($DETECTED.xml), $FB." warn "the answer file for $desc was not found ($DETECTED.xml), $FB."
fi
return 0 return 0
fi fi
@ -740,12 +777,19 @@ detectImage() {
fi fi
info=$(wimlib-imagex info -xml "$loc" | tr -d '\000') info=$(wimlib-imagex info -xml "$loc" | tr -d '\000')
! checkPlatform "$info" && exit 67
DETECTED=$(detectVersion "$info") DETECTED=$(detectVersion "$info")
if [ -z "$DETECTED" ]; then if [ -z "$DETECTED" ]; then
msg="Failed to determine Windows version from image" msg="Failed to determine Windows version from image"
setXML "" && info "${msg}!" && return 0 if setXML "" || [[ "$MANUAL" == [Yy1]* ]]; then
warn "${msg}, $FB" && return 0 info "${msg}!"
else
MANUAL="Y"
warn "${msg}, $FB."
fi
return 0
fi fi
desc=$(printEdition "$DETECTED" "$DETECTED") desc=$(printEdition "$DETECTED" "$DETECTED")
@ -756,9 +800,13 @@ detectImage() {
msg="the answer file for $desc was not found ($DETECTED.xml)" msg="the answer file for $desc was not found ($DETECTED.xml)"
local fallback="/run/assets/${DETECTED%%-*}.xml" local fallback="/run/assets/${DETECTED%%-*}.xml"
setXML "$fallback" && warn "${msg}." && return 0 if setXML "$fallback" || [[ "$MANUAL" == [Yy1]* ]]; then
[[ "$MANUAL" != [Yy1]* ]] && warn "${msg}."
else
MANUAL="Y"
warn "${msg}, $FB." warn "${msg}, $FB."
fi
return 0 return 0
} }
@ -800,12 +848,18 @@ updateImage() {
local dir="$1" local dir="$1"
local asset="$2" local asset="$2"
local path src loc xml index result local file="autounattend.xml"
local org="${file/.xml/.org}"
local dat="${file/.xml/.dat}"
local desc path src loc xml index result
[ ! -s "$asset" ] || [ ! -f "$asset" ] && return 0 if [ ! -s "$asset" ] || [ ! -f "$asset" ]; then
asset=""
path=$(find "$dir" -maxdepth 1 -type f -iname autounattend.xml | head -n 1) if [[ "$MANUAL" != [Yy1]* ]]; then
[ -n "$path" ] && cp "$asset" "$path" MANUAL="Y"
warn "no answer file provided, $FB."
fi
fi
src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1) src=$(find "$dir" -maxdepth 1 -type d -iname sources | head -n 1)
@ -822,9 +876,6 @@ updateImage() {
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
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')
@ -832,8 +883,56 @@ updateImage() {
index="2" index="2"
fi fi
if ! wimlib-imagex update "$loc" "$index" --command "add $asset /autounattend.xml" > /dev/null; then if wimlib-imagex extract "$loc" "$index" "/$file" "--dest-dir=$TMP" >/dev/null 2>&1; then
warn "failed to add answer file ($xml) to ISO image, $FB" && return 1 if ! wimlib-imagex extract "$loc" "$index" "/$dat" "--dest-dir=$TMP" >/dev/null 2>&1; then
if ! wimlib-imagex extract "$loc" "$index" "/$org" "--dest-dir=$TMP" >/dev/null 2>&1; then
if ! wimlib-imagex update "$loc" "$index" --command "rename /$file /$org" > /dev/null; then
warn "failed to backup original answer file ($file)."
fi
fi
fi
rm -f "$TMP/$dat"
rm -f "$TMP/$org"
rm -f "$TMP/$file"
fi
if [[ "$MANUAL" != [Yy1]* ]]; then
xml=$(basename "$asset")
info "Adding $xml for automatic installation..."
if ! wimlib-imagex update "$loc" "$index" --command "add $asset /$file" > /dev/null; then
MANUAL="Y"
warn "failed to add answer file ($xml) to ISO image, $FB"
else
wimlib-imagex update "$loc" "$index" --command "add $asset /$dat" > /dev/null || true
fi
fi
if [[ "$MANUAL" == [Yy1]* ]]; then
wimlib-imagex update "$loc" "$index" --command "delete --force /$file" > /dev/null || true
if wimlib-imagex extract "$loc" "$index" "/$org" "--dest-dir=$TMP" >/dev/null 2>&1; then
if ! wimlib-imagex update "$loc" "$index" --command "add $TMP/$org /$file" > /dev/null; then
warn "failed to restore original answer file ($org)."
fi
rm -f "$TMP/$org"
fi
fi
local find="$file"
[[ "$MANUAL" == [Yy1]* ]] && find="$org"
path=$(find "$dir" -maxdepth 1 -type f -iname "$find" | head -n 1)
if [ -f "$path" ]; then
if [[ "$MANUAL" != [Yy1]* ]]; then
mv -f "$path" "${path%.*}.org"
else
mv -f "$path" "${path%.*}.xml"
fi
fi fi
return 0 return 0
@ -938,7 +1037,7 @@ buildImage() {
[ -s "$log" ] && error="$(<"$log")" [ -s "$log" ] && error="$(<"$log")"
[[ "$error" != "$hide" ]] && echo "$error" [[ "$error" != "$hide" ]] && echo "$error"
mv "$out" "$BOOT" ! mv -f "$out" "$BOOT" && return 1
return 0 return 0
} }
@ -989,10 +1088,10 @@ bootWindows() {
BOOT_MODE="windows_secure" BOOT_MODE="windows_secure"
echo "$BOOT_MODE" > "$STORAGE/windows.mode" echo "$BOOT_MODE" > "$STORAGE/windows.mode"
if [ -f "$STORAGE/windows.rom" ] && [ ! -f "$STORAGE/$BOOT_MODE.rom" ]; then if [ -f "$STORAGE/windows.rom" ] && [ ! -f "$STORAGE/$BOOT_MODE.rom" ]; then
mv "$STORAGE/windows.rom" "$STORAGE/$BOOT_MODE.rom" mv -f "$STORAGE/windows.rom" "$STORAGE/$BOOT_MODE.rom"
fi fi
if [ -f "$STORAGE/windows.vars" ] && [ ! -f "$STORAGE/$BOOT_MODE.vars" ]; then if [ -f "$STORAGE/windows.vars" ] && [ ! -f "$STORAGE/$BOOT_MODE.vars" ]; then
mv "$STORAGE/windows.vars" "$STORAGE/$BOOT_MODE.vars" mv -f "$STORAGE/windows.vars" "$STORAGE/$BOOT_MODE.vars"
fi fi
fi fi
fi fi

View File

@ -29,10 +29,12 @@ boot() {
if [ -s "$QEMU_PTY" ]; then if [ -s "$QEMU_PTY" ]; then
if [ "$(stat -c%s "$QEMU_PTY")" -gt 7 ]; then if [ "$(stat -c%s "$QEMU_PTY")" -gt 7 ]; then
if ! grep -Fq "BOOTMGR is missing" "$QEMU_PTY"; then
info "Windows started succesfully, visit http://localhost:8006/ to view the screen..." info "Windows started succesfully, visit http://localhost:8006/ to view the screen..."
return 0 return 0
fi fi
fi fi
fi
error "Timeout while waiting for QEMU to boot the machine!" error "Timeout while waiting for QEMU to boot the machine!"
return 0 return 0
@ -48,8 +50,10 @@ ready() {
local bios="Booting from Hard" local bios="Booting from Hard"
last=$(grep "^Booting.*" "$QEMU_PTY" | tail -1) last=$(grep "^Booting.*" "$QEMU_PTY" | tail -1)
if [[ "${last,,}" == "${bios,,}"* ]]; then if [[ "${last,,}" == "${bios,,}"* ]]; then
if ! grep -Fq "BOOTMGR is missing" "$QEMU_PTY"; then
return 0 return 0
fi fi
fi
return 1 return 1
fi fi