kernel: microcode in every initramfs through mkinitcpio's microcode hook (issue 1977)

Declares amd-ucode and intel-ucode, the drop-in /etc/mkinitcpio.conf.d/mesh-microcode.conf, the
initramfs script and mesh-kernel-initramfs.service; kernel_boot answers the running revision and
whether the images were built with the drop-in. Tests: 1977/AC1-AC5.

Builds: L1, L2, L3, L4, L5 (issue 1977 note 2)
This commit is contained in:
2026-11-12 20:52:21 +01:00
parent a60728e6f0
commit 5795f4d230
9 changed files with 303 additions and 8 deletions
+25
View File
@@ -23,6 +23,30 @@ type BootState struct {
Booted string `json:"booted"`
FallbackPresent bool `json:"fallback_present"`
BootFreeKiB int64 `json:"boot_free_kib"`
// MicrocodeRevision is the revision the CPU runs, the first "microcode" line of /proc/cpuinfo ("" when it has none).
MicrocodeRevision string `json:"microcode_revision"`
// ImagesBuiltWithMicrocode is true when the initramfs images were last built with the microcode drop-in as it is now
// (novox/hq issue 1977).
ImagesBuiltWithMicrocode bool `json:"images_built_with_microcode"`
}
// stateDir is the module's own directory on the machine, where the initramfs script records the drop-in it built with.
const stateDir = "var/lib/mesh-kernel"
const microcodeDropIn = "etc/mkinitcpio.conf.d/mesh-microcode.conf"
var cpuMicrocode = regexp.MustCompile(`(?m)^microcode\s*:\s*(\S+)`)
// microcode reads the revision the CPU runs and whether the images carry the drop-in as it is now.
func (m *Machine) microcode(b *BootState) {
if raw, err := m.read("proc/cpuinfo"); err == nil {
if r := cpuMicrocode.FindStringSubmatch(raw); r != nil {
b.MicrocodeRevision = r[1]
}
}
built, err := m.read(stateDir + "/initramfs-built")
now, err2 := m.read(microcodeDropIn)
b.ImagesBuiltWithMicrocode = err == nil && err2 == nil && built == now
}
var grubKernel = regexp.MustCompile(`(?m)^\s*linux\s+(?:/boot)?/(vmlinuz-\S+)`)
@@ -33,6 +57,7 @@ var bootImage = regexp.MustCompile(`BOOT_IMAGE=(?:/boot)?/?(\S+)`)
// systemd-boot, a grub.cfg without it GRUB.
func (m *Machine) Boot() (*BootState, error) {
b := &BootState{Loader: "none", Entries: []string{}, Kernels: []string{}}
m.microcode(b)
files, _ := filepath.Glob(m.path("boot/vmlinuz-*"))
for _, f := range files {
b.Kernels = append(b.Kernels, filepath.Base(f))
+2 -1
View File
@@ -51,7 +51,8 @@ func tools(m *Machine) []stdio.Tool {
Description: "How this machine boots and whether the fallback kernel is on its menu (novox/hq ADR 0508 §9): the loader that booted it " +
"(systemd-boot, read from the EFI variable it sets, grub, or none), the menu's entries, the kernels in /boot, the entry " +
"the machine booted (systemd-boot) or the kernel image it booted (grub), whether the fallback kernel linux-lts is on " +
"the menu with its kernel in /boot, and the room free on /boot in KiB (the fallback kernel needs about 72 MB). " +
"the menu with its kernel in /boot, and the room free on /boot in KiB (the fallback kernel needs about 72 MB), the microcode revision the CPU runs " +
"(/proc/cpuinfo) and whether the initramfs images were built with the microcode drop-in (novox/hq issue 1977). " +
"Replaces ls /boot, bootctl list, reading grub.cfg and df /boot. (r)",
Input: schema(map[string]any{}),
Run: func(args map[string]any) (any, error) { return m.Boot() },
@@ -24,7 +24,7 @@ func TestTheDefaultIsMadviseAndTheUnitFollowsTheSetting(t *testing.T) {
for _, r := range m.Resources {
ids = append(ids, r["id"].(string))
}
if strings.Join(ids, " ") != "state huge-pages unit apply boot-entries boot-unit boot-hook boot-apply linux-lts linux-lts-headers modules-load modules-keep modules-cleanup" {
if strings.Join(ids, " ") != "state huge-pages unit apply boot-entries boot-unit boot-hook boot-apply linux-lts linux-lts-headers modules-load modules-keep modules-cleanup amd-ucode intel-ucode microcode-hook initramfs initramfs-unit initramfs-apply" {
t.Fatalf("order: %v", ids)
}
script := m.resource(t, "huge-pages")
@@ -0,0 +1,137 @@
package main
// Microcode in every initramfs (novox/hq issue 1977, lead answers L1-L4): the manifest, the drop-in sourced by bash,
// the initramfs script run with sh over stand-in files and a stand-in mkinitcpio, and kernel_boot's answer.
import (
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
// 1977/AC1
func TestAC1TheManifestDeclaresTheMicrocodePackagesDropInScriptAndService(t *testing.T) {
m := manifest(t)
var ids []string
for _, r := range m.Resources {
ids = append(ids, r["id"].(string))
}
if !strings.HasSuffix(strings.Join(ids, " "), "modules-cleanup amd-ucode intel-ucode microcode-hook initramfs initramfs-unit initramfs-apply") {
t.Fatalf("order: %v", ids)
}
for id, pkg := range map[string]string{"amd-ucode": "amd-ucode", "intel-ucode": "intel-ucode"} {
if r := m.resource(t, id); r["type"] != "package" || r["package"] != pkg {
t.Fatalf("%s: %v", id, r)
}
}
if r := m.resource(t, "microcode-hook"); r["path"] != "/etc/mkinitcpio.conf.d/mesh-microcode.conf" {
t.Fatalf("drop-in: %v", r)
}
if r := m.resource(t, "initramfs"); r["path"] != "${dir:state}/initramfs" || r["mode"] != "0755" || r["trusted"] != true {
t.Fatalf("script: %v", r)
}
if r := m.resource(t, "initramfs-unit"); r["path"] != "/etc/systemd/system/mesh-kernel-initramfs.service" {
t.Fatalf("unit: %v", r)
}
a := m.resource(t, "initramfs-apply")
on := a["restart-on"].([]any)
if a["unit"] != "mesh-kernel-initramfs.service" || a["state"] != "running" || a["boot"] != "enabled" ||
len(on) != 3 || on[0] != "initramfs-unit" || on[1] != "initramfs" || on[2] != "microcode-hook" {
t.Fatalf("service: %v", a)
}
}
// 1977/AC2
func TestAC2TheDropInAddsMicrocodeToHooksOnce(t *testing.T) {
drop := filepath.Join(t.TempDir(), "mesh-microcode.conf")
write(t, drop, manifest(t).resource(t, "microcode-hook").text(t), 0o644)
for _, c := range []struct{ hooks, want string }{
{"base udev autodetect modconf block filesystems keyboard fsck", "base udev autodetect modconf block filesystems keyboard fsck microcode"},
{"base udev autodetect microcode block", "base udev autodetect microcode block"},
} {
out, err := exec.Command("bash", "-c", "HOOKS=("+c.hooks+"); . "+drop+"; echo \"${HOOKS[*]}\"").CombinedOutput()
if err != nil || strings.TrimSpace(string(out)) != c.want {
t.Errorf("%q: %v %q", c.hooks, err, out)
}
}
}
type initBed struct{ script, dropin, state, runs, bin string }
func newInitBed(t *testing.T, mkinitcpioExit string) initBed {
t.Helper()
dir := t.TempDir()
b := initBed{script: filepath.Join(dir, "initramfs"), dropin: filepath.Join(dir, "mesh-microcode.conf"), state: filepath.Join(dir, "state"),
runs: filepath.Join(dir, "runs"), bin: filepath.Join(dir, "bin")}
for _, d := range []string{b.state, b.bin} {
if err := os.MkdirAll(d, 0o755); err != nil {
t.Fatal(err)
}
}
content := strings.ReplaceAll(manifest(t).resource(t, "initramfs").text(t), "${dir:state}", b.state)
if strings.Contains(content, "${dir") {
t.Fatal("a substitution is left in the script")
}
write(t, b.script, content, 0o755)
write(t, b.dropin, "HOOKS+=(microcode)\n", 0o644)
write(t, filepath.Join(b.bin, "mkinitcpio"), "#!/bin/sh\necho \"$@\" >>"+b.runs+"\nexit "+mkinitcpioExit+"\n", 0o755)
return b
}
func (b initBed) run(t *testing.T) (string, error) {
cmd := exec.Command("sh", b.script, "apply", b.dropin, b.state)
cmd.Env = append(os.Environ(), "PATH="+b.bin+string(os.PathListSeparator)+os.Getenv("PATH"))
out, err := cmd.CombinedOutput()
return string(out), err
}
func (b initBed) builds(t *testing.T) string {
raw, _ := os.ReadFile(b.runs)
return string(raw)
}
// 1977/AC3
func TestAC3TheImagesAreBuiltOnceAndAgainWhenTheDropInChanges(t *testing.T) {
b := newInitBed(t, "0")
if out, err := b.run(t); err != nil || b.builds(t) != "-P\n" {
t.Fatalf("first: %v %s %q", err, out, b.builds(t))
}
if raw, _ := os.ReadFile(filepath.Join(b.state, "initramfs-built")); string(raw) != "HOOKS+=(microcode)\n" {
t.Fatalf("recorded: %q", raw)
}
if out, err := b.run(t); err != nil || !strings.Contains(out, "as it was") || b.builds(t) != "-P\n" {
t.Fatalf("again: %v %s %q", err, out, b.builds(t))
}
write(t, b.dropin, "HOOKS+=(microcode)\n# new\n", 0o644)
if _, err := b.run(t); err != nil || b.builds(t) != "-P\n-P\n" {
t.Fatalf("changed: %v %q", err, b.builds(t))
}
}
// 1977/AC4
func TestAC4AFailedMkinitcpioFailsTheUnitAndRecordsNothing(t *testing.T) {
b := newInitBed(t, "1")
out, err := b.run(t)
if err == nil || !strings.Contains(out, "mkinitcpio failed") {
t.Fatalf("%v %s", err, out)
}
if _, err := os.Stat(filepath.Join(b.state, "initramfs-built")); !os.IsNotExist(err) {
t.Fatalf("recorded after a failure: %v", err)
}
}
// 1977/AC5
func TestAC5KernelBootNamesTheRunningMicrocodeAndWhetherTheImagesCarryTheDropIn(t *testing.T) {
root := t.TempDir()
put(t, root, "proc/cpuinfo", "processor\t: 0\nmicrocode\t: 0x0a201016\nmodel name\t: x\n")
put(t, root, "etc/mkinitcpio.conf.d/mesh-microcode.conf", "HOOKS+=(microcode)\n")
if got := bootOf(t, root); got.MicrocodeRevision != "0x0a201016" || got.ImagesBuiltWithMicrocode {
t.Fatalf("no record: %+v", got)
}
put(t, root, "var/lib/mesh-kernel/initramfs-built", "HOOKS+=(microcode)\n")
if got := bootOf(t, root); got.MicrocodeRevision != "0x0a201016" || !got.ImagesBuiltWithMicrocode {
t.Fatalf("recorded: %+v", got)
}
}