Mount ESP under /efi if possible + identify EFI run source (#158)

This commit is contained in:
Itxaka
2023-09-25 14:14:56 +02:00
committed by GitHub
parent 1211b070c9
commit 7f2813e5b7
3 changed files with 102 additions and 4 deletions

View File

@@ -233,3 +233,24 @@ func GetHostProcCmdline() string {
} }
return proc return proc
} }
// EfiBootFromInstall will try to check the /sys/firmware/efi/LoaderDevicePartUUID-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
// systemd vendor Id is 4a67b082-0a4c-41cf-b6c7-440b29bb8c4f and will never change
// LoaderDevicePartUUID contains the partition UUID of the EFI System Partition the boot loader was run from. Set by the boot loader.
// This will return true if we are running from a DISK device, which sets the efivar
// This wil return false when running from a volatile media, like CD or netboot as it cannot infer where it was booted from
// Useful to check if we are on install phase or not
// This efi var is VOLATILE so once we reboot is GONE. No way of keeping it across reboots, its set by the bootloader.
func EfiBootFromInstall() bool {
file := "/sys/firmware/efi/efivars/LoaderDevicePartUUID-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f"
readFile, err := os.ReadFile(file)
if err != nil {
Log.Debug().Err(err).Msg("Error reading LoaderDevicePartUUID file")
return false
}
if len(readFile) == 0 || string(readFile) == "" {
Log.Debug().Str("file", string(readFile)).Msg("Error reading LoaderDevicePartUUID file")
return false
}
return true
}

View File

@@ -2,6 +2,7 @@ package mount
import ( import (
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"os" "os"
@@ -384,9 +385,19 @@ func (s *State) WriteSentinelDagStep(g *herd.Graph, deps ...string) error {
// Lets add a uki sentinel as well! // Lets add a uki sentinel as well!
cmdline, _ := os.ReadFile(internalUtils.GetHostProcCmdline()) cmdline, _ := os.ReadFile(internalUtils.GetHostProcCmdline())
if strings.Contains(string(cmdline), "rd.immucore.uki") { if strings.Contains(string(cmdline), "rd.immucore.uki") {
err = os.WriteFile("/run/cos/uki_mode", []byte("1"), os.ModePerm) // sentinel for uki mode
if err != nil { if internalUtils.EfiBootFromInstall() {
return err internalUtils.Log.Info().Str("to", "uki_boot_mode").Msg("Setting sentinel file")
err = os.WriteFile("/run/cos/uki_boot_mode", []byte("1"), os.ModePerm)
if err != nil {
return err
}
} else {
internalUtils.Log.Info().Str("to", "uki_install_mode").Msg("Setting sentinel file")
err := os.WriteFile("/run/cos/uki_install_mode", []byte("1"), os.ModePerm)
if err != nil {
return err
}
} }
} }
@@ -430,6 +441,13 @@ func (s *State) UKIMountBaseSystem(g *herd.Graph) error {
syscall.MS_NOSUID | syscall.MS_NODEV, syscall.MS_NOSUID | syscall.MS_NODEV,
"", "",
}, },
{
"/sys/firmware/efi/efivars",
"efivarfs",
"efivarfs",
syscall.MS_NOSUID | syscall.MS_NODEV | syscall.MS_NOEXEC | syscall.MS_RELATIME,
"",
},
} }
for _, m := range mounts { for _, m := range mounts {
e := os.MkdirAll(m.where, 0755) e := os.MkdirAll(m.where, 0755)
@@ -545,7 +563,7 @@ func (s *State) LoadKernelModules(g *herd.Graph) error {
cmd := fmt.Sprintf("modprobe %s", driver) cmd := fmt.Sprintf("modprobe %s", driver)
out, err := internalUtils.CommandWithPath(cmd) out, err := internalUtils.CommandWithPath(cmd)
if err != nil { if err != nil {
internalUtils.Log.Err(err).Str("out", out).Msg("modprobe") internalUtils.Log.Debug().Err(err).Str("out", out).Msg("modprobe")
} }
} }
return nil return nil
@@ -608,3 +626,59 @@ func (s *State) RunKcryptUpgrade(g *herd.Graph, opts ...herd.OpOption) error {
return internalUtils.UpgradeKcryptPartitions() return internalUtils.UpgradeKcryptPartitions()
}))...) }))...)
} }
type LsblkOutput struct {
Blockdevices []struct {
Name string `json:"name,omitempty"`
Parttype interface{} `json:"parttype,omitempty"`
Children []struct {
Name string `json:"name,omitempty"`
Parttype string `json:"parttype,omitempty"`
} `json:"children,omitempty"`
} `json:"blockdevices,omitempty"`
}
// MountESPPartition tries to mount the ESP into /efi
// Doesnt matter if it fails, its just for niceness.
func (s *State) MountESPPartition(g *herd.Graph, opts ...herd.OpOption) error {
return g.Add("mount-esp", append(opts, herd.WithCallback(func(ctx context.Context) error {
if !internalUtils.EfiBootFromInstall() {
internalUtils.Log.Debug().Msg("Not mounting ESP as we think we are booting from removable media")
return nil
}
cmd := "lsblk -J -o NAME,PARTTYPE"
out, err := internalUtils.CommandWithPath(cmd)
internalUtils.Log.Debug().Str("out", out).Str("cmd", cmd).Msg("ESP")
if err != nil {
internalUtils.Log.Err(err).Msg("ESP")
return nil
}
lsblk := &LsblkOutput{}
err = json.Unmarshal([]byte(out), lsblk)
if err != nil {
return nil
}
for _, bd := range lsblk.Blockdevices {
for _, cd := range bd.Children {
if strings.TrimSpace(cd.Parttype) == "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" {
// This is the ESP device
device := filepath.Join("/dev", cd.Name)
if !internalUtils.IsMounted(device) {
op := s.MountOP(
device,
s.path("/efi"),
"vfat",
[]string{
"ro",
}, 5*time.Second)
return op(ctx)
}
}
}
}
return nil
}))...)
}

View File

@@ -21,6 +21,9 @@ func (s *State) RegisterUKI(g *herd.Graph) error {
// Udev for devices discovery // Udev for devices discovery
s.LogIfError(s.UKIUdevDaemon(g), "udev") s.LogIfError(s.UKIUdevDaemon(g), "udev")
// Mount ESP partition under efi if it exists
s.LogIfError(s.MountESPPartition(g, herd.WithDeps(cnst.OpSentinel, cnst.OpUkiUdev)), "mount ESP partition")
// Run rootfs stage // Run rootfs stage
s.LogIfError(s.RootfsStageDagStep(g, herd.WithDeps(cnst.OpSentinel, cnst.OpUkiUdev)), "uki rootfs") s.LogIfError(s.RootfsStageDagStep(g, herd.WithDeps(cnst.OpSentinel, cnst.OpUkiUdev)), "uki rootfs")