diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-03-30 21:20:42 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-03-30 23:01:08 +0900 |
| commit | f03c0fb249ea8787ae8ec086970eb089109ebf6f (patch) | |
| tree | 5e89ba203112c5e3ca984da96b9dc60be19ade2a /internal/uevent/coldboot.go | |
| parent | a6600be34ad812ff13c89f45c3cadaac6d994e67 (diff) | |
internal/uevent: synthetic events for coldboot
This causes the kernel to regenerate events that happened before earlyinit started.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/uevent/coldboot.go')
| -rw-r--r-- | internal/uevent/coldboot.go | 71 |
1 files changed, 71 insertions, 0 deletions
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 + }) +} |
