How to add kernel parameters and files to a Fedora ISO?

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.

To place files in the Users home directory, you just need them to copy to /etc/skel/
This stands for “skeleton” and is the base for new user homes.

Regarding kernel parameter, I’d place files with ending “.conf” into /etc/sysctl.d/
like described here:
https://discussion.fedoraproject.org/t/is-it-possible-to-add-a-kernel-parameter-and-load-it-without-a-reboot/15979/2?u=huben

The “Newer Way”.
Also see
https://www.freedesktop.org/software/systemd/man/sysctl.d.html

I have two questions about that:

  1. Are you sure I can add kernel parameters like iommu or intel_iommu this way? Becasue I couldn’t find a way to set those parameters during runtime with the sysctl command.
  2. Can the parameters set using the sysctl.d directory be modified manually in the grub menu when booting the ISO?

Edit:
I just managed to get a bootable ISO after making modifications to it using xoriso.

    xorriso -indev "${ISO_FILE}" -outdev "${ISO_FILE_MODIFIED}" -compliance no_emul_toc \
    -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" \
    -boot_image any replay

Adding the kernel parameters to those 4 files, however, did not did not affect the kernel parameters that showed up in the grub boot menu when pressing e. And they also didn’t show up in cat /proc/cmdline after booting, so the parameters were definitely not set.

Now that I’m able to modify the ISO and still have a bootable ISO, I will experiment with modifying the squashfs/rootfs.

No, I’m not sure.

  1. It needs to b enabled in the UEFI/BIOS. (I don’t use this technology, so I may not find them)
  2. It seems to be that it must be enabled in grub.

However I’m not sure if it gets automatically enabled when you enable it inBIOS/UEF.

Depends on the parameter. Some parameter can be changed during runtime with sysctl others not.
You can set parameters during runtime, in grub or while compiling your own kernel.

I have it enabled in the UEFI and it works just fine when I set the parameters in grub on my actual fedora installation. It doesn’t get enabled automatically though.
I think the iommu parameters can’t be changed during runtime.
But I don’t know if that necessarily means that they can’t be enabled by a config file in sysctl.d.

I’d really like to avoid rebuilding the kernel that’s on the ISO because it is very resource intensive and takes a lot of time.

Edit:

I managed to modify rootfs image and rebuild the whole ISO while still keeping it bootable.

ISO_FILE="/home/fedora/Downloads/Fedora-Workstation-Live-x86_64-34-1.2.iso"
ISO_FILE_MODIFIED="/home/fedora/Downloads/Fedora-Workstation-Live-x86_64-34-1.2.modified.iso"

SOURCE_SQUASHFS_IMG="/LiveOS/squashfs.img"
SQUASHFS_IMG="/tmp/squashfs.img"
SQUASHFS_EXTRACTED="/tmp/squashfs-extracted"
SQUASHFS_IMG_MODIFIED="/tmp/squashfs.modified.img"

ROOTFS_IMG="${SQUASHFS_EXTRACTED}/LiveOS/rootfs.img"
ROOTFS_MOUNTPOINT="/tmp/rootfs-mountpoint"

sudo rm -rf "${ISO_FILE_MODIFIED}"

# Extract the squashfs image and unsquash it
sudo rm -f "${SQUASHFS_IMG}"
xorriso -dev "${ISO_FILE}" -osirrox "on" -extract "${SOURCE_SQUASHFS_IMG}" "${SQUASHFS_IMG}"
sudo unsquashfs -d "${SQUASHFS_EXTRACTED}" "${SQUASHFS_IMG}" # Unsquash the squashfs and mount the rootfs in read-write mode
sudo rm -f "${SQUASHFS_IMG}"

# Mount the rootfs image of the unsquashed squashfs image
sudo umount --force "${ROOTFS_MOUNTPOINT}"
sudo rm -rf "${ROOTFS_MOUNTPOINT}"
sudo mkdir -p "${ROOTFS_MOUNTPOINT}"
sudo mount -t ext4 -o loop,rw "${ROOTFS_IMG}" "${ROOTFS_MOUNTPOINT}"

# Add file to the Desktop
sudo mkdir "${ROOTFS_MOUNTPOINT}/etc/skel/Desktop/"
sudo cp "/home/fedora/Projects/test/test.sh" "${ROOTFS_MOUNTPOINT}/etc/skel/Desktop/"

# Unmount the rootfs image again
sudo umount "${ROOTFS_MOUNTPOINT}"

# Make a new squashfs image from the unsquashed modified squashfs image
sudo mksquashfs "${SQUASHFS_EXTRACTED}" "${SQUASHFS_IMG_MODIFIED}" -b 1024k -comp xz -Xbcj x86 -e boot
sudo rm -rf "${SQUASHFS_EXTRACTED}"

# Overwrite the squashfs image inside the ISO with the modified one
xorriso -indev "${ISO_FILE}" -outdev "${ISO_FILE_MODIFIED}" -compliance no_emul_toc \
-update "${SQUASHFS_IMG_MODIFIED}" "/LiveOS/squashfs.img" \
-boot_image any replay

# Remove modified squashfs image
sudo rm -f "${SQUASHFS_IMG_MODIFIED}"

Unfortunately when booting the ISO I can’t select the Test this media & start Fedora-Workstation-Live 34 option because the checksum information is not available:

1 Like

After using livecd-iso-to-disk instead of balena Etcher, I no longer got the checksum error, but still I haven’t found a way to set kernel parameters.

Adding them through a conf file in the /etc/sysctl.d/ directory in the rootfs didn’t cause them to be loaded.

There’s got to be a way to change the default grub parameters, right?

Since you seem to edit a live iso, you may directly change the boot parameter in the /boot/ folder.
...Live-Immage/EFI/BOOT/grub.cfg
Which is not exactly best praxis however.

The live iso grub ist another one as you would install.

I have tried that though and it did not work…

I’ve actually tried adding my kernel params to all of these files:

/EFI/BOOT/BOOT.conf
/EFI/BOOT/grub.cfg
/isolinux/grub.conf
/tmp/isolinux.cfg

using this function:

function addKernelParams() {
    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/$1 &/" "/tmp/grub.conf"
    sudo sed -i "s/rd.live.image/$1 &/" "/tmp/isolinux.cfg"
    sudo sed -i "s/rd.live.image/$1 &/" "/tmp/BOOT.conf"
    sudo sed -i "s/rd.live.image/$1 &/" "/tmp/grub.cfg"

    xorriso -indev "${ISO_FILE}" -outdev "${ISO_FILE_MODIFIED}" -compliance no_emul_toc \
    -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" \
    -boot_image any replay
}

addKernelParams "iommu=1 intel_iommu=on"

and it still didn’t work.

Neither did the parameters show up when pressing e in the grub menu, nor did the parameters show up in cat /proc/cmdline after booting.

Under
...Live-Image/images/
there is an efiboot.img

You can open it and find another grub.cfg.
Maybe this one is the right one to edit.

Did you try already?

I figured it out now. The issue is that livecd-iso-to-disk removes the kernel parameters for whatever reason.
You can add the kernel parameters again using the --extra-kernel-args "my kernel params" on livecd-iso-to-disk.

1 Like

Very good and nice to know. :+1: