This guide will assume you already have a functioning PXELINUX setup and want to add a Windows boot option to it.
Requirements
- Windows workstation host with the Windows ADK installed.
- TFTP Server with PXELINUX.
- DHCP Server setup to direct your PXE Boot clients to your TFTP Server.
- SAMBA/CIFS Server to host the installation files.
- Windows installation DVD.
Note: The TFTP, DHCP, and SAMBA/CIFS services can all be hosted on the same server.
Windows ADK
Download and install the Deployment Tools and Windows Preinstallation Environment (Windows PE) from the Windows Assessment and Deployment Kit (ADK) for Windows 10 from Microsoft. You can install all of the ADK if you want, but it is not required.
Services
I referenced this PXELINUX guide to set up TFTP and DHCP. Additionally, don’t forget to make sure your TFTP and DHCP service are set to start at boot.
TFTP
I would recommend using the tftp-hpa TFTP server because it allows you to map certain paths to other things. This is useful to map \boot to /winpe. Create a file called /etc/tftpd.map and add the content below to it.
re ^bootmgr\.exe winpe/bootmgr.exe
ri ^\\boot\\ winpe/
ri ^boot/ winpe/
ri ^/boot/ winpe/
r ^\\ winpe/
rg \\ /
If you are using Gentoo, edit your /etc/conf.d/in.tftpd file and add -m /etc/tftpd.map to the INTFTPD_OPTS variable. It should look something like this:
INTFTPD_OPTS="-c -R 4096:32767 -s ${INTFTPD_PATH} -m /etc/tftpd.map"
PXELINUX
Menu Entry
The menu entry may be constructed differently in your /tftproot/pxelinux.cfg/default file then mine. Just make sure the kernel line looks the same.
#display menu
DEFAULT menu.c32
PROMPT 0
MENU TITLE My PXE Boot Menu
TIMEOUT 150
TOTALTIMEOUT 900
label Localboot
localboot -1
label Windows
menu label Windows
kernel winpe/pxeboot.0 keeppxe
SAMBA/CIFS
Preferably password-less and read only. Share out a directory or make a directory in an already existing share. This will need several gigabytes of space. This guide will refer to this share as: \fileserver\pe
Source Files
The contents of the “sources” directory on the Windows installation DVD needs to be copied to this under sub directories for each version of Windows you want to host. This guide assumes you copied your Windows 10 sources to \fileserver\pe\win10x64, Windows 8.1 x64 sources to \fileserver\pe\win81x64, Windows 7 SP1 x64 sources to \fileserver\pe\win7x64sp1. Doing this will allow you to host multiple versions of Windows on your share.
Install.bat
We are going to put a batch file with a selection of operating systems to install on the SAMBA/CIFS fileserver can call it from the PE boot image we are going to create later so we don’t have to update the boot image every time we want to add another OS to choose from. We just update the batch file on the fileserver to update it. The boot image would need to be updated if the fileserver or share name were to ever change.
- Copy your c:\windows\system32\choice.exe to your \fileserver\pe share.
- Copy and paste the following code into a file called install.bat in the \fileserver\pe share.
- Set FILESERVER to your preferably your fileserver IPv4 address or hostname.
- Set the SHARE to the name of the share.
@echo off
set FILESERVER=fileserver
set SHARE=pe
@echo off
rem ############################################################################
rem This is the subroutine to draw the menu
rem ############################################################################
:menu
rem Clear the screen
cls
rem Draw the menu, max is 24 lines by 80 characters across
echo.
echo Please choose an install option
echo.
echo 1 - Exit the installer and return to a shell
echo.
echo 2 - Windows 10 x64
echo Home, Professional
echo.
echo 3 - Windows 8.1 x64
echo Professional
echo.
echo 4 - Windows 7 x64 SP1
echo Home Basic, Home Premium, Professional, Ultimate
echo.
echo 5 - Windows 2012 R2 x64 (Full and Server Core versions)
echo Standard, Datacenter
echo.
rem Prompt for a choice
rem Add more options after the /c
rem
rem /c - possible choices
rem /d - default option
rem /m - message to display
rem /t - seconds to wait
rem
rem choice /c:<options> /d <default option> /m "<message>" /t <timeout seconds>
rem
\\%FILESERVER%\%SHARE%\choice.exe /c:12345 /d 2 /m "Install option:" /t 30
if errorlevel 5 goto win2012r2x64
if errorlevel 4 goto win7x64sp1
if errorlevel 3 goto win81x64
if errorlevel 2 goto win10x64
if errorlevel 1 goto end
goto menu
rem ############################################################################
rem These are subroutines to run the installer for each menu choice
rem ############################################################################
:win10x64
echo.
cls
echo Running installer for: Windows 10 x64
echo Please wait...
\\%FILESERVER%\%SHARE%\win10x64\setup.exe
goto end
:win81x64
echo.
cls
echo Running installer for: Windows 8.1 x64
echo Please wait...
\\%FILESERVER%\%SHARE%\win81x64\setup.exe
goto end
:win7x64sp1
echo.
cls
echo Running installer for: Windows 7 Ultimate x64
echo Please wait...
\\%FILESERVER%\%SHARE%\win7x64sp1\setup.exe
goto end
:win2012r2x64
echo.
cls
echo Running installer for: Windows 2012 R2 x64
echo Please wait...
\\%FILESERVER%\%SHARE%\win2012r2x64\setup.exe
goto end
:end
echo.
echo Run 'startnet' to run the installer again.
echo.
echo Have a nice day!
echo.
Windows PE Image Creation
Run this as a batch file and run it in a “Deployment and Imaging Tools Environment” running as Administrator. The shell should be located on your start menu under “Windows Kits” -> “Windows ADK”. Make sure you are running the “Deployment and Imaging Tools Environment” as administrator (right click -> More -> Run as administrator) and not a regular command prompt because it sets up a few variables for you which are needed by the commands in the following script. You will need about 500MB of free space on the drive where PEPATH is located. I would recommend changing the image via this script and not manually modifying any files in the image if you mount the image by hand. That is an easy way to forget the changes you have made for when you need to rebuild the image for whatever reason.
@echo off
rem The fileserver IP
set FILESERVER=172.16.160.37
rem Share on the fileserver.
set SHARE=pe
rem Username for the share
set SHAREUSER=shareusernamehere
rem Password for the share
set SHAREPASS=sharepasswordhere
rem amd64 or x86
set ARCH=amd64
rem Path to hold working files. Needs about 500MB of free space.
set PEPATH="c:\winpe_%ARCH%"
rem Path to where drivers are to install in the image (remove rem from the next line to enable this)
rem set DRIVERDIR="c:\program files\common files\vmware\drivers"
rem ##########################################################
rem Don't edit anything below here
rem ##########################################################
echo Creating the PE image
call copype.cmd %ARCH% %PEPATH% > NUL
echo Mounting the image
dism /Mount-Wim /WimFile:%PEPATH%\media\sources\boot.wim /index:1 /MountDir:%PEPATH%\mount /quiet
echo Adding commands to the startup script in PE
echo. >> %PEPATH%\mount\windows\system32\startnet.cmd
echo ping %FILESERVER% >> %PEPATH%\mount\windows\system32\startnet.cmd
if defined SHAREUSER echo net use z: \\%FILESERVER%\%SHARE% %SHAREPASS% /u:%FILESERVER%\%SHAREUSER% >> %PEPATH%\mount\windows\system32\startnet.cmd
if not defined SHAREUSER echo net use z: \\%FILESERVER%\%SHARE% >> %PEPATH%\mount\windows\system32\startnet.cmd
echo z:\64.bat >> %PEPATH%\mount\windows\system32\startnet.cmd
echo Creating the pxeboot directory
mkdir %PEPATH%\pxeboot > NUL
mkdir %PEPATH%\pxeboot\Fonts > NUL
copy /y %PEPATH%\mount\windows\boot\pxe\bootmgr.exe %PEPATH%\pxeboot\ > NUL
copy /y %PEPATH%\mount\windows\boot\pxe\pxeboot.n12 %PEPATH%\pxeboot\pxeboot.0 > NUL
copy /y %PEPATH%\mount\windows\boot\Fonts\*.* %PEPATH%\pxeboot\Fonts\ > NUL
copy /y "%WinPERoot%\%ARCH%\Media\Boot\boot.sdi" %PEPATH%\pxeboot\ > NUL
if defined DRIVERDIR echo Installing drivers
if defined DRIVERDIR dism /image:%PEPATH%\mount /Add-Driver:%DRIVERDIR% /recurse
echo Unmounting the image
dism /unmount-Wim /MountDir:%PEPATH%\mount /Commit /quiet
echo Optimizing the image
imagex /EXPORT %PEPATH%\media\sources\boot.wim 1 %PEPATH%\pxeboot\boot.wim > NUL
echo Creating the boot file
set BCDStore=%PEPATH%\pxeboot\BCD
bcdedit /createstore %BCDStore% > NUL
bcdedit /store %BCDStore% /create {ramdiskoptions} /d "Ramdisk options" > NUL
bcdedit /store %BCDStore% /set {ramdiskoptions} ramdisksdidevice Boot > NUL
bcdedit /store %BCDStore% /set {ramdiskoptions} ramdisksdipath \Boot\boot.sdi > NUL
for /f "Tokens=3" %%i in ('bcdedit /store %BCDStore% /create /d "Windows Install Image" /application osloader') do set GUID=%%i
bcdedit /store %BCDStore% /set %GUID% systemroot \Windows > NUL
bcdedit /store %BCDStore% /set %GUID% detecthal Yes > NUL
bcdedit /store %BCDStore% /set %GUID% winpe Yes > NUL
bcdedit /store %BCDStore% /set %GUID% osdevice ramdisk=[boot]\Boot\boot.wim,{ramdiskoptions} > NUL
bcdedit /store %BCDStore% /set %GUID% device ramdisk=[boot]\Boot\boot.wim,{ramdiskoptions} > NUL
bcdedit /store %BCDStore% /create {bootmgr} /d "Windows Boot Manager" > NUL
bcdedit /store %BCDStore% /set {bootmgr} timeout 30 > NUL
bcdedit /store %BCDStore% /set {bootmgr} displayorder %GUID% > NUL
echo.
echo All the files you need for your PXE server are in: %PEPATH%\pxeboot\
Note: The bcdedit line with displayorder seems to be required for the Windows 10 PE environment to boot. Previous versions seemed to work fine without it.
PXELINUX
Boot Files
Copy the files from the pxeboot directory on your Windows host created during the Windows PE Image creation process to your TFTP directory on your Linux host.
Note: Your tftproot directory may be different then mine. It might be tftpboot or something.
Note: Case matters. Fonts is Fonts, not fonts. You don’t really need the Fonts directory, but Windows PE checks for it, so might as well put it there.
/tftproot/winpe
total 212M
drwxr-xr-x 3 root root 4.0K Jul 30 19:27 .
drwxr-xr-x 6 root root 4.0K Jul 30 18:16 ..
-rw-r--r-- 1 root root 256K Jul 30 18:15 BCD
drwxr-xr-x 2 root root 4.0K Jul 30 18:14 Fonts
-rw-r--r-- 1 root root 3.1M Jun 17 18:08 boot.sdi
-rw-r--r-- 1 root root 208M Jul 30 18:15 boot.wim
-rw-r--r-- 1 root root 636K Jul 10 06:30 bootmgr.exe
-rw-r--r-- 1 root root 25K Jul 10 06:30 pxeboot.0
/tftproot/winpe/Fonts:
total 244K
drwxr-xr-x 2 root root 4.0K Jul 30 18:14 .
drwxr-xr-x 3 root root 4.0K Jul 30 19:27 ..
-rw-r--r-- 1 root root 36K Jul 10 06:30 segmono_boot.ttf
-rw-r--r-- 1 root root 76K Jul 10 06:30 segoe_slboot.ttf
-rw-r--r-- 1 root root 76K Jul 10 06:30 segoen_slboot.ttf
-rw-r--r-- 1 root root 47K Jul 10 06:30 wgl4_boot.ttf