1. Overview
NETSetup uses a custom Windows PE (WinPE) boot image to bootstrap the OS deployment process. The WinPE boots from an ISO or USB, launches NETSetup, which then drives the unattended Windows installation.
The WinPE boot.wim and related boot loader files live in src/NETSetup/WinPE/ (the git source of truth).
The create-iso command copies these into NETSetupDEV/BOOT/ and packages them into NETSetup.iso.
2. Boot Chain
The full boot sequence from power-on to NETSetup execution:
UEFI Firmware
|
+-- Reads ISO El Torito boot image (efisys.bin)
+-- Loads efi/boot/bootx64.efi (= bootmgr.efi, Microsoft-signed)
|
v
Windows Boot Manager (bootmgr.efi)
|
+-- Reads BCD from efi/microsoft/boot/bcd
+-- BCD must be in WinPE mode (NOT Windows Setup mode)
+-- Loads sources/boot.wim Index 1 into RAM (ramdisk -> X:)
|
v
WinPE Kernel (winload.efi -> ntoskrnl)
|
+-- Boot-start drivers load (storvsc, vmbus, vioscsi, viostor, stornvme, etc.)
+-- winpeshl.exe starts (WinPE shell host)
+-- No winpeshl.ini -> runs: cmd.exe /k startnet.cmd
|
v
startnet.cmd (inside boot.wim at X:\Windows\System32\startnet.cmd)
|
+-- wpeinit (initializes network, PnP, assigns drive letters)
+-- Scans all drives A-Z for AutoExecute.ps1
+-- Finds AutoExecute.ps1 on the ISO/USB partition (e.g. D:\)
|
v
AutoExecute.ps1 (on ISO/USB at BOOT\AutoExecute.ps1, NOT inside boot.wim)
|
+-- cd NETSetup
+-- .\NETSetup.exe install
+-- powershell (fallback interactive shell if NETSetup exits)
|
v
NETSetup.exe install
|
+-- Detects WinPE environment (host.IsOnWinPE())
+-- Loads customer config (matches machine by serial number)
+-- Partitions disk, generates unattend.xml
+-- Calls setup.exe /unattend:{path} (Windows Setup)
+-- Reboots into Windows installation
3. ISO File Layout
The create-iso command produces an ISO with this structure:
BOOT/ <-- ISO root (oscdimg/xorriso builds from here)
+-- bootmgr <-- BIOS boot manager (from ISO, matches boot.wim version)
+-- bootmgr.efi <-- UEFI boot manager (from ISO, matches boot.wim version)
+-- boot/
| +-- bcd <-- BIOS BCD (NETSetup-specific, NEVER from ISO)
| +-- boot.sdi <-- System Deployment Image
| +-- fonts/ <-- Boot menu fonts
+-- efi/
| +-- boot/bootx64.efi <-- UEFI entry point (from ISO)
| +-- microsoft/boot/
| +-- bcd <-- UEFI BCD (NETSetup-specific, NEVER from ISO)
| +-- efisys.bin <-- El Torito UEFI boot image
| +-- (NO cipolicies/) <-- Must NOT exist
+-- sources/
| +-- boot.wim <-- WinPE image (~545 MB, built from ADK)
+-- AutoExecute.ps1 <-- NETSetup launcher script
+-- NETSetup/
| +-- NETSetup.exe <-- Main binary (win-x64)
| +-- NETSetup <-- Linux binary (linux-musl-x64)
| +-- Config/ <-- Customer configs (offline mode only)
| +-- Images/ <-- install.wim (offline mode only)
| +-- Drivers/ <-- VirtIO etc. (offline mode only)
+-- linux/
+-- grub/ <-- GRUB bootloader for Linux PE
+-- vmlinuz, initramfs <-- Void Linux PE kernel
4. Source of Truth
| Component | Path |
|---|---|
boot.wim (WinPE image) |
|
Boot loader binaries |
|
BCD configuration |
|
EFI boot loader |
|
AutoExecute.ps1 |
|
ISO build script (Windows) |
|
ISO build script (Linux) |
|
Copies (not authoritative):
-
C:\NETSetupDEV\BOOT\— local working copy, rebuilt bycreate-iso -
%USERPROFILE%\osisa Dropbox\NETSetup\BOOT\— synced for all dev machines
5. Building boot.wim
5.1. Rule: Always use ADK, never ISO boot.wim
Starting with Windows 11 24H2 (build 26100), the ISO’s boot.wim has self-integrity checks in winload.efi.
When DISM adds packages or drivers, it breaks these checks, causing 0xc0000487 on \windows\system32\boot\winload.efi at boot.
This was NOT an issue with 22H2 (build 22621).
The ADK’s winpe.wim is specifically designed for DISM customization and has no integrity enforcement.
ADK base image: C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\amd64\en-us\winpe.wim
5.2. WinPE packages
21 packages added via DISM /Add-Package:
WinPE-WMI, WinPE-NetFx, WinPE-Scripting, WinPE-PowerShell, WinPE-DismCmdlets, WinPE-SecureStartup, WinPE-SecureBootCmdlets, WinPE-EnhancedStorage, WinPE-StorageWMI, WinPE-Setup, WinPE-Setup-Client, WinPE-Setup-Server, WinPE-WDS-Tools, WinPE-HTA, WinPE-MDAC, WinPE-FMAPI, WinPE-PlatformId, WinPE-Dot3Svc, WinPE-PPPoE, WinPE-RNDIS, WinPE-WinReCfg
5.3. startnet.cmd
@echo off
wpeinit
for %%a in ( a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
if exist "%%a:\AutoExecute.ps1" cd /d "%%a:" && goto :exec
)
:exec
powershell -ep bypass .\AutoExecute.ps1
5.4. Drivers
Drivers must be injected via dism /Add-Driver (not just present as .sys files).
Without proper registration in the WinPE SYSTEM registry hive, drivers silently fail to load.
5.4.1. VirtIO (Proxmox/QEMU) — not inbox, must inject
| Driver | Source |
|---|---|
vioscsi (VirtIO SCSI) |
|
viostor (VirtIO Block) |
|
NetKVM (VirtIO Network) |
|
Balloon (VirtIO Memory) |
|
Use /ForceUnsigned for VirtIO drivers.
5.4.2. Hyper-V — files exist in ADK but NOT registered, must explicitly add
| Driver | Source |
|---|---|
wstorvsc (Hyper-V SCSI) |
Host DriverStore: |
wnetvsc (Hyper-V Network) |
Host DriverStore: |
wvmbus (Hyper-V VMBus) |
Host DriverStore: |
Source: C:\Windows\System32\DriverStore\FileRepository{pattern}
5.4.3. Already inbox (no action needed)
-
stornvme (NVMe)
-
storahci (SATA/AHCI)
6. Updating Boot Loader Files
When the boot.wim version changes (e.g. 22621 → 26100), the boot loader binaries must also be updated.
6.1. What to update from the Windows 11 ISO
-
bootmgr— BIOS boot manager binary -
bootmgr.efi— UEFI boot manager binary -
efi/boot/bootx64.efi— UEFI entry point -
boot/fonts/— boot menu fonts -
boot/memtest.exe,boot/boot.sdi— utilities
6.2. What to NEVER replace
|
Important
|
BCD files ( The ISO’s BCD is configured for "Windows Setup" mode, which auto-launches If accidentally replaced, restore from git:
|
|
Important
|
CI policies ( |
7. Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
BSOD: |
boot.wim built from ISO boot.wim (24H2 integrity checks) |
Rebuild from ADK winpe.wim |
BSOD: instant blue screen, VM shuts down |
bootmgr.efi version mismatch with boot.wim |
Update bootmgr from matching ISO |
"Windows Server Setup" instead of NETSetup |
BCD replaced with ISO version (Windows Setup mode) |
Restore NETSetup BCD from git |
"Install driver to display hardware" |
Storage drivers not registered in WinPE |
Inject via |
DISM Error 50 "not supported" |
Stale DISM mount from previous failure |
Run |
setup.exe fails at ~5% with 0xC1900108 |
WinPE version older than install.wim |
Update WinPE to match install.wim version |
8. Version History
| Date | Version | Change |
|---|---|---|
2026-04-01 |
10.0.26100 |
Rebuilt from ADK (was ISO-based 22621). Added VirtIO + Hyper-V driver injection. Updated boot loader binaries. Fixed BCD (must not use ISO version). |