Breathe new life into an old computer with PXE boot and TinyCore Linux

Boot Story

© Lead Image © Evgeny Atamanenko, 123RF.com

© Lead Image © Evgeny Atamanenko, 123RF.com

Article from Issue 230/2020
Author(s):

Implementing PXE boot with TinyCore Linux lets you boot a computer over the network – a great solution for revitalizing old computing hardware.

One of my passions is enabling the reuse of older computer hardware that others consider obsolete. I picked up a used laptop at a local university's surplus equipment sale for $15. It was a pretty decent little thing – an older 32-bit dual core CPU with 1-2GB of memory – but my thought was that it would be a great laptop for my kids. The problem: It had no hard drive. My initial thought was to put Linux on a USB drive and boot to that. This worked wonderfully for the first few days – until my kids failed to remember to shut it down properly, which hosed the USB filesystem. To their sadness and my frustration, the computer sat for a few months. Then one day an idea popped into my head: PXE boot the laptop. Preboot eXecution Environment (PXE) is a standard for booting computers across the network. I knew it used DHCP, but that was the extent of my knowledge. This is the story of what I learned about PXE boot, how I implemented it using TinyCore Linux [1], and how I found the coolest, geekiest solution for my kids.

Laying the Groundwork

Almost all of us have seen the PXE or Network boot option on our BIOS screen. PXE uses the network interface to load the operating system and necessary configuration files over a network. This is accomplished using two particular network protocols: Dynamic Host Configuration Protocol (DHCP) and Trivial File Transfer Protocol (TFTP). DHCP is used to request client configuration data before any operating system is loaded. Once the client has network access, files are downloaded via TFTP and are loaded into memory on the client machine. Once the files are loaded, the operating system will boot on the client completely in memory without requiring any local storage. Knowing a little about these two components will improve the ability to properly implement a PXE environment.

One of the key components of a PXE boot environment is a DHCP server. DHCP allows a client configuration to be requested and delivered over a network. When a client device connects to a network, a series of requests and responses must take place to complete a DHCP session using the following steps:

  1. The client device issues a broadcast request for available DHCP servers.
  2. If there is an available DHCP server, it will respond to the client indicating that it is available.
  3. The client sends a request to the DHCP server.
  4. The server responds with the configuration data for the client device.

The data returned to the client in Step 4 is where DHCP's power lives. Although the host configuration portion of the response contains the client IP address and gateway address (along with a few other pieces of data), the response also includes a section containing other configuration options. Depending on the DHCP server configuration, this step can be used to provide many other pieces of client configuration data, including DHCP lease information, router addresses, DNS servers, the time server, the TFTP server address, and many other parameters. The PXE hardware on most computers has the ability to perform the preceding steps to obtain configuration data from a DHCP server. At this point, the client can begin loading the operating system and prepare the boot environment.

To complete the loading of the boot environment, PXE will request the necessary files from a TFTP server. TFTP allows for discrete transferring of files over a network without the authentication or filesystem browsing overhead of other protocols, such as FTP. This minimal functionality means a small memory footprint, making it ideal for a PXE environment. In order to create the boot environment, the PXE firmware for the operating system must be loaded onto the client device. The firmware, along with other boot files and the TFTP path to download additional files, is specified in the DHCP response, along with other client configuration options.

Back to the project involving my kids' laptop: While the network boot environment provided the resiliency of being able to reboot and attain a clean running operating system, I also wanted a limited environment allowing my kids to do specific tasks like send email or browse the web. Having played with TinyCore Linux in the past, I looked at it first. Its small memory footprint made it incredibly desirable for the PXE environment. For a bit of context, the TinyCore ISO image for the command-line and GUI desktop environments are 11MB and 16MB respectively. While it does not measure up to a mature distribution like Debian or CentOS, it does provide a repository of popular software packages. All of the software I wanted to run (such as Thunderbird, Firefox, Gimp, and AbiWord) are all available through the TinyCore repository.

I have identified all of the high-level moving parts of this custom PXE environment. The implementation will require the installation and configuration of a DHCP server and a TFTP server. It will also involve customizing TinyCore's out-of-the-box distribution, which will involve installing the desired applications and reconfiguring the GUI. This approach will not only provide a stable and functional environment to do various tasks, but it will provide a platform to easily deploy new applications that can be delivered via PXE boot.

Preparing the Base Files

To boot my PXE environment, all of the required files will come from two places: the Syslinux Project [2] and the TinyCore ISO image [1]. The Syslinux Project contains bootloaders for Linux, including ones designed for network booting (PXELINUX) and CD-ROM booting (ISOLINUX). For now, I will focus on PXELINUX as the bootloader; ISOLINUX will be referenced later in this article. The PXE bootloader file is named pxelinux.0. While it is technically possible to build this file from the Syslinux source, an older version is available on the Syslinux website that contains a pre-built binary version of pxelinux.0, which will work nicely. To download the Syslinux package and extract the necessary file, run the following command:

curl -s https://mirrors.edge.kernel.org/pub/linux/utils/boot/syslinux/syslinux-4.04.tar.gz | tar -zxvf- syslinux-4.04/core/pxelinux.0

This will create the syslinux-4.04 folder in the current working directory, which in turn contains a folder named core and within that folder is the pxelinux.0 firmware file. To make this file available to a PXE client, it will need to reside within the TFTP root folder, which you create with the following command:

mkdir -p /opt/lib/tftp/boot

For this example, I have set the TFTP root directory to /opt/lib/tftp, and the PXE firmware should be placed in the boot folder within the TFTP root.

Next, I will complete the file configuration with the TinyCore ISO image. For this project, I am opting to go with the 16MB ISO containing the GUI environment. Since the process of preparing the TinyCore specific files is quite involved, it will be divided into two steps: preparing the base operating system and adding new applications.

The initial setup of the base system requires the /boot folder's contents to be extracted for further customization. This can be accomplished using the following template script:

sudo mount -o loop TINYCORE.ISO /mnt/cdrom
cp -R /mnt/cdrom/boot/* /opt/lib/tftp/boot

In this script, TINYCORE.ISO should be replaced with the path to the TinyCore ISO image. All of the files mentioned in this section (PXE firmware, kernel, init ramdisk, and boot folder contents) will need to be located within the TFTP root. Leave the ISO image mounted as more files will be needed later in the process. Once extracted, the target folder will contain three items: vmlinuz (the kernel), core.gz (the init ramdisk), and isolinux (the folder containing the boot menu configuration). The kernel file will not be modified and will remain in the boot folder in the TFTP root. The init ramdisk file, core.gz, will be modified to contain all of the files necessary to run the GUI environment. To modify the contents of core.gz, it must be extracted to a folder. This can be done using the following template script:

mkdir /tmp/initrd-contents
cd /tmp/initrd-contents
gzip -cd /opt/lib/tftp/boot/core.gz | cpio -i

In this example, the contents of the init ramdisk are located in /tmp/initrd-contents. Note that the cpio command is available for all popular distributions, but it may need to be installed. As mentioned earlier, the whole desktop environment will be copied onto the init ramdisk. To accomplish this, the file will need to be copied from the ISO image to a folder on the init ramdisk with the following template script:

mkdir -p /tmp/initrd-contents/usr/local/share/install-base
cp /mnt/cdrom/cde/optional/*tcz /tmp/initrd-contents/usr/local/share/install-base

The files that were copied with the TCZ file extension will be installed at boot time. Since TinyCore is a single-user distribution, this can be accomplished by editing the script located in /etc/profile to install the files and start X windows. The following lines will be added to the end of the /etc/profile file in the init ramdisk:

tce-load -i /usr/local/share/install-base/*tcz
startx

At this point, the init ramdisk content is configured to boot into the default out-of-the-box GUI configuration. This is a great time to repackage the init ramdisk as a base boot image. This can be done using the following script template:

cd /tmp/initrd-contents
find . | cpio -H newc -o > /opt/lib/tftp/boot/core
gzip -f /opt/lib/tftp/boot/core

Note that running this script will overwrite the init ramdisk in the boot folder under the TFTP root folder. This finalizes the creation of the init ramdisk image. To automate the process of customizing the init ramdisk the inity.sh scrip can be used [3]. Now that a base image has been created, the Firefox application will be added and saved as a new init ramdisk image. This will be accomplished by modifying the above commands that were added to the /etc/profile script to the following:

tce-load -i /usr/local/share/install-base/*tcz
tce-load -w -i firefox-esr.tcz
startx

This modification will allow the Firefox package to be installed after the base system has been installed. It should be noted that the larger an application is the longer it will take to install and therefore boot the environment. This is now ready to be repackaged into a new init ramdisk image, which can be accomplished with the following template script:

cd /tmp/initrd-contents
find . | cpio -H newc -o > /opt/lib/tftp/boot/core-firefox
gzip -f /opt/lib/tftp/boot/core-firefox

Note that the name of the new init ramdisk will be core-firefox.gz. The last step of our process is to modify the boot menu to display two boot options: the base image and the new Firefox image. The boot menu is contained in the /opt/lib/tftp/boot/isolinux/isolinux.cfg file. This file has three main sections separated by empty lines. The first section contains general configuration items, such as DEFAULT, UI, PROMPT, and so on. The second section contains configurations beginning with MENU, which will be used to configure the boot menu's look and feel. The third section contains multiple line-separated groups of configurations that correspond to menu items. The first line in each group of configurations should begin with a LABEL statement. All of the entries in the third section may be removed for this project. After removing the existing menu entries, the file will look similar to Listing 1.

Listing 1

Modified Boot Menu

DEFAULT tc
UI menu.c32
PROMPT 0
TIMEOUT 600
ONTIMEOUT tc
F1 f1
F2 f2
F3 f3
F4 f4
MENU TITLE TinyCore
MENU MARGIN 10
MENU VSHIFT 5
MENU ROWS 5
MENU TABMSGROW 14
MENU TABMSG Press ENTER to boot, TAB to edit, or press F1 for more information.
MENU HELPMSGROW 15
MENU HELPMSGENDROW -3
MENU AUTOBOOT BIOS default device boot in # second{,s}...

There might be minor differences depending on the TinyCore version being used. Now the new PXE environments will be added to the menu. The environment with the base init ramdisk image should look like this:

LABEL tc
MENU LABEL TinyCore Base
KERNEL /boot/vmlinuz
INITRD /boot/core.gz

The Firefox environment will look the same as this base configuration with the exception of the INITRD configuration, which will have a value of /boot/core-firefox.gz. This completes the configuration of the available PXE environments into which you can boot. The remaining step involves configuring the network services that power the PXE boot environments: DHCP and TFTP.

Configuring DHCP and TFTP

Not wanting to set up a whole new server for DCHP and TFTP, I opted to use a Raspberry Pi I had on my network to host them. Luckily for this project there is a single application that will run both of these services: dnsmasq [4]. Dnsmasq is a server application that provides, among other services, DHCP, DNS, and TFTP. Since services are being delivered over the network, the server OS distribution is not important. Luckily dnsmasq is available for most popular Linux distributions. The first step is configuring the DHCP server portion of dnsmasq. Enter a basic DHCP configuration into the /etc/dnsmasq.conf file as shown in Listing 2.

Listing 2

A Basic DHCP Configuration

01 interface=eth0
02 dhcp-range=192.168.1.100,192.168.1.200,12h
03 dhcp-option=3,192.168.1.1

Line 1 of Listing 2 uses the interface directive to set the network interface on which the DHCP service will be listening (in this case, eth0). Line 2 uses the dhcp-range directive to specify the range of IP addresses that will be available for client use and the DHCP lease length. In this case, the IP addresses between 192.168.1.100 and 192.168.1.200 will be available and will be leased for 12 hours. Line 3 uses the dhcp-option directive to set a DHCP option 3, which corresponds to the default gateway address (192.168.1.1). Once this has been completed, you can configure the custom DHCP parameters to enable PXE boot. This will involve adding Listing 3 to the /etc/dnsmasq.conf file.

Listing 3

Configuring Custom DHCP Parameters

01 dhcp-boot=/opt/lib/tftp/boot/pxelinux.0,192.168.1.10
02 dhcp-option-force=209,/boot/isolinux/isolinux.cfg
03 dhcp-option-force=210,/
04 dhcp-option-force=66,192,168.1.10
05 enable-tftp
06 tftp-root=/opt/lib/tftp

Line 1 of Listing 3 uses the dhcp-boot directive to specify the full path of the PXE firmware on the TFTP server along with the TFTP server IP address. The next three lines are setting specific DHCP options. Option 209 on line 2 is the relative path (within the TFTP root) to the PXELINUX configuration file. Since the configuration file was copied from the TinyCore ISO image, it is named isolinux.cfg, which corresponds to the Syslinux type that was used to boot the CD. Since both types are based on Syslinux, this will not be an issue for this project. Option 210 on line 3 sets the directory to look for PXELINUX boot files (the kernel, the init ramdisk, etc.), which like option 209 is relative to the TFTP root path. Option 66 on line 4 sets the TFTP server's IP address. All of these options will be returned in the DHCP response packet. Lines 5 and 6 are configuring the TFTP server. Line 5 uses the enable-tftp directive to enable listening for TFTP connections. Line 6 uses the tftp-root directive to specify the full path where files that will be available over TFTP will be located.

The PXE environment configuration is now complete and is ready to boot clients over a LAN. If your network already uses a DHCP server, this could cause problems as there is no assurance which DHCP server will respond to the client first. Consequently, this configuration should be deployed either on a network segment where DHCP is currently not running or configured to work with the existing DHCP service. When I implemented this solution, I was running DD-WRT on my router, which uses dnsmasq as its DNS and DHCP. So, I added the advanced DHCP options above to my DD-WRT instance and used my Raspberry Pi as the TFTP server only.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Ask Klaus!

     

  • PXE Boot

    PXE lets you start your computer by downloading a boot image from the network. We’ll show you how to use PXE to install Linux.

  • Ubuntu autoinstall with cloud-init

    The new automatic installation method rolled out with Ubuntu 22.04 borrows some tools from the cloud configuration toolbox. We'll show you how to get started.

  • iPXE

    iPXE simplifies the task of booting images over a network and also lets admins design dynamic boot menus that integrate scripts and boot images via HTTP(S).

  • LTSP

    The Linux Terminal Server Project offers a comprehensive approach to terminal services in Linux, including easy access to local sound cards, printers, and USB sticks.

comments powered by Disqus