treewide: use architecture-specific UEFI boot path
The default UEFI boot path depends on the architecture. This change is
needed for aarch64 support.
Change-Id: I69916ac5063e963b67ecdcdd814b0678c61da9fb
Reviewed-on: https://review.monogon.dev/c/monogon/+/4195
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/cli/metroctl/core/BUILD.bazel b/metropolis/cli/metroctl/core/BUILD.bazel
index cd95ac1..d785fad 100644
--- a/metropolis/cli/metroctl/core/BUILD.bazel
+++ b/metropolis/cli/metroctl/core/BUILD.bazel
@@ -19,9 +19,11 @@
"//metropolis/node/core/rpc/resolver",
"//metropolis/proto/api",
"//osbase/blockdev",
+ "//osbase/build/mkimage/osimage",
"//osbase/fat32",
"//osbase/gpt",
"//osbase/oci",
+ "//osbase/oci/osimage",
"//osbase/structfs",
"@io_k8s_client_go//pkg/apis/clientauthentication/v1:clientauthentication",
"@io_k8s_client_go//tools/clientcmd",
diff --git a/metropolis/cli/metroctl/core/install.go b/metropolis/cli/metroctl/core/install.go
index 92e8303..0927ba1 100644
--- a/metropolis/cli/metroctl/core/install.go
+++ b/metropolis/cli/metroctl/core/install.go
@@ -13,9 +13,11 @@
"source.monogon.dev/metropolis/proto/api"
"source.monogon.dev/osbase/blockdev"
+ "source.monogon.dev/osbase/build/mkimage/osimage"
"source.monogon.dev/osbase/fat32"
"source.monogon.dev/osbase/gpt"
"source.monogon.dev/osbase/oci"
+ ociosimage "source.monogon.dev/osbase/oci/osimage"
"source.monogon.dev/osbase/structfs"
)
@@ -29,7 +31,7 @@
// Optional NodeParameters to be embedded for use by the installer.
NodeParams *api.NodeParameters
- // Optional OS image for use by the installer.
+ // OS image for use by the installer.
Image *oci.Image
}
@@ -41,12 +43,18 @@
return errors.New("installer is mandatory")
}
+ osImage, err := ociosimage.Read(args.Image)
+ if err != nil {
+ return fmt.Errorf("failed to read OS image: %w", err)
+ }
+ bootPath, err := osimage.EFIBootPath(osImage.Config.ProductInfo.Architecture())
+ if err != nil {
+ return err
+ }
+
var espRoot structfs.Tree
- // This needs to be a "Removable Media" according to the UEFI Specification
- // V2.9 Section 3.5.1.1. This file is booted by any compliant UEFI firmware
- // in absence of another bootable boot entry.
- if err := espRoot.PlaceFile("EFI/BOOT/BOOTx64.EFI", args.Installer); err != nil {
+ if err := espRoot.PlaceFile(bootPath, args.Installer); err != nil {
return err
}
@@ -59,17 +67,14 @@
return err
}
}
- if args.Image != nil {
- imageLayout, err := oci.CreateLayout(args.Image)
- if err != nil {
- return err
- }
- if err := espRoot.PlaceDir("metropolis-installer/osimage", imageLayout); err != nil {
- return err
- }
+ imageLayout, err := oci.CreateLayout(args.Image)
+ if err != nil {
+ return err
+ }
+ if err := espRoot.PlaceDir("metropolis-installer/osimage", imageLayout); err != nil {
+ return err
}
var targetDev blockdev.BlockDev
- var err error
targetDev, err = blockdev.Open(args.TargetPath)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
diff --git a/metropolis/cli/takeover/install.go b/metropolis/cli/takeover/install.go
index 1bd00e6..37068ed 100644
--- a/metropolis/cli/takeover/install.go
+++ b/metropolis/cli/takeover/install.go
@@ -88,6 +88,7 @@
System: 4096,
Data: 128,
},
+ Architecture: osImage.Config.ProductInfo.Architecture(),
SystemImage: systemImage,
EFIPayload: efiPayload,
ABLoader: structfs.Bytes(abloader),
diff --git a/metropolis/installer/main.go b/metropolis/installer/main.go
index baf9cc8..20a8240 100644
--- a/metropolis/installer/main.go
+++ b/metropolis/installer/main.go
@@ -186,6 +186,7 @@
// whenever it's writing to block devices, such as now.
Data: 128,
},
+ Architecture: osImage.Config.ProductInfo.Architecture(),
SystemImage: systemImage,
EFIPayload: efiPayload,
ABLoader: structfs.Bytes(abloader),
diff --git a/metropolis/installer/test/BUILD.bazel b/metropolis/installer/test/BUILD.bazel
index 903f46e..d68f78a 100644
--- a/metropolis/installer/test/BUILD.bazel
+++ b/metropolis/installer/test/BUILD.bazel
@@ -25,6 +25,7 @@
"//osbase/build/mkimage/osimage",
"//osbase/cmd",
"//osbase/oci",
+ "//osbase/oci/osimage",
"//osbase/structfs",
"@com_github_diskfs_go_diskfs//:go-diskfs",
"@com_github_diskfs_go_diskfs//disk",
diff --git a/metropolis/installer/test/run_test.go b/metropolis/installer/test/run_test.go
index 5008be0..bba323f 100644
--- a/metropolis/installer/test/run_test.go
+++ b/metropolis/installer/test/run_test.go
@@ -27,6 +27,7 @@
"source.monogon.dev/osbase/build/mkimage/osimage"
"source.monogon.dev/osbase/cmd"
"source.monogon.dev/osbase/oci"
+ ociosimage "source.monogon.dev/osbase/oci/osimage"
"source.monogon.dev/osbase/structfs"
)
@@ -59,6 +60,7 @@
// installerImage is a filesystem path pointing at the installer image that
// is generated during the test, and is removed afterwards.
installerImage string
+ bootPath string
)
// runQemu starts a new QEMU process, expecting the given output to appear
@@ -124,9 +126,9 @@
return fmt.Errorf("couldn't read the installer ESP: %w", err)
}
// Make sure the EFI payload exists by attempting to open it.
- efiPayload, err := fs.OpenFile("/"+osimage.EFIPayloadPath, os.O_RDONLY)
+ efiPayload, err := fs.OpenFile("/"+bootPath, os.O_RDONLY)
if err != nil {
- return fmt.Errorf("couldn't open the installer's EFI Payload at %q: %w", osimage.EFIPayloadPath, err)
+ return fmt.Errorf("couldn't open the installer's EFI Payload at %q: %w", bootPath, err)
}
efiPayload.Close()
return nil
@@ -145,6 +147,15 @@
log.Fatal(err)
}
+ osImage, err := ociosimage.Read(image)
+ if err != nil {
+ log.Fatal(err)
+ }
+ bootPath, err = osimage.EFIBootPath(osImage.Config.ProductInfo.Architecture())
+ if err != nil {
+ log.Fatal(err)
+ }
+
iargs := mctl.MakeInstallerImageArgs{
Installer: installer,
TargetPath: installerImage,
diff --git a/metropolis/node/core/update/e2e/BUILD.bazel b/metropolis/node/core/update/e2e/BUILD.bazel
index a5dcc5e..19738eb 100644
--- a/metropolis/node/core/update/e2e/BUILD.bazel
+++ b/metropolis/node/core/update/e2e/BUILD.bazel
@@ -28,6 +28,7 @@
"//osbase/blockdev",
"//osbase/build/mkimage/osimage",
"//osbase/oci",
+ "//osbase/oci/osimage",
"//osbase/oci/registry",
"//osbase/structfs",
"@io_bazel_rules_go//go/runfiles",
diff --git a/metropolis/node/core/update/e2e/e2e_test.go b/metropolis/node/core/update/e2e/e2e_test.go
index ec51281..8bc2bb9 100644
--- a/metropolis/node/core/update/e2e/e2e_test.go
+++ b/metropolis/node/core/update/e2e/e2e_test.go
@@ -23,6 +23,7 @@
"source.monogon.dev/osbase/blockdev"
"source.monogon.dev/osbase/build/mkimage/osimage"
"source.monogon.dev/osbase/oci"
+ ociosimage "source.monogon.dev/osbase/oci/osimage"
"source.monogon.dev/osbase/oci/registry"
"source.monogon.dev/osbase/structfs"
)
@@ -149,6 +150,11 @@
t.Fatal(err)
}
+ osImageY, err := ociosimage.Read(imageY)
+ if err != nil {
+ t.Fatal(err)
+ }
+
registryServer := registry.NewServer()
registryServer.AddImage("testos", "y", imageY)
registryServer.AddImage("testos", "z", imageZ)
@@ -184,10 +190,11 @@
}
if _, err := osimage.Write(&osimage.Params{
- Output: rootDisk,
- ABLoader: loader,
- EFIPayload: boot,
- SystemImage: system,
+ Output: rootDisk,
+ Architecture: osImageY.Config.ProductInfo.Architecture(),
+ ABLoader: loader,
+ EFIPayload: boot,
+ SystemImage: system,
PartitionSize: osimage.PartitionSizeInfo{
ESP: 128,
System: 256,
diff --git a/metropolis/node/core/update/update.go b/metropolis/node/core/update/update.go
index d620677..ee53f90 100644
--- a/metropolis/node/core/update/update.go
+++ b/metropolis/node/core/update/update.go
@@ -428,7 +428,12 @@
var abloader []byte
func (s *Service) fixupPreloader() error {
- abLoaderFile, err := os.Open(filepath.Join(s.ESPPath, osimage.EFIPayloadPath))
+ efiBootPath, err := osimage.EFIBootPath(productinfo.Get().Info.Architecture())
+ if err != nil {
+ return err
+ }
+ efiBootFilePath := filepath.Join(s.ESPPath, efiBootPath)
+ abLoaderFile, err := os.Open(efiBootFilePath)
if err != nil {
s.Logger.Warningf("A/B preloader not available, attempting to restore: %v", err)
} else {
@@ -458,7 +463,7 @@
return fmt.Errorf("while sync'ing preloader swap file: %w", err)
}
preloader.Close()
- if err := os.Rename(filepath.Join(s.ESPPath, "preloader.swp"), filepath.Join(s.ESPPath, osimage.EFIPayloadPath)); err != nil {
+ if err := os.Rename(filepath.Join(s.ESPPath, "preloader.swp"), efiBootFilePath); err != nil {
return fmt.Errorf("while swapping preloader: %w", err)
}
s.Logger.Info("Successfully wrote current preloader")
@@ -468,6 +473,11 @@
// fixupEFI checks for the existence and correctness of the EFI boot entry
// repairs/recreates it if needed.
func (s *Service) fixupEFI() error {
+ efiBootPath, err := osimage.EFIBootPath(productinfo.Get().Info.Architecture())
+ if err != nil {
+ return err
+ }
+ efiBootVarPath := "/" + efiBootPath
varNames, err := efivarfs.List(efivarfs.ScopeGlobal)
if err != nil {
return fmt.Errorf("failed to list EFI variables: %w", err)
@@ -504,7 +514,7 @@
}
switch p := e.FilePath[1].(type) {
case efivarfs.FilePath:
- if string(p) == "/"+osimage.EFIPayloadPath {
+ if string(p) == efiBootVarPath {
if validBootEntryIdx == -1 {
validBootEntryIdx = int(idx)
} else {
@@ -540,7 +550,7 @@
PartitionUUID: s.ESPPart.ID,
},
},
- efivarfs.FilePath("/" + osimage.EFIPayloadPath),
+ efivarfs.FilePath(efiBootVarPath),
},
})
if err == nil {