Skip to content

Instantly share code, notes, and snippets.

@dzogrim
Last active November 12, 2025 16:04
Show Gist options
  • Save dzogrim/b177bb0b9b746653f691ff01c9391a31 to your computer and use it in GitHub Desktop.
Save dzogrim/b177bb0b9b746653f691ff01c9391a31 to your computer and use it in GitHub Desktop.
Kickstart Fedora 42 x86_64 minimal TTY Live hybrid ISO for firmware on/offline updates (fwupd)
# SPDX-License-Identifier: MIT
#version=DEVEL
# Fedora 42 x86_64 minimal TTY Live hybrid ISO for firmware on/offline updates (fwupd)
#
# Purpose (what this ISO is for)
# - Text-only (TTY) Fedora 42 Live ISO to run firmware updates with fwupd.
# - Works online (LVFS over HTTPS) or offline using a restored cache.
# - Boots on UEFI and BIOS/legacy.
# - No GUI (nmcli only). Wi-Fi supported.
# - Persistence supported via an ext4 partition labeled 'overlay' on the USB stick.
# - Includes bolt for Thunderbolt security/updates.
# Released: 2025-11-12 (6.14.0-63.fc42)
#
# Build prerequisites:
# sudo dnf install -y \
# lorax lorax-lmc-novirt lorax-templates-generic pykickstart shim-x64 \
# anaconda-core anaconda-tui anaconda-dracut gdisk \
# xorriso isomd5sum dosfstools policycoreutils-python-utils \
# grub2-tools grub2-tools-minimal grub2-tools-extra \
# grub2-efi-x64 grub2-efi-x64-modules grub2-efi-x64-cdboot \
# grub2-pc grub2-pc-modules
#
# Create ISO:
# curl -L https://gist.github.com/dzogrim/dd025b82664c91e8aaf38355f3afcfe7/raw > fedora42-live-fwupd-tty.ks
# sudo setenforce 0
# sudo livemedia-creator --make-iso --no-virt --releasever 42 \
# --resultdir ./out --ks ./fedora42-live-fwupd-tty.ks --keep-image \
# --lorax-templates /usr/share/lorax/templates.d/99-generic \
# --project Fedora-Live-fwupd-tty --volid FWUPDLIVE --iso-name fwupd-live-42-x86_64.iso
# === Installation source (Everything base tree) ===
url --url=https://download.fedoraproject.org/pub/fedora/linux/releases/42/Everything/$basearch/os/
# === System configuration ===
lang en_US.UTF-8 # System language
keyboard fr # French Keyboard layout
timezone Europe/Paris # Time zone
rootpw --plaintext liveuser # Root password (live only)
selinux --permissive # Keep host enforcing; live image runs permissive
# === Default user (for live use) ===
user --name=liveuser --groups=wheel --plaintext --password liveuser
# === Services to enable (TTY only) ===
services --enabled=NetworkManager,fwupd,chronyd,ModemManager
# === Bootloader (Live stick with persistence overlay) ===
bootloader --timeout=5 --append="rd.live.image rd.live.overlay=LABEL=overlay rd.live.overlay.overlayfs=1 rd.efi.writevars=1"
# === Networking ===
network --device=link --bootproto=dhcp --activate --hostname=fwupd-live
# === Target disk layout for the Live image (info) ===
# 1) BIOS boot partition (for BIOS on GPT)
part biosboot --fstype=biosboot --size=1
# 2) "/boot/efi": EFI System Partition
# * UEFI firmware requires FAT
# * 2 GiB = enough for multiple kernel versions + UEFI firmware capsules
# * Label "BOOT" makes manual mount/debug easier if needed
part /boot/efi --size=2048 --fstype=vfat --label=BOOT
# 3) "/": Root filesystem
# * Contains the live OS image and runtime environment
# * ext4 chosen for robustness and OverlayFS compatibility
# * Label "ROOT"
# * Size can be adjusted depending on the package set
part / --size=10240 --fstype=ext4 --label=ROOT
# 4) "/overlay": persistence partition
# * ext4, labeled "overlay"
# * Mountpoint is found automatically via rd.live.overlay=LABEL=overlay
# * "--grow" consumes all remaining space
part /overlay --fstype=ext4 --label=overlay --size=1 --grow
# === Package selection (no GUI) ===
%packages --excludedocs
# System base
@core
@hardware-support
# Kernel and extra drivers
kernel
kernel-modules-extra
# Firmware update via UEFI capsule
fwupd
fwupd-efi
fwupd-plugin-flashrom
fwupd-plugin-modem-manager
fwupd-plugin-uefi-capsule-data
ModemManager
tpm2-tss
bolt
# Device support + tooling (QoL picks)
bash-completion
iw
iwl*firmware
less
linux-firmware
nano
sudo
usbutils
zstd
# Networking (nmcli is included in NetworkManager) & time
NetworkManager
NetworkManager-wifi
wpa_supplicant
wireless-regdb
ca-certificates
chrony
# Live essentials
dracut-live
livesys-scripts
# Boot (BIOS/UEFI)
efibootmgr
grub2-efi-x64
grub2-efi-x64-cdboot
grub2-efi-x64-modules
grub2-pc
grub2-pc-modules
grub2-tools-extra
grub2-tools-minimal
shim-x64
# Avoid glibc-all-langpacks
glibc-langpack-en
# Aggressive exclusions enforcement
# Keep this lean: explicitly avoid heavy apps
-*debuginfo
-cheese
-gnome-*
-gstreamer*
-gtk3
-gtk4
-libreoffice*
-man-db
-man-pages
-mediawriter
-nano-langpack
-plymouth-theme-*
%end
########
# POST #
########
# === Post-install ===
%post
set -euo pipefail
# Ensure overlay is mounted on next boots (idempotent)
if ! grep -q '^LABEL=overlay /overlay ' /etc/fstab; then
mkdir -p /overlay
echo "LABEL=overlay /overlay ext4 noauto,x-systemd.automount,nofail 0 0" >> /etc/fstab
fi
mkdir -p /overlay
# Ensure efivars is writable in live (for UEFI/dbx/capsules)
cat >/etc/systemd/system/efivars-rw.service <<'EOF'
[Unit]
Description=Ensure efivarfs is mounted read-write for firmware updates
After=local-fs.target
ConditionPathExists=/sys/firmware/efi/efivars
[Service]
Type=oneshot
ExecStart=/usr/bin/sh -c '\
/usr/bin/mkdir -p /sys/firmware/efi/efivars ; \
/usr/bin/mountpoint -q /sys/firmware/efi/efivars || /usr/bin/mount -t efivarfs efivarfs /sys/firmware/efi/efivars || true ; \
/usr/bin/mount -o remount,rw /sys/firmware/efi/efivars || true \
'
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
install -d /etc/systemd/system/multi-user.target.wants
ln -sf ../efivars-rw.service /etc/systemd/system/multi-user.target.wants/efivars-rw.service
# 'sudo': allow the batch script without password; nothing else
install -d -m 0750 /etc/sudoers.d
cat >/etc/sudoers.d/90-fwupd-batch <<'EOF'
liveuser ALL=(root) NOPASSWD: /usr/local/sbin/fwupd-batch.sh, /usr/local/sbin/fwupd-restore.sh
Defaults!/usr/local/sbin/fwupd-batch.sh !requiretty
Defaults!/usr/local/sbin/fwupd-restore.sh !requiretty
EOF
chmod 0440 /etc/sudoers.d/90-fwupd-batch
# ======================
# = First-boot Service =
# ======================
# First-boot LVFS refresh with robust connectivity wait (One-shot service)
## Starting with "fwupd-refresh-once.service" ...
cat >/etc/systemd/system/fwupd-refresh-once.service <<'EOF'
[Unit]
Description=Refresh LVFS metadata on first boot (robust online wait)
Wants=network-online.target
After=network-online.target
ConditionPathExists=!/var/lib/fwupd/.refreshed
RequiresMountsFor=/overlay
[Service]
Type=oneshot
ExecStart=/usr/bin/sh -c '\
/usr/bin/mkdir -p /var/lib/fwupd; \
[ -f /var/lib/fwupd/.refreshed ] && exit 0; \
/usr/bin/nm-online -s -q || true; \
/usr/bin/fwupdmgr refresh --force && \
/usr/bin/touch /var/lib/fwupd/.refreshed \
'
[Install]
WantedBy=multi-user.target
EOF
## Done with "fwupd-refresh-once.service".
# Enable par symlink (pas de reload necessaire lors du build)
install -d /etc/systemd/system/multi-user.target.wants
ln -sf ../fwupd-refresh-once.service \
/etc/systemd/system/multi-user.target.wants/fwupd-refresh-once.service
# Activer aussi le timer fwupd (fourni par le paquet fwupd)
install -d /etc/systemd/system/timers.target.wants
ln -sf /usr/lib/systemd/system/fwupd-refresh.timer \
/etc/systemd/system/timers.target.wants/fwupd-refresh.timer
# ===============
# = Main Script =
# ===============
# Batch script: updates + cache archiving by product model/P-N, logging, retries, optional auto-reboot
install -d -m 0755 /usr/local/sbin
install -m 0755 /dev/stdin /usr/local/sbin/fwupd-batch.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
umask 022
LOG="/var/log/fwupd-batch.log"
exec > >(tee -a "$LOG") 2>&1
USE_TESTING="${USE_TESTING:-0}" # 1 = enable lvfs-testing
AUTO_REBOOT="${AUTO_REBOOT:-0}" # 1 = reboot automatically if required
MAX_RETRY="${MAX_RETRY:-2}" # retries for refresh/update
CACHE_DIR="/var/cache/fwupd"
OVERLAY="/overlay"
pick_model() {
for f in /sys/class/dmi/id/product_sku /sys/class/dmi/id/product_name /sys/class/dmi/id/board_name; do
[[ -s "$f" ]] && { cat "$f"; return 0; }
done
echo "unknown-model"
}
model_raw="$(pick_model)"
model_norm="$(echo -n "$model_raw" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9._-]+/-/g;s/^-+|-+$//g')"
STAMP="$(date -u +%Y%m%d-%H%M%S)"
ARCHIVE="${OVERLAY}/fwupd-cache-${model_norm}-${STAMP}.tar.zst"
MANIFEST="${ARCHIVE}.sha256"
echo "== fwupd-batch start =="
echo "Model: $model_raw -> $model_norm"
echo "Log: $LOG"
###############################
# Detect ONLINE / OFFLINE
###############################
HAS_NET=0
nm-online -q 2>/dev/null && HAS_NET=1
if [[ "$HAS_NET" -eq 1 ]]; then
echo "-- network detected: ONLINE mode"
if [[ "$USE_TESTING" == "1" ]]; then
echo "-- enabling lvfs-testing"
fwupdmgr enable-remote lvfs-testing || true
fi
try() { local n=0; until "$@"; do n=$((n+1)); [[ $n -ge $MAX_RETRY ]] && return 1; echo "retry $n/$MAX_RETRY: $*"; sleep 3; done; }
echo "-- refresh metadata (online)"
try fwupdmgr refresh --force
else
echo "-- no network found: OFFLINE mode"
# Find the most recent matching cache
LATEST_CACHE="$(
find "$OVERLAY" -maxdepth 1 -type f -name "fwupd-cache-${model_norm}-*.tar.zst" -print0 2>/dev/null \
| xargs -0 -r stat -c '%Y %n' 2>/dev/null \
| sort -nr | head -n1 | cut -d' ' -f2-
)"
if [[ -n "$LATEST_CACHE" ]]; then
# Optional safety: ensure archive name contains the model
case "$LATEST_CACHE" in
*"$model_norm"*) : ;;
*)
echo "!! Cache archive exists but does not match this model: $model_norm"
echo "Aborting to avoid flashing wrong firmware"
exit 1
;;
esac
echo "-- found previous cache: $LATEST_CACHE"
[[ -f "${LATEST_CACHE}.sha256" ]] && sha256sum -c "${LATEST_CACHE}.sha256" || true
tar -C / -I zstd -xf "$LATEST_CACHE"
echo "-- cache restored"
else
echo "!! no cache archive found for this model: $model_norm"
echo "Offline mode cannot continue without preloaded firmware."
exit 1
fi
fi
###############################
# Firmware update logic
###############################
echo "-- device inventory"
fwupdmgr get-devices || true
echo "-- check updates"
fwupdmgr get-updates || true
echo "-- apply updates"
if ! fwupdmgr update -y; then
rc=$?
echo "fwupd batch/update exited $rc; some updates may require reboot or second pass."
fi
###############################
# ONLINE ONLY: Save new cache
###############################
if [[ "$HAS_NET" -eq 1 ]]; then
if [[ -d "$CACHE_DIR" ]]; then
echo "-- archiving new cache -> $ARCHIVE"
tar -C / -I zstd -cf "$ARCHIVE" \
"var/cache/fwupd" \
"var/lib/fwupd"
sha256sum "$ARCHIVE" > "$MANIFEST"
echo "Archive: $ARCHIVE"
echo "SHA256: $(cut -d' ' -f1 "$MANIFEST")"
else
echo "WARNING: cache directory not found, nothing to archive"
fi
fi
###############################
# Reboot logic
###############################
NEEDS_REBOOT=0
if fwupdmgr get-history 2>/dev/null | grep -qiE 'restart required|restart.*pending|pending.*device'; then
NEEDS_REBOOT=1
fi
echo "== fwupd-batch done =="
if [[ "$NEEDS_REBOOT" -eq 1 ]]; then
echo "Reboot required to complete firmware installation."
if [[ "$AUTO_REBOOT" -eq 1 ]]; then
echo "AUTO_REBOOT=1 -> rebooting in 5 seconds..."
sleep 5
/usr/bin/systemctl reboot
fi
fi
EOF
# NetworkManager / Wi-Fi helper
mkdir -p /usr/local/sbin
install -m 0755 /dev/stdin /usr/local/sbin/wifi.sh <<'EOS'
#!/usr/bin/env bash
ssid="$1"
nmcli radio wifi on
nmcli dev wifi connect "$ssid" --ask
EOS
# Restore helper: quickly restore a saved cache archive
install -m 0755 /dev/stdin /usr/local/sbin/fwupd-restore.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
ARCHIVE="${1:-}"
[[ -z "$ARCHIVE" ]] && { echo "Usage: fwupd-restore.sh /path/to/fwupd-cache-*.tar.zst"; exit 1; }
if [[ -f "${ARCHIVE}.sha256" ]]; then
sha256sum -c "${ARCHIVE}.sha256"
fi
tar -C / -I zstd -xf "$ARCHIVE"
fwupdmgr refresh --force
fwupdmgr get-updates || true
EOF
# Convenience alias for the live user (uses NOPASSWD sudo for scripts only)
mkdir -p /etc/profile.d
cat >/etc/profile.d/fwupd.sh <<'EOF'
alias fwupd-batch='sudo /usr/local/sbin/fwupd-batch.sh'
alias fwupd-restore='sudo /usr/local/sbin/fwupd-restore.sh'
EOF
chmod 0644 /etc/profile.d/fwupd.sh
# Also copy same aliases into skel so liveuser inherits them explicitly
mkdir -p /etc/skel
cat >>/etc/skel/.bashrc <<'EOF'
# Firmware update helper aliases (auto-added)
alias fwupd-batch='sudo /usr/local/sbin/fwupd-batch.sh'
alias fwupd-restore='sudo /usr/local/sbin/fwupd-restore.sh'
EOF
# =========
# = Usage =
# =========
# Create a usage file in the live user home
mkdir -p /etc/skel
cat >/etc/skel/USAGE.md <<'EOF'
# Firmware Update Live environment (TTY only)
# Network
- Ethernet = auto
- Wi-Fi with "wifi.sh" or via nmcli:
nmcli radio wifi on
nmcli dev wifi list
nmcli dev wifi connect "SSID" password "pass"
# Run firmware updates
- Firmware batch (on stable LVFS):
fwupd-batch
- Firmware batch (with lvfs-testing):
USE_TESTING=1 fwupd-batch
- Firmware batch (with auto-reboot):
AUTO_REBOOT=1 fwupd-batch
# Restore a previous cache
- Restore a previous cache:
fwupd-restore /overlay/fwupd-cache-<model>-<stamp>.tar.zst
# Offline update (no network required if cache exists)
- Just locally run:
fwupd-batch
EOF
chmod 0644 /etc/skel/USAGE.md
install -d -m 0750 /home/liveuser
cp -n /etc/skel/USAGE.md /home/liveuser/USAGE.md
grep -q "fwupd-batch" /home/liveuser/.bashrc || cat /etc/skel/.bashrc >> /home/liveuser/.bashrc
chown -R liveuser:liveuser /home/liveuser
# Field teams reminder and usage banner
mkdir -p /etc/motd.d/
install -d -m 0755 /etc/motd.d
cat >/etc/motd.d/10-oem-requirements.motd <<'EOF'
------------------------------------------------------------
Fedora Firmware Live Environment (SELinux: permissive)
------------------------------------------------------------
FIELD TEAM REMINDERS
- Some firmware updates require AC power. Plug in now.
- For Thunderbolt devices not yet authorized:
sudo boltctl list
sudo boltctl enroll <UUID>
TO BEGIN
- Read usage instructions:
cat USAGE.md
------------------------------------------------------------
EOF
# === Dynamic HW Part Number in MOTD ===
install -d -m 0755 /usr/local/sbin
cat >/usr/local/sbin/gen-motd-hw.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
sku=""
for f in /sys/class/dmi/id/product_sku /sys/class/dmi/id/board_asset_tag; do
[[ -s "$f" ]] && { sku="$(cat "$f")"; break; }
done
model=""
for f in /sys/class/dmi/id/product_name /sys/class/dmi/id/board_name; do
[[ -s "$f" ]] && { model="$(cat "$f")"; break; }
done
sku=${sku:-unknown}
model=${model:-unknown}
cat >/etc/motd.d/90-hw.motd <<EOM
------------------------------------------------------------
Hardware: Part Number (SKU): ${sku}
Model: ${model}
------------------------------------------------------------
EOM
EOF
chmod 0755 /usr/local/sbin/gen-motd-hw.sh
cat >/etc/systemd/system/motd-hw.service <<'EOF'
[Unit]
Description=Generate MOTD with HW Part Number (SKU)
After=local-fs.target
ConditionPathExists=/sys/class/dmi/id
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/gen-motd-hw.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
install -d /etc/systemd/system/multi-user.target.wants
ln -sf ../motd-hw.service /etc/systemd/system/multi-user.target.wants/motd-hw.service
# Active pam_motd pour TTY et SSH (idempotent)
#grep -q 'pam_motd.so' /etc/pam.d/login || {
# printf '%s\n' 'session optional pam_motd.so motd_dir=/etc/motd.d' >> /etc/pam.d/login
#}
#rm -f /home/liveuser/.hushlogin || true
# Prepopulate bash history for convenience
HISTFILE_SKEL="/etc/skel/.bash_history"
cat >"$HISTFILE_SKEL" <<'EOF'
cat USAGE.md
fwupd-batch
EOF
chmod 0600 "$HISTFILE_SKEL"
# If liveuser home already exists, also seed it now
if [ -d /home/liveuser ]; then
install -m 0600 "$HISTFILE_SKEL" /home/liveuser/.bash_history
chown liveuser:liveuser /home/liveuser/.bash_history
fi
%end
# Shutdown when the build completes
shutdown
#!/usr/bin/env bash
set -euo pipefail
shopt -s failglob
DEVICE=${DEVICE:-/dev/sdb}
BUILTSRC="/home/liveuser/Downloads/out"
ESP_SIZE="1024MiB"
if [[ ! -b "$DEVICE" ]]; then echo "Device $DEVICE not found"; exit 1; fi
if [[ ! -d "$BUILTSRC" ]]; then echo "Live project $BUILTSRC not found"; exit 1; fi
for f in "$BUILTSRC/images/pxeboot/vmlinuz" \
"$BUILTSRC/images/pxeboot/initrd.img" \
"$BUILTSRC/LiveOS/squashfs.img" \
"$BUILTSRC/EFI/BOOT/BOOTX64.EFI"; do
[[ -f "$f" ]] || { echo "Missing $f"; exit 1; }
done
part() {
case "$DEVICE" in
*[0-9]) printf "%sp%s" "$DEVICE" "$1" ;;
*) printf "%s%s" "$DEVICE" "$1" ;;
esac
}
# ensure cleanup if script stops (Ctrl-C, error, etc.)
trap 'set +e; sync; sudo umount /mnt/efi /mnt/usb 2>/dev/null || true' EXIT
printf "\nCurrently set device %s will be destroyed!\n" "$DEVICE"
udevadm info --query=property --name "${DEVICE}" | grep -E 'ID_BUS=|ID_MODEL=|ID_SERIAL=|ID_SERIAL_SHORT=' || true
BUS="$(udevadm info --query=property --name "${DEVICE}" | sed -n 's/^ID_BUS=//p')"
TRAN="$(lsblk -dno TRAN "${DEVICE}" || true)"
if [[ "${BUS:-}" != "usb" && "${TRAN:-}" != "usb" ]]; then
echo "ERROR: ${DEVICE} does not look like a USB drive (BUS='${BUS:-}', TRAN='${TRAN:-}'). Abort." >&2
exit 1
fi
printf "\nTHIS WILL WIPE %s. Type YES to continue: " "$DEVICE"; read -r ANSWER
[[ "$ANSWER" == "YES" ]] || { echo "Aborted."; exit 1; }
while IFS= read -r line; do
dev=${line%% *}; mp=${line#* }
[[ -n "$mp" && "$mp" != "$dev" ]] && sudo umount -- "$mp"
done < <(lsblk -nrpo NAME,MOUNTPOINTS "$DEVICE" | awk 'NF>1')
sync
EFI_DEV="$(part 1)"
LIVE_DEV="$(part 2)"
OVLY_DEV="$(part 3)"
sudo wipefs -a "$DEVICE"
sudo sgdisk --zap-all "$DEVICE"
sudo parted -s "$DEVICE" mklabel gpt
sudo parted -s -a optimal "$DEVICE" mkpart ESP fat32 1MiB "$ESP_SIZE"
sudo parted -s "$DEVICE" set 1 esp on
sudo parted -s -a optimal "$DEVICE" mkpart LIVE ext4 "$ESP_SIZE" 95%
sudo parted -s -a optimal "$DEVICE" mkpart OVERLAY ext4 95% 100%
# after partitioning force kernel/udev to see them
sudo partprobe "$DEVICE" || true
sudo udevadm settle
sudo mkfs.vfat -F32 -n EFI "$EFI_DEV"
sudo mkfs.ext4 -F -L live "$LIVE_DEV"
sudo mkfs.ext4 -F -L overlay "$OVLY_DEV"
sudo mkdir -p /mnt/efi /mnt/usb
sudo mount "$EFI_DEV" /mnt/efi
sudo mount "$LIVE_DEV" /mnt/usb
# Copy payload to the live partition (root of /mnt/usb)
sudo install -D "$BUILTSRC/images/pxeboot/vmlinuz" /mnt/usb/vmlinuz
sudo install -D "$BUILTSRC/images/pxeboot/initrd.img" /mnt/usb/initrd.img
sudo mkdir -p /mnt/usb/LiveOS
sudo install -D "$BUILTSRC/LiveOS/squashfs.img" /mnt/usb/LiveOS/squashfs.img
# Copy EFI payload to the ESP
sudo mkdir -p /mnt/efi/EFI/BOOT
sudo rsync -aH --delete "$BUILTSRC/EFI/BOOT/" /mnt/efi/EFI/BOOT/
# Refresh cache once, then non-root reads are fine:
sudo blkid -g
# read UUIDs (quotes are important)
EFI_UUID="$(sudo blkid -s UUID -o value "$EFI_DEV")"
LIVE_UUID="$(sudo blkid -s UUID -o value "$LIVE_DEV")"
OVLY_UUID="$(sudo blkid -s UUID -o value "$OVLY_DEV")"
# Sanity print
echo "EFI_DEV=$EFI_DEV EFI_UUID=$EFI_UUID"
echo "LIVE_DEV=$LIVE_DEV LIVE_UUID=$LIVE_UUID"
echo "OVLY_DEV=$OVLY_DEV OVLY_UUID=$OVLY_UUID"
lsblk -o NAME,FSTYPE,UUID,MOUNTPOINT "${DEVICE}"
# if any is empty, stop here
for v in EFI_UUID LIVE_UUID OVLY_UUID; do
[[ -n "${!v}" ]] || { echo "ERROR: $v is empty"; exit 1; }
done
EFI_CFG="/mnt/efi/EFI/BOOT/grub.cfg"
sudo tee "$EFI_CFG" >/dev/null <<EOF
set default=0
set timeout=10
insmod part_gpt
insmod fat
insmod ext2
insmod gzio
insmod efi_gop
insmod all_video
# Set prefix on the ESP (FAT) so GRUB can load its modules
search --no-floppy --fs-uuid --set=efi ${EFI_UUID}
set prefix=(\$efi)/EFI/BOOT
# Set root to the live (ext4) partition that holds vmlinuz/initrd/LiveOS
search --no-floppy --set=root --fs-uuid ${LIVE_UUID}
menuentry 'Start LiveFwupd42' {
linuxefi /vmlinuz root=live:UUID=${LIVE_UUID} rd.live.overlay=UUID=${OVLY_UUID} rd.live.image quiet rhgb
initrdefi /initrd.img
}
menuentry 'Test this media & start LiveFwupd42' {
linuxefi /vmlinuz root=live:UUID=${LIVE_UUID} rd.live.overlay=UUID=${OVLY_UUID} rd.live.image rd.live.check quiet rhgb
initrdefi /initrd.img
}
EOF
echo "== GRUB (EFI) =="
grep -E '^(set (default|timeout)|search )|linuxefi|initrdefi|rd.live.overlay' "$EFI_CFG" || true
echo "LIVE_UUID=${LIVE_UUID} (vmlinuz/initrd/squashfs)"
echo "OVLY_UUID=${OVLY_UUID} (overlay)"
sync
sudo umount /mnt/efi || true
sudo umount /mnt/usb || true
sync
lsblk -f "$DEVICE"
#sudo parted ${DEVICE} resizepart 3 100%
#sudo e2fsck -f ${DEVICE}3
#sudo resize2fs ${DEVICE}3
echo "Done."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment