Skip to content
This repository was archived by the owner on Dec 16, 2024. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions pkg/action/build-iso.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package action

import (
"fmt"
"os"
"path/filepath"
"strings"
"time"
Expand Down Expand Up @@ -96,6 +97,12 @@ func (b *BuildISOAction) ISORun() (err error) {
return err
}

err = b.prepareBootArtifacts(isoDir)
if err != nil {
b.cfg.Logger.Errorf("Failed preparing boot artifacts: %v", err)
return err
}

b.cfg.Logger.Infof("Creating ISO image...")
err = b.burnISO(isoDir)
if err != nil {
Expand All @@ -106,6 +113,24 @@ func (b *BuildISOAction) ISORun() (err error) {
return err
}

// prepareBootArtifacts will write the needed artifacts for BIOS cd boot into the isoDir
// so xorriso can use those to build the bootable iso file
func (b *BuildISOAction) prepareBootArtifacts(isoDir string) error {
err := os.WriteFile(filepath.Join(isoDir, constants.IsoBootFile), constants.Eltorito, constants.FilePerm)
if err != nil {
return err
}
err = os.WriteFile(filepath.Join(isoDir, constants.IsoHybridMBR), constants.BootHybrid, constants.FilePerm)
if err != nil {
return err
}
err = os.MkdirAll(filepath.Join(isoDir, constants.GrubPrefixDir), constants.DirPerm)
if err != nil {
return err
}
return os.WriteFile(filepath.Join(isoDir, constants.GrubPrefixDir, constants.GrubCfg), constants.GrubLiveBiosCfg, constants.FilePerm)
}

func (b BuildISOAction) prepareISORoot(isoDir string, rootDir string, uefiDir string) error {
kernel, initrd, err := b.e.FindKernelInitrd(rootDir)
if err != nil {
Expand Down
Binary file added pkg/constants/boot_hybrid.img
Binary file not shown.
38 changes: 35 additions & 3 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,38 @@ import (
"path/filepath"
)

import _ "embed"

// Eltorito image is basically a grub cdboot.img + grub core image
// So basically you build a grub image with modules embedded and prepend it with the cdboot, which allows it to boot from
// CDRom and run the grub embedded in the image directly from BIOS
// This can be generated from any distro by runing something like:
/*
grub2-mkimage -O i386-pc -o core.img -p /boot/grub2 -d PATH_TO_i386_MODULES ext2 iso9660 linux echo configfile search_label search_fs_file search search_fs_uuid ls normal gzio gettext font gfxterm gfxmenu all_video test true loadenv part_gpt part_msdos biosdisk vga vbe chain boot
cat $(find / -name cdboot.img -print) core.img > eltorito.img

Important things in the grub image creation:
- -O i386-pc is the architecture we want to build the image for. Bios is i386
- -p is the prefix dir, this is where grub will start searching for things, including the grub.cfg config, when it boots
- -d is the current dir where modules and images are. Usually this is automatically set so it can be dropped
- the list at the end are the modules to bundle for grub. Honestly the list is not too big and it can probably be dropped to like half for the livecd
as it only uses linux, echo, font, video ones and boot. But it doesnt hurt to have extra modules.
*/
//go:embed eltorito.img
var Eltorito []byte

// BootHybrid is boot_hybrid.img which comes bundled with grub
// Its ASM to boot from the grub image embedded
// You can check its source here: https://github.com/rhboot/grub2/blob/fedora-39/grub-core/boot/i386/pc/cdboot.S
//
//go:embed boot_hybrid.img
var BootHybrid []byte

// GrubLiveBiosCfg is the livecd config for BIOS boot
//
//go:embed grub_live_bios.cfg
var GrubLiveBiosCfg []byte

type UkiOutput string

const IsoOutput UkiOutput = "iso"
Expand Down Expand Up @@ -34,9 +66,9 @@ const (
"\nset prefix=($root)" + GrubPrefixDir +
"\nconfigfile $prefix/" + GrubCfg

IsoHybridMBR = "/boot/x86_64/loader/boot_hybrid.img"
IsoBootCatalog = "/boot/x86_64/boot.catalog"
IsoBootFile = "/boot/x86_64/loader/eltorito.img"
IsoHybridMBR = "/boot/boot_hybrid.img"
IsoBootCatalog = "/boot/boot.catalog"
IsoBootFile = "/boot/eltorito.img"

// These paths are arbitrary but coupled to grub.cfg
IsoKernelPath = "/boot/kernel"
Expand Down
Binary file added pkg/constants/eltorito.img
Binary file not shown.
58 changes: 58 additions & 0 deletions pkg/constants/grub_live_bios.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@

search --file --set=root /boot/kernel
set default=0
set timeout=10
set timeout_style=menu

set font=($root)/boot/${grub_cpu}/loader/grub2/fonts/unicode.pf2
if [ -f ${font} ];then
loadfont ${font}
fi
menuentry "Kairos" --class os --unrestricted {
echo Loading kernel...
linux ($root)/boot/kernel cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs net.ifnames=1 console=ttyS0 console=tty1 rd.cos.disable vga=795 nomodeset install-mode selinux=0 rd.live.overlay.overlayfs
echo Loading initrd...
initrd ($root)/boot/initrd
}

menuentry "Kairos (manual)" --class os --unrestricted {
echo Loading kernel...
linux ($root)/boot/kernel cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs net.ifnames=1 console=ttyS0 console=tty1 rd.cos.disable vga=795 nomodeset selinux=0 rd.live.overlay.overlayfs
echo Loading initrd...
initrd ($root)/boot/initrd
}

menuentry "kairos (interactive install)" --class os --unrestricted {
echo Loading kernel...
linux ($root)/boot/kernel cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs net.ifnames=1 console=ttyS0 console=tty1 rd.cos.disable vga=795 nomodeset install-mode-interactive selinux=0 rd.live.overlay.overlayfs
echo Loading initrd...
initrd ($root)/boot/initrd
}

menuentry "Kairos (remote recovery mode)" --class os --unrestricted {
echo Loading kernel...
linux ($root)/boot/kernel cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs net.ifnames=1 console=ttyS0 console=tty1 rd.cos.disable vga=795 nomodeset kairos.remote_recovery_mode selinux=0 rd.live.overlay.overlayfs
echo Loading initrd...
initrd ($root)/boot/initrd
}

menuentry "Kairos (boot local node from livecd)" --class os --unrestricted {
echo Loading kernel...
linux ($root)/boot/kernel cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs net.ifnames=1 console=ttyS0 console=tty1 kairos.boot_live_mode vga=795 nomodeset selinux=0 rd.live.overlay.overlayfs
echo Loading initrd...
initrd ($root)/boot/initrd
}

menuentry "Kairos (debug)" --class os --unrestricted {
echo Loading kernel...
linux ($root)/boot/kernel cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs net.ifnames=1 console=tty0 rd.debug rd.shell rd.cos.disable rd.immucore.debug vga=795 nomodeset selinux=0 rd.live.overlay.overlayfs
echo Loading initrd...
initrd ($root)/boot/initrd
}

if [ "${grub_platform}" = "efi" ]; then
hiddenentry "Text mode" --hotkey "t" {
set textmode=true
terminal_output console
}
fi