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
This commit is contained in:
2026-07-27 19:23:29 +03:00
parent 482c5d9c9a
commit f0b2d7846a
6 changed files with 334 additions and 31 deletions

View File

@@ -49,36 +49,41 @@ See [firmware.md](firmware.md) if it cannot find the Windows partition.
## Installing to internal storage
Once the USB image is behaving, copy it onto the internal UFS.
Once the USB image is behaving, copy it onto the internal UFS. Boot from the
USB stick and run, on the laptop:
Shrink the Windows partition from within Windows (**Disk Management → Shrink
Volume**) rather than from Linux — Windows is fussy about its own filesystem
being moved underneath it.
Then, booted from USB, write the image to the free space. The simplest approach
that keeps Windows intact is to create the partitions by hand and copy the
filesystems across rather than `dd`-ing the whole image, since `dd` would
overwrite the existing GPT and the Windows ESP:
1. `sudo gdisk /dev/sda` — add a `/boot` partition (1 GiB, type 8300) and a root
partition (type 8300) in the free space. Keep the existing Windows ESP.
2. `mkfs.ext4 -O ^orphan_file,^metadata_csum_seed /dev/sdaN` for both.
3. Copy the running system across with `rsync -aHAX --exclude=/dev --exclude=/proc
--exclude=/sys --exclude=/run --exclude=/boot`, then `/boot` separately.
4. Copy `EFI/fedora` from the USB stick's ESP onto the Windows ESP, and edit
`EFI/fedora/grub.cfg` so the `--fs-uuid` matches the new `/boot`.
5. Update `/etc/fstab` and the `root=UUID=` in
`/boot/loader/entries/c630-*.conf` to the new UUIDs.
Finally, point the firmware at GRUB from an Administrator command prompt in
Windows:
```
bcdedit /set {bootmgr} path \EFI\fedora\grubaa64.efi
```sh
sudo ./build/install-to-disk.sh --dry-run # show the plan, touch nothing
sudo ./build/install-to-disk.sh # do it
```
Windows resets this on some updates. To get back, boot the USB stick and run it
again, or use `efibootmgr` from Linux.
It partitions the disk, copies the running system across, and rewrites every
UUID that has to change. Reboot afterwards and pick the internal drive from the
boot menu (**Fn+F12**), or just pull the stick out.
**This wipes the target disk.** If you still have Windows and want to keep it,
do not run this — shrink the Windows partition from within Windows first and
adapt the steps by hand.
Two things about this machine make the obvious approaches fail, both of which
the script handles:
**You cannot `dd` the image onto the internal drive.** The UFS reports
**4096-byte logical sectors**; the disk image is built with 512-byte sector
geometry. Its GPT header and every partition offset would land in the wrong
place. The disk has to be partitioned on the machine, at its own sector size.
**`efibootmgr` does not work here.** There are no EFI runtime variables —
`efibootmgr` reports *"EFI variables are not supported on this system"* — so
nothing can register a boot entry. GRUB therefore goes at the removable-media
path, `EFI/BOOT/BOOTAA64.EFI`, where the firmware finds it unprompted.
If you would rather do it by hand, the sequence is: `sgdisk` an ESP, a `/boot`
and a root partition; `mkfs.vfat` and `mkfs.ext4 -O
^orphan_file,^metadata_csum_seed`; copy `/`, `/boot` and the ESP separately
(preserving xattrs, or SELinux labels are lost); then update `/etc/fstab`,
`/etc/kernel/cmdline`, `root=UUID=` in `/boot/loader/entries/*.conf`, and the
`--fs-uuid` in both `/boot/grub2/grub.cfg` and `EFI/fedora/grub.cfg`.
## If it does not boot