Skip to content

Instantly share code, notes, and snippets.

@ninlith
Last active February 8, 2024 21:27
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save ninlith/377dae59feed1f726e15c28bcbceb877 to your computer and use it in GitHub Desktop.
Save ninlith/377dae59feed1f726e15c28bcbceb877 to your computer and use it in GitHub Desktop.
Hybrid UEFI/BIOS multiboot USB drive
# Hybrid UEFI/BIOS multiboot USB drive
# Install required packages
sudo apt install gdisk grub2-common grub-efi-amd64-bin grub-pc-bin qemu-system
# Create an empty disk image
target_size=3.6G # $(lsblk -b --output SIZE -n -d /dev/sdX) for drive size
qemu-img create -f raw boottitikku.img "$target_size"
# Create a GUID Partition Table (GPT)
/sbin/sgdisk -n 1::+1M -c 1:"BIOS boot partition" -t 1:ef02 boottitikku.img
/sbin/sgdisk -n 2::+50M -c 2:"EFI System" -t 2:ef00 boottitikku.img
/sbin/sgdisk -n 3::-0 -c 3:"Linux filesystem" -t 3:8300 boottitikku.img
# Create a hybrid MBR partition table
/sbin/sgdisk --hybrid=1:2:3 boottitikku.img
# Associate a loop device with the image file
loop_device=$(sudo losetup --partscan --show --find boottitikku.img)
# Format
sudo mkfs.fat -F32 "$loop_device"p2
sudo mkfs.ext4 "$loop_device"p3
# Mount
sudo mkdir /mnt/{efi,data}
sudo mount -o rw,umask=0000 "$loop_device"p2 /mnt/efi
sudo mount "$loop_device"p3 /mnt/data
# Install GRUB for UEFI and BIOS booting
sudo grub-install --target=x86_64-efi --recheck --removable \
--uefi-secure-boot --efi-directory=/mnt/efi --boot-directory=/mnt/efi/boot
sudo grub-install --target=i386-pc --recheck \
--boot-directory=/mnt/data/boot "$loop_device"
# Remove problematic files
rm /mnt/efi/EFI/BOOT/BOOTX64.CSV
rm /mnt/efi/EFI/BOOT/fbx64.efi
rm /mnt/efi/EFI/BOOT/grub.cfg
# Take recursive ownership of the data partition
sudo chown -R 1000:1000 /mnt/data
# Create sample configuration files
cat > /mnt/efi/boot/grub/grub.cfg << EOF
search --set=root --file /grubhybrid.cfg
configfile /grubhybrid.cfg
EOF
cp /mnt/efi/boot/grub/grub.cfg /mnt/data/boot/grub/grub.cfg
cat > /mnt/data/grubhybrid.cfg << "EOF"
set menu_color_normal=black/cyan
set menu_color_highlight=light-cyan/cyan
menuentry "Reboot" { reboot }
menuentry "Poweroff" { halt }
if [ ${grub_platform} == "efi" ]; then
menuentry "UEFI setup" { fwsetup }
fi
EOF
# Test
sync && kvm -m 1G boottitikku.img # BIOS
sync && kvm -bios OVMF.fd -m 1G boottitikku.img # UEFI
# Set up boot options
...
# Write the image to a physical drive
sudo cp boottitikku.img /dev/sdX
sync
insmod regexp
insmod part_msdos
insmod part_gpt
insmod fat
insmod ntfs
insmod ntfscomp
loadfont unicode
#set pager=1
echo "Switching to graphics mode. Press ESC to cancel."
if sleep --verbose --interruptible 3 ; then
clear
insmod all_video
set gfxmode=auto
set gfxpayload=keep
set gfxterm_font=unicode
terminal_output gfxterm
set locale_dir=/boot/grub/locale/
set lang=fi
fi
clear
set menu_color_normal=black/cyan
set menu_color_highlight=light-cyan/cyan
export menu_color_normal
export menu_color_highlight
function addcomment {
set offset=50
set string="$1 "
regexp --set substring "(.{$offset})" "${string}"
output="${substring}$2"
export output
}
# ------------------------------------------------------------------------------
# GParted
# ------------------------------------------------------------------------------
function gpartedmenuentry {
menuentry "GParted Live ($1, fi_FI)" "$2" "$3" {
set isofile=$2
set bootoptions="$3"
echo "Using ${isofile}..."
loopback loop $isofile
echo "Loading kernel..."
linux (loop)/live/vmlinuz findiso=${isofile} boot=live union=overlay username=user config components quiet noswap locales=fi_FI.UTF-8 keyboard-layouts=fi_FI $bootoptions
echo "Loading initial ramdisk..."
initrd (loop)/live/initrd.img
}
}
for isofile in /iso/gparted-live-*.iso; do
if [ ! -e "$isofile" ]; then break; fi
regexp \
--set 1:isoname \
--set 2:version \
--set 3:arch \
"^/iso/(gparted-live-(.+)-([^-]+)\.iso)\$" "${isofile}"
set title="GParted Live ${version}-${arch} ->"
addcomment "$title" "# Osiointi, SMART-tiedot (GSmartControl)"
submenu "${output}" "${isofile}" {
set isofile=$2
gpartedmenuentry "Default settings, i915.modeset=0" $isofile "i915.modeset=0 ip= net.ifnames=0 nosplash"
gpartedmenuentry "Default settings" $isofile "ip= net.ifnames=0 nosplash"
gpartedmenuentry "Default settings, KMS with large font & To RAM" $isofile "vga=791 toram=filesystem.squashfs ip= net.ifnames=0 nosplash live_console_font_size=16x32"
gpartedmenuentry "Default settings, KMS" $isofile "vga=791 ip= net.ifnames=0 nosplash"
gpartedmenuentry "To RAM, boot media can be removed later" $isofile "toram=filesystem.squashfs ip= net.ifnames=0 nosplash "
gpartedmenuentry "Safe graphic settings (vga=normal)" $isofile "ip= net.ifnames=0 nomodeset vga=normal nosplash"
gpartedmenuentry "Failsafe mode" $isofile "acpi=off irqpoll noapic noapm nodma nomce nolapic nosmp ip= net.ifnames=0 nomodeset vga=normal nosplash"
if [ ${grub_platform} == "pc" ]; then
menuentry "GParted Live (memdisk)" "${isofile}" {
set isofile=$2
echo "Loading ISO to memory..."
linux16 /boot/memdisk iso
initrd16 ${isofile}
}
fi
if [ ${grub_platform} == "efi" ]; then
menuentry "Local operating system (if available)" "${isofile}" {
set isofile=$2
loopback loop $isofile
echo "Booting first local disk..."
# Generate boot menu automatically
configfile (loop)/boot/grub/boot-local-efi.cfg
# If not chainloaded, definitely no uEFI boot loader was found.
echo "No uEFI boot loader was found!"
sleep 15
}
fi
}
done
# ------------------------------------------------------------------------------
# Clonezilla
# ------------------------------------------------------------------------------
function clonezillamenuentry {
menuentry "Clonezilla Live ($1)" "$2" "$3" {
set isofile=$2
set bootoptions="$3"
echo "Using ${isofile}..."
loopback loop $isofile
echo "Loading kernel..."
linux (loop)/live/vmlinuz boot=live findiso=${isofile} union=overlay username=user config components quiet noswap edd=on $bootoptions
echo "Loading initial ramdisk..."
initrd (loop)/live/initrd.img
}
}
for isofile in /iso/clonezilla-live-*.iso; do
if [ ! -e "$isofile" ]; then break; fi
regexp \
--set 1:isoname \
--set 2:version \
--set 3:arch \
"^/iso/(clonezilla-live-(.+)-([^-]+)\.iso)\$" "${isofile}"
set title="Clonezilla Live ${version}-${arch} ->"
addcomment "$title" "# Kloonaus"
submenu "${output}" "${isofile}" {
set isofile=$2
clonezillamenuentry "Default settings, VGA 800x600" $isofile "nomodeset enforcing=0 locales= keyboard-layouts= ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_batch="no" vga=788 ip= net.ifnames=0 splash i915.blacklist=yes radeonhd.blacklist=yes nouveau.blacklist=yes vmwgfx.enable_fbdev=1"
clonezillamenuentry "Default settings, KMS with large font & To RAM" $isofile "enforcing=0 locales= keyboard-layouts= ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_batch="no" vga=791 toram=live,syslinux,EFI,boot,.disk,utils ip= net.ifnames=0 splash live_console_font_size=16x32"
clonezillamenuentry "Speech synthesis" $isofile "nomodeset enforcing=0 locales= keyboard-layouts= ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_batch="no" vga=788 ip= net.ifnames=0 splash i915.blacklist=yes radeonhd.blacklist=yes nouveau.blacklist=yes vmwgfx.enable_fbdev=1 speakup.synth=soft ---"
clonezillamenuentry "Default settings, VGA 1024x768" $isofile "nomodeset enforcing=0 locales= keyboard-layouts= ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_batch="no" vga=791 ip= net.ifnames=0 splash i915.blacklist=yes radeonhd.blacklist=yes nouveau.blacklist=yes vmwgfx.enable_fbdev=1"
clonezillamenuentry "Default settings, VGA 640x480" $isofile "nomodeset enforcing=0 locales= keyboard-layouts= ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_batch="no" vga=785 ip= net.ifnames=0 splash i915.blacklist=yes radeonhd.blacklist=yes nouveau.blacklist=yes vmwgfx.enable_fbdev=1"
clonezillamenuentry "Default settings, KMS" $isofile "enforcing=0 locales= keyboard-layouts= ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_batch="no" vga=791 ip= net.ifnames=0 splash"
clonezillamenuentry "To RAM, boot media can be removed later" $isofile "nomodeset enforcing=0 locales= keyboard-layouts= ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_batch="no" vga=788 toram=live,syslinux,EFI,boot,.disk,utils ip= net.ifnames=0 splash i915.blacklist=yes radeonhd.blacklist=yes nouveau.blacklist=yes vmwgfx.enable_fbdev=1"
clonezillamenuentry "Safe graphic settings (vga=normal)" $isofile "nomodeset enforcing=0 locales= keyboard-layouts= ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_batch="no" ip= net.ifnames=0 nomodeset vga=normal nosplash"
clonezillamenuentry "Failsafe mode" $isofile "nomodeset enforcing=0 locales= keyboard-layouts= ocs_live_run="ocs-live-general" ocs_live_extra_param="" ocs_live_batch="no" acpi=off irqpoll noapic noapm nodma nomce nolapic nosmp ip= net.ifnames=0 nomodeset vga=normal nosplash"
if [ ${grub_platform} == "pc" ]; then
menuentry "Clonezilla Live (memdisk)" "${isofile}" {
set isofile=$2
echo "Loading ISO to memory..."
linux16 /boot/memdisk iso
initrd16 ${isofile}
}
menuentry "FreeDOS" "${isofile}" {
set isofile=$2
loopback loop $isofile
linux16 (loop)/syslinux/memdisk
initrd16 (loop)/live/freedos.img
}
menuentry "iPXE" "${isofile}" {
set isofile=$2
loopback loop $isofile
linux16 (loop)/live/ipxe.lkn
}
fi
if [ ${grub_platform} == "efi" ]; then
menuentry "Local operating system (if available)" "${isofile}" {
set isofile=$2
loopback loop $isofile
echo "Booting first local disk..."
# Generate boot menu automatically
configfile (loop)/boot/grub/boot-local-efi.cfg
# If not chainloaded, definitely no uEFI boot loader was found.
echo "No uEFI boot loader was found!"
sleep 15
}
menuentry "Network boot via iPXE" "${isofile}" {
set isofile=$2
loopback loop $isofile
search --no-floppy --set=root -f (loop)/live/ipxe.efi
chainloader (loop)/live/ipxe.efi + 1
}
fi
}
done
# ------------------------------------------------------------------------------
# ShredOS
# ------------------------------------------------------------------------------
function shredosmenuentry {
menuentry "ShredOS ($1)" "$2" "$3" {
set imagefile=$2
set nwipeoptions="$3"
echo "Loading..."
loopback loop $imagefile
linux (loop,1)/boot/shredos console=tty3 loglevel=3 loadkeys=fi nwipe_options="${nwipeoptions}"
}
}
for imagefile in /boot/shredos-*.img; do
if [ ! -e "$imagefile" ]; then break; fi
regexp \
--set 1:imagename \
--set 2:buildroot_version \
--set 3:shredos_minor_version \
--set 4:architecture \
--set 5:nwipe_version \
--set 6:date \
"^/boot/(shredos-(.{7})\.([^_]+)_(.+)_(.+)_(.+)\.img)\$" "${imagefile}"
set title="ShredOS ${buildroot_version}.${shredos_minor_version} ${architecture} nwipe ${nwipe_version} ->"
addcomment "$title" "# Tyhjennys (nwipe myös SystemRescuessa ja Grmlissa)"
submenu "${output}" "${imagefile}" {
set imagefile=$2
shredosmenuentry "Default" $imagefile ""
shredosmenuentry "Ignore USB devices, shutdown on completion" $imagefile "--nousb --autopoweroff"
shredosmenuentry "Ignore USB devices, shutdown on completion, zero method, no verification, no blanking" $imagefile "--method=zero --verify=off --noblank --nousb --autopoweroff"
}
done
# ------------------------------------------------------------------------------
# Grml
# ------------------------------------------------------------------------------
menuentry "Grml 2020.06 amd64 full" {
set isofile=/iso/grml64-full_2020.06.iso
echo "Using ${isofile}..."
loopback loop $isofile
set oldroot=$root
set root=(loop)
set iso_path=$isofile
export iso_path
configfile /boot/grub/loopback.cfg
set root=$oldroot
loopback --delete loop
clear
}
# ------------------------------------------------------------------------------
# SystemRescue
# ------------------------------------------------------------------------------
function systemrescuemenuentry {
menuentry "SystemRescue ($3)" "$2" "$1" {
set isofile=$2
set bootoptions="$3"
probe -u $root --set=imgdevuuid
set imgdevpath="/dev/disk/by-uuid/$imgdevuuid"
echo "Using ${isofile}..."
loopback loop $isofile
echo "Loading kernel..."
linux (loop)/sysresccd/boot/x86_64/vmlinuz archisobasedir=sysresccd img_dev=$imgdevpath img_loop=$isofile earlymodules=loop $bootoptions
echo "Loading initial ramdisk..."
initrd (loop)/sysresccd/boot/intel_ucode.img (loop)/sysresccd/boot/amd_ucode.img (loop)/sysresccd/boot/x86_64/sysresccd.img
}
}
for isofile in /iso/systemrescue-*.iso; do
if [ ! -e "$isofile" ]; then break; fi
regexp \
--set 1:isoname \
--set 2:version \
--set 3:arch \
"^/iso/(systemrescue-(.+)-([^-]+)\.iso)\$" "${isofile}"
set title="SystemRescue ${version}-${arch} ->"
addcomment "$title" "# Graafinen käyttöliittymä (startx-komennolla)"
submenu "${output}" "${isofile}" {
set isofile=$2
systemrescuemenuentry "" $isofile "Default options"
systemrescuemenuentry "copytoram" $isofile "Copy system to RAM"
systemrescuemenuentry "checksum" $isofile "Verify integrity of the medium"
systemrescuemenuentry "nomodeset" $isofile "Basic display drivers"
systemrescuemenuentry "findroot" $isofile "Boot a Linux operating system installed on the disk"
systemrescuemenuentry "break" $isofile "Stop during the boot process before mounting the root filesystem"
if [ ${grub_platform} == "pc" ]; then
menuentry "SystemRescue (memdisk)" "${isofile}" {
set isofile=$2
echo "Loading ISO to memory..."
linux16 /boot/memdisk iso
initrd16 ${isofile}
}
fi
}
done
# ------------------------------------------------------------------------------
# Super Grub2 Disk
# ------------------------------------------------------------------------------
for isofile in /iso/super_grub2_disk_*.iso; do
if [ ! -e "$isofile" ]; then break; fi
regexp \
--set 1:isoname \
--set 2:variant \
--set 3:version \
"^/iso/(super_grub2_disk_([^_]+)_([^_]+)\.iso)\$" "${isofile}"
submenu "Super Grub2 Disk ${version} ${variant} ->" "${isofile}" {
set isofile=$2
menuentry "Super Grub2 Disk (loopback.cfg)" "${isofile}" {
set isofile=$2
echo "Using ${isofile}..."
loopback loop $isofile
set oldroot=$root
set root=(loop)
set iso_path=$isofile
export iso_path
configfile /boot/grub/loopback.cfg
set root=$oldroot
loopback --delete loop
}
if [ ${grub_platform} == "pc" ]; then
menuentry "Super Grub2 Disk (memdisk)" "${isofile}" {
set isofile=$2
echo "Loading ISO to memory..."
linux16 /boot/memdisk iso
initrd16 ${isofile}
}
fi
}
done
# ------------------------------------------------------------------------------
# Arch Linux Netboot
# ------------------------------------------------------------------------------
menuentry "Arch Linux Netboot (iPXE)" {
if [ ${grub_platform} == "pc" ]; then
linux16 /boot/arch_netboot.lkrn
else
chainloader /boot/arch_netboot.efi
fi
}
# ------------------------------------------------------------------------------
# iPXE
# ------------------------------------------------------------------------------
menuentry "iPXE 1.21.1" {
if [ ${grub_platform} == "pc" ]; then
linux16 /boot/ipxe.lkrn
else
chainloader /boot/ipxe.efi
fi
}
# ------------------------------------------------------------------------------
# netboot.xyz
# ------------------------------------------------------------------------------
addcomment "netboot.xyz ->" "# Verkkokäynnistyviä (asennus)ohjelmia"
submenu "${output}" {
if [ ${grub_platform} == "pc" ]; then
menuentry "boot.netboot.xyz Legacy (PCBIOS) iPXE Bootloader" {
linux16 /boot/netboot.xyz.lkrn
}
menuentry "Generic iPXE + initrd script (HTTP)" {
linux16 /boot/ipxe.lkrn
initrd16 /boot/netboot.xyz-initrd
}
menuentry "Generic iPXE + command line script (HTTP)" {
linux16 /boot/ipxe.lkrn dhcp \&\& chain --autofree http://boot.netboot.xyz/ipxe/netboot.xyz.lkrn
}
else
menuentry "boot.netboot.xyz DHCP boot image file, uses built-in iPXE NIC drivers" {
chainloader /boot/netboot.xyz.efi
}
menuentry "boot.netboot.xyz EFI w/ Simple Network Protocol, attempts to boot all net devices" {
chainloader /boot/netboot.xyz-snp.efi
}
menuentry "boot.netboot.xyz EFI w/ Simple Network Protocol, only boots from device chained from" {
chainloader /boot/netboot.xyz-snponly.efi
}
fi
}
# ------------------------------------------------------------------------------
# Other
# ------------------------------------------------------------------------------
if [ ${grub_platform} == "pc" ]; then
menuentry "Grub4dos 0.4.6a version 2019-09-09 (-> HBCD)" {
ntldr /boot/grub/grldr # /boot/grub/menu.lst
}
submenu "memtest86+ 5.01 ->" {
menuentry "Memory test (memtest86+)" {
linux16 /boot/memtest86+.bin
}
menuentry "Memory test (memtest86+, serial console 115200)" {
linux16 /boot/memtest86+.bin console=ttyS0,115200n8
}
menuentry "Memory test (memtest86+, experimental multiboot)" {
multiboot /boot/memtest86+_multiboot.bin
}
menuentry "Memory test (memtest86+, serial console 115200, experimental multiboot)" {
multiboot /boot/memtest86+_multiboot.bin console=ttyS0,115200n8
}
}
menuentry "HDT (Hardware Detection Tool) 0.5.2" {
linux16 /boot/memdisk
initrd16 /boot/hdt-0.5.2.img.gz
}
menuentry "The All In One Boot Floppy (gPXE, FreeDOS...)" {
linux16 /boot/memdisk
initrd16 /boot/allinone.img.gz
}
menuentry "GRUB Invaders" {
multiboot /boot/invaders.exec
}
menuentry "Chainload a partition's VBR (hd1,0)" {
set root=(hd1,0)
chainloader +1
boot
}
menuentry "Chainload a disk's MBR or a partitionless disk's VBR (hd1)" {
set root=hd1
chainloader +1
boot
}
fi
if [ ${grub_platform} == "efi" ]; then
menuentry "UEFI setup" {
fwsetup
}
menuentry "UEFI Shell v1" {
chainloader /boot/uefi_shell_v1.efi
}
menuentry "UEFI Shell v2" {
chainloader /boot/uefi_shell_v2.efi
}
submenu "From Super UEFIinSecureBoot Disk v3 ->" {
menuentry "Memtest86" {
chainloader "($root)/boot/suisbd/memtest86/BOOTX64.efi"
}
menuentry "Microsoft Windows Vista/7/8/8.1/10 UEFI/GPT" {
search --no-floppy --file /EFI/Microsoft/Boot/bootmgfw.efi --set temproot
chainloader "($temproot)/EFI/Microsoft/Boot/bootmgfw.efi"
}
submenu "EFI Tools" {
for efifile in /boot/suisbd/*.efi; do
if [ ! -e "$efifile" ]; then break; fi
menuentry "$efifile" "$efifile" {
chainloader "($root)$1"
}
done
}
submenu "EFI Drivers" {
for efifile in /boot/suisbd/drivers/*.efi; do
if [ ! -e "$efifile" ]; then break; fi
menuentry "$efifile" "$efifile" {
chainloader "($root)$1"
}
done
}
}
fi
menuentry "Reboot" {
reboot
}
menuentry "Shutdown" {
halt
}
@ninlith
Copy link
Author

ninlith commented Jan 14, 2021

BIOS:
screenshot-bios

UEFI:
screenshot-uefi

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