Skip to content

Instantly share code, notes, and snippets.

@ithilelda
Last active January 2, 2024 10:35
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ithilelda/4b6198bd6640f7270603bd11677bfe9c to your computer and use it in GitHub Desktop.
Save ithilelda/4b6198bd6640f7270603bd11677bfe9c to your computer and use it in GitHub Desktop.
actually working pxe boot with grub2 on bios (client setup)
set default=0
set timeout=60
set root=(http,$net_default_server:8080)
menuentry 'Reboot' {
reboot
}
menuentry 'Shutdown' {
halt
}
submenu 'System Utilities' --hotkey=u {
menuentry 'Clonezilla' --class os {
set sys_root="/clonezilla/iso"
echo "Loading kernel..."
linux $sys_root/live/vmlinuz boot=live union=overlay username=user config components quiet loglevel=0 noswap edd=on nomodeset enforcing=0 noeject locales= keyboard-layouts= ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_batch="no" nodmraid net.ifames=0 nosplash fetch="http://$net_default_server:8080$sys_root/live/filesystem.squashfs"
echo "Loading initrd..."
initrd $sys_root/live/initrd.img
}
menuentry 'System Rescue' --class os {
set sys_root="/sysresccd/iso"
echo "Loading kernel..."
linux $sys_root/sysresccd/boot/x86_64/vmlinuz ip=dhcp archisobasedir=sysresccd archiso_http_srv="http://$net_default_server:8080$sys_root/" checksum iomem=relaxed
echo "Loading initrd..."
initrd $sys_root/sysresccd/boot/amd_ucode.img $sys_root/sysresccd/boot/intel_ucode.img $sys_root/sysresccd/boot/x86_64/sysresccd.img
}
}
submenu 'Linux' --hotkey=l {
menuentry 'Arch Linux' --class os {
set arch_root="/archlinux/iso"
echo "Loading kernel..."
linux $arch_root/arch/boot/x86_64/vmlinuz-linux ip=dhcp archisobasedir=arch archiso_http_srv="http://$net_default_server:8080$arch_root/" cms_verify=y
echo "Loading initrd..."
initrd $arch_root/arch/boot/amd-ucode.img $arch_root/arch/boot/intel-ucode.img $arch_root/arch/boot/x86_64/initramfs-linux.img
}
menuentry 'ArchLabs LTS' --class os {
set arch_root="/archlabs/iso"
echo "Loading kernel..."
linux $arch_root/arch/boot/x86_64/vmlinuz-linux-lts ip=dhcp archisobasedir=arch archiso_http_srv="http://$net_default_server:8080$arch_root/" checksum
echo "Loading initrd..."
initrd $arch_root/arch/boot/amd-ucode.img $arch_root/arch/boot/intel-ucode.img $arch_root/arch/boot/x86_64/initramfs-linux-lts.img
}
menuentry 'ArcoLinuxD' --class os {
set arch_root="/arcoxd/iso"
echo "Loading kernel..."
linux $arch_root/arch/boot/x86_64/vmlinuz-linux ip=dhcp archisobasedir=arch archiso_http_srv="http://$net_default_server:8080$arch_root/" checksum
echo "Loading initrd..."
initrd $arch_root/arch/boot/amd-ucode.img $arch_root/arch/boot/intel-ucode.img $arch_root/arch/boot/x86_64/initramfs-linux.img
}
menuentry 'Artix' --class os {
set arch_root="/artix/iso"
echo "Loading kernel..."
linux $arch_root/boot/vmlinuz-x86_64 ip=dhcp artix_http_srv="http://$net_default_server:8080$arch_root/"
echo "Loading initrd..."
initrd $arch_root/boot/amd-ucode.img $arch_root/boot/intel-ucode.img $arch_root/../initramfs-patched.img
}
menuentry 'Almalinux 8.7' --class os {
set alma_root="/alma-8.7/iso"
echo "Loading kernel..."
linux $alma_root/images/pxeboot/vmlinuz ip=dhcp inst.stage2="http://$net_default_server:8080$alma_root"
echo "Loading initrd..."
initrd $alma_root/images/pxeboot/initrd.img
}
menuentry 'Almalinux 9.1' --class os {
set alma_root="/alma-9.1/iso"
echo "Loading kernel..."
linux $alma_root/images/pxeboot/vmlinuz ip=dhcp inst.stage2="http://$net_default_server:8080$alma_root"
echo "Loading initrd..."
initrd $alma_root/images/pxeboot/initrd.img
}
menuentry 'Devuan Netboot' --class os {
echo "Loading kernel..."
linux /devuan/linux --- quiet
echo "Loading initrd..."
initrd /devuan/initrd.gz
}
menuentry 'Ubuntu Server (Require > 4G RAM)' --class os {
echo "Loading kernel..."
linux /ubuntu/vmlinuz ip=dhcp url="http://$net_default_server:8080/ubuntu/ubuntu-22.04.2-live-server-amd64.iso"
echo "Loading initrd..."
initrd /ubuntu/initrd
}
}
submenu 'BSD' --hotkey=b {
menuentry 'Install OpenBSD' --class os {
set bsd_root="/openbsd/iso"
echo "Loading OpenBSD installation kernel..."
kopenbsd $bsd_root/7.2/amd64/bsd.rd
}
menuentry 'Install NetBSD' --class os {
set bsd_root="/netbsd/iso"
echo "Loading NetBSD-INSTALL kernel..."
knetbsd $bsd_root/amd64/binary/kernel/netbsd-INSTALL.gz
}
menuentry 'Install DragonflyBSD' --class os {
set bsd_root="/dflybsd/iso"
echo "Loading DragonflyBSD kernel..."
kfreebsd $bsd_root/boot/kernel/kernel
}
}

PXE Boot Setup with GRUB2 Tutorial

There are many tutorials on the internet that tell you how to setup a PXE Boot server with PXELINUX. There are however other options to replace PXELINUX like GRUB2 and iPXE. In this tutorial, I'm going to teach you how to setup a PXE Boot Environment with GRUB2, and later add menu entries to boot many popular OSes.

Notice: I'm not going to repeat the part where you setup the DHCP and TFTP server. Such section in other tutorials still applies to this scenario.

Making the GRUB2 image to be loaded by NIC

think the GRUB2 image as the same as PXELINUX's pxelinux.0 file. Your DHCP server must point to it, and it must be available on your TFTP server. Instead of shoving a blob down your throat and telling you that it just works, I'm going to walk you through the process of making one yourself by using an readily available linux installation.

GRUB2 image build requirement

You will need one of the following to build a GRUB2 boot image:

  • A working linux distribution that has the grub package installed. You don't need to use GRUB2 to boot the linux system.
  • use WSL on Windows to have a linux subsystem.
  • other distributions that has the grub package.
  • If you really wanna go the long way, download GRUB2's source code from GNU, and compile it yourself.

The program we need is grub-mkimage. It is more flexible than grub-mknetdir, and I'm using it to explain the details.

grub-mkimage command common pattern

angle brackets indicates names that you can replace yourself.

grub-mkimage -O <target> -o <output file name> -p <prefix directory> <list of modules separated by space>

Explanation:

  • The <target> part chooses which boot system you want the image for. You have many choices including BIOS, UEFI32 and UEFI64.
  • Choose whatever you want of the <output file name>.
  • the <prefix directory> is the directory relative to your TFTP root to put your grub.cfg file. For example, if we set it to /grub and our TFTP root is /srv/tftp, then your grub.cfg file must be at /srv/tftp/grub/grub.cfg.
  • modules are not included by default. You can add them at <list of modules separated by space>.

Command to build legacy BIOS

  • First, run the following command to build the image:

      grub-mkimage -O i386-pc-pxe -o <output file name> -p /grub tftp pxe normal ls echo minicmd halt reboot http linux bsd zfs
    
    • <target> must be i386-pc-pxe for BIOS images.
    • tftp pxe and normal are REQUIRED modules for BIOS boot.
    • other useful modules include:
      • ls, echo, minicmd: provides basic commands for debug.
      • halt, reboot: so that you can easily reboot your system from GRUB2.
      • http: MUST have if you want to download kernel/ram disks from http servers instead of tftp servers.
      • linux: REQUIRED to boot linux systems.
      • bsd: REQUIRED to boot BSD-derived systems, for example OpenBSD, NetBSD and FreeBSD.
      • zfs: OpenBSD and NetBSD's installation kernel need this module to load. Otherwise, it will produce an invalid a.out header error.
  • Second, upload the created image to your TFTP server. Again, I'm not shoving a fixed method down your throat. There are many to choose from, including scp and rsync, go check their respective manual.

Command to build UEFI (TODO)

Writing the grub.cfg config file

This is the more involving part. Usually one does not write grub.cfg themselves, but a grub file to be used by grub-mkconfig autogeneration utility. However, we don't have that luxury here. We need to do it by ourselves. The syntax is kinda documented on their website, but it's a giant page. People who need this guide won't have time to read it lol. So I'm going to do some small explanations here. The completed grub.cfg file is in this gist too, so you can just grab it if you need.

The top section

This section is the global settings. Usually we set global variables like root default and timeout here.

set default=0
set timeout=60
set root=(http,$net_default_server:8080)

The first two are self-explanatory. The third line needs a little explanation:

  • root is a special variable. It will be appended to all paths you specified later.
  • In GRUB2, the syntax to denote a device is (device, partition). For example, the 5th partition on the first disk is (hd0,5).
  • With the http module included at build, grub can create an http partition named (http, <server address>:<http port>). you can use any ip addresses or host names (www.example.com). I have not tested ipv6 addresses yet. You can also use any port, not limited to the default 80 port. Here, I use the port 8080 because my HTTP server is setup so.
  • With the tftp module, grub can also create an tftp partition named (tftp, <server ip address>). Now the server address must be IP, and no port is allowed.
  • I'm using the variable $net_default_server. It is the IP address of your DHCP server. I have my HTTP server on my router, thus they share the same IP and I can dynamically configure it without hardcoding any address. You can have a domain name bound to your HTTP server so you don't have to hardcode IP addresses either. Ways to do that is beyond the scope of this tutorial.
  • Thus, the third line says that I want to set the root variable to point to the root folder of my HTTP server. Any later path reference will be on the HTTP server, so I can put my kernels and ramdisks on my http server, and download them on the fly when booting. Most tutorials out there tells you to put your kernels and ramdisks on the TFTP server. I'm not doing that. What I've tested is that HTTP is a little faster and a little more reliable in downloading larger files. You can also use nfs and nbd as your file storage instead of HTTP. Just search those terms online.

Menu Entries

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment