From f03c0fb249ea8787ae8ec086970eb089109ebf6f Mon Sep 17 00:00:00 2001 From: Ophestra Date: Mon, 30 Mar 2026 21:20:42 +0900 Subject: internal/uevent: synthetic events for coldboot This causes the kernel to regenerate events that happened before earlyinit started. Signed-off-by: Ophestra --- internal/uevent/coldboot.go | 71 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 internal/uevent/coldboot.go (limited to 'internal/uevent/coldboot.go') diff --git a/internal/uevent/coldboot.go b/internal/uevent/coldboot.go new file mode 100644 index 00000000..07f6497f --- /dev/null +++ b/internal/uevent/coldboot.go @@ -0,0 +1,71 @@ +package uevent + +import ( + "context" + "errors" + "io/fs" + "log" + "os" + "path/filepath" +) + +// synthAdd is prepared bytes written to uevent to cause a synthetic add event +// to be emitted during coldboot. +var synthAdd = []byte(KOBJ_ADD.String()) + +// Coldboot writes "add" to every uevent file that it finds in /sys/devices. +// This causes the kernel to regenerate the uevents for these paths. +// +// The specified pathname must present the sysfs root. +// +// Note that while [AOSP documentation] claims to also scan /sys/class and +// /sys/block, this is no longer the case, and the documentation was not updated +// when this changed. +// +// [AOSP documentation]: https://android.googlesource.com/platform/system/core/+/master/init/README.ueventd.md +func Coldboot( + ctx context.Context, + pathname string, + visited chan<- string, + handleWalkErr func(error) error, +) error { + if handleWalkErr == nil { + handleWalkErr = func(err error) error { + if errors.Is(err, fs.ErrNotExist) { + log.Println("coldboot", err) + return nil + } + return err + } + } + + return filepath.WalkDir(filepath.Join(pathname, "devices"), func( + path string, + d fs.DirEntry, + err error, + ) error { + if err != nil { + return handleWalkErr(err) + } + if err = ctx.Err(); err != nil { + return err + } + + if d.IsDir() || d.Name() != "uevent" { + return nil + } + if err = os.WriteFile(path, synthAdd, 0); err != nil { + return handleWalkErr(err) + } + + select { + case visited <- path: + break + + case <-ctx.Done(): + return ctx.Err() + } + + return nil + }) +} -- cgit v1.3.1