Skip to content

Instantly share code, notes, and snippets.

@iamacarpet
Last active February 8, 2024 14:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iamacarpet/46c9a03f7527840491c6e47cd9f0891b to your computer and use it in GitHub Desktop.
Save iamacarpet/46c9a03f7527840491c6e47cd9f0891b to your computer and use it in GitHub Desktop.
Glazier UEFI network boot (Secure Boot enabled)

Glazier UEFI network boot

You’ll need

  • A TFTP server
  • A HTTP server (needs to support custom configuration, ideally nginx)
  • The ability to configure custom DHCP options on your existing DHCP server.

Files required

  • x64/snponly_x64.efi (Secure Boot signed iPXE from 2Pint Software)
  • 2PXE/File/logo (PNG splash screen image)
  • 2PXE/Boot (iPXE script containing boot configuration).
  • wimboot.x86_64.efi (Secure Boot signed wimboot, can be stored in remote object storage)

Additional files

  • x64/snponly_usb_x64.efi (Secure Boot signed iPXE from 2Pint Software, designed to be booted via USB)

TFTP server

TFTP server needs to be configured to serve x64/snponly_x64.efi.

It doesn’t need to be in the local subnet, but you can run into some issues if it isn’t.

It’ll need to only be accessible over a private network, not something that can be exposed or accessed over the internet.

HTTP server

Based on the URL provided in DHCP option 175, iPXE will request some files via HTTP.

It’ll first request:

GET /2PXE/File/logo

Then:

POST /2PXE/Boot

This POST request does include a lot of variables that allow for a dynamic response (see https://gist.github.com/iamacarpet/d37c17bcaf8767093a53265ed4d04b83#file-2pxe-ipxe-L237), however, we want to ignore that & just return a static boot menu file.

Ideally, we’d serve straight from Google Cloud Storage or similar, but it doesn’t allow POST requests without a specific data structure in the form parameters, so we’re best to use nginx (and this can be remote, over the internet, if it’s easier to host that way, but may need to use an IP address rather than a DNS domain, as it’s not clear if DNS is available here).

Example nginx configuration

server {
        listen 8050 default_server;

        root /srv/tftp;

        index index.html index.htm index.nginx-debian.html;

        server_name _;

        error_page 405 =200 $uri;

        location /healthz {
                access_log off;
                keepalive_timeout 0;

                add_header Content-Type text/plain;
                return 200 "OK";
        }

}

where “/srv/tftp” is the folder containing the HTTP files referenced above.

Note the line error_page 405 =200 $uri; that allows a POST for a static file.

Configure the following DHCP options

  • Option 66: TFTP Server IP, e.g. 10.25.0.250
  • Option 67: x64/snponly_x64.efi
  • Option 175 (custom, string): HTTP URL for additional files, e.g. http://10.25.0.250:8050/
#!ipxe
# Some menu defaults
set menu-timeout 60000
set submenu-timeout ${menu-timeout}
isset ${menu-default} || set menu-default exit
###################### MAIN MENU ####################################
:start
menu iPXE boot menu for Example Ltd
item --gap -- ----------------------- Glazier Images (Blank) --------------------------
item --key b windows-blank Run Glazier with windows-blank (Windows 11 Pro) configuration
item --key n win10-blank Run Glazier with win10-blank (Windows 10 Pro) configuration
item --gap -- -------------------- Glazier Images (autopilot) --------------------------
item --key y windows-autopilot Run Galazier with windows-autopilot (Windows 11 Pro) configuration
item --gap -- ------------------------- Advanced options -------------------------------
item shell Drop to iPXE shell
item reboot Reboot computer
item
item --key x exit Exit iPXE and continue BIOS boot
choose --timeout ${menu-timeout} --default ${menu-default} selected || goto cancel
set menu-timeout 0
goto ${selected}
:cancel
echo You cancelled the menu, dropping you to a shell
:shell
echo Type 'exit' to get the back to the menu
shell
set menu-timeout 0
goto start
:failed
echo Booting failed, dropping to shell
goto shell
:reboot
reboot
:exit
exit
############ MAIN MENU ITEMS ############
:windows-blank
echo Booting WinPE for Glazier with windows-blank configuration
kernel http://storage.googleapis.com/example-glazier-files/wimboot.x86_64.efi
## wimboot allows replacing files inside the WIM by loading them as initrd entires here,
## where I believe they end up exposed in C-Windows-System32
initrd http://storage.googleapis.com/example-glazier-config/blank/autobuild.ps1 autobuild.ps1
initrd http://storage.googleapis.com/example-glazier-files/Boot/BCD BCD
initrd http://storage.googleapis.com/example-glazier-files/Boot/boot.sdi boot.sdi
initrd http://storage.googleapis.com/example-glazier-files/sources/boot.wim boot.wim
boot || goto failed
goto start
:win10-blank
echo Booting WinPE for Glazier with win10-blank configuration
kernel http://storage.googleapis.com/example-glazier-files/wimboot.x86_64.efi
## wimboot allows replacing files inside the WIM by loading them as initrd entires here,
## where I believe they end up exposed in C-Windows-System32
initrd http://storage.googleapis.com/example-glazier-config/win10-blank/autobuild.ps1 autobuild.ps1
initrd http://storage.googleapis.com/example-glazier-files/Boot/BCD BCD
initrd http://storage.googleapis.com/example-glazier-files/Boot/boot.sdi boot.sdi
initrd http://storage.googleapis.com/example-glazier-files/sources/boot.wim boot.wim
boot || goto failed
goto start
:windows-autopilot
echo Booting WinPE for Glazier with windows-autopilot configuration
kernel http://storage.googleapis.com/example-glazier-files/wimboot.x86_64.efi
## wimboot allows replacing files inside the WIM by loading them as initrd entires here,
## where I believe they end up exposed in C-Windows-System32
initrd http://storage.googleapis.com/example-glazier-config/autopilot/autobuild.ps1 autobuild.ps1
initrd http://storage.googleapis.com/example-glazier-files/Boot/BCD BCD
initrd http://storage.googleapis.com/example-glazier-files/Boot/boot.sdi boot.sdi
initrd http://storage.googleapis.com/example-glazier-files/sources/boot.wim boot.wim
boot || goto failed
goto start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment