Files
c630/docs/firmware.md
rob thijssen 2457df7a37
All checks were successful
build image / build (push) Successful in 53m10s
docs: record what the GPU firmware trace actually proves
Tested on the machine. With the generic Adreno firmware reachable from the
initramfs and the model-signed blob absent, the GPU gets two files in and stops:

    loaded qcom/a630_sqe.fw from new location
    loaded qcom/a630_gmu.bin from new location
    *ERROR* Unable to load qcom/sdm850/LENOVO/81JL/qcdxkmsuc850.mbn
    *ERROR* gpu hw init failed: -2

That settles a question the docs had been hedging: the zap shader is a hard
requirement, not an optimisation, and the generic pieces are necessary but not
sufficient. Getting past sqe and gmu only to die at zap is about as clean a
demonstration as the hardware will give.

Two things fall out of the same trace and are worth writing down, because
nothing upstream documents them for this machine. The driver never falls back
to the installed sdm845/a630_zap.mbn — the device tree pins the model-specific
path — and a fallback would not help anyway, since the shader is signed against
this device's own secure-boot chain. And the display survives the failure
entirely: msm_dpu still binds the panel, so a dead GPU costs acceleration
rather than a picture, and a desktop runs on llvmpipe.

Also record why these files have to travel in the initramfs at all: msm_dpu
probes around six seconds in, while the initramfs is still root, and never
retries.

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

6.6 KiB

Firmware

The C630's firmware splits into two groups, and the split is about licensing, not difficulty.

What ships in the image

Qualcomm permits redistribution of these, so Fedora packages them and the build installs them:

Package Files Enables
atheros-firmware ath10k/WCN3990/hw1.0/{firmware-5.bin,board-2.bin,wlanmdsp.mbn} WiFi and Bluetooth
qcom-firmware qcom/a630_gmu.bin, qcom/a630_sqe.fw The generic half of the Adreno 630 — necessary but not sufficient

Networking therefore works on a freshly written image. Graphics does not: see below.

What has to come off the Windows partition

These are signed against per-model keys, so nobody can redistribute them and they exist on your machine only inside its Windows install. The list is not a guess — it is every firmware-name property in the mainline device tree, arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts:

File Device tree node Lost without it
qcdxkmsuc850.mbn gpu_zap_shader Accelerated graphics
qcadsp850.mbn adsp_pas Audio — speakers, microphone
qcslpi850.mbn slpi_pas Sensor hub — lid switch, accelerometer, auto-rotate
qccdsp850.mbn cdsp_pas Compute DSP offload
qcvss850.mbn venus Hardware video decode
qcdsp1v2850.mbn mss_pil Modem, stage 1
qcdsp2850.mbn mss_pil Modem, stage 2
ipa_fws.elf ipa IPA datapath, needed by the modem

They belong under /lib/firmware/updates/qcom/sdm850/LENOVO/81JL/.

The GPU one is worth calling out, because it is easy to assume otherwise: Fedora does ship an sdm845/a630_zap.mbn, but that is the generic Snapdragon 845 zap shader and not what this device asks for. The C630's device tree names qcom/sdm850/LENOVO/81JL/qcdxkmsuc850.mbn specifically, so until you supply it you get an unaccelerated display.

Each file is independent, so a partial recovery is still worth having — qcdxkmsuc850.mbn on its own buys you working graphics.

Confirmed on the hardware

This is not inferred from the device tree. On a machine with the generic Adreno firmware present and the model-signed blob absent, the GPU gets two files in and then stops:

[drm:adreno_request_fw]   loaded qcom/a630_sqe.fw from new location
[drm:adreno_request_fw]   loaded qcom/a630_gmu.bin from new location
[drm:zap_shader_load_mdt] *ERROR* Unable to load qcom/sdm850/LENOVO/81JL/qcdxkmsuc850.mbn
[drm:adreno_load_gpu]     *ERROR* gpu hw init failed: -2

So the generic pieces are necessary and not sufficient, and the zap shader is a hard requirement rather than an optimisation. Two details follow from that trace:

The driver never falls back to sdm845/a630_zap.mbn, even though the file is installed — the device tree's firmware-name pins the model-specific path. Nor would falling back help: the zap shader is signed against the device's own secure-boot chain, and the Snapdragon 845 development board's copy will not validate here.

The display keeps working throughout. msm_dpu binds the panel and the console lands on msmdrmfb regardless, so a failed GPU costs you acceleration, not a picture. A desktop still runs on llvmpipe — though /dev/dri/renderD128 is present even when hw init has failed, so mesa may try freedreno, fail, and take the display manager down with it. LIBGL_ALWAYS_SOFTWARE=1 in /etc/environment avoids that.

These have to be in the initramfs

msm_dpu probes about six seconds in, while the initramfs is still the root filesystem, and does not retry. Firmware that only exists on the real root is therefore invisible to it:

msm_dpu ae01000.display-controller: Direct firmware load for qcom/a630_sqe.fw failed with error -2

overlay/etc/dracut.conf.d/10-c630.conf puts the Adreno files in the initramfs for this reason, and c630-firmware adds the extracted DSP blobs to it after extraction — the ADSP has to be up before the root filesystem is mounted, and dracut rejects install_items globs that match nothing, so the entry can only be written once the files exist.

Finding them on a backup

If Windows is long gone from the machine but you kept a copy of the files, one search catches all eight, since seven share a suffix:

find /mnt/backup -type f \
    \( -iname 'qc*850.mbn' -o -iname 'ipa_fws.elf' -o -iname 'bdwlan*.bin' \) \
    -printf '%10s  %p\n'

They originally lived in C:\Windows\System32\DriverStore\FileRepository\, in directories named qcdx850.inf_arm64_* and qcadsp*.inf_arm64_*. If the loose files turn up nothing, look for those directories wholesale:

find /mnt/backup -type d -iname 'qc*.inf_arm64_*'

Expect a few hundred KB to a few MB each. file reports them as data — they are signed Qualcomm MBN containers, not ELF, apart from ipa_fws.elf.

Lenovo does not appear to publish a driver package for the 81JL containing these, so an old backup or a surviving Windows partition are the only routes.

Extracting them

The image ships Fedora's qcom-firmware-extract. Run it once:

sudo c630-firmware
sudo reboot

That wraps qcom-firmware-extract and regenerates the initramfs afterwards, which matters — the ADSP firmware has to be available before the root filesystem is mounted, and overlay/etc/dracut.conf.d/10-c630.conf only takes effect on a rebuild.

If it cannot find Windows, mount it yourself and point the tool at it:

lsblk -o NAME,SIZE,FSTYPE,LABEL       # find the NTFS partition
sudo mkdir -p /mnt/windows
sudo mount /dev/sda4 /mnt/windows
sudo qcom-firmware-extract --windows-dir /mnt/windows

qcom-firmware-extract was written for the Snapdragon 8cx and X Elite laptops. If it does not recognise the SDM850, copy the files by hand — they are in Windows/System32/DriverStore/FileRepository/ under a qcdx*.inf_arm64_* directory:

sudo find /mnt/windows/Windows/System32/DriverStore/FileRepository \
    -iname 'qc*850.mbn' -o -iname 'ipa_fws.elf' -o -iname 'qcdxkmsuc850.mbn'

sudo mkdir -p /lib/firmware/updates/qcom/sdm850/LENOVO/81JL
sudo cp <each file> /lib/firmware/updates/qcom/sdm850/LENOVO/81JL/
sudo dracut --force --regenerate-all

Check it took:

dmesg | grep -iE 'remoteproc|adsp|cdsp'

Baking firmware into the image

If you would rather not repeat the extraction on every reinstall, drop the files into firmware/local/ in this repo, mirroring the /usr/lib/firmware/updates/ layout:

firmware/local/qcom/sdm850/LENOVO/81JL/qcadsp850.mbn
firmware/local/qcom/sdm850/LENOVO/81JL/qccdsp850.mbn
...

build/stage2.sh picks them up automatically. They are gitignored, and should stay that way — this repository is public and the blobs are not yours to publish.