A dnf upgrade to 7.1.8 installed the kernel rpm cleanly, then ran /boot out
of space. dracut wrote no initramfs, and because kernel-install stops at the
first failing plugin, 95-c630-devicetree never ran either — leaving a boot
entry with neither an initrd nor a devicetree line, which on this machine can
never boot. dnf reported success and nothing retried.
A kernel costs ~336 MiB here: a 210 MiB hostonly=no initramfs, a 98 MiB
dtb-<kver> directory carrying every board's device tree, plus vmlinuz and
System.map. Three of those cannot fit 1 GiB, so /boot goes to 2 GiB and
installonly_limit drops to 2.
Also fixes the quieter half of the same trap. snd-soc-wsa881x lives outside
the kernel package, so the speakers go silent after any kernel update with
nothing in the logs to explain it. c630-wsa881x rebuilds it and
96-c630-wsa881x.install calls it on each kernel-install add — always exiting
0, since a plugin failure is precisely what caused the damage above.
grub.cfg gains the next_entry one-shot block that has been carried by hand all
along, so testing a kernel costs a power cycle rather than a rescue.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011XgGF5wfxLDAybVnNz6eNQ
The WCN3990 has no burned-in Bluetooth address, so the kernel registers
the controller unconfigured and bluetoothd never sees it. The factory
address is on the machine all along: QCOM/BT.PROVISION on the DPP
partition, a three-byte header followed by the six-byte address.
c630-bt-addr reads it and hands it to btmgmt before bluetooth.service
starts. Verified on hardware: controller configures, powers, scans, and
streams A2DP.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011XgGF5wfxLDAybVnNz6eNQ
aarch64-laptops' support table ticks WiFi for this machine, so the path exists.
Following their WiFi README got considerably further and then stopped somewhere
useful to have documented.
Two of the four services they list are in the kernel now (pd-mapper, qrtr-ns).
The other two, rmtfs and tqftpserv, are packaged in Fedora and shipped
disabled — tqftpserv was not even installed. Both are now in base.pkgs and
enabled by stage2. Enabling them took qrtr-lookup from 19 registered services
to 25; a working setup is said to show around 40.
The step worth having written down: the modem does not read wlanmdsp.mbn from
/lib/firmware. It asks tqftpserv for it over TFTP, from
/lib/firmware/readonly/firmware/image/. Nothing reports this as an error —
ath10k_snoc binds, registers a QMI client, and waits forever for a service that
never registers. c630-firmware now places the file there, and creates the
writable area the modem asks tqftpserv for.
Where it stops: the modem boots and dies at "RF stuck in QLINK start state",
about every 42 seconds, never reaching the point of requesting wlanmdsp. Three
firmware pairings give three distinct failures, recorded in the doc — the _nm
"no modem" variants, which are the obvious idea and would skip cellular RF
entirely, turn out not to be signed for this device.
The result that narrows it: aarch64-laptops' own wifi directory carries the
qcdsp1v2850.mbn, qcdsp2850.mbn and wlanmdsp.mbn from the setup whose table ticks
WiFi. All three differ from the WOA-Project copies. Installed here with the
services running and wlanmdsp in the TFTP path, they produce the identical QLINK
failure — so it is neither the firmware nor the userspace. What is left is the
kernel: 5.x from 2019 there against 7.1.5 here, with both of their ath10k
patches long since upstream. That points at a regression, and confirming it
means a bisect rather than another file.
Also record what is untried: the other eight driver versions (this machine's
UEFI is from 2019 and the newest package may be the wrong vintage),
mcfg_subsys_ext850.cab, and building board-2.bin from the C630's own bdwlan.*
files.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS
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
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
I had this wrong. The claim that accelerated graphics works on the firmware
Fedora ships does not survive contact with the device tree.
Fedora does package an sdm845/a630_zap.mbn, which is what led me astray, but
that is the generic Snapdragon 845 zap shader. The C630's node in
sdm850-lenovo-yoga-c630.dts names qcom/sdm850/LENOVO/81JL/qcdxkmsuc850.mbn
specifically — model-signed, present only in the machine's Windows partition.
Until it is supplied the display is unaccelerated.
Also add qcslpi850.mbn and qcvss850.mbn, which were missing entirely, and
attribute the sensor hub to slpi_pas rather than cdsp_pas. The list is now
every firmware-name property in the mainline device tree rather than a
recollection of forum posts, so it should be complete: eight files, not five.
WiFi and Bluetooth are unaffected — ath10k WCN3990 including wlanmdsp.mbn is
genuinely redistributable and genuinely shipped.
Add a section on locating the blobs on an old backup, for the case where
Windows is long gone from the machine.
Only comments changed in config/packages/base.pkgs, so the package set hashes
identically and the staged base stays valid.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS
Assembles a ready-to-write disk image via Gitea Actions. Mainline has carried
sdm850-lenovo-yoga-c630.dts since 5.5 and Fedora ships it in kernel-core, so
unlike aarch64-laptops/build there is no kernel or GRUB to compile — what is
left is producing an image that boots on firmware which hands Linux no device
tree.
The build runs in an aarch64 container under qemu-user and builds filesystems
from directory trees with mke2fs -d and mcopy rather than mounting loop
devices, so it works on runners that will not hand out /dev/loop-control.
A kernel-install hook writes the devicetree line into each BLS entry; without
it the first `dnf update kernel` would produce an unbootable system.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS