Commit Graph

8 Commits

Author SHA1 Message Date
755031ac16 Remove the custom motd, and stop asserting a guess as the cause
Some checks failed
build image / build (push) Has been cancelled
Two problems, one of them mine twice over.

The motd is gone entirely. It had been wrong in a way that mattered — telling
anyone who logged in that onboard WiFi worked when it does not — and a login
banner is a bad place to keep claims that need revising every time we learn
something.

The worse issue is what it and the docs said about why the modem fails. I
inferred from the WOA-Project repository being named "Qualcomm-Reference-
Drivers" that its modem image was a generic reference build unsuited to this
machine's radio, and wrote that up as the explanation. That was a guess resting
on a repository name, and the naming is about redistribution rather than the
contents. Removed from both README and docs/firmware.md.

What is actually established stays: the modem boots, loads mpss, and dies at
"RF stuck in QLINK start state", roughly every 42 seconds. The cause is not
known. The machine has a SIM slot and its modem worked under Windows, so the
radio hardware is present — and the same cabinets supply the GPU, DSP and venus
firmware, all of which work, so whatever is wrong is specific to the modem.
The docs now say that and stop there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS
2026-07-28 08:25:26 +03:00
8fa461a41b docs: record what firmware fixed, and what it turns out not to fix
Some checks failed
build image / build (push) Has been cancelled
The motd was the worst of it — it told anyone logging in that "WiFi and
Bluetooth work with the firmware Fedora ships", which is precisely backwards for
the onboard adapter, and pointed at a Windows partition this machine no longer
has.

What the blobs did fix, verified: the GPU initialises, ADSP/CDSP/SLPI all run,
sensors appear as IIO devices, venus registers /dev/video0-3.

What they did not, and why, so nobody repeats the search:

Onboard WiFi is loaded by the modem — wlan*mdsp* is the WLAN Modem DSP — so
ath10k_snoc binds and then waits silently on a QMI service that never arrives.
The modem boots and dies at "RF stuck in QLINK start state", the RF front-end,
which is board-specific wiring in a way the SoC-level blobs are not. These are
Qualcomm *reference* drivers; good enough for the GPU and DSPs, evidently not
for this machine's radio. Three plausible fixes that do not work are recorded
too: rmtfs (correct to enable, does not help), the _nm firmware variants
(rejected at PBL), and unplugging the USB dongle (different bus entirely — it
was never competing).

Audio gets further than expected. The codec answers over SLIMbus with its chip
id, so hardware and ADSP are fine; what fails is the codec's SoundWire block
declaring two data-in ports where the controller expects six. That is a kernel
mismatch and needs a kernel change.

Also record the mesa caveat properly: the GPU works, but freedreno's EGL path
segfaults gnome-shell into a login loop, and LIBGL_ALWAYS_SOFTWARE does nothing
because mutter uses EGL. MESA_LOADER_DRIVER_OVERRIDE=kms_swrast is what works.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS
2026-07-28 08:24:11 +03:00
3a2fc2a329 docs: record the clock trap, and confirm booting from internal storage
Some checks failed
build image / build (push) Has been cancelled
It boots from the internal drive with the stick removed — 18s to multi-user,
no failed units.

The first thing tried on it was `dnf install net-tools`, which failed with:

    Transaction failed: Rpm transaction failed.
      - systemd is needed by net-tools-2.0-0.77.20160912git.fc44.aarch64

systemd is obviously installed; the machine had just booted. The cause is the
clock. This machine's RTC cannot be set at all — ioctl(RTC_SET_TIME) returns
"No such device" — and reads 1970 every boot, so systemd advances it to its own
build date. That is close enough to look plausible and early enough that rpm
treats package signatures created after it as not yet valid, skips those
headers outright, and reports the packages as absent:

    Signature created at Sat Jul 25 18:33:30 2026 invalid: signature is not alive
    error: rpmdbNextIterator: skipping h# 282
    package systemd is not installed

chrony was already added to base.pkgs for the drift; it turns out to be load
bearing rather than a nicety, and it syncs within about five seconds of the
network appearing. Documented, because the symptom points nowhere near the
cause.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS
2026-07-27 19:35:34 +03:00
f0b2d7846a Add install-to-disk.sh, and get the GPU firmware into the initramfs
Some checks failed
build image / build (push) Has been cancelled
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
2026-07-27 19:23:29 +03:00
482c5d9c9a Label the filesystem for SELinux at build time
All checks were successful
build image / build (push) Successful in 25m5s
The image booted. Kernel came up, the device tree loaded — UFS, display,
WiFi and IPA all probed as platform devices — framebuffer console came up, root
mounted off USB and systemd started. Then:

    systemd[1]: Unable to fix SELinux security context of /dev/tty..: Permission denied
    (x hundreds)
    systemd[1]: Too many messages being logged to kmsg, ignoring
    [!!!!!!] Failed to allocate manager object.

The filesystem had no SELinux labels. mke2fs -d carries security.* xattrs
across faithfully, but nothing had ever set them: the tree came from dnf, not
from a running SELinux system. I had relied on /.autorelabel, which cannot
work here — PID 1 dies long before anything acts on the flag.

Label the tree with setfiles instead, after the bind mounts are torn down (or
it would walk the builder's /proc) and before /boot is split out, so /boot's
files are labelled along with everything else. Verified in a privileged
container beforehand that security.selinux xattrs can actually be written
through a bind mount, rather than assuming it.

I had listed policycoreutils in the gongfoo build base for exactly this and
then never called setfiles. It is now also in stage2's fallback toolchain, so
the stock-Fedora path works too.

Ship permissive regardless. The labels make enforcing viable, but the failure
mode is unusually punishing — no login prompt, no shell, nothing to repair from
— and on a machine this awkward to reach that is not a default worth choosing.
SELINUX_MODE in config/device.env flips it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS
2026-07-27 18:05:28 +03:00
3762f13d8b docs: correct the firmware split — graphics needs a Windows blob too
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
2026-07-27 12:51:01 +03:00
4d1fd98683 Cache the expensive half of the build so iteration is cheap
Some checks failed
build image / prepare (push) Successful in 0s
build image / build (push) Failing after 29s
The dnf transaction is essentially the whole cost of a build — emulated rpm
scriptlets for 502 packages on minimal, 1929 on workstation. Everything after
it is minutes. Getting this laptop to boot will take several attempts at the
kernel command line and the dracut driver list, and paying for a reinstall each
time is not tenable.

Stage the post-dnf tree under <work>/base, keyed on a hash of the package
lists, release and variant, and copy it per build with --reflink=auto (a CoW
clone on btrfs). Config and overlay edits now reuse it; package list edits
invalidate it on their own, so --fresh is only needed to force the issue.

Keep downloaded rpms in a cachedir outside the install root, so even --fresh
re-runs the scriptlets without re-downloading. keepcache=0 was exactly the
wrong setting for a build meant to be run repeatedly.

Add --work so CI can put both outside the job workspace, which is wiped between
runs, and default the build container to the gongfoo aarch64 build base so the
assembly tooling is not installed under emulation every time. That image is a
speedup, not a dependency: fall back to stock Fedora when it is unreachable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS
2026-07-27 11:58:12 +03:00
280874f564 Build Fedora aarch64 images for the Lenovo Yoga C630
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
2026-07-27 11:24:53 +03:00