Files
c630/docs/firmware.md
rob thijssen 18252b37f5
All checks were successful
build image / build (push) Successful in 24m42s
docs: the firmware is downloadable — WOA-Project reference drivers
The blobs turned out to be a public download rather than something to recover
from a lost backup. WOA-Project/Qualcomm-Reference-Drivers collects the
Windows-on-ARM driver cabinets by SoC, and three of them cover this machine
completely: qcdx850.cab has the zap shader and venus, qcipa850.cab has
ipa_fws.elf, and qcsubsys850.cab has the four DSP images plus WLANMDSP.MBN —
the WiFi firmware, which is not in the device tree's firmware-name list at all
and so was never on our list of things to look for.

Correct three claims elsewhere in the file that this disproves. `file` reports
these as ELF QUALCOMM DSP6 images, not as `data` — worth stating precisely,
since it is the quickest way to tell a real blob from a download that returned
an HTML error page. The sizes span 14KB to 60MB rather than "a few hundred KB
to a few MB". And the heading claiming they must come off the Windows partition
is no longer true of the easiest route.

Also narrow what c630-firmware puts in the initramfs. It globbed every .mbn in
the firmware directory, which would have pulled in the 60MB qcdsp2850.mbn and
inflated the initramfs roughly twentyfold. Only the GPU needs to be there —
msm_dpu probes at six seconds, while the initramfs is still root; the ADSP,
CDSP, SLPI, venus and modem all probe around forty seconds in and load from the
real root perfectly happily.

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

255 lines
9.9 KiB
Markdown

# 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 you have to supply
These are signed against per-model keys and Fedora does not ship them, so a
stock install has none of them. Nothing about them is unredistributable in
principle — the equivalent files for the
ThinkPad X13s *are* in linux-firmware — it is that nobody has obtained
permission for this model. See [If you have no
backup](#if-you-have-no-backup).
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 `qcdxkmsuc850.mbn` once it exists.
Only the GPU needs this. The ADSP, CDSP, SLPI, venus and modem all probe around
forty seconds in, well after the real root is mounted, and load from it
perfectly happily. That distinction is worth keeping: `qcdsp2850.mbn` alone is
60 MB, so sweeping the whole firmware directory into the initramfs would inflate
it roughly twentyfold for no benefit.
## 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:
```sh
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:
```sh
find /mnt/backup -type d -iname 'qc*.inf_arm64_*'
```
Sizes range from 14 KB (`qcdxkmsuc850.mbn`) to 60 MB (`qcdsp2850.mbn`).
Despite the `.mbn` extension they are ELF images, and `file` should say so:
```
qcdxkmsuc850.mbn: ELF 32-bit LSB executable, QUALCOMM DSP6, version 1 (SYSV)
```
Anything reporting as text or HTML is a download that went wrong.
Lenovo does not appear to publish a driver package for the 81JL containing
these. If the backups turn up nothing, see [If you have no
backup](#if-you-have-no-backup) — the files are not tied to your individual
machine, so yours is not the only possible source.
## If you have no backup
Losing the Windows partition is not the end of it, because **these blobs are
signed per model, not per machine**. A copy from any other Yoga C630 works on
yours.
The evidence is in linux-firmware itself, which already ships the exact
analogous set for the ThinkPad X13s — one copy serving every unit of that
model:
```
qcom/sc8280xp/LENOVO/21BX/qcdxkmsuc8280.mbn zap shader
qcom/sc8280xp/LENOVO/21BX/qcadsp8280.mbn audio
qcom/sc8280xp/LENOVO/21BX/qccdsp8280.mbn compute DSP
qcom/sc8280xp/LENOVO/21BX/qcslpi8280.mbn sensors
qcom/sc8280xp/LENOVO/21BX/qcvss8280.mbn video
```
A one-to-one match with the C630's list, differing only in the model. So these
files are redistributable once Lenovo and Qualcomm permit it — it is a
licensing question, not a technical one.
`qcom/sdm850/LENOVO/81JL/` has simply never been contributed. Fedora ships no
sdm850 model firmware at all, so it will not turn up in a `linux-firmware`
update. Three routes, easiest first:
**The WOA-Project reference drivers.** <https://github.com/WOA-Project/Qualcomm-Reference-Drivers>
collects the Windows-on-ARM driver packages by SoC. The C630's are three
cabinet files, and between them they hold every file this machine asks for:
| Cabinet | Contains |
|---|---|
| `qcdx850.cab` | `qcdxkmsuc850.mbn` (zap shader), `qcvss850.mbn` (venus) |
| `qcipa850.cab` | `ipa_fws.elf` |
| `qcsubsys850.cab` | `qcadsp850.mbn`, `qccdsp850.mbn`, `qcslpi850.mbn`, `qcdsp1v2850.mbn`, `qcdsp2850.mbn`, and `WLANMDSP.MBN` |
That last one is a bonus — the WiFi firmware, which is not in the device tree's
`firmware-name` list but is what the onboard ath10k needs.
`cabextract` or `7z x` will open them:
```sh
for f in qcdx850.cab qcipa850.cab qcsubsys850.cab; do 7z x -o./extracted "$f"; done
find ./extracted -iname 'qc*850.mbn' -o -iname 'ipa_fws.elf' -o -iname 'WLANMDSP.MBN'
```
Ignore the `_nm` and `_CLS` variants; the device tree asks for the plain names.
Verify what you get with `file` — they should report as
`ELF 32-bit LSB executable, QUALCOMM DSP6`, not as text or HTML.
**Lenovo's Digital Download Recovery Service.** Lenovo builds a Windows
recovery image against a machine's serial number and lets the owner download
it. That image contains `Windows/System32/DriverStore/FileRepository`, and
therefore all eight files. Slower than the cabinets, but it is unambiguously
your own machine's firmware.
**Another C630 owner.** The aarch64-laptops project is where these have
circulated before, and any 81JL's copy is as good as your own.
Whichever route, drop the result into `firmware/local/` and rebuild — see
[Baking firmware into the image](#baking-firmware-into-the-image).
## Extracting them
The image ships Fedora's `qcom-firmware-extract`. Run it once:
```sh
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:
```sh
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:
```sh
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:
```sh
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.