package uboot import ( "context" "errors" "fmt" "os" "path/filepath" "strings" monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1" "example.com/monok8s/pkg/controller/osimage" "example.com/monok8s/pkg/node" ) func ConfigureABBoot(ctx context.Context, nctx *node.NodeContext) error { exePath, err := os.Executable() if err != nil { return fmt.Errorf("get current executable path: %w", err) } doWrite := false writer := NewFWEnvWriter(HostFWEnvCfgPath, exePath) bootPart, err := writer.GetEnv(ctx, "boot_part") if err != nil { if errors.Is(err, ErrEnvNotFound) { state, err := osimage.ReadBootState() if err != nil { return fmt.Errorf("read boot state: %w", err) } bootPart := state["BOOT_PART"] if bootPart == "" { return fmt.Errorf("BOOT_PART missing") } doWrite = true } else { return fmt.Errorf("get boot_part: %w", err) } } bootSource, err := writer.GetEnv(ctx, "boot_source") if err != nil { if errors.Is(err, ErrEnvNotFound) { target, err := os.Readlink(monov1alpha1.AltPartDeviceLink) if err != nil { return fmt.Errorf("readlink %q: %w", monov1alpha1.AltPartDeviceLink, err) } if !filepath.IsAbs(target) { target = filepath.Join(filepath.Dir(monov1alpha1.AltPartDeviceLink), target) } resolved, err := filepath.EvalSymlinks(target) if err != nil { return fmt.Errorf("resolve %q: %w", target, err) } base := filepath.Base(resolved) if strings.HasPrefix(base, "mmcblk") { bootSource = "emmc" } else { bootSource = "usb" } doWrite = true } else { return fmt.Errorf("get boot_source: %w", err) } } if doWrite { return writer.EnsureBootEnv(ctx, BootEnvConfig{ BootSource: bootSource, BootPart: bootPart, }) } return nil } // This is called by the agent controller/osupgrade/handler.go func ConfigureNextBoot(ctx context.Context, fwEnvCfgPath string) error { exePath, err := os.Executable() if err != nil { return fmt.Errorf("get current executable path: %w", err) } writer := NewFWEnvWriter(fwEnvCfgPath, exePath) currBootPart, err := writer.GetEnv(ctx, "boot_part") if err != nil { return fmt.Errorf("get boot_part: %w", err) } next := "A" if currBootPart == "A" { next = "B" } currBootSource, err := writer.GetEnv(ctx, "boot_source") if err != nil { return fmt.Errorf("get boot_source: %w", err) } return writer.EnsureBootEnv(ctx, BootEnvConfig{ BootSource: currBootSource, BootPart: next, }) }