Files
c630/overlay/usr/local/sbin/c630-firmware
rob thijssen f0b2d7846a
Some checks failed
build image / build (push) Has been cancelled
Add install-to-disk.sh, and get the GPU firmware into the initramfs
Validated by running it on the machine, twice, and inspecting the result.

Two properties of this laptop rule out the obvious approach, and the script
exists mainly to encode them. Its internal UFS reports 4096-byte logical
sectors, so the image — built with 512-byte geometry — cannot be dd'd onto it;
the GPT header and every partition offset would land in the wrong place. And
there are no EFI runtime variables, so efibootmgr cannot register a boot entry
and GRUB has to sit at the removable-media path where the firmware looks
unprompted.

Three things the validation runs caught that review would not have:

rsync is not in the image. I had put it in the build container and never in
the package list, so the first run died at the copy. It now falls back to tar
(--xattrs-include='*', or SELinux labels are silently dropped and the result
does not boot), and rsync is in base.pkgs for the progress output.

Copying a live root makes tar exit non-zero — files change underneath it, and
this machine's clock is wrong besides, so every mtime looks like it is in the
future. With pipefail that aborted the install after the root filesystem and
before /boot, leaving a half-installed disk that looked plausible. Warning-level
exits are now tolerated and only a fatal exit 2 stops the run.

systemd-machine-id-setup keeps an existing valid id, and one had just been
copied off the stick, so the installed system was a clone. The file is removed
first now.

Also: msm_dpu probes ~6s in, while the initramfs is still root, and asks for
qcom/a630_sqe.fw before the real filesystem carrying it is reachable. It never
retries. Adding the Adreno firmware to the initramfs is a few tens of
kilobytes. c630-firmware does the same for the DSP blobs once they exist, since
dracut rejects install_items globs that match nothing.

chrony, because the RTC reads 1970 and nothing was correcting it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS
2026-07-27 19:23:29 +03:00

64 lines
2.3 KiB
Bash
Executable File

#!/usr/bin/bash
#
# Pull the model-specific Qualcomm blobs off this machine's Windows partition.
#
# Fedora ships everything for the C630 that Qualcomm allows to be
# redistributed, which covers ath10k WCN3990 (WiFi/Bluetooth) outright. What it
# cannot ship is the per-model signed firmware, which is signed against this
# machine's own keys and lives only in its Windows install.
#
# Without those you lose accelerated graphics, audio, the sensor hub (lid
# switch, accelerometer, auto-rotate) and hardware video decode.
#
# Graphics is the surprising one. The generic Adreno 630 pieces are packaged,
# but this device's tree asks for a model-signed zap shader —
# qcom/sdm850/LENOVO/81JL/qcdxkmsuc850.mbn — and Fedora's generic
# sdm845/a630_zap.mbn is a different device's file.
set -euo pipefail
if [ "$(id -u)" -ne 0 ]; then
echo "c630-firmware: needs root — try: sudo c630-firmware" >&2
exit 1
fi
echo "Looking for a Windows installation to extract firmware from..."
echo
if ! command -v qcom-firmware-extract >/dev/null; then
echo "qcom-firmware-extract is not installed. Install it with:" >&2
echo " sudo dnf install qcom-firmware-extract" >&2
exit 1
fi
qcom-firmware-extract "$@"
echo
# The ADSP has to be up before the root filesystem is mounted, so these have to
# travel in the initramfs. Only write the glob now that the files exist —
# dracut objects to install_items that match nothing.
FW_DIR=/usr/lib/firmware/updates/qcom/sdm850/LENOVO/81JL
if compgen -G "${FW_DIR}/*.mbn" >/dev/null || compgen -G "${FW_DIR}/*.elf" >/dev/null; then
printf 'install_items+=" %s/*.mbn %s/*.elf "\n' "$FW_DIR" "$FW_DIR" \
> /etc/dracut.conf.d/20-c630-extracted-firmware.conf
echo "Extracted firmware will be included in the initramfs."
fi
echo "Regenerating the initramfs..."
dracut --force --regenerate-all
cat <<'EOF'
Done. Reboot to pick up the new firmware.
If qcom-firmware-extract could not find the Windows partition, mount it by hand
and point the tool at it:
sudo mkdir -p /mnt/windows
sudo mount /dev/disk/by-partlabel/Windows /mnt/windows # adjust as needed
sudo qcom-firmware-extract --windows-dir /mnt/windows
See docs/firmware.md in the c630 repo for the full file list and the manual
fallback if the tool does not recognise this model.
EOF