Is there a simple way to modify an existing Fedora ISO adding a few kernel parameters to it and a file to the live user’s home directory? And I mean a way that can be fully automated.
I’ve been trying to write a Bash script to do this, but I’m not sure if this would even work.
At the moment I’m getting errors because /etc/default/grub
doesn’t exist in the rootfs image and also because the home directory for the live user doesn’t exist yet.
#!/usr/bin/env bash
ISO_FILE="/home/fedora/Downloads/Fedora-Workstation-Live-x86_64-34-1.2.iso"
ISO_EXTRACTED="/tmp/iso-extracted"
ISO_MOUNTPOINT="/tmp/iso-mountpoint"
ISO_FILE_MODIFIED="/home/fedora/Downloads/Fedora-Workstation-Live-x86_64-34-1.2.modified.iso"
SQUASHFS_IMG="${ISO_EXTRACTED}/LiveOS/squashfs.img"
SQUASHFS_EXTRACTED="/tmp/squashfs-extracted"
SQUASHFS_IMG_MODIFIED="${ISO_EXTRACTED}/LiveOS/squashfs.modified.img"
ROOTFS_IMG="${SQUASHFS_EXTRACTED}/LiveOS/rootfs.img"
ROOTFS_MOUNTPOINT="/tmp/rootfs-mountpoint"
function cleanUp() {
sudo umount --force "${ISO_MOUNTPOINT}"
sudo umount --force "${ROOTFS_MOUNTPOINT}"
sudo rm -rf "${ISO_MOUNTPOINT}"
sudo rm -rf "${ROOTFS_MOUNTPOINT}"
sudo rm -rf "${ISO_EXTRACTED}"
sudo rm -rf "${SQUASHFS_EXTRACTED}"
sudo rm -rf "${ISO_FILE_MODIFIED}"
sudo rm -rf "${SQUASHFS_IMG_MODIFIED}"
}
function extractIso() {
sudo mkdir -p "${ISO_EXTRACTED}"
sudo mkdir -p "${ISO_MOUNTPOINT}"
sudo mount -t iso9660 -o loop "${ISO_FILE}" "${ISO_MOUNTPOINT}"
sudo cp -Rva ${ISO_MOUNTPOINT}/* "${ISO_EXTRACTED}"
sudo umount "${ISO_MOUNTPOINT}"
sudo mkdir -p "${ROOTFS_MOUNTPOINT}"
# Unsquash the squashfs and mount the rootfs in read-write mode
sudo unsquashfs -d "${SQUASHFS_EXTRACTED}" "${SQUASHFS_IMG}"
sudo mount -t ext4 -o loop,rw "${ROOTFS_IMG}" "${ROOTFS_MOUNTPOINT}"
}
function modifyExtractedIso() {
# Check what kind of CPU the system has (Intel or AMD)
LSCPU_OUTPUT="$(sudo lscpu)"
if echo -e "$LSCPU_OUTPUT" | grep "Model name: " | grep -qi "intel"; then
export HAS_INTEL_CPU=true
fi
if echo -e "$LSCPU_OUTPUT" | grep "Model name: " | grep -qi "AMD"; then
export HAS_AMD_CPU=true
fi
# If the system has an Intel CPU set the intel_iommu kernel parameter
if [ "$HAS_INTEL_CPU" = true ]; then
addKernelParam "intel_iommu=on"
fi
# If the system has an AMD CPU set the amd_iommu kernel parameter
if [ "$HAS_AMD_CPU" = true ]; then
addKernelParam "amd_iommu=on"
fi
# Set the iommu kernel parameter
addKernelParam "iommu=1"
# Apply the kernel parameter changes
applyKernelParamChanges
# Add file to the Desktop
sudo cp /home/fedora/test.sh "${ROOTFS_MOUNTPOINT}/home/???????????/Desktop/"
}
function createNewIso() {
sudo umount "${ROOTFS_MOUNTPOINT}"
sudo mksquashfs "${SQUASHFS_EXTRACTED}" "${SQUASHFS_IMG_MODIFIED}" -b 1024k -comp xz -Xbcj x86 -e boot
sudo rm -f "${SQUASHFS_IMG}"
sudo cp "${SQUASHFS_IMG_MODIFIED}" "${SQUASHFS_IMG}"
( cd "$ISO_EXTRACTED" && sudo genisoimage -U -r -v -T -J -joliet-long -V "Fedora-WS-Live-34-1-2" -volset "Fedora-WS-Live-34-1-2" -A "Fedora-WS-Live-34-1-2" -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e images/efiboot.img -no-emul-boot -o "$ISO_FILE_MODIFIED" . )
}
GRUB_CFG_PATH="${ROOTFS_MOUNTPOINT}/etc/default/grub"
function addKernelParam() {
if ! sudo cat "$GRUB_CFG_PATH" | grep "GRUB_CMDLINE_LINUX=" | grep --quiet "$1"; then
sudo sed -i "s/^GRUB_CMDLINE_LINUX=\"/&$1 /" "$GRUB_CFG_PATH"
echo "addKernelParam: Added \"$1\" to GRUB_CMDLINE_LINUX in $GRUB_CFG_PATH"
else
echo "addKernelParam: No action required. \"$1\" already exists in GRUB_CMDLINE_LINUX of $GRUB_CFG_PATH"
fi
}
GRUB_EFI_PATH="${ROOTFS_MOUNTPOINT}/etc/grub2-efi.cfg"
function applyKernelParamChanges() {
sudo sh -c "grub2-mkconfig > GRUB_EFI_PATH"
}
cleanUp
extractIso
modifyExtractedIso
createNewIso
cleanUp
#################### EDIT 1 ####################
I just noticed a few different files outside of the rootfs image that appear to contain kernel parameters:
/isolinux/grub.conf
#debug --graphics
default=1
splashimage=@SPLASHPATH@
timeout 60
hiddenmenu
title Start Fedora-Workstation-Live 34
findiso
kernel @KERNELPATH@ @ROOT@ @EXTRA@ rd.live.image quiet
initrd @INITRDPATH@
title Test this media & start Fedora-Workstation-Live 34
findiso
kernel @KERNELPATH@ @ROOT@ @EXTRA@ rd.live.image rd.live.check quiet
initrd @INITRDPATH@
/isolinux/isolinux.cfg
...
label linux
menu label ^Start Fedora-Workstation-Live 34
kernel vmlinuz
append initrd=initrd.img root=live:CDLABEL=Fedora-WS-Live-34-1-2 rd.live.image quiet
label check
menu label Test this ^media & start Fedora-Workstation-Live 34
menu default
kernel vmlinuz
append initrd=initrd.img root=live:CDLABEL=Fedora-WS-Live-34-1-2 rd.live.image rd.live.check quiet
...
label vesa
menu indent count 5
menu label Start Fedora-Workstation-Live 34 in ^basic graphics mode
text help
Try this option out if you're having trouble starting
Fedora-Workstation-Live 34.
endtext
kernel vmlinuz
append initrd=initrd.img root=live:CDLABEL=Fedora-WS-Live-34-1-2 rd.live.image nomodeset quiet
...
/EFI/BOOT/BOOT.conf AND /EFI/BOOT/grub.cfg (Apparently identical)
...
### BEGIN /etc/grub.d/10_linux ###
menuentry 'Start Fedora-Workstation-Live 34' --class fedora --class gnu-linux --class gnu --class os {
linuxefi /images/pxeboot/vmlinuz root=live:CDLABEL=Fedora-WS-Live-34-1-2 rd.live.image quiet
initrdefi /images/pxeboot/initrd.img
}
menuentry 'Test this media & start Fedora-Workstation-Live 34' --class fedora --class gnu-linux --class gnu --class os {
linuxefi /images/pxeboot/vmlinuz root=live:CDLABEL=Fedora-WS-Live-34-1-2 rd.live.image rd.live.check quiet
initrdefi /images/pxeboot/initrd.img
}
submenu 'Troubleshooting -->' {
menuentry 'Start Fedora-Workstation-Live 34 in basic graphics mode' --class fedora --class gnu-linux --class gnu --class os {
linuxefi /images/pxeboot/vmlinuz root=live:CDLABEL=Fedora-WS-Live-34-1-2 rd.live.image nomodeset quiet
initrdefi /images/pxeboot/initrd.img
}
}
Do I have to modify all of these files to add kernel parameters?
#################### EDIT 2 ####################
It seems like I can’t even produce an equivalent ISO when I just extract the files from the original ISO and them build a new ISO from that. When I try to burn that new ISO onto a USB thumb drive using balena Etcher, I get the error It looks like this is not a bootable image. The image does not appear to contain a partition table, and might not be recognized or bootable by your device.
But I can’t get any closer that that:
ISO_FILE="/home/fedora/Downloads/Fedora-Workstation-Live-x86_64-34-1.2.iso"
ISO_EXTRACTED="/tmp/iso-extracted"
ISO_MOUNTPOINT="/tmp/iso-mountpoint"
ISO_FILE_MODIFIED="/home/fedora/Downloads/Fedora-Workstation-Live-x86_64-34-1.2.modified.iso"
# Clean up in advance (just in case)
sudo umount --force "${ISO_MOUNTPOINT}" &> /dev/null
sudo rm -rf "${ISO_MOUNTPOINT}" &> /dev/null
sudo rm -rf "${ISO_EXTRACTED}" &> /dev/null
sudo rm -f "${ISO_FILE_MODIFIED}" &> /dev/null
# Extract ISO
sudo mkdir -p "${ISO_EXTRACTED}"
sudo mkdir -p "${ISO_MOUNTPOINT}"
sudo mount -t iso9660 -o loop "${ISO_FILE}" "${ISO_MOUNTPOINT}"
sudo cp -Rva ${ISO_MOUNTPOINT}/* "${ISO_EXTRACTED}"
sudo umount "${ISO_MOUNTPOINT}"
sudo rm -rf "${ISO_MOUNTPOINT}"
# Build new ISO
( cd "$ISO_EXTRACTED" && sudo genisoimage -sysid "" -p "XORRISO-1.5.4 2021.01.30.150001, LIBISOBURN-1.5.4, LIBISOFS-1.5.4, LIBBURN-1.5.4" -U -r -v -T -J -joliet-long -V "Fedora-WS-Live-34-1-2" -volset "" -A "" -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e images/efiboot.img -no-emul-boot -o "$ISO_FILE_MODIFIED" . )
# Post clean up
sudo rm -rf "${ISO_EXTRACTED}"
Here are the differences I could find with dumpet and isoinfo:
(Red is what is missing on the rebuilt ISO and green is what the original ISO did not have.)
#################### EDIT 3 ####################
I found a tool called xoriso which can modify some ISOs to a certain degree. I was able to extract and to update files on the ISO like this:
sudo rm -f "/tmp/grub.conf"
sudo rm -f "/tmp/isolinux.cfg"
sudo rm -f "/tmp/BOOT.conf"
sudo rm -f "/tmp/grub.cfg"
xorriso -dev "${ISO_FILE}" -osirrox "on" -extract "/isolinux/grub.conf" "/tmp/grub.conf" \
-- -extract "/isolinux/isolinux.cfg" "/tmp/isolinux.cfg" \
-- -extract "/EFI/BOOT/BOOT.conf" "/tmp/BOOT.conf" \
-- -extract "/EFI/BOOT/grub.cfg" "/tmp/grub.cfg"
sudo sed -i "s/rd.live.image/$MY_KERNEL_PARAMS &/" "/tmp/grub.conf"
sudo sed -i "s/rd.live.image/$MY_KERNEL_PARAMS &/" "/tmp/isolinux.cfg"
sudo sed -i "s/rd.live.image/$MY_KERNEL_PARAMS &/" "/tmp/BOOT.conf"
sudo sed -i "s/rd.live.image/$MY_KERNEL_PARAMS &/" "/tmp/grub.cfg"
xorriso -indev "${ISO_FILE}" -outdev "${ISO_FILE_MODIFIED}" -update "/tmp/grub.conf" "/isolinux/grub.conf" \
-- -update "/tmp/isolinux.cfg" "/isolinux/isolinux.cfg" \
-- -update "/tmp/BOOT.conf" "/EFI/BOOT/BOOT.conf" \
-- -update "/tmp/grub.cfg" "/EFI/BOOT/grub.cfg"
Balena Etcher does not complain about anything this time and I’m able to burn the ISO to my USB thumb drive with it.
Unfortunately when when trying to boot from it, UEFI boot is not available and the legacy boot option just fails causing a restart.