m/p/efivarfs: add boot settings manipulation routines
This adds CreateBootEntry and SetBootOrder.
Both functions can be used to adjust EFI boot settings by writing to
EFI variable files exposed through efivarfs.
Change-Id: I0b1364357bcf1e8dabf24ef4046861924306e029
Reviewed-on: https://review.monogon.dev/c/monogon/+/436
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/metropolis/pkg/efivarfs/efivarfs.go b/metropolis/pkg/efivarfs/efivarfs.go
index 0287fc9..fc6100e 100644
--- a/metropolis/pkg/efivarfs/efivarfs.go
+++ b/metropolis/pkg/efivarfs/efivarfs.go
@@ -23,6 +23,7 @@
"bytes"
"fmt"
"io/ioutil"
+ "os"
"path/filepath"
"strings"
@@ -73,3 +74,42 @@
}
return strings.ToLower(contents), nil
}
+
+// CreateBootEntry creates an EFI boot entry variable and returns its
+// non-negative index on success. It may return an io error.
+func CreateBootEntry(be *BootEntry) (int, error) {
+ // Find the index by looking up the first empty slot.
+ var ep string
+ var n int
+ for ; ; n++ {
+ en := fmt.Sprintf("Boot%04x-%s", n, GlobalGuid)
+ ep = filepath.Join(Path, en)
+ _, err := os.Stat(ep)
+ if os.IsNotExist(err) {
+ break
+ }
+ if err != nil {
+ return -1, err
+ }
+ }
+
+ // Create the boot variable.
+ bem, err := be.Marshal()
+ if err != nil {
+ return -1, fmt.Errorf("while marshaling the EFI boot entry: %w", err)
+ }
+ if err := ioutil.WriteFile(ep, bem, 0644); err != nil {
+ return -1, fmt.Errorf("while creating a boot entry variable: %w", err)
+ }
+ return n, nil
+}
+
+// SetBootOrder replaces contents of the boot order variable with the order
+// specified in ord. It may return an io error.
+func SetBootOrder(ord *BootOrder) error {
+ op := filepath.Join(Path, fmt.Sprintf("BootOrder-%s", GlobalGuid))
+ if err := ioutil.WriteFile(op, ord.Marshal(), 0644); err != nil {
+ return fmt.Errorf("while creating a boot order variable: %w", err)
+ }
+ return nil
+}