Skip to content

Commit d34786b

Browse files
ItxakaCopilot
andauthored
feat: add support for locating systemd-boot files in source (#381)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 1dfefa6 commit d34786b

File tree

2 files changed

+107
-28
lines changed

2 files changed

+107
-28
lines changed

internal/cmd/build-uki.go

Lines changed: 97 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"io"
7+
"io/fs"
78
"log/slog"
89
"math"
910
"os"
@@ -145,6 +146,11 @@ var BuildUKICmd = cli.Command{
145146
Value: false,
146147
Usage: "Use the new cmdline v2 format to generate a multiprofile efi with all the extra cmdlines. This requires systemd-boot 257 or newer.",
147148
},
149+
&cli.BoolFlag{
150+
Name: "sdboot-in-source",
151+
Value: false,
152+
Usage: "Try to find systemd-boot files in the source rootfs instead of using the bundled ones.",
153+
},
148154
},
149155
Before: func(ctx *cli.Context) error {
150156
// // Mark flags as mutually exclusive
@@ -238,6 +244,7 @@ var BuildUKICmd = cli.Command{
238244
if ctx.Bool("debug") {
239245
logLevel = "debug"
240246
}
247+
241248
logger := sdkTypes.NewKairosLogger("auroraboot", logLevel, false)
242249

243250
// TODO: Get rid of "configs".
@@ -337,37 +344,64 @@ var BuildUKICmd = cli.Command{
337344
GetUkiCmdline(extendCmdline, boodBranding, extraCmdlines, cmdLinesV2),
338345
GetUkiSingleCmdlines(boodBranding, singleEfiCmdlines, logger)...)
339346

340-
for _, entry := range entries {
341-
logger.Info(fmt.Sprintf("Running ukify for cmdline: %s: %s", entry.Title, entry.Cmdline))
342-
343-
logger.Infof("Generating: %s.efi", entry.FileName)
344-
345-
// New ukifier !!
346-
// Create Builder instance
347-
stub, err := getEfiStub(config.Arch)
347+
var stub, systemdBoot, outputSystemdBootEfi string
348+
// Get sdboot files from source if requested
349+
if ctx.Bool("sdboot-in-source") {
350+
if utils.IsAmd64(config.Arch) {
351+
// Find the stub and systemd-boot in source dir
352+
stub, err = FindFirstFileInDir(sourceDir, constants.UkiSystemdBootStubx86Name)
353+
if err != nil {
354+
return fmt.Errorf("finding systemd-boot stub in source: %w", err)
355+
}
356+
systemdBoot, err = FindFirstFileInDir(sourceDir, constants.UkiSystemdBootx86Name)
357+
if err != nil {
358+
return fmt.Errorf("finding systemd-boot in source: %w", err)
359+
}
360+
outputSystemdBootEfi = constants.EfiFallbackNamex86
361+
} else if utils.IsArm64(config.Arch) {
362+
// Find the stub and systemd-boot in source dir
363+
stub, err = FindFirstFileInDir(sourceDir, constants.UkiSystemdBootStubArmName)
364+
if err != nil {
365+
return fmt.Errorf("finding systemd-boot stub in source: %w", err)
366+
}
367+
systemdBoot, err = FindFirstFileInDir(sourceDir, constants.UkiSystemdBootArmName)
368+
if err != nil {
369+
return fmt.Errorf("finding systemd-boot in source: %w", err)
370+
}
371+
outputSystemdBootEfi = constants.EfiFallbackNameArm
372+
}
373+
} else {
374+
// Fallback to bundled files
375+
stub, err = getEfiStub(config.Arch)
348376
if err != nil {
349377
return err
350378
}
351379
// Get systemd-boot info (we can sign it at the same time)
352-
var systemdBoot string
353-
var outputSystemdBootEfi string
354380
if utils.IsAmd64(config.Arch) {
355-
systemdBoot = constants.UkiSystemdBootx86
381+
systemdBoot = constants.UkiSystemdBootx86Path
356382
outputSystemdBootEfi = constants.EfiFallbackNamex86
357383
} else if utils.IsArm64(config.Arch) {
358-
systemdBoot = constants.UkiSystemdBootArm
384+
systemdBoot = constants.UkiSystemdBootArmPath
359385
outputSystemdBootEfi = constants.EfiFallbackNameArm
360386
} else {
361387
return fmt.Errorf("unsupported arch: %s", config.Arch)
362388
}
389+
}
390+
391+
for _, entry := range entries {
392+
logger.Info(fmt.Sprintf("Running ukify for cmdline: %s: %s", entry.Title, entry.Cmdline))
393+
394+
logger.Infof("Generating: %s.efi", entry.FileName)
395+
396+
// New ukifier !!
397+
// Create Builder instance
363398

364399
if logger.GetLevel().String() == "debug" {
365400
slog.SetLogLoggerLevel(slog.LevelDebug)
366401
}
367402
builder := &uki.Builder{
368403
Arch: config.Arch,
369404
Version: kairosVersion,
370-
SdStubPath: stub,
371405
KernelPath: filepath.Join(artifactsTempDir, "vmlinuz"),
372406
InitrdPath: filepath.Join(artifactsTempDir, "initrd"),
373407
Cmdline: entry.Cmdline,
@@ -377,6 +411,7 @@ var BuildUKICmd = cli.Command{
377411
SBKey: ctx.String("sb-key"),
378412
SBCert: ctx.String("sb-cert"),
379413
SdBootPath: systemdBoot,
414+
SdStubPath: stub,
380415
OutSdBootPath: outputSystemdBootEfi,
381416
Splash: ctx.String("splash"),
382417
}
@@ -501,13 +536,13 @@ func checkBuildUKIDeps(arch string) error {
501536
func getEfiNeededFiles(arch string) ([]string, error) {
502537
if utils.IsAmd64(arch) {
503538
return []string{
504-
constants.UkiSystemdBootStubx86,
505-
constants.UkiSystemdBootx86,
539+
constants.UkiSystemdBootStubx86Path,
540+
constants.UkiSystemdBootx86Path,
506541
}, nil
507542
} else if utils.IsArm64(arch) {
508543
return []string{
509-
constants.UkiSystemdBootStubArm,
510-
constants.UkiSystemdBootArm,
544+
constants.UkiSystemdBootStubArmPath,
545+
constants.UkiSystemdBootArmPath,
511546
}, nil
512547
} else {
513548
return nil, fmt.Errorf("unsupported arch: %s", arch)
@@ -559,9 +594,17 @@ func setupDirectoriesAndFiles(workDir string) error {
559594
}
560595

561596
func copyKernel(sourceDir, targetDir string) error {
562-
linkTarget, err := os.Readlink(filepath.Join(sourceDir, "boot", "vmlinuz"))
563-
if err != nil {
564-
return err
597+
// Check if its a symlink or a file
598+
kernel := filepath.Join(sourceDir, "boot", "vmlinuz")
599+
600+
var linkTarget string
601+
var err error
602+
603+
if linkTarget, err = os.Readlink(kernel); err == nil {
604+
// It's a symlink, linkTarget now contains the symlink target
605+
} else {
606+
// It's not a symlink, use the kernel file directly
607+
linkTarget = kernel
565608
}
566609

567610
kernelFile := filepath.Base(linkTarget)
@@ -702,9 +745,9 @@ func ZstdFile(sourcePath, targetPath string) error {
702745

703746
func getEfiStub(arch string) (string, error) {
704747
if utils.IsAmd64(arch) {
705-
return constants.UkiSystemdBootStubx86, nil
748+
return constants.UkiSystemdBootStubx86Path, nil
706749
} else if utils.IsArm64(arch) {
707-
return constants.UkiSystemdBootStubArm, nil
750+
return constants.UkiSystemdBootStubArmPath, nil
708751
} else {
709752
return "", nil
710753
}
@@ -1128,3 +1171,35 @@ func NameFromCmdline(basename, cmdline string) string {
11281171

11291172
return finalName
11301173
}
1174+
1175+
// FindFirstFileInDir finds the first file matching the pattern in the given directory.
1176+
// It walks over any subdirectories as well.
1177+
// It returns as soon as it finds the first match.
1178+
// It returns the full path to the file if found, or an error if not found or any other error occurs.
1179+
func FindFirstFileInDir(dir, pattern string) (string, error) {
1180+
var foundFile string
1181+
err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
1182+
if err != nil {
1183+
return err
1184+
}
1185+
if !d.IsDir() {
1186+
matched, err := filepath.Match(pattern, d.Name())
1187+
if err != nil {
1188+
return err
1189+
}
1190+
if matched {
1191+
foundFile = path
1192+
return filepath.SkipAll // Stop walking once we found the file
1193+
}
1194+
1195+
}
1196+
return nil
1197+
})
1198+
if err != nil {
1199+
return "", err
1200+
}
1201+
if foundFile == "" {
1202+
return "", fmt.Errorf("no file matching pattern %s found in directory %s", pattern, dir)
1203+
}
1204+
return foundFile, nil
1205+
}

pkg/constants/constants.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,16 @@ const (
8080
ArchAmd64 = "amd64"
8181
Archaarch64 = "aarch64"
8282

83-
UkiCmdline = "console=ttyS0 console=tty1 net.ifnames=1 rd.immucore.oemlabel=COS_OEM rd.immucore.oemtimeout=2 rd.immucore.uki selinux=0 panic=5 rd.shell=0 systemd.crash_reboot=yes"
84-
UkiCmdlineInstall = "install-mode"
85-
UkiSystemdBootx86 = "/amd/systemd-boot/systemd-bootx64.efi"
86-
UkiSystemdBootStubx86 = "/amd/systemd-boot/linuxx64.efi.stub"
87-
UkiSystemdBootArm = "/arm/systemd-boot/systemd-bootaa64.efi"
88-
UkiSystemdBootStubArm = "/arm/systemd-boot/linuxaa64.efi.stub"
83+
UkiCmdline = "console=ttyS0 console=tty1 net.ifnames=1 rd.immucore.oemlabel=COS_OEM rd.immucore.oemtimeout=2 rd.immucore.uki selinux=0 panic=5 rd.shell=0 systemd.crash_reboot=yes"
84+
UkiCmdlineInstall = "install-mode"
85+
UkiSystemdBootx86Name = "systemd-bootx64.efi"
86+
UkiSystemdBootx86Path = "/amd/systemd-boot/" + UkiSystemdBootx86Name
87+
UkiSystemdBootStubx86Name = "linuxx64.efi.stub"
88+
UkiSystemdBootStubx86Path = "/amd/systemd-boot/" + UkiSystemdBootStubx86Name
89+
UkiSystemdBootArmName = "systemd-bootaa64.efi"
90+
UkiSystemdBootArmPath = "/arm/systemd-boot/" + UkiSystemdBootArmName
91+
UkiSystemdBootStubArmName = "linuxaa64.efi.stub"
92+
UkiSystemdBootStubArmPath = "/arm/systemd-boot/" + UkiSystemdBootStubArmName
8993

9094
EfiFallbackNamex86 = "BOOTX64.EFI"
9195
EfiFallbackNameArm = "BOOTAA64.EFI"

0 commit comments

Comments
 (0)