Build Fedora aarch64 images for the Lenovo Yoga C630

Assembles a ready-to-write disk image via Gitea Actions. Mainline has carried
sdm850-lenovo-yoga-c630.dts since 5.5 and Fedora ships it in kernel-core, so
unlike aarch64-laptops/build there is no kernel or GRUB to compile — what is
left is producing an image that boots on firmware which hands Linux no device
tree.

The build runs in an aarch64 container under qemu-user and builds filesystems
from directory trees with mke2fs -d and mcopy rather than mounting loop
devices, so it works on runners that will not hand out /dev/loop-control.

A kernel-install hook writes the devicetree line into each BLS entry; without
it the first `dnf update kernel` would produce an unbootable system.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS
This commit is contained in:
2026-07-27 11:24:53 +03:00
commit 280874f564
21 changed files with 1294 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="@DEVICE_CMDLINE@"
GRUB_DISABLE_RECOVERY=true
GRUB_ENABLE_BLSCFG=true
# Consumed by grub2-mkconfig on aarch64. The BLS entries carry their own
# `devicetree` line as well (written by 95-c630-devicetree.install), because
# kernel-install does not read this file.
GRUB_DEFAULT_DTB=/dtb/@DEVICE_DTB@

View File

@@ -0,0 +1,12 @@
# The image is built on a machine that is nothing like a C630, so the initramfs
# must be generic — a host-only initramfs would contain the builder's drivers.
hostonly="no"
hostonly_cmdline="no"
# UFS is the C630's only internal storage and the rootfs lives on it, so the
# controller and PHY drivers have to be in the initramfs, not modules loaded
# later from a filesystem we cannot yet read.
add_drivers+=" ufshcd-core ufshcd-pltfrm ufs-qcom phy-qcom-qmp-ufs "
# Needed before the display comes up, and cheap to include.
add_drivers+=" nvmem_qfprom qcom_scm rtc-pm8xxx "

View File

@@ -0,0 +1,47 @@
#!/usr/bin/bash
#
# Teach kernel-install about the C630's device tree.
#
# The C630's UEFI hands Linux no device tree, so GRUB has to load one. Fedora's
# BLS snippets have a `devicetree` key for exactly this, but nothing in the
# stock toolchain populates it — which means a plain `dnf update kernel` would
# otherwise produce an unbootable entry. This hook runs after 20-grub.install
# and patches the entry it just wrote.
set -eu
COMMAND="${1:?}"
KERNEL_VERSION="${2:?}"
DTB_REL="@DEVICE_DTB@"
BOOT_ROOT="${KERNEL_INSTALL_BOOT_ROOT:-/boot}"
ENTRIES_DIR="${BOOT_ROOT}/loader/entries"
case "$COMMAND" in
add)
dtb_path="/dtb-${KERNEL_VERSION}/${DTB_REL}"
if [ ! -e "${BOOT_ROOT}${dtb_path}" ]; then
echo "95-c630-devicetree: ${BOOT_ROOT}${dtb_path} is missing;" \
"leaving boot entries alone rather than writing a bad one" >&2
exit 0
fi
shopt -s nullglob
for entry in "${ENTRIES_DIR}"/*-"${KERNEL_VERSION}".conf; do
# Drop any stale devicetree line, then append the current one. Doing it
# in that order makes the hook idempotent across re-installs.
tmp="${entry}.c630.$$"
grep -v '^devicetree[[:space:]]' "$entry" > "$tmp"
printf 'devicetree %s\n' "$dtb_path" >> "$tmp"
mv -f "$tmp" "$entry"
echo "95-c630-devicetree: set devicetree ${dtb_path} in ${entry}"
done
;;
remove)
# The build writes its own bootstrap entry under a fixed name, which
# kernel-install would not otherwise clean up when the kernel goes away.
rm -f "${ENTRIES_DIR}/c630-${KERNEL_VERSION}.conf"
;;
esac
exit 0

View File

@@ -0,0 +1,7 @@
Fedora @FEDORA_RELEASE@ for the @DEVICE_DESC@ (built @BUILD_DATE@ from @BUILD_REF@)
Graphics and WiFi work with the firmware Fedora ships. Audio, the sensor
hub and hardware video decode need per-model blobs from the Windows
partition — run `sudo c630-firmware` once to extract them.

View File

@@ -0,0 +1,15 @@
[Unit]
Description=Grow C630 root filesystem to fill the medium
DefaultDependencies=no
After=systemd-remount-fs.service
Before=local-fs.target sysinit.target
ConditionPathExists=!/var/lib/c630/growfs-done
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/c630-growfs
RemainAfterExit=yes
StandardOutput=journal+console
[Install]
WantedBy=sysinit.target