chore: aarch64 qemu local secureboot support
Support booting with SecureBoot on aarch64 with `talosctl cluster create` with QEMU provisioner. Signed-off-by: Noel Georgi <git@frezbo.dev>
This commit is contained in:
parent
da6263506a
commit
106c17d0b5
@ -5,8 +5,10 @@
|
||||
package qemu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// Arch abstracts away differences between different architectures.
|
||||
@ -74,18 +76,47 @@ type PFlash struct {
|
||||
func (arch Arch) PFlash(uefiEnabled bool, extraUEFISearchPaths []string) []PFlash {
|
||||
switch arch {
|
||||
case ArchArm64:
|
||||
uefiSourcePaths := []string{"/usr/share/qemu-efi-aarch64/QEMU_EFI.fd", "/usr/share/OVMF/QEMU_EFI.fd", "/usr/share/edk2/aarch64/QEMU_EFI.fd"}
|
||||
for _, p := range extraUEFISearchPaths {
|
||||
uefiSourcePaths = append(uefiSourcePaths, filepath.Join(p, "QEMU_EFI.fd"))
|
||||
// default search paths
|
||||
uefiSourcePathPrefixes := []string{
|
||||
"/usr/share/AAVMF", // most standard location
|
||||
"/usr/share/qemu-efi-aarch64",
|
||||
"/usr/share/OVMF",
|
||||
"/usr/share/edk2/aarch64", // Fedora
|
||||
"/usr/share/edk2/experimental", // Fedora
|
||||
}
|
||||
|
||||
// Secure boot enabled firmware files
|
||||
uefiSourceFiles := []string{
|
||||
"AAVMF_CODE.secboot.fd", // debian, EFI vars not protected
|
||||
"QEMU_EFI.secboot.testonly.fd", // Fedora, ref: https://bugzilla.redhat.com/show_bug.cgi?id=1882135
|
||||
}
|
||||
|
||||
// Non-secure boot firmware files
|
||||
uefiSourceFilesInsecure := []string{
|
||||
"AAVMF_CODE.fd",
|
||||
"QEMU_EFI.fd",
|
||||
"OVMF.stateless.fd",
|
||||
}
|
||||
|
||||
// Empty vars files
|
||||
uefiVarsFiles := []string{
|
||||
"AAVMF_VARS.fd",
|
||||
"QEMU_VARS.fd",
|
||||
}
|
||||
|
||||
// Append extra search paths
|
||||
uefiSourcePathPrefixes = append(uefiSourcePathPrefixes, extraUEFISearchPaths...)
|
||||
|
||||
uefiSourcePaths, uefiVarsPaths := generateUEFIPFlashList(uefiSourcePathPrefixes, uefiSourceFiles, uefiVarsFiles, uefiSourceFilesInsecure)
|
||||
|
||||
return []PFlash{
|
||||
{
|
||||
Size: 64 * 1024 * 1024,
|
||||
SourcePaths: uefiSourcePaths,
|
||||
},
|
||||
{
|
||||
Size: 64 * 1024 * 1024,
|
||||
SourcePaths: uefiVarsPaths,
|
||||
Size: 64 * 1024 * 1024,
|
||||
},
|
||||
}
|
||||
case ArchAmd64:
|
||||
@ -127,25 +158,7 @@ func (arch Arch) PFlash(uefiEnabled bool, extraUEFISearchPaths []string) []PFlas
|
||||
// Append extra search paths
|
||||
uefiSourcePathPrefixes = append(uefiSourcePathPrefixes, extraUEFISearchPaths...)
|
||||
|
||||
var uefiSourcePaths []string
|
||||
|
||||
var uefiVarsPaths []string
|
||||
|
||||
for _, p := range uefiSourcePathPrefixes {
|
||||
for _, f := range uefiSourceFiles {
|
||||
uefiSourcePaths = append(uefiSourcePaths, filepath.Join(p, f))
|
||||
}
|
||||
|
||||
for _, f := range uefiVarsFiles {
|
||||
uefiVarsPaths = append(uefiVarsPaths, filepath.Join(p, f))
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range uefiSourcePathPrefixes {
|
||||
for _, f := range uefiSourceFilesInsecure {
|
||||
uefiSourcePaths = append(uefiSourcePaths, filepath.Join(p, f))
|
||||
}
|
||||
}
|
||||
uefiSourcePaths, uefiVarsPaths := generateUEFIPFlashList(uefiSourcePathPrefixes, uefiSourceFiles, uefiVarsFiles, uefiSourceFilesInsecure)
|
||||
|
||||
return []PFlash{
|
||||
{
|
||||
@ -162,6 +175,26 @@ func (arch Arch) PFlash(uefiEnabled bool, extraUEFISearchPaths []string) []PFlas
|
||||
}
|
||||
}
|
||||
|
||||
func generateUEFIPFlashList(uefiSourcePathPrefixes, uefiSourceFiles, uefiVarsFiles, uefiSourceFilesInsecure []string) (uefiSourcePaths, uefiVarsPaths []string) {
|
||||
for _, p := range uefiSourcePathPrefixes {
|
||||
for _, f := range uefiSourceFiles {
|
||||
uefiSourcePaths = append(uefiSourcePaths, filepath.Join(p, f))
|
||||
}
|
||||
|
||||
for _, f := range uefiVarsFiles {
|
||||
uefiVarsPaths = append(uefiVarsPaths, filepath.Join(p, f))
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range uefiSourcePathPrefixes {
|
||||
for _, f := range uefiSourceFilesInsecure {
|
||||
uefiSourcePaths = append(uefiSourcePaths, filepath.Join(p, f))
|
||||
}
|
||||
}
|
||||
|
||||
return uefiSourcePaths, uefiVarsPaths
|
||||
}
|
||||
|
||||
// QemuExecutable returns name of qemu executable for the arch.
|
||||
func (arch Arch) QemuExecutable() string {
|
||||
binaries := []string{
|
||||
@ -179,7 +212,43 @@ func (arch Arch) QemuExecutable() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Architecture returns the architecture.
|
||||
func (arch Arch) Architecture() string {
|
||||
return string(arch)
|
||||
// TPMDeviceArgs returns arguments for qemu to enable TPM device.
|
||||
func (arch Arch) TPMDeviceArgs(socketPath string) []string {
|
||||
tpmDeviceArgs := []string{
|
||||
"-chardev",
|
||||
fmt.Sprintf("socket,id=chrtpm,path=%s", socketPath),
|
||||
"-tpmdev",
|
||||
"emulator,id=tpm0,chardev=chrtpm",
|
||||
"-device",
|
||||
}
|
||||
|
||||
switch arch {
|
||||
case ArchAmd64:
|
||||
return slices.Concat(tpmDeviceArgs, []string{"tpm-tis,tpmdev=tpm0"})
|
||||
case ArchArm64:
|
||||
return slices.Concat(tpmDeviceArgs, []string{"tpm-tis-device,tpmdev=tpm0"})
|
||||
default:
|
||||
panic("unsupported architecture")
|
||||
}
|
||||
}
|
||||
|
||||
// KVMArgs returns arguments for qemu to enable KVM.
|
||||
func (arch Arch) KVMArgs(kvmEnabled bool) []string {
|
||||
if !kvmEnabled {
|
||||
return []string{"-machine", arch.QemuMachine()}
|
||||
}
|
||||
|
||||
machineArg := arch.QemuMachine() + ",accel=kvm"
|
||||
|
||||
switch arch {
|
||||
case ArchAmd64:
|
||||
machineArg += ",smm=on"
|
||||
|
||||
return []string{"-machine", machineArg}
|
||||
case ArchArm64:
|
||||
// smm is not supported on aarch64
|
||||
return []string{"-machine", machineArg}
|
||||
default:
|
||||
panic("unsupported architecture")
|
||||
}
|
||||
}
|
||||
|
@ -43,14 +43,11 @@ type LaunchConfig struct {
|
||||
DiskDrivers []string
|
||||
VCPUCount int64
|
||||
MemSize int64
|
||||
QemuExecutable string
|
||||
Architecture string
|
||||
KernelImagePath string
|
||||
InitrdPath string
|
||||
ISOPath string
|
||||
PFlashImages []string
|
||||
KernelArgs string
|
||||
MachineType string
|
||||
MonitorPath string
|
||||
DefaultBootOrder string
|
||||
EnableKVM bool
|
||||
@ -58,6 +55,7 @@ type LaunchConfig struct {
|
||||
TPM2Config tpm2Config
|
||||
NodeUUID uuid.UUID
|
||||
BadRTC bool
|
||||
ArchitectureData Arch
|
||||
|
||||
// Talos config
|
||||
Config string
|
||||
@ -390,18 +388,7 @@ func launchVM(config *LaunchConfig) error {
|
||||
}
|
||||
}
|
||||
|
||||
machineArg := config.MachineType
|
||||
|
||||
if config.EnableKVM {
|
||||
machineArg += ",accel=kvm"
|
||||
|
||||
// smm is not supported on aarch64
|
||||
if Arch(config.QemuExecutable) == ArchAmd64 {
|
||||
machineArg += ",smm=on"
|
||||
}
|
||||
}
|
||||
|
||||
args = append(args, "-machine", machineArg)
|
||||
args = append(args, config.ArchitectureData.KVMArgs(config.EnableKVM)...)
|
||||
|
||||
pflashArgs := make([]string, 2*len(config.PFlashImages))
|
||||
for i := range config.PFlashImages {
|
||||
@ -440,12 +427,7 @@ func launchVM(config *LaunchConfig) error {
|
||||
}
|
||||
|
||||
args = append(args,
|
||||
"-chardev",
|
||||
fmt.Sprintf("socket,id=chrtpm,path=%s", tpm2SocketPath),
|
||||
"-tpmdev",
|
||||
"emulator,id=tpm0,chardev=chrtpm",
|
||||
"-device",
|
||||
"tpm-tis,tpmdev=tpm0",
|
||||
config.ArchitectureData.TPMDeviceArgs(tpm2SocketPath)...,
|
||||
)
|
||||
}
|
||||
|
||||
@ -470,9 +452,9 @@ func launchVM(config *LaunchConfig) error {
|
||||
)
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "starting %s with args:\n%s\n", config.QemuExecutable, strings.Join(args, " "))
|
||||
fmt.Fprintf(os.Stderr, "starting %s with args:\n%s\n", config.ArchitectureData.QemuExecutable(), strings.Join(args, " "))
|
||||
cmd := exec.Command(
|
||||
config.QemuExecutable,
|
||||
config.ArchitectureData.QemuExecutable(),
|
||||
args...,
|
||||
)
|
||||
|
||||
|
@ -129,16 +129,14 @@ func (p *provisioner) createNode(state *vm.State, clusterReq provision.ClusterRe
|
||||
}
|
||||
|
||||
launchConfig := LaunchConfig{
|
||||
QemuExecutable: arch.QemuExecutable(),
|
||||
Architecture: arch.Architecture(),
|
||||
DiskPaths: diskPaths,
|
||||
ArchitectureData: arch,
|
||||
DiskPaths: diskPaths,
|
||||
DiskDrivers: xslices.Map(nodeReq.Disks, func(disk *provision.Disk) string {
|
||||
return disk.Driver
|
||||
}),
|
||||
VCPUCount: vcpuCount,
|
||||
MemSize: memSize,
|
||||
KernelArgs: cmdline.String(),
|
||||
MachineType: arch.QemuMachine(),
|
||||
PFlashImages: pflashImages,
|
||||
MonitorPath: state.GetRelativePath(fmt.Sprintf("%s.monitor", nodeReq.Name)),
|
||||
EnableKVM: opts.TargetArch == runtime.GOARCH,
|
||||
|
Loading…
x
Reference in New Issue
Block a user