All checks were successful
build image / build (push) Successful in 1h51m36s
The repo named WOA-Project as a source and called its cabinets "the easiest route", while aarch64-laptops appeared only as a place where files "have circulated before" — despite it having actual .mbn files checked into its tree and being where the WiFi trio used in today's testing came from. That ranking was mine, not something the evidence supports. Both are now documented with what each actually contains. They overlap and neither is a superset: WOA-Project is the only source of the two for qcdxkmsuc850.mbn, qcadsp850.mbn, qccdsp850.mbn, qcslpi850.mbn, qcvss850.mbn and ipa_fws.elf, and publishes nine versions whose cabinets differ. aarch64-laptops carries the modem/WLAN trio, the bdwlan board data, a prebuilt board-2.bin and the script that makes it, a630_gmu.bin, the machine's ACPI tables and a device tree — none of which WOA-Project has, and it has none of the six above. Its wifi/firmware-5.bin is an HTML error page rather than firmware, which is worth knowing before copying it somewhere. Also restate the modem result without implying a verdict on either source. Both sets produce the identical QLINK failure here; that shows changing firmware does not change the outcome, not that either set is wrong, and not that one is more trustworthy than the other. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS
437 lines
18 KiB
Markdown
437 lines
18 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. Four sources are known:
|
|
|
|
Two projects publish C630 firmware. They overlap but neither is a superset of
|
|
the other, and both are worth knowing about.
|
|
|
|
**WOA-Project** — <https://github.com/WOA-Project/Qualcomm-Reference-Drivers>
|
|
|
|
Windows-on-ARM driver packages by vendor and model, under `Lenovo/YogaC630/`.
|
|
Nine versions are published, `200.0.1.0` through `200.0.19.0`; the cabinets
|
|
differ between them. This is the only source here for the GPU, DSP, sensor and
|
|
venus blobs:
|
|
|
|
| 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`, `WLANMDSP.MBN` |
|
|
| `qcwlan850.cab` | `bdwlan.bin`, `bdwlan.b3*` — ath10k board data |
|
|
| `mcfg_subsys_ext850.cab` | `MCFG/*` modem configuration |
|
|
| `qcsubsys_extension850.cab` | ADSP/CDSP runtime modules, `fastrpc_shell_*` |
|
|
|
|
`cabextract` or `7z x` opens them. Ignore the `_nm` and `_CLS` variants; the
|
|
device tree asks for the plain names. Fetch via the GitHub API's
|
|
`download_url` — the `raw.githubusercontent.com` paths return 404.
|
|
|
|
**aarch64-laptops** — <https://github.com/aarch64-laptops/build>
|
|
|
|
Files checked directly into `misc/lenovo-yoga-c630/`, no extraction needed.
|
|
A narrower set, but with things WOA-Project does not carry:
|
|
|
|
| Path | Contains |
|
|
|---|---|
|
|
| `wifi/` | `qcdsp1v2850.mbn`, `qcdsp2850.mbn`, `wlanmdsp.mbn`, `bdwlan.*` |
|
|
| `wifi/create-board-2.bin/` | a prebuilt `board-2.bin`, and the script that makes it |
|
|
| `gpu/firmware/` | `a630_gmu.bin` |
|
|
| `acpi/`, `laptop-lenovo-yoga-c630.dts` | the machine's ACPI tables and a device tree |
|
|
|
|
It has none of `qcdxkmsuc850.mbn`, `qcadsp850.mbn`, `qccdsp850.mbn`,
|
|
`qcslpi850.mbn`, `qcvss850.mbn` or `ipa_fws.elf`. Note `wifi/firmware-5.bin` is
|
|
an HTML error page in the checkout, not firmware — Fedora's `atheros-firmware`
|
|
ships a real one.
|
|
|
|
**Which to use.** For the GPU, DSPs, sensors and venus, WOA-Project is the only
|
|
option of the two. For the modem and WLAN trio both publish files, and they are
|
|
different builds — same sizes for the modem pair, different checksums. On this
|
|
machine both produce identical results, so nothing here distinguishes them; see
|
|
[What the firmware does not fix](#what-the-firmware-does-not-fix).
|
|
|
|
**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 the whole set as shipped for your specific machine. Slower than
|
|
either repository, and untested here.
|
|
|
|
**Another C630 owner.** 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).
|
|
|
|
## What the firmware does not fix
|
|
|
|
Installing all of it still leaves two things broken, both for reasons that are
|
|
not about firmware. Recorded here so nobody repeats the search.
|
|
|
|
### Onboard WiFi: everything is in place except a working modem
|
|
|
|
The name gives it away: **wlan*mdsp*** is the WLAN *Modem* DSP. On SDM845 the
|
|
WiFi firmware runs on the modem, so `ath10k_snoc` binds to `18800000.wifi` and
|
|
then sits silent. It logs nothing and fails nothing — it has registered a QMI
|
|
client and is waiting for service 69, `wlfw`, which only appears once the modem
|
|
is up. `qrtr-lookup` shows what is and is not there.
|
|
|
|
Everything on the WiFi side checks out:
|
|
|
|
- `ath10k_snoc` binds successfully and is not in deferred probe
|
|
- the device tree carries `qcom,calibration-variant = "Lenovo_C630"`
|
|
- Fedora's `board-2.bin` contains a matching `variant=Lenovo_C630` entry
|
|
- `modemst1` and `modemst2` hold ~2 MB of real NV data — not wiped
|
|
|
|
#### The userspace services are required, and mostly missing by default
|
|
|
|
[aarch64-laptops' WiFi README][aal-wifi] lists four services. On a current
|
|
Fedora two of them are now in the kernel, and the other two are packaged but
|
|
inactive:
|
|
|
|
| Service | Status here |
|
|
|---|---|
|
|
| `pd-mapper` | in-kernel as `qcom_pd_mapper` — nothing to install |
|
|
| `qrtr-ns` | in-kernel — the `qrtr` package supplies only `qrtr-lookup`/`qrtr-cfg` |
|
|
| `rmtfs` | packaged, **disabled by default** — serves the modem's NV partitions |
|
|
| `tqftpserv` | packaged, **not installed** — serves files to the modem over TFTP |
|
|
|
|
```sh
|
|
sudo dnf install rmtfs tqftpserv qrtr
|
|
sudo systemctl enable --now rmtfs tqftpserv
|
|
```
|
|
|
|
Enabling these took `qrtr-lookup` from 19 services to 25. A working setup is
|
|
said to show around 40.
|
|
|
|
[aal-wifi]: https://github.com/aarch64-laptops/build/tree/master/misc/lenovo-yoga-c630/wifi
|
|
|
|
#### The modem fetches wlanmdsp over TFTP
|
|
|
|
This is the step that is easy to miss, and the reason `tqftpserv` exists.
|
|
`tqftpserv` serves from `/lib/firmware/`, and the modem asks it for the WLAN
|
|
firmware by path:
|
|
|
|
```sh
|
|
sudo mkdir -p /lib/firmware/readonly/firmware/image
|
|
sudo cp wlanmdsp.mbn /lib/firmware/readonly/firmware/image/
|
|
```
|
|
|
|
The modem also wants a writable area, and says so in the `tqftpserv` journal:
|
|
|
|
```
|
|
[TQFTP] RRQ: /readwrite/ota_firewall/ruleset → unable to open (2), reject
|
|
[TQFTP] WRQ: /readwrite/server_check.txt
|
|
```
|
|
|
|
```sh
|
|
sudo mkdir -p /lib/firmware/readwrite/ota_firewall
|
|
sudo touch /lib/firmware/readwrite/ota_firewall/ruleset
|
|
sudo chmod -R 0777 /lib/firmware/readwrite
|
|
```
|
|
|
|
Watching `journalctl -u tqftpserv` while starting the modem is the best
|
|
available feedback channel — it shows exactly which paths the modem wants.
|
|
|
|
#### Where it actually stops
|
|
|
|
The modem boots and then dies at RF front-end initialisation, roughly every 42
|
|
seconds until stopped:
|
|
|
|
```
|
|
qcom-q6v5-mss 4080000.remoteproc: MBA booted without debug policy, loading mpss
|
|
qcom-q6v5-mss 4080000.remoteproc: fatal error received:
|
|
RFLM@rflm_qlnk.cpp:1087 [3,3] RF stuck in QLINK start state: 0x0 after maximum
|
|
remoteproc remoteproc0: crash detected ... recovering
|
|
```
|
|
|
|
It never gets far enough to request `wlanmdsp`, so WLAN never starts.
|
|
|
|
Three firmware pairings, three distinct failures — worth recording, because the
|
|
differences are informative:
|
|
|
|
| MBA (stage 1) | mpss (stage 2) | Result |
|
|
|---|---|---|
|
|
| full | full | boots, dies at `RF stuck in QLINK start state` |
|
|
| `_nm` | `_nm` | `PBL returned unexpected status` — rejected by the boot ROM |
|
|
| full | `_nm` | `MPSS header authentication failed: -3` |
|
|
|
|
The `_nm` ("no modem") variants are the obvious idea — Fedora ships the
|
|
equivalent `modem_nm.mbn` for generic sdm845, and skipping cellular RF is
|
|
exactly what is wanted here. They are not signed for this device and cannot be
|
|
made to load.
|
|
|
|
#### Firmware has been eliminated as the variable
|
|
|
|
The test that narrows it: both projects publish the modem trio, and their
|
|
copies differ — the modem pair matches on size but not checksum. Both were
|
|
installed on this machine, with `rmtfs` and `tqftpserv` running and `wlanmdsp`
|
|
in the TFTP path. Both produce the **identical** QLINK failure.
|
|
|
|
That is worth stating carefully. It does not show either set to be wrong, and
|
|
it does not make one more trustworthy than the other — the aarch64-laptops
|
|
copies come from a setup whose support table ticks WiFi, but on a 2019 kernel,
|
|
and neither set has been shown to work here. What it does show is that changing
|
|
firmware does not change the outcome.
|
|
|
|
So the difference is not the firmware, and not the userspace services. What
|
|
remains is the kernel: that setup ran `aarch64-laptops/linux` branch `gpu`,
|
|
circa 2019 on 5.x, against 7.1.5 here. Both ath10k patches it applied are long
|
|
upstream — the device tree carries `qcom,snoc-host-cap-8bit-quirk` from the
|
|
first of them. Six years of `qcom-q6v5-mss` churn sits between the two.
|
|
|
|
That points at a kernel regression rather than anything missing on disk.
|
|
Confirming it means bisecting or booting an older kernel, which nothing here
|
|
does yet.
|
|
|
|
Things that sound like they should help and do not:
|
|
|
|
- **Unplugging the USB WiFi dongle.** Different bus, different driver.
|
|
`ath10k_snoc` is waiting on the modem, not competing for a radio.
|
|
- **`rmtfs` alone.** Necessary, not sufficient. Its "failed to update start
|
|
state" warnings are its optional remoteproc-control helper and are harmless.
|
|
- **The `_nm` variants.** See above.
|
|
|
|
Untried, in rough order of promise: the other eight driver versions under
|
|
`Lenovo/YogaC630/` (this machine's UEFI is `9UCN33WW(V2.06)` from 2019, and the
|
|
newest package may not be the right vintage); `mcfg_subsys_ext850.cab`, which
|
|
holds modem configuration data; and building `board-2.bin` from the C630's own
|
|
`bdwlan.*` files rather than relying on Fedora's.
|
|
|
|
### Audio is a kernel driver problem
|
|
|
|
The ADSP runs, the audio services register, and the codec answers:
|
|
|
|
```
|
|
wcd934x-slim 217:250:1:0: WCD934x chip id major 0x108, minor 0x1
|
|
```
|
|
|
|
So SLIMbus, the ADSP and the hardware are all fine. What fails is one sub-device
|
|
of the codec:
|
|
|
|
```
|
|
qcom-soundwire wcd934x-soundwire.12.auto: din-ports (2) mismatch with controller (6)
|
|
platform sound: deferred probe pending: msm-snd-sdm845: SLIM Playback: codec dai not found
|
|
```
|
|
|
|
The codec's SoundWire block declares two data-in ports where the controller
|
|
expects six, so it never probes, so the sound card has no codec DAI and never
|
|
appears. That is a mismatch inside the kernel, and needs a kernel or
|
|
device-tree change rather than any blob.
|
|
|
|
One thing worth knowing if you go looking: `slim_qcom_ngd_ctrl` can probe before
|
|
the ADSP is ready and log `QMI wait timeout`. Reloading the module afterwards
|
|
gets the codec detected, which is how the chip ID above was obtained — but it
|
|
does not get past the SoundWire mismatch.
|
|
|
|
## 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.
|