PXE Booting

In this post I’m going to try and give a detailed set of instructions for setting up a PXE server that can boot to Ubuntu Live, WinPE, or a number of other utilities. The instruction set given here allows booting to: Ubuntu Desktop 12.04 x86 & x64, WinPE x86 & x64, Clonezilla, Memtest, MHDD, Parted Magic, and lastly Derik’s Boot And Nuke (DBAN).

One last thing before getting started, you pretty much need to sudo every command, but I’ve left it off.

I’m using Ubuntu 12.04 Server Edition as my PXE server. So right off the bat I need to install some packages:

apt-get install tftpd-hpa syslinux nfs-kernel-server samba proftpd

Now edit /etc/default/tftpd-hpa. We need to change our TFTP_Directory and add the option for a remap file. It should look like the following:

vim /etc/default/tftpd-hpa
---
TFTP_USERNAME=”tftp”
#TFTP_DIRECTORY=”/var/lib/tftpboot”
TFTP_DIRECTORY=”/media/pxe”
TFTP_ADDRESS=”0.0.0.0:69″
TFTP_OPTIONS=”–secure –map-file /etc/tftpd.remap”

You can also add the argument ‘-vvv’ to ‘TFTP_OPTIONS’ to get some more verbose output in ‘/var/log/syslog’ to help in troubleshooting.

If you notice, TFTP_OPTIONS includes the argument ‘–map-file /etc/tftpd.remap’. If you are not planning on trying to PXE boot Windows, then you don’t need it. However, since I am planning to boot Windows, I need to create a remap file.

vim /etc/tftpd.remap
---
#Remap path separators
gr \ /
#Locate bootmgr.exe
r ^bootmgr.exe /WinPE/bootmgr.exe
#Map /Boot to /Windows
r ^/Boot /WinPE
#Map /boot to /Windows
r ^/boot /WinPE

Next, create a directory for tftp to have access to and then copy the necessary files to enable tftpbooting.

mkdir /media/pxe
cp /usr/lib/syslinux/pxelinux.0 /media/pxe/
cp /usr/lib/syslinux/vesamenu.c32 /media/pxe/
mkdir /media/pxe/pxelinux.cfg
touch /media/pxe/pxelinux.cfg/default
touch /media/pxe/pxelinux.cfg/pxe.conf

This is where our menu system starts. When it comes to these menus, it’s important to remember that a pxe booted machine essentially gets chroot’d to our pxe directory, in this case it’s going to be ‘/media/pxe’. This means that to the PXE booted machine ‘/media/pxe’ becomes ‘/’.

Add some params to the ‘/media/pxe/pxelinux.cfg/pxe.conf’. If you want a logo, replace logo.png with it. Note that the image needs to be 640×480:

MENU TITLE PXE Server
MENU BACKGROUND pxelinux.cfg/logo.png
NOESCAPE 1
ALLOWOPTIONS 1
PROMPT 0
menu width 80
menu rows 14
MENU TABMSGROW 24
MENU MARGIN 10
menu color border 30;44 #ffffffff #00000000 std

Add entries to '/media/pxe/pxelinux.cfg/default'. This one defaults to booting to the local hard drive after 60 seconds. But if one of the options (Utilities, Ubuntu, or Windows) is chosen, it will display menus that exist in the location indicated by the MENU INCLUDE parameter.

DEFAULT vesamenu.c32
TIMEOUT 600
ONTIMEOUT BootLocal
PROMPT 0
MENU INCLUDE pxelinux.cfg/pxe.conf
NOESCAPE 1
LABEL BootLocal
localboot 0
TEXT HELP
Boot to local hard disk
ENDTEXT
MENU BEGIN Utilities
MENU TITLE Utilities
LABEL Previous
MENU LABEL Previous Menu
TEXT HELP
Return to previous menu
ENDTEXT
MENU EXIT
MENU SEPARATOR
MENU INCLUDE utilities/utilities.menu
MENU END
MENU BEGIN Ubuntu
MENU TITLE Ubuntu
LABEL Previous
MENU LABEL Previous Menu
TEXT HELP
Return to previous menu
ENDTEXT
MENU EXIT
MENU SEPARATOR
MENU INCLUDE ubuntu1204/ubuntu.menu
MENU END
MENU BEGIN WinPE
MENU TITLE WinPE
LABEL Previous
MENU LABEL Previous Menu
TEXT HELP
Return to previous menu
ENDTEXT
MENU EXIT
MENU SEPARATOR
MENU INCLUDE WinPE/WinPE.menu
MENU END

Looking at the MENU INCLUDE params in /media/pxe/pxelinux.cfg/default, I'm going to need some folders. But because I know I want to include several items in the utilities menu, I'm going to go ahead and create directories for those items as well.

mkdir -p /media/pxe/utilities/{clonezilla,dariks-boot-and-nuke,memtest,mhdd,parted-magic}

Download the PXE specific version of Clonezilla from http://www.clonezilla.org/livepxe.php and mount it to /mnt and copy the needed files to it's utility directory.

cp /mnt/live/{filesystem.squashfs,initrd.img,vmlinuz} /media/pxe/utilities/clonezilla/

Next, download DBAN from http://sourceforge.net/projects/dban/, mount it, and copy it's needed files to the utility directory.

cp /mnt/dban.bzi /media/pxe/utilities/dariks-boot-and-nuke/

Continue this process of downloading, mounting, and copying the necessary files from each of these isos.

You can get Memtest from http://www.memtest.org/#downiso and you will only need the memtest86+ file. 

For MHDD, get it from http://hddguru.com/software/2005.10.02-MHDD/. You will need the mhdd.img file.

Get Parted Magic from http://partedmagic.com/ and copy out the files: bzImage and initrd.img.

 

Now you need to build the /media/pxe/utilities/utilities.menu file. If you've placed all the files as described, this file should look like this:

LABEL 1
MENU LABEL Memtest+ v4.20
KERNEL utilities/MemTest86-4.20/memtest86+-4.20
TEXT HELP
Boot Memtest+ v4.20
ENDTEXT
LABEL 2
MENU LABEL MHDD32 v4.6
KERNEL memdisk
APPEND initrd=utilities/MHDD/mhdd.img
TEXT HELP
Boot MHDD v4.6 Hard Drive Utility
ENDTEXT
LABEL 3
MENU LABEL Clonezilla
KERNEL utilities/clonezilla/vmlinuz
APPEND boot=live netboot=nfs initrd=utilities/clonezilla/initrd.img config noswap nolocales edd=on nomodeset ocs_live_run=”ocs-live-general” ocs_live_extra_param=”” ocs_live_keymap=”” ocs_live_batch=”no” ocs_lang=”” vga=788 fetch=tftp://your server ip/utilities/clonezilla/filesystem.squashfs
TEXT HELP
Boot Clonezilla
ENDTEXT
LABEL 4
MENU LABEL Parted Magic
LINUX utilities/parted-magic/bzImage
INITRD utilities/parted-magic/initrd.img
APPEND edd=off load_ramdisk=1 prompt_ramdisk=0 rw vga=normal loglevel=9 max_loop=256
TEXT HELP
Parted Magic
ENDTEXT
LABEL 5
MENU LABEL Darik’s Boot and Nuke (2.2.7-Beta)
KERNEL utilities/Dariks-Boot-And-Nuke/dban.bzi
APPEND nuke=”dwipe” silent floppy=0,16,cmos
TEXT HELP
Warning!!! This will erase the hard drive!
ENDTEXT

XE boot Ubuntu Live or Ubuntu Server:

I will actually need two sets of folders. I need some for tftp access and some for nfs access.
Download the latest Ubuntu distro from http://www.ubuntu.com/download
Start by building this folder structure:
mkdir -p /media/pxe/ubuntu1204/desktop/amd64
mkdir -p /media/pxe/ubuntu1204/server/amd64
mkdir -p /media/pxe/nfs/ubuntu1204/desktop/amd64
mkdir -p /media/pxe/nfs/ubuntu1204/server/amd64

Now mount the desktop iso to /mnt
Copy the files initrd.lz and vmlinuz from /mnt/casper to /media/pxe/ubuntu1204/desktop/amd64/
And then copy /mnt/* to /media/pxe/nfs/ubuntu/desktop/amd64/
cp -a /mnt/* /media/pxe/nfs/ubuntu1204/desktop/amd64/ && cp -a /mnt/.disk /media/pxe/nfs/ubuntu1204/desktop/amd64/

cp /mnt/casper/{initrd.lz,vmlinuz} /media/pxe/ubuntu1204/desktop/amd64/
cp -a /mnt/* /media/pxe/nfs/ubuntu1204/desktop/amd64/
cp -a /mnt/.disk /media/pxe/nfs/ubuntu1204/desktop/amd64/

After that unmount the iso
Repeat for all the other Ubuntu versions but placing the files in the appropriate directories.

With all of that done, you just need to create the /media/pxe/ubuntu1204/ubuntu.menu file. It should look like what follows:

LABEL 1
MENU LABEL Ubuntu Desktop 12.04 (64-bit)
KERNEL ubuntu1204/desktop/amd64/vmlinuz
APPEND boot=casper netboot=nfs nfsroot=10.234.63.99:/media/pxe/nfs/ubuntu1204/desktop/amd64 initrd=ubuntu1204/desktop/amd64/initrd.lz
TEXT HELP
Boot the Ubuntu 12.04 Desktop 64-bit DVD
ENDTEXT
LABEL 2
MENU LABEL Ubuntu Server 12.04 (64-bit)
KERNEL ubuntu1204/server/amd64/vmlinuz
APPEND boot=casper netboot=nfs nfsroot=10.234.63.99:/media/pxe/nfs/ubuntu1204/server/amd64 initrd=ubuntu1204/server/amd64/initrd.gz
TEXT HELP
Boot the Ubuntu 12.04 Server 64-bit DVD
ENDTEXT

Windows – now it gets quite a bit more complicated.
Credit for helping to figure out this section is due from reading the following two sites:

http://etherboot.org/wiki/winpe

http://solitudo.net/blah/posts/Create_Windows_PE_rescue_and_installation_images_using_WAIK_for_Windows_7_and_configure_Linux_boot_server_for_PXE_booting_the_images/

First you will need a Windows machine with WAIK (Windows Automated Installation Toolkit installed)
Download from here: http://www.microsoft.com/en-us/download/details.aspx?id=5753
In that Windows machine open notepad. Paste in the following:

cd “C:Program FilesWindows AIKToolsPETools”
mkdir c:temp
call copype.cmd amd64 c:tempWinPE-x64
del /q etfsboot.com
move isobootboot.sdi boot.sdi
rmdir /s /q iso
imagex /mountrw winpe.wim 1 mount
copy mountWindowsBootPXEpxeboot.n12 pxeboot.n12
copy mountWindowsBootPXEbootmgr.exe bootmgr.exe
copy mountWindowsSystem32bcdedit.exe bcdedit.exe
copy “C:Program FilesWindows AIKToolsamd64imagex.exe” mountwindowssystem32imagex.exe
copy /Y c:users<username>DesktopPXE_Toolsstartnet.cmd mountwindowssystem32startnet.cmd
copy /Y c:users<username>DesktopPXE_ToolsWinPE.bmp mountwindowssystem32WinPE.bmp
imagex /unmount mount /commit
rmdir /q mount

bcdedit -createstore BCD
set BCDEDIT=bcdedit -store BCD
%BCDEDIT% -create {ramdiskoptions}
%BCDEDIT% -set {ramdiskoptions} ramdisksdidevice boot
%BCDEDIT% -set {ramdiskoptions} ramdisksdipath Bootboot.sdi
%BCDEDIT% -create {bootmgr} -d “Windows Boot Manager”
%BCDEDIT% -set {bootmgr} timeout 30

for /f “tokens=3″ %%a in (‘%BCDEDIT% -create -d “WinPE-x86″ -application osloader’) do set GUID1=%%a
%BCDEDIT% -set %GUID1% systemroot Windows
%BCDEDIT% -set %GUID1% detecthal Yes
%BCDEDIT% -set %GUID1% winpe Yes
%BCDEDIT% -set %GUID1% osdevice ramdisk=[boot]WinPEWinPE-x86winpe.wim,{ramdiskoptions}
%BCDEDIT% -set %GUID1% device ramdisk=[boot]WinPEWinPE-x86winpe.wim,{ramdiskoptions}

for /f “tokens=3″ %%a in (‘%BCDEDIT% -create -d “WinPE-x64″ -application osloader’) do set GUID2=%%a
%BCDEDIT% -set %GUID2% systemroot Windows
%BCDEDIT% -set %GUID2% detecthal Yes
%BCDEDIT% -set %GUID2% winpe Yes
%BCDEDIT% -set %GUID2% osdevice ramdisk=[boot]WinPEWinPE-x64winpe.wim,{ramdiskoptions}
%BCDEDIT% -set %GUID2% device ramdisk=[boot]WinPEWinPE-x64winpe.wim,{ramdiskoptions}
%BCDEDIT% -displayorder %GUID1% %GUID2%

del /q bcdedit.exe
cd c:
move c:temp c:WinPE
mkdir c:WinPE-x86
copy “C:Program FilesWindows AIKToolsPEToolsx86winpe.wim” c:WinPE-x86
cd c:WinPE-x86
mkdir c:WinPE-x86mount
imagex /mountrw winpe.wim 1 mount
copy “C:Program FilesWindows AIKToolsx86imagex.exe” mountwindowssystem32imagex.exe
copy /Y c:users<username>Desktopstartnet.cmd mountwindowssystem32startnet.cmd
copy /Y c:users<username>DesktopWinPE.bmp mountwindowssystem32WinPE.bmp
imagex /unmount mount /commit
rmdir /q mount

cd c:WinPE
move c:WinPE-x86 c:WinPEWinPE-x86

move WinPE-x64BCD .
move WinPE-x64boot.sdi .
move WinPE-x64bootmgr.exe .
move WinPE-x64efisys.bin .
move WinPE-x64efisys_noprompt.bin .
move WinPE-x64pxeboot.n12 .

echo LABEL 1 > WinPE.menu
echo MENU LABEL WinPE >> WinPE.menu
echo KERNEL WinPE/pxeboot.0 >> WinPE.menu
echo APPEND – >> WinPE.menu
echo TEXT HELP >> WinPE.menu
echo Boot WinPE >> WinPE.menu
echo ENDTEXT >> WinPE.menu
cd c:

Save it on the desktop as a ‘winpe.bat’ file
Change the 4 <username> entries to match your username.
On the desktop, create a file called ‘startnet.cmd’ and open it up in notepad.
You can put any commands you want your WinPE session to run in here. I like to have it automatically map back to the SMB share on my PXE server.

wpeinit
net use z: \<pxe_server><share> user:nobody
z:
dir z:

You should also put an image that your want as the background on the desktop and rename it to ‘WinPE.bmp’
Run the ‘winpe.bat’ file.
Now copy ‘c:WinPE’ to ‘<PXE_Server>/media/pxe/WinPE’.

Back on our PXE Server:
Our PXE server won’t boot anything that doesn’t end in .0, so we need to create a symlink,
`cd /media/pxe/WinPE`
`ln -s pxeboot.n12 pxeboot.0`

Restart the TFTP-HPA process: `sudo /etc/init.d/tftp-hpa restart`

Now we need to configure our other listening services:
NFS
`vim /etc/exports`
Add the line: ‘/media/pxe/nfs <allowed_subnet>(ro,async,no_root_squash,no_subtree_check)’
Your <allowed_subnet> should be something like ‘192.168.1.0/24′
As I use IP Tables to help me secure my servers, I need to make sure that NFS only uses ports that I know about.
`vim /etc/default/nfs-common`
NEED_STATD=”yes”
STATDOPTS=”-p 4000 -c 4004″
`vim /etc/default/nfs-kernel-server`
RPCMOUNTDOPTS=”-p 4002 -g”
`/etc/init.d/nfs-kernel-server restart`

Samba
`vim /etc/samba/smb.conf`
Add a section:

[Something]
comment = Stuff
browseable = yes
create mask = 0775
directory mask = 0775
path = /media/Something
guest ok = yes
guest only = yes
guest account = nobody
writable = yes

Save it.
`/etc/init.d/smbd restart`
Now put anything in there that you want available to your PXE booted WinPE sessions.
I use this method to prototype and deploy special Windows builds.
If you copy the contents of a Windows install iso here, PXE boot to WinPE and run setup.exe, it will install Windows.

The last thing you need to do is to get your PXE server working is point your DHCP server at it.

Done!