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)

src/NETSetup/WinPE/sources/boot.wim

Boot loader binaries

src/NETSetup/WinPE/bootmgr, bootmgr.efi

BCD configuration

src/NETSetup/WinPE/boot/bcd, efi/microsoft/boot/bcd

EFI boot loader

src/NETSetup/WinPE/efi/boot/bootx64.efi

AutoExecute.ps1

src/NETSetup/NETSetupDEV/SRC/AutoExecute.ps1

ISO build script (Windows)

src/NETSetup/NETSetupDEV/SRC/UPDATE.ps1

ISO build script (Linux)

src/NETSetup/NETSetupDEV/UPDATE.sh

Copies (not authoritative):

  • C:\NETSetupDEV\BOOT\ — local working copy, rebuilt by create-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)

C:\NETSetupDEV\Drivers\Proxmox\vioscsi\w11\amd64

viostor (VirtIO Block)

C:\NETSetupDEV\Drivers\Proxmox\viostor\w11\amd64

NetKVM (VirtIO Network)

C:\NETSetupDEV\Drivers\Proxmox\NetKVM\w11\amd64

Balloon (VirtIO Memory)

C:\NETSetupDEV\Drivers\Proxmox\Balloon\w11\amd64

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: wstorvsc*

wnetvsc (Hyper-V Network)

Host DriverStore: wnetvsc*

wvmbus (Hyper-V VMBus)

Host DriverStore: wvmbus*

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 (boot/bcd and efi/microsoft/boot/bcd) must NEVER be replaced with ISO versions.

The ISO’s BCD is configured for "Windows Setup" mode, which auto-launches setup.exe and bypasses the NETSetup boot chain (startnet.cmdAutoExecute.ps1NETSetup.exe). The NETSetup BCD files are configured for WinPE command-line mode.

If accidentally replaced, restore from git: git checkout <pre-update-commit> — src/NETSetup/WinPE/boot/bcd src/NETSetup/WinPE/efi/microsoft/boot/bcd

Important

CI policies (efi/microsoft/boot/cipolicies/) must be removed after copying from the ISO. Windows 24H2 CI policies block DISM-customized WinPE images from booting (0xc0000487).

7. Troubleshooting

Symptom Cause Fix

BSOD: winload.efi 0xc0000487

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 /Add-Driver (not just file copy)

DISM Error 50 "not supported"

Stale DISM mount from previous failure

Run dism /Cleanup-Wim, reboot if needed

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).