From 69dcfe1d9f39942500dbcc59eadf3ba20a7f8195 Mon Sep 17 00:00:00 2001 From: Guofang Date: Sat, 17 Oct 2026 17:43:29 +0800 Subject: [PATCH] Install the VirtIO Arm64 drivers with pnputil; make OpenSSH a batch file On Arm64 Windows the VirtIO guest tools installer is an x86 program and the VirtIO ISO has no Arm64 package for it, so the first-logon script failed there and the guest had no network (no NetKVM driver). Install the Arm64 NetKVM, vioserial, Balloon, viorng and vioinput drivers from their folders on the ISO with pnputil instead. The OpenSSH Server capability is downloaded through Windows Update, which can take very long and blocked the rest of the script. Move it, with the administrator authorized key, into 05-Install-OpenSSH-Admin.bat, which the script copies to the Installers folder on the desktop to run by hand. Update the vm-images submodule to the build script that runs on Debian. Co-Authored-By: Claude Sonnet 5.5 --- README.md | 18 ++-- .../windows11/05-Install-OpenSSH-Admin.bat | 50 +++++++++ seediso/windows11/Configure-Windows.ps1 | 101 ++++++++---------- vm-images | 2 +- 4 files changed, 104 insertions(+), 67 deletions(-) create mode 100644 seediso/windows11/05-Install-OpenSSH-Admin.bat diff --git a/README.md b/README.md index 841121c..b1714c3 100644 --- a/README.md +++ b/README.md @@ -168,13 +168,17 @@ from the shared Windows 11 QCOW2 base image: It creates a persistent 64G disk at `.vm/windows11/disk.qcow2`, automatically partitions it, completes OOBE, creates the local administrator `guofang` with the initial password `wang`, and enables Remote Desktop on -`localhost:3389`. During the first login it also installs and enables the -Windows OpenSSH Server on `localhost:2222` and silently installs the VirtIO -Windows guest tools. It also installs the host's configured SSH public key for -passwordless administrator login. The installer includes the VirtIO drivers, SPICE vdagent, -and QEMU Guest Agent. Connect with `ssh guofang@localhost -p 2222`. The launcher -exposes the vdagent channel for host/guest clipboard integration and the QEMU Guest Agent at -`.vm/windows11/qemu-guest-agent.sock`. Change the password after first login. +`localhost:3389`. During the first login it also silently installs the VirtIO +drivers (the guest tools installer on amd64, the Arm64 driver packages from the +VirtIO ISO with `pnputil` on arm64), without which the guest has no network on +arm64. The installer includes the VirtIO drivers, SPICE vdagent, and QEMU Guest +Agent. The launcher exposes the vdagent channel for host/guest clipboard +integration and the QEMU Guest Agent at `.vm/windows11/qemu-guest-agent.sock`. +Change the password after first login. The OpenSSH Server is downloaded through +Windows Update, which can be slow, so it is not installed automatically: run +`05-Install-OpenSSH-Admin.bat` from the `Installers` folder on the desktop as +administrator, then connect with `ssh guofang@localhost -p 2222`; it also installs +the host's configured SSH public key for passwordless administrator login. The Windows VM hardware (8G memory, 8 CPUs, system disk, devices) is defined in `qemu/windows11.ini`, with the accelerators and machine type in `qemu/windows11--.ini`; the launcher renders the former to diff --git a/seediso/windows11/05-Install-OpenSSH-Admin.bat b/seediso/windows11/05-Install-OpenSSH-Admin.bat new file mode 100644 index 0000000..c4c99ca --- /dev/null +++ b/seediso/windows11/05-Install-OpenSSH-Admin.bat @@ -0,0 +1,50 @@ +@echo off +setlocal +title Install OpenSSH Server + +fltmc >nul 2>&1 +if errorlevel 1 ( + echo Please right-click this file and choose "Run as administrator". + pause + exit /b 1 +) + +rem The capability is downloaded through Windows Update, which can be slow. +echo Installing the OpenSSH Server Windows capability... +dism.exe /Online /Add-Capability /CapabilityName:OpenSSH.Server~~~~0.0.1.0 +set "RC=%ERRORLEVEL%" +if not "%RC%"=="0" if not "%RC%"=="3010" ( + echo dism exited with code %RC%. + pause + exit /b %RC% +) + +echo Starting the sshd service... +sc.exe config sshd start= auto +net.exe start sshd >nul 2>&1 +sc.exe query sshd | find "RUNNING" >nul +if errorlevel 1 ( + echo The sshd service is not running. + pause + exit /b 1 +) + +netsh.exe advfirewall firewall show rule name="OpenSSH-Server-In-TCP" >nul 2>&1 +if errorlevel 1 ( + netsh.exe advfirewall firewall add rule name="OpenSSH-Server-In-TCP" ^ + dir=in action=allow protocol=TCP localport=22 profile=private,public +) + +echo Installing the administrator authorized key... +set "KEYFILE=%ProgramData%\ssh\administrators_authorized_keys" +> "%KEYFILE%" echo ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCwsF2ZDSHDaXM9BdDq3Vxkp6T+DJEakKaVZQJUEHexS34mbrxYAxmGBUPCrddfE01dS31kGS4XHVBa+wGUYodY+nPwnrfD1Q4phKVSzXr65K1Y/sCcjSiANBPWpv2Xd7IMOfLlrdLtmf5QcKWroIqO2LaIDGECwzUUHrfprgeaF9N0FGcmrgbmm23JUk+f6guRQ4br88L4rWIWEBvL9bTdwErNkdfsYE2F/U8aIFpMcVy2eJIOgy8ZjZvkGdm4r730YkTDL1VmAjiHH3/m2R1EOvwLzFhyWKoa4ULk/IQW+8iNnG42QEcaWRM+hMwlVdnNhPJP6WzS+fAEbibD3zM0q2X/4ex+cXRNOCd2/0KhnD2+3p1BM5QeFTzDappkk8W2meQkDE3hvTjtIQCzygFO6LNWtEEa7BTvvlMqF3CZWh88J9XiP750SjESe3Ge5o9A0T2hcJa+KZ1LxVEmNt4nD6E/OD4EymoaLIJZ1fH5ksSFjHzJ+mJouSVjc/H/VSE= guofang@GUOFANG-OFFICE +icacls.exe "%KEYFILE%" /inheritance:r /grant "*S-1-5-32-544:F" /grant "*S-1-5-18:F" >nul +if errorlevel 1 ( + echo icacls exited with code %ERRORLEVEL%. + pause + exit /b 1 +) + +echo Done. SSH is available on port 22 of this machine. +pause +exit /b 0 diff --git a/seediso/windows11/Configure-Windows.ps1 b/seediso/windows11/Configure-Windows.ps1 index 72ac0fc..bc37055 100644 --- a/seediso/windows11/Configure-Windows.ps1 +++ b/seediso/windows11/Configure-Windows.ps1 @@ -34,7 +34,49 @@ if (-not (Test-Administrator)) { exit $elevated.ExitCode } +# The guest tools installer is an x86 program and the VirtIO ISO has no Arm64 +# package for it, so on Arm64 Windows the Arm64 drivers are installed from their +# folders on the ISO instead. NetKVM is the network driver; without it the guest +# has no network. +function Install-VirtIOArm64Drivers { + $roots = (Get-PSDrive -PSProvider FileSystem).Root + $drivers = @( + @{ Folder = 'NetKVM'; Inf = 'netkvm.inf' }, + @{ Folder = 'vioserial'; Inf = 'vioser.inf' }, + @{ Folder = 'Balloon'; Inf = 'balloon.inf' }, + @{ Folder = 'viorng'; Inf = 'viorng.inf' }, + @{ Folder = 'vioinput'; Inf = 'vioinput.inf' } + ) + + $installed = 0 + foreach ($driver in $drivers) { + $inf = $roots | + ForEach-Object { Join-Path $_ "$($driver.Folder)\w11\ARM64\$($driver.Inf)" } | + Where-Object { Test-Path -LiteralPath $_ } | + Select-Object -First 1 + if (-not $inf) { + if ($driver.Folder -eq 'NetKVM') { + throw 'The Arm64 NetKVM driver was not found on the attached media.' + } + continue + } + + & pnputil.exe /add-driver $inf /install | Out-Host + # 3010 asks for a restart; 259 means that no device uses the driver. + if ($LASTEXITCODE -notin 0, 259, 3010) { + throw "pnputil failed to install $inf (exit code $LASTEXITCODE)." + } + $installed++ + } + Write-Host "Installed $installed VirtIO Arm64 driver packages." +} + function Install-VirtIOGuestTools { + if ([Runtime.InteropServices.RuntimeInformation]::OSArchitecture -eq 'Arm64') { + Install-VirtIOArm64Drivers + return + } + $installer = Get-ChildItem ` -Path (Get-PSDrive -PSProvider FileSystem).Root ` -Filter 'virtio-win-guest-tools.exe' ` @@ -57,63 +99,6 @@ function Install-VirtIOGuestTools { } } -function Install-OpenSSHServer { - $capability = Get-WindowsCapability -Online -Name 'OpenSSH.Server*' | - Select-Object -First 1 - - if (-not $capability) { - throw 'The OpenSSH Server Windows capability was not found.' - } - - if ($capability.State -ne 'Installed') { - Add-WindowsCapability -Online -Name $capability.Name | Out-Null - } - - Set-Service -Name 'sshd' -StartupType Automatic - Start-Service -Name 'sshd' - - $rule = Get-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -ErrorAction SilentlyContinue - if ($rule) { - Set-NetFirewallRule ` - -Name 'OpenSSH-Server-In-TCP' ` - -Enabled True ` - -Profile Private, Public - } - else { - New-NetFirewallRule ` - -Name 'OpenSSH-Server-In-TCP' ` - -DisplayName 'OpenSSH SSH Server (sshd)' ` - -Enabled True ` - -Direction Inbound ` - -Protocol TCP ` - -Action Allow ` - -LocalPort 22 ` - -Profile Private, Public | Out-Null - } -} - -function Install-AdministratorAuthorizedKey { - $authorizedKeys = Join-Path $env:ProgramData 'ssh\administrators_authorized_keys' - $publicKey = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCwsF2ZDSHDaXM9BdDq3Vxkp6T+DJEakKaVZQJUEHexS34mbrxYAxmGBUPCrddfE01dS31kGS4XHVBa+wGUYodY+nPwnrfD1Q4phKVSzXr65K1Y/sCcjSiANBPWpv2Xd7IMOfLlrdLtmf5QcKWroIqO2LaIDGECwzUUHrfprgeaF9N0FGcmrgbmm23JUk+f6guRQ4br88L4rWIWEBvL9bTdwErNkdfsYE2F/U8aIFpMcVy2eJIOgy8ZjZvkGdm4r730YkTDL1VmAjiHH3/m2R1EOvwLzFhyWKoa4ULk/IQW+8iNnG42QEcaWRM+hMwlVdnNhPJP6WzS+fAEbibD3zM0q2X/4ex+cXRNOCd2/0KhnD2+3p1BM5QeFTzDappkk8W2meQkDE3hvTjtIQCzygFO6LNWtEEa7BTvvlMqF3CZWh88J9XiP750SjESe3Ge5o9A0T2hcJa+KZ1LxVEmNt4nD6E/OD4EymoaLIJZ1fH5ksSFjHzJ+mJouSVjc/H/VSE= guofang@GUOFANG-OFFICE' - - [IO.File]::WriteAllText( - $authorizedKeys, - $publicKey + [Environment]::NewLine, - [Text.Encoding]::ASCII - ) - - & icacls.exe ` - $authorizedKeys ` - '/inheritance:r' ` - '/grant' ` - '*S-1-5-32-544:F' ` - '*S-1-5-18:F' - - if ($LASTEXITCODE -ne 0) { - throw "icacls.exe exited with code $LASTEXITCODE." - } -} - function Enable-AutomaticLogon { $winlogonPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' @@ -172,8 +157,6 @@ try { if ($InstallVirtIO) { Install-VirtIOGuestTools } - Install-OpenSSHServer - Install-AdministratorAuthorizedKey if ($EnableAutomaticLogon) { Enable-AutomaticLogon } diff --git a/vm-images b/vm-images index 2ae7658..21604f5 160000 --- a/vm-images +++ b/vm-images @@ -1 +1 @@ -Subproject commit 2ae7658df5f063294a22f12a01b854821281eb6a +Subproject commit 21604f511fc05e91350c08ba39cffca694767812