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 }) }