# 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: ```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_*' ``` 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: ```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 /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.