Changes RSS

====== Differences ====== This shows you the differences between two versions of the page.

Link to this comparison view

guides:pxe [2010/04/18 23:03]
fishy Re-started setup, and documenting it this time...
guides:pxe [2010/04/19 17:39] (current)
fishy Meat for the Nested Menus
Line 99: Line 99:
 </code> </code>
  
-So, no menu yet, just a real simple test.+So, no menu yet, just a real simple test. Using any PXE-capable client computer, test this setup. You should be 
 +presented with quite a bit of pxelinux output, followed but the contents of boot.txt and a prompt. Trying to boot the 'linux' LABEL should naturally fail, but still confirms that things are working. Booting the default option 'boot_hd0' should boot your system normally (assuming the first BIOS drive is your boot device). 
 + 
 +===== First 'real-world' boot setup ===== 
 + 
 +Now, we will introduce the simples PXE-bootable installer, the Debian netinstall, and a menu to select it. 
 + 
 +We start by fetching the netboot-kit for Lenny: 
 + 
 +<code> 
 +mkdir /tmp/pxetmp; cd /tmp/pxetmp 
 +wget ftp://ftp.uio.no/debian/dists/lenny/main/installer-i386/20090123lenny6/images/netboot/netboot.tar.gz 
 +tar zxvf netboot.tar.gz 
 + 
 +mkdir -p /var/lib/tftpboot/debian/i386/lenny 
 +cp /tmp/pxetmp/debian-installer/i386/initrd.gz var/lib/tftpboot/debian/lenny/i386 
 +cp /tmp/pxetmp/debian-installer/i386/linux /var/lib/tftpboot/debian/lenny/i386 
 +</code> 
 + 
 +Now, we change /var/lib/tftpboot/pxelinux.cfg/default a little bit to start using menus. Replace 
 +the contents: 
 +<code> 
 +DEFAULT menu.c32 
 +MENU TITLE PXE Boot menu 0.1 
 + 
 +LABEL linux 
 +        MENU LABEL Debian Lenny i386 netinstall 
 +        KERNEL debian/lenny/i386/linux 
 +        APPEND vga=normal initrd=debian/lenny/i386/initrd.gz  -- 
 + 
 +LABEL boot_hd0 
 +        MENU LABEL Boot from first hard drive 
 +        MENU DEFAULT 
 +        COM32 chain.c32 
 +        APPEND hd0 
 + 
 +PROMPT 0 
 +MENU WIDTH 80 
 +MENU MARGIN 10 
 +MENU ROWS 12 
 +MENU TABMSGROW 18 
 +MENU CMDLINEROW 12 
 +MENU ENDROW 24 
 +MENU TIMEOUTROW 20 
 +ONTIMEOUT boot_hd0 
 +TIMEOUT 200 
 +</code> 
 + 
 +===== Getting fancy ===== 
 + 
 +The setup will now introduce quite a few components: 
 +  * "Graphical" menu using vesamenu.c32 
 +  * A fancy background image 
 +  * Common menu-config with color and layout settings for vesamenu.c32 
 +  * Nested/chained menus. 
 + 
 +We will set the basic framework using the two working options we already have in our menu to introduce the concept. After this, all elements of the sub-menus are simply variations on the basic setup we make here, and all specifics for each menu/os/installer/tool will be presented on separate pages. 
 + 
 +==== Preparing vesamenu.c32 ==== 
 + 
 +A text-based menu is swell, and probably recommended for some older platforms, but I wanted a menu with a tad of "bling" and a "modern" feel. Most of the boot-cds and images for Linux distributions these days use a VESA graphics syslinux/grub setup, and I wanted to do the same. 
 + 
 +The menu.c32 comboot module provides the menu we used in the previous step. To move from the text-only menu, to a 'graphical' menu with a background-image and more, we simple need to use vesamenu.c32 in place of menu.c32, and add some vesamenu-specific options.  
 + 
 +Pull in vesamenu.c32 from the syslinux packages: 
 + 
 +<code> 
 +cp /usr/lib/syslinux/vesamenu.c32 /var/lib/tftpboot 
 +</code> 
 + 
 +Next, get/create a suitable background image to use, and place it in the tftpboot-hierarchy. This is the background image I started out with, stored as /var/lib/tftpboot/menus/background.png 
 + 
 +{{:guides:pxemenu-background.png?160|background.png}} 
 + 
 +The specs for image-files that vesamenu.c32 accepts are fairly simple: A 640x480 pixels PNG or JPG image, displayable at 16bpp. So, more or less any 640x480 PNG will do. 
 + 
 +==== Some words about directory hierarchy layout ==== 
 + 
 +Since I am going to be putting rather large amounts of files in both TFTP and NFS shares, it does not hurt to have a  
 +plan for structuring content. 
 + 
 +For the tftpboot directory: 
 +^ TFTP   ^^ 
 +^ Directory ^ Use ^ 
 +| /var/lib/tftpboot/                      | Root of TFTP data, and location for pxelinux/syslinux binaries| 
 +| /var/lib/tftpboot/pxelinux.cfg/         | Contains the default cfg-file | 
 +| /var/lib/tftpboot/menus/                | Location for all files used to create the actual pxelinux-menus | 
 +| /var/lib/tftpboot/menus/$dist.cfg       | Sub-menu for a given OS distribution | 
 +| /var/lib/tftpboot/$dist/$ver/$arch | Files needed for TFTP-boot of OS Installer | 
 +| /var/lib/tftpboot/live/$dist/$ver/$arch | Files needed for TFTP boot of Live-system | 
 +^ NFS   ^^ 
 +^ Directory ^ Use ^ 
 +| /srv/boot/install/$dist/$ver/$arch      | NFS share for OS installer files | 
 +| /srv/boot/live/${DIST}/$dist/$ver/$arch         | NFS share for Live-boot OS files | 
 + 
 +So, a 32-bit Ubuntu 10.4 Live environment will use the paths: 
 + 
 +  * /var/lib/tftpboot/menus/ubuntu.cfg for its menu-option 
 +  * /var/lib/tftpboot/live/ubuntu/10.4/i386 for kernel- and initrd 
 +  * /srv/boot/live/ubuntu/10.4/i386 as NFS root for the Live-environment. 
 + 
 +Naturally, some installers will need various degrees of "fixed location" for files, but the above is the "standard" 
 +that these deviate from. 
 + 
 +==== Common configuration ==== 
 + 
 +Aiming to use multiple sub-menus, it will be very useful to gather all common configuration to one location, and avoid having to retype/copy the same settings to all menu-configurations. Luckily the syslinux menu system allows us to include settings from different files, and this is the mechanism we'll use to centralize common settings. 
 + 
 +My common configuration looks like this: 
 + 
 +<code> 
 +# /var/lib/tftpboot/menus/common.cfg 
 +MENU BACKGROUND menus/background.png 
 +ALLOWOPTIONS 1 
 +PROMPT 0 
 +MENU WIDTH 77 
 +MENU ROWS 14 
 +MENU TABMSGROW 25 
 +MENU CMDLINEROW 25 
 +MENU HELPMSGROW 23 
 +MENU MARGIN 15 
 +MENU VSHIFT 4 
 +MENU COLOR BORDER       30;44   #00000000 #00000000 none 
 +MENU COLOR SEL          7;37;40 #ffffffff #9090a0f0 std 
 +MENU COLOR HOTSEL       7;37;40 #ffffffff #204040f0 std 
 +MENU COLOR TIMEOUT_MSG  37;40   #aaaaaaaa #00000000 std 
 +MENU COLOR TIMEOUT      1;37;40 #ffaaaaff #00000000 std 
 +MENU SEPARATOR 
 +</code> 
 + 
 +Line for line description 
 +  * Set the background image (path relative to tftp root) 
 +  * ALLOWOPTIONS 1 
 +  * Disable the command/loader prompt 
 +  * Set the width, in characters, of the menu 
 +  * Set the height, in text-rows, of the menu. 
 +  * Set the location of the "Press TAB" text 
 +  * Set the location of the commandline when user presses TAB 
 +  * Set the location of the HELP text/verbose info 
 +  * Add a left-margin of 15 characters on the menu (move right) 
 +  * Shift the menu 4 text-rows down from default location 
 +  * Remove the border of the menu 
 +  * Set the colors and shading of the selection-bar 
 +  * Set the colors and shading of the menu hotkeys when selected 
 +  * Set the color of the "Autoboot in" string 
 +  * Set a different color for the TIME indicator. 
 +  * Add a fixed "space" between the header and the menu items. 
 + 
 +Naturally, more look-and-feel options may be added here. Also, settings like password-protection are prime candidates for the common.cfg file. 
 + 
 +==== Nested menus ==== 
 + 
 +So, we have our common configuration and COM32 modules ready. Let us modify pxelinux.cfg/default completely, and let it become our main menu. There are quite a few ways to build a complex menu system with syslinux. One approach is to use "MENU TITLE" to create submenus directly in the global configuration. This has the advantage that any LABEL of the menu and submenus can be typed directly on a prompt to boot. But, in my opinion, it also makes the menu vulnerable to errors in INCLUDE'd parts of the config. Another option is to chain-load the menus. This is related, but not as good, as the third option: loading each sub-menu as a COM32 module, with a separate complete config file for each sub-menu.  
 + 
 +This is a reliable approach, and a flexible one when debugging. Every time you select a sub-menu, or to return to the main menu, the entire config is re-read and applied. So, you can test changes to the menu by navigating back and forth in it. This naturally implies that the vesamenu.c32 and sub-menu config files will 
 +need to be transferred over TFTP every time you change menus, but in regard of the flexibility it gives for changing the menu on-the-fly is in my eyes a big plus, and the final selling point for me is the fact that a borken sub-config will not break my entire setup. 
 + 
 +The initial main menu configuration looks like this: 
 + 
 +<code> 
 +# /var/lib/tftpboot/pxelinux.cfg/default 
 +DEFAULT vesamenu.c32 
 +MENU INCLUDE menus/common.cfg 
 +MENU TITLE PXE Boot menu 0.1 
 + 
 +LABEL debian 
 +        MENU LABEL ^1 Debian  
 +        TEXT HELP 
 +Debian installers and live-boot options. 
 +        ENDTEXT 
 +        COM32 vesamenu.c32 
 +        APPEND menus/debian.cfg 
 + 
 +MENU SEPARATOR  
 + 
 +LABEL boot_hd0 
 +        MENU LABEL Boot from first hard drive 
 +        MENU DEFAULT 
 +        TEXT HELP 
 +Boots your system as normal from the first BIOS drive 
 +        ENDTEXT 
 +        COM32 chain.c32 
 +        APPEND hd0 
 + 
 +ONTIMEOUT boot_hd0 
 +TIMEOUT 300 
 +</code> 
 + 
 +I choose to use the COM32 loader-keyword, opposed to KERNEL. Using KERNEL will normally auto-detect what type of image/boot-program it is trying to load by looking at the file suffix or magic number, it just feels more correct 
 +to say COM32 when I know that is what I am going to load. 
 + 
 +Note that the pxelinux.cfg/default is the only configuration file in my setup that has the line "DEFAULT vesamenu.c32" included. This is because for all the sub-menus, the module is already loaded by being the actual image "booted". 
 + 
 +In all the sub-menus, I include a "Return to Main Menu" option on the top, to loads the default config and thus the main menu. 
 + 
 +<code> 
 +# /var/lib/tftpboot/menus/debian.cfg 
 +MENU INCLUDE menus/common.cfg 
 +MENU TITLE Debian Installers 
 + 
 +LABEL mainmenu 
 +        MENU LABEL ^R Return to Main Menu 
 +        COM32 vesamenu.c32 
 +        APPEND ~ 
 + 
 +MENU SEPARATOR 
 + 
 +LABEL lenny_i386_install 
 +        MENU LABEL ^1 Debian Lenny i386 netinstall 
 +        KERNEL debian/lenny/i386/linux 
 +        APPEND vga=normal initrd=debian/lenny/i386/initrd.gz  -- 
 + 
 +TIMEOUT 900 
 +</code> 
 + 
 +In the menus I am extensively using hotkeys. Hotkeys are identified my a caret (^) directly infront of the 
 +character used as the hot-key. Hotkeys should be in the A-Z,0-9 range, to make sure that you are independent  
 +of misc keyboard layouts. Hotkeys can also (naturally) only be assigned once in a single menu. If you asssign the same hotkey to multiple options, they will display as hot-keys, but none of them will be selected by pressing the key. 
 + 
 +Seeing how I load the menus using the COM32 keyword with an APPEND line, you should be able to notice that there is really no limit on how deep you can nest your menus, and that it is fully possible to use the same menu as a "sub" in multiple places.