package hostmode import ( "bufio" "context" "log" "os" "os/exec" "strings" ) // setPXEBootNext points the next boot at a PXE-capable BootOrder // entry via efibootmgr --bootnext. Best-effort: absent efibootmgr, // non-UEFI firmware, or zero PXE entries all fall through silently — // the operator's BIOS/DHCP chain will still PXE-boot on most hosts. func setPXEBootNext(ctx context.Context) { if _, err := os.Stat("/sys/firmware/efi"); err != nil { log.Printf("hostmode: not a UEFI system; skipping efibootmgr") return } bin, err := exec.LookPath("efibootmgr") if err != nil { log.Printf("hostmode: efibootmgr not installed; skipping") return } boots, err := exec.CommandContext(ctx, bin, "-v").Output() if err != nil { log.Printf("hostmode: efibootmgr -v: %v", err) return } num := findPXEBootNum(string(boots)) if num == "" { log.Printf("hostmode: no PXE boot entry found") return } if err := exec.CommandContext(ctx, bin, "--bootnext", num).Run(); err != nil { log.Printf("hostmode: efibootmgr --bootnext %s: %v", num, err) return } log.Printf("hostmode: efibootmgr --bootnext %s", num) } // findPXEBootNum picks the first BootXXXX entry whose description // looks like a network boot. efibootmgr -v output lines look like: // // Boot0003* UEFI: IPv4 Intel I225-V PciRoot(0x0)/Pci(...)/MAC(...) // Boot0001* ubuntu HD(1,GPT,...)/File(\EFI\ubuntu\shimx64.efi) func findPXEBootNum(out string) string { scan := bufio.NewScanner(strings.NewReader(out)) for scan.Scan() { line := scan.Text() if !strings.HasPrefix(line, "Boot") || len(line) < 8 { continue } low := strings.ToLower(line) if !(strings.Contains(low, "pxe") || strings.Contains(low, "ipv4") || strings.Contains(low, "ipv6") || strings.Contains(low, "network")) { continue } return line[4:8] } return "" }