deploy-kernel.sh never installs modules, so modprobe cannot work #54

Closed
opened 2026-08-29 13:31:40 +00:00 by tiagoagueda · 1 comment
Owner

modprobe cannot work on this board. /lib/modules holds directories for two kernels that are no longer running:

/lib/modules/7.2.0-g45c13f3f9e3b-dirty
/lib/modules/7.2.0-g747bd0902650-dirty

and none for the running one. Confirmed:

# modprobe zram
modprobe: FATAL: Module zram not found in directory /lib/modules/7.2.0-...
# find /lib/modules/$(uname -r) -name '*.ko*' | wc -l
0

Cause

deploy-kernel.sh builds and installs uImage and the dtb and nothing else. It never runs make modules_install, and never has.

Why nothing has noticed

Everything this board needs is built into the kernel. That is also why CONFIG_ZRAM was added as =y rather than =m in #13 — =m would simply not have loaded.

The one visible symptom is a warning on every initramfs build:

W: missing /lib/modules/7.2.0-14857-g0a8c6926d04f
W: Ensure all necessary drivers are built into the linux image!
depmod: ERROR: could not open directory /lib/modules/...

/boot/config-$(uname -r) is missing too, so update-initramfs cannot check compression support and assumes it.

Why it matters anyway

  1. provision.sh cannot honestly claim to rebuild this system (#8). It says so at the end of every run.
  2. Every future driver decision is silently constrained to =y. Nobody chose that, and nobody is reminded of it at the moment they are editing a defconfig.
  3. The ad-hoc probe modules this project relies on (probe/*.c, insmoded directly) work only because they bypass /lib/modules entirely. That is luck, not design.
  4. The stale directories are actively misleading: ls /lib/modules suggests modules are managed here.

Done when

  • deploy-kernel.sh installs modules and /boot/config-$(uname -r) alongside the kernel, md5-verified like the rest
  • sync-rescue-sd.sh propagates them to the card, which currently builds its initramfs with the same warnings
  • the two stale /lib/modules directories are removed
  • update-initramfs runs clean on both media
`modprobe` cannot work on this board. `/lib/modules` holds directories for two kernels that are no longer running: ``` /lib/modules/7.2.0-g45c13f3f9e3b-dirty /lib/modules/7.2.0-g747bd0902650-dirty ``` and none for the running one. Confirmed: ``` # modprobe zram modprobe: FATAL: Module zram not found in directory /lib/modules/7.2.0-... # find /lib/modules/$(uname -r) -name '*.ko*' | wc -l 0 ``` ## Cause `deploy-kernel.sh` builds and installs `uImage` and the dtb and nothing else. It never runs `make modules_install`, and never has. ## Why nothing has noticed Everything this board needs is built into the kernel. That is also why `CONFIG_ZRAM` was added as `=y` rather than `=m` in #13 — `=m` would simply not have loaded. The one visible symptom is a warning on every initramfs build: ``` W: missing /lib/modules/7.2.0-14857-g0a8c6926d04f W: Ensure all necessary drivers are built into the linux image! depmod: ERROR: could not open directory /lib/modules/... ``` `/boot/config-$(uname -r)` is missing too, so `update-initramfs` cannot check compression support and assumes it. ## Why it matters anyway 1. **`provision.sh` cannot honestly claim to rebuild this system** (#8). It says so at the end of every run. 2. Every future driver decision is silently constrained to `=y`. Nobody chose that, and nobody is reminded of it at the moment they are editing a defconfig. 3. The ad-hoc probe modules this project relies on (`probe/*.c`, `insmod`ed directly) work only because they bypass `/lib/modules` entirely. That is luck, not design. 4. The stale directories are actively misleading: `ls /lib/modules` suggests modules are managed here. ## Done when - [x] `deploy-kernel.sh` installs modules and `/boot/config-$(uname -r)` alongside the kernel, md5-verified like the rest - [x] `sync-rescue-sd.sh` propagates them to the card, which currently builds its initramfs with the same warnings - [x] the two stale `/lib/modules` directories are removed - [x] `update-initramfs` runs clean on both media
Author
Owner

Done — and installing the modules broke two other things on the way

deploy-kernel.sh now builds and installs the module tree and /boot/config-$(uname -r), both md5-verified end to end like the kernel and dtb, and sync-rescue-sd.sh carries them to the card.

Both orphaned trees were pruned on the first run, by a rule rather than by hand: a module tree whose version appears in no image in /boot can never be loaded, so it goes. That is what stops this recurring — and it is why the problem was invisible in the first place, since ls /lib/modules looked managed.

The script itself was never in the repo. It lived only at ~/a80/deploy-kernel.sh on the build host while five files here referenced it. Now tracked at tools/deploy-kernel.sh.

>> modules installed: 1 .ko, 408K
>> pruned orphaned module tree 7.2.0-g45c13f3f9e3b-dirty (no image in /boot uses it)
>> pruned orphaned module tree 7.2.0-g747bd0902650-dirty (no image in /boot uses it)

Only CONFIG_DMATEST=m comes out of this config, so barely any .ko was being lost. What was being lost is modules.builtin, modules.order, modules.alias and modules.builtin.modinfo — which is why depmod failed and update-initramfs warned every run.

The part worth reading: fixing this broke the initramfs, then broke wifi

With modules.builtin.modinfo finally present, initramfs-tools can enumerate built-in drivers' firmware — so it began copying regulatory.db itself, resolved through /etc/alternatives, which on Debian is the Debian-signed variant.

First failure. copy_file returns 1 when the target already exists. As the last statement in hook-draco-firmware that became the hook's exit status:

E: /etc/initramfs-tools/hooks/draco-firmware failed with return 1.
update-initramfs: failed for /boot/initrd.img-... with 1.

The board could no longer regenerate its initramfs at all.

Second failure, caused by my first fix. Adding || true made it worse, and silently. copy_file does not overwrite, so the hook simply stopped installing the upstream-signed regulatory.db. This kernel is built with CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS and carries only the upstream key, so at boot:

cfg80211: loaded regulatory.db is malformed or signature is missing/invalid
iw reg get -> country 00: DFS-UNSET     (was country FR: DFS-ETSI)

Every 5 GHz band back to passive-scan — precisely the fault this hook exists to prevent, reintroduced by fixing something unrelated. || true turned a loud failure into a quiet wrong answer, which is the worse of the two.

The hook now writes into $DESTDIR directly instead of asking copy_file to, so the upstream signature wins regardless of what copied first.

Verified, by content rather than inference

  • eMMC and card initramfs each carry the upstream .p7s (1ab34236cbd7, not the Debian db6cb32aaaa5) and sun9i-a80-arisc.bin
  • modprobe dmatest loads on both
  • update-initramfs runs clean on both
  • after reboot the card reports 0 malformed-signature errors and country FR: DFS-ETSI
  • /lib/modules on both holds exactly one tree, matching the running kernel

One caveat stated rather than glossed: the eMMC's own initramfs was verified by extracting and comparing signatures, not by booting it. Every reboot in this session used the card's emmc entry, which loads the card's initrd. Confirming the eMMC end to end needs the card physically removed.

Done when

  • deploy-kernel.sh installs modules and /boot/config-$(uname -r), md5-verified
  • sync-rescue-sd.sh propagates them to the card
  • the two stale /lib/modules directories are removed
  • update-initramfs runs clean on both media
## Done — and installing the modules broke two other things on the way `deploy-kernel.sh` now builds and installs the module tree and `/boot/config-$(uname -r)`, both md5-verified end to end like the kernel and dtb, and `sync-rescue-sd.sh` carries them to the card. Both orphaned trees were pruned on the first run, by a rule rather than by hand: **a module tree whose version appears in no image in `/boot` can never be loaded**, so it goes. That is what stops this recurring — and it is why the problem was invisible in the first place, since `ls /lib/modules` looked managed. The script itself was never in the repo. It lived only at `~/a80/deploy-kernel.sh` on the build host while five files here referenced it. Now tracked at `tools/deploy-kernel.sh`. ``` >> modules installed: 1 .ko, 408K >> pruned orphaned module tree 7.2.0-g45c13f3f9e3b-dirty (no image in /boot uses it) >> pruned orphaned module tree 7.2.0-g747bd0902650-dirty (no image in /boot uses it) ``` Only `CONFIG_DMATEST=m` comes out of this config, so barely any `.ko` was being lost. What was being lost is `modules.builtin`, `modules.order`, `modules.alias` and `modules.builtin.modinfo` — which is why `depmod` failed and `update-initramfs` warned every run. ## The part worth reading: fixing this broke the initramfs, then broke wifi With `modules.builtin.modinfo` finally present, initramfs-tools can enumerate built-in drivers' firmware — so it began copying `regulatory.db` **itself**, resolved through `/etc/alternatives`, which on Debian is the **Debian-signed** variant. **First failure.** `copy_file` returns 1 when the target already exists. As the last statement in `hook-draco-firmware` that became the hook's exit status: ``` E: /etc/initramfs-tools/hooks/draco-firmware failed with return 1. update-initramfs: failed for /boot/initrd.img-... with 1. ``` The board could no longer regenerate its initramfs at all. **Second failure, caused by my first fix.** Adding `|| true` made it *worse*, and silently. `copy_file` does not overwrite, so the hook simply stopped installing the upstream-signed `regulatory.db`. This kernel is built with `CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS` and carries only the upstream key, so at boot: ``` cfg80211: loaded regulatory.db is malformed or signature is missing/invalid iw reg get -> country 00: DFS-UNSET (was country FR: DFS-ETSI) ``` Every 5 GHz band back to passive-scan — precisely the fault this hook exists to prevent, reintroduced by fixing something unrelated. `|| true` turned a loud failure into a quiet wrong answer, which is the worse of the two. The hook now writes into `$DESTDIR` directly instead of asking `copy_file` to, so the upstream signature wins regardless of what copied first. ## Verified, by content rather than inference - **eMMC and card** initramfs each carry the upstream `.p7s` (`1ab34236cbd7`, not the Debian `db6cb32aaaa5`) and `sun9i-a80-arisc.bin` - `modprobe dmatest` loads on both - `update-initramfs` runs clean on both - after reboot the card reports **0** malformed-signature errors and `country FR: DFS-ETSI` - `/lib/modules` on both holds exactly one tree, matching the running kernel One caveat stated rather than glossed: the eMMC's *own* initramfs was verified by extracting and comparing signatures, not by booting it. Every reboot in this session used the card's `emmc` entry, which loads the **card's** initrd. Confirming the eMMC end to end needs the card physically removed. ## Done when - [x] `deploy-kernel.sh` installs modules and `/boot/config-$(uname -r)`, md5-verified - [x] `sync-rescue-sd.sh` propagates them to the card - [x] the two stale `/lib/modules` directories are removed - [x] `update-initramfs` runs clean on both media
Sign in to join this conversation.
No description provided.