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 {
501536func 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
561596func 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
703746func 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+ }
0 commit comments