mirror of
https://github.com/dockur/windows.git
synced 2026-08-05 21:47:16 +01:00
feat: Avoid ISO rebuilding for dramatically faster preparation (#2032)
This commit is contained in:
+192
-25
@@ -11,6 +11,7 @@ SHUTDOWN_SIGNAL=0
|
||||
|
||||
QEMU_PTY="$QEMU_DIR/qemu.pty"
|
||||
QEMU_END="$QEMU_DIR/qemu.end"
|
||||
ACPI_SOCKET="$QEMU_DIR/acpi.sock"
|
||||
CONSOLE_PID="$QEMU_DIR/console.pid"
|
||||
CONSOLE_SOCKET="$QEMU_DIR/console.sock"
|
||||
QEMU_START_PID="$QEMU_DIR/qemu.start.pid"
|
||||
@@ -28,56 +29,96 @@ bootStatus() {
|
||||
last="${line#*:}"
|
||||
recent=$(tail -n +"${line%%:*}" "$QEMU_PTY")
|
||||
|
||||
if [[ "$last" == "Booting from DVD/CD"* ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
grep -Fq "Loading FreeLoader..." <<< "$recent" && return 0
|
||||
|
||||
grep -Fq \
|
||||
if grep -Fq \
|
||||
-e "No bootable device." \
|
||||
-e "BOOTMGR is missing" \
|
||||
-e "Boot failed: not a bootable disk" \
|
||||
-e "Boot failed: could not read the boot disk" \
|
||||
<<< "$recent" && return 1
|
||||
<<< "$recent"; then
|
||||
return 2
|
||||
fi
|
||||
|
||||
return 0
|
||||
if grep -Fq \
|
||||
-e "Boot failed: not a bootable disk" \
|
||||
-e "Boot failed: Could not read from CDROM" \
|
||||
-e "Boot failed: could not read the boot disk" \
|
||||
<<< "$recent"; then
|
||||
return 5
|
||||
fi
|
||||
|
||||
if [[ "$last" == "Booting from Hard Disk"* ]]; then
|
||||
return 3
|
||||
fi
|
||||
|
||||
if [[ "$last" == "Booting from DVD/CD"* ]]; then
|
||||
return 4
|
||||
fi
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
grep -Fq "UEFI Interactive Shell" "$QEMU_PTY" && return 2
|
||||
local line last recent
|
||||
|
||||
local last
|
||||
last=$(grep -E \
|
||||
line=$(grep -nE \
|
||||
'BdsDxe: starting Boot[[:xdigit:]]{4} ' \
|
||||
"$QEMU_PTY" | tail -1)
|
||||
|
||||
[ -z "$last" ] && return 1
|
||||
[ -z "$line" ] && return 1
|
||||
|
||||
last="${line#*:}"
|
||||
recent=$(tail -n +"${line%%:*}" "$QEMU_PTY")
|
||||
|
||||
if [[ "$last" == *'"Windows Boot Manager"'* ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
grep -Eq \
|
||||
'BdsDxe: failed to start Boot[[:xdigit:]]{4} "UEFI QEMU .*DVD-ROM.*: Time out' \
|
||||
<<< "$recent" && return 2
|
||||
|
||||
grep -Fq "UEFI Interactive Shell" <<< "$recent" && return 2
|
||||
|
||||
grep -Eq \
|
||||
-e '"Windows Boot Manager"' \
|
||||
-e '"UEFI QEMU .*DVD-ROM' \
|
||||
-e 'CDROM\(' \
|
||||
-e 'USB\(' \
|
||||
<<< "$last"
|
||||
<<< "$last" && return 4
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
waitForBoot() {
|
||||
|
||||
local pid="$1"
|
||||
local timeout="${2:-30}"
|
||||
local keySent=0
|
||||
local pendingType=0
|
||||
local pendingLine=""
|
||||
local pendingDeadline=0
|
||||
local keyDelay status marker
|
||||
local deadline=$((SECONDS + timeout))
|
||||
local screen="visit http://127.0.0.1:$WEB_PORT/ to view the screen..."
|
||||
|
||||
while isAlive "$pid"; do
|
||||
|
||||
if (( ! keySent )) && needsBootKey; then
|
||||
|
||||
if keyDelay=$(bootKeyDelay); then
|
||||
if sendKey spc "$keyDelay" 500; then
|
||||
keySent=1
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if bootStatus; then
|
||||
local status=0
|
||||
status=0
|
||||
else
|
||||
local status=$?
|
||||
status=$?
|
||||
fi
|
||||
|
||||
case "$status" in
|
||||
|
||||
|
||||
0) echo
|
||||
|
||||
if [[ "${DISPLAY,,}" == "web" ]] && ! disabled "${WEB:-Y}"; then
|
||||
@@ -90,9 +131,47 @@ waitForBoot() {
|
||||
|
||||
2) echo
|
||||
|
||||
error "$(app) could not boot, aborting..."
|
||||
terminateQemu
|
||||
return 0 ;;
|
||||
error "$(app) could not boot, aborting..."
|
||||
terminateQemu
|
||||
return 0 ;;
|
||||
|
||||
3 | 4)
|
||||
|
||||
marker=$(getBootMarker)
|
||||
|
||||
if [[ "$marker" != "$pendingLine" ]] || (( status != pendingType )); then
|
||||
pendingLine="$marker"
|
||||
pendingType=$status
|
||||
|
||||
pendingDeadline=$((SECONDS + 6))
|
||||
fi
|
||||
|
||||
if (( pendingDeadline > 0 && SECONDS >= pendingDeadline )); then
|
||||
echo
|
||||
|
||||
if [[ "${DISPLAY,,}" == "web" ]] && ! disabled "${WEB:-Y}"; then
|
||||
info "$(app) started successfully, $screen"
|
||||
else
|
||||
info "$(app) started successfully."
|
||||
fi
|
||||
|
||||
echo && return 0
|
||||
fi
|
||||
;;
|
||||
|
||||
5)
|
||||
|
||||
pendingType=0
|
||||
pendingLine=""
|
||||
pendingDeadline=0
|
||||
;;
|
||||
|
||||
*)
|
||||
|
||||
pendingType=0
|
||||
pendingLine=""
|
||||
pendingDeadline=0
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
@@ -101,7 +180,7 @@ waitForBoot() {
|
||||
sleep 0.25
|
||||
done
|
||||
|
||||
! isAlive "$pid" && return 0
|
||||
isAlive "$pid" || return 0
|
||||
[ -f "$QEMU_END" ] && return 0
|
||||
|
||||
error "Timeout while waiting for QEMU to boot the machine, aborting..."
|
||||
@@ -149,12 +228,100 @@ ready() {
|
||||
"$QEMU_PTY" | tail -1)
|
||||
|
||||
grep -Eq \
|
||||
'BdsDxe: starting Boot[[:xdigit:]]{4} "Windows Boot Manager" from HD\(' \
|
||||
'BdsDxe: starting Boot[[:xdigit:]]{4} "Windows Boot Manager" from .*HD\(' \
|
||||
<<< "$last" && return 0
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
sendKey() {
|
||||
|
||||
local key="$1"
|
||||
local delay="${2:-0}"
|
||||
local hold="${3:-100}"
|
||||
local output
|
||||
|
||||
[ ! -S "$ACPI_SOCKET" ] && return 1
|
||||
[[ "$delay" != "0" ]] && sleep "$delay"
|
||||
|
||||
if ! output=$(
|
||||
printf 'sendkey %s %s\n' "$key" "$hold" |
|
||||
nc -q 1 -w 1 -U "$ACPI_SOCKET" 2>&1
|
||||
); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if grep -Eqi \
|
||||
-e 'unknown command' \
|
||||
-e 'unknown key' \
|
||||
-e 'invalid parameter' \
|
||||
-e 'invalid key' \
|
||||
-e '^error:' \
|
||||
<<< "$output"; then
|
||||
|
||||
warn "failed to send boot key through QEMU monitor!"
|
||||
|
||||
if enabled "${DEBUG:-}"; then
|
||||
echo "$output"
|
||||
fi
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
supportsBootKey() {
|
||||
|
||||
local id="$1"
|
||||
|
||||
[[ "${id,,}" == "win"* ]]
|
||||
}
|
||||
|
||||
needsBootKey() {
|
||||
|
||||
[ ! -s "$BOOT" ] && return 1
|
||||
[[ "${BOOT,,}" != *".iso" ]] && return 1
|
||||
[ -f "$STORAGE/windows.boot" ] && return 1
|
||||
|
||||
supportsBootKey "$DETECTED"
|
||||
}
|
||||
|
||||
bootKeyDelay() {
|
||||
|
||||
[ ! -s "$QEMU_PTY" ] && return 1
|
||||
|
||||
if grep -Fq "Press any key to" "$QEMU_PTY"; then
|
||||
echo 0
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then
|
||||
grep -Fq "Booting from DVD/CD" "$QEMU_PTY" || return 1
|
||||
else
|
||||
grep -Eq \
|
||||
'BdsDxe: starting Boot[[:xdigit:]]{4} "UEFI QEMU .*DVD-ROM' \
|
||||
"$QEMU_PTY" || return 1
|
||||
fi
|
||||
|
||||
echo 0.5
|
||||
return 0
|
||||
}
|
||||
|
||||
getBootMarker() {
|
||||
|
||||
if [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then
|
||||
grep -nE '^Booting from (Hard Disk|DVD/CD)' "$QEMU_PTY" | tail -1
|
||||
return 0
|
||||
fi
|
||||
|
||||
grep -nE \
|
||||
'BdsDxe: starting Boot[[:xdigit:]]{4} ' \
|
||||
"$QEMU_PTY" | tail -1
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
markWindowsBooted() {
|
||||
|
||||
local file="$STORAGE/windows.boot"
|
||||
@@ -164,7 +331,7 @@ markWindowsBooted() {
|
||||
fi
|
||||
|
||||
# Remove CD-ROM ISO after install
|
||||
! ready && return 0
|
||||
ready || return 0
|
||||
|
||||
if ! touch "$file"; then
|
||||
warn "failed to create Windows installation marker!"
|
||||
@@ -288,7 +455,7 @@ gracefulShutdown() {
|
||||
finish "$code"
|
||||
}
|
||||
|
||||
! enabled "$SHUTDOWN" && return 0
|
||||
enabled "$SHUTDOWN" || return 0
|
||||
[ -n "${QEMU_TIMEOUT:-}" ] && TIMEOUT="$QEMU_TIMEOUT"
|
||||
|
||||
if interactive; then
|
||||
|
||||
Reference in New Issue
Block a user