Skip to content

Commit

Permalink
New output format: iso-efi-initrd
Browse files Browse the repository at this point in the history
This option was previously not available and required postprocessing of a `tar-kernel-initrd` output.

Comparison with `iso-efi`:

`iso-efi` only loads the kernel at boot, and the root filesystem is mounted from the actual boot media (eg, a CD-ROM - physical or emulated). This can often cause trouble (it has for us) for multiple reasons:
- the linuxkit kernel might not have the correct drivers built-in for the hardware (see linuxkit#3154)
- especially with virtual or emulated CD-ROMs, performance can be abysmal: we saw the case where the server IPMI allowed using a ISO stored in AWS S3 over HTTP...you can imagine what happens when you start doing random I/O on the root fs in that case.
- The ISO image has the root device name baked in (ie, `/dev/sr0`) which fails if for some reason the CD-ROM we're running from doesn't end up using that device, so manual tweaking is required (see linuxkit#2375)

`iso-efi-initrd`, on the other hand, packs the root filesystem as an initramfs (ie similar to what the raw output does, except that in this case we're preparing an ISO image), so both the kernel and the initramfs are loaded in memory by the boot loader and, once running, we don't need to worry about root devices or kernel drivers (and the speed is good, as everything runs in RAM).

Also, the generated ISO can be copied verbatim (eg with `dd`) onto a USB media and it still works.

Finally, the image size is much smaller compared to `iso-efi`.

IMHO, `iso-efi-initrd` could be used almost anywhere `iso-efi` would be used, or might even supersede it. I can't think of a scenario where one might explicitly want to use `iso-efi`.

Points to consider:

- Not tested under aarch64 as I don't have access to that arch. If the automated CI tests also test that, then it should be fine.
- I'm not sure what to put inside `images.yaml` for the `iso-efi-initrd` image. As it is it works of course (my personal image on docker hub), but I guess it'll have to be some more "official" image. However, that cannot be until this PR is merged, so it's kind of a chicken and egg situation. Please advise.
- I can look into adding the corresponding `iso-bios-initrd` builder if there is interest.

![cute seal](https://sites.psu.edu/siowfa16/files/2016/09/baby-seal-29vsgyf-288x300.jpg)

Signed-off-by: Davide Brini <waldner@katamail.com>
  • Loading branch information
waldner committed Jul 11, 2022
1 parent ad3d8bd commit 860934d
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 12 deletions.
25 changes: 13 additions & 12 deletions src/cmd/linuxkit/moby/images.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
iso: linuxkit/mkimage-iso:3189befa740156b22c987be9cd46fd6e444b4eeb
iso-bios: linuxkit/mkimage-iso-bios:583857f93befadcc6d7dadca348bb862185e262b
iso-efi: linuxkit/mkimage-iso-efi:2e50a41e4d2ba15a005a738720b499844c0df1b4
raw-bios: linuxkit/mkimage-raw-bios:88ea52ae69c5d5c15f029074b632bcd14d8c9ac5
raw-efi: linuxkit/mkimage-raw-efi:3a923776eabab765444e89a1e2252f2677a4bf29
squashfs: linuxkit/mkimage-squashfs:463e0db20f222810fb09d952f6710f4814515144
gcp: linuxkit/mkimage-gcp:a7416d21d4ef642bb2ba560c8f7651250823546d
qcow2-efi: linuxkit/mkimage-qcow2-efi:2ddcfc53048a409937e90f98bbe0032e0667b1aa
vhd: linuxkit/mkimage-vhd:4cc60c4f46b07e11c64ba618e46b81fa0096c91f
dynamic-vhd: linuxkit/mkimage-dynamic-vhd:99b9009ed54a793020d3ce8322a42e0cc06da71a
vmdk: linuxkit/mkimage-vmdk:b55ea46297a16d8a4448ce7f5a2df987a9602b27
rpi3: linuxkit/mkimage-rpi3:54682f9312701afa01eaf92fa5253b76c7d5c635
iso: linuxkit/mkimage-iso:3189befa740156b22c987be9cd46fd6e444b4eeb
iso-bios: linuxkit/mkimage-iso-bios:583857f93befadcc6d7dadca348bb862185e262b
iso-efi: linuxkit/mkimage-iso-efi:2e50a41e4d2ba15a005a738720b499844c0df1b4
iso-efi-initrd: linuxkit/mkimage-iso-efi-initrd:e763a5f89c50d0d7bd5734da6a4e15c4431f9f50
raw-bios: linuxkit/mkimage-raw-bios:88ea52ae69c5d5c15f029074b632bcd14d8c9ac5
raw-efi: linuxkit/mkimage-raw-efi:3a923776eabab765444e89a1e2252f2677a4bf29
squashfs: linuxkit/mkimage-squashfs:463e0db20f222810fb09d952f6710f4814515144
gcp: linuxkit/mkimage-gcp:a7416d21d4ef642bb2ba560c8f7651250823546d
qcow2-efi: linuxkit/mkimage-qcow2-efi:2ddcfc53048a409937e90f98bbe0032e0667b1aa
vhd: linuxkit/mkimage-vhd:4cc60c4f46b07e11c64ba618e46b81fa0096c91f
dynamic-vhd: linuxkit/mkimage-dynamic-vhd:99b9009ed54a793020d3ce8322a42e0cc06da71a
vmdk: linuxkit/mkimage-vmdk:b55ea46297a16d8a4448ce7f5a2df987a9602b27
rpi3: linuxkit/mkimage-rpi3:54682f9312701afa01eaf92fa5253b76c7d5c635
13 changes: 13 additions & 0 deletions src/cmd/linuxkit/moby/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package moby
import (
"archive/tar"
"bytes"

// fix: #3742
// golint requires comments on non-main(test)
// package for blank import
Expand Down Expand Up @@ -71,6 +72,18 @@ var outFuns = map[string]func(string, io.Reader, int) error{
}
return nil
},
"iso-efi-initrd": func(base string, image io.Reader, size int) error {
kernel, initrd, cmdline, _, err := tarToInitrd(image)
if err != nil {
return fmt.Errorf("Error converting to initrd: %v", err)
}

err = outputImg(outputImages["iso-efi-initrd"], base+"-efi-initrd.iso", kernel, initrd, cmdline)
if err != nil {
return fmt.Errorf("Error writing iso-efi-initrd output: %v", err)
}
return nil
},
"raw-bios": func(base string, image io.Reader, size int) error {
kernel, initrd, cmdline, _, err := tarToInitrd(image)
if err != nil {
Expand Down
22 changes: 22 additions & 0 deletions test/cases/000_build/000_formats/013_iso-efi-initrd/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/sh
# SUMMARY: Check that iso-efi-initrd output format is generated
# LABELS:

set -e

# Source libraries. Uncomment if needed/defined
#. "${RT_LIB}"
. "${RT_PROJECT_ROOT}/_lib/lib.sh"

NAME=check

clean_up() {
rm -f ${NAME}*
}

trap clean_up EXIT

linuxkit build -format iso-efi-initrd -name "${NAME}" ../test.yml
[ -f "${NAME}"-efi-initrd.iso ] || exit 1

exit 0
21 changes: 21 additions & 0 deletions tools/mkimage-iso-efi-initrd/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM linuxkit/grub:4de02c056b3295f510b7fb4f9b5a2785f854ac23 AS grub

FROM linuxkit/alpine:33063834cf72d563cd8703467836aaa2f2b5a300 AS mirror
RUN mkdir -p /out/etc/apk && cp -r /etc/apk/* /out/etc/apk/
RUN apk add --no-cache --initdb -p /out \
alpine-baselayout \
binutils \
busybox \
dosfstools \
libarchive-tools \
mtools \
xorriso \
&& true
RUN mv /out/etc/apk/repositories.upstream /out/etc/apk/repositories

FROM scratch
WORKDIR /
COPY --from=mirror /out/ /
COPY --from=grub /BOOT*.EFI /usr/local/share/
COPY . .
ENTRYPOINT [ "/make-efi-initrd" ]
5 changes: 5 additions & 0 deletions tools/mkimage-iso-efi-initrd/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
image: mkimage-iso-efi-initrd
network: true
arches:
- amd64
- arm64
62 changes: 62 additions & 0 deletions tools/mkimage-iso-efi-initrd/make-efi-initrd
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/bin/sh

set -e

# get the GRUB2 boot file name
ARCH=`uname -m`
case $ARCH in
x86_64)
BOOTFILE=BOOTX64.EFI
LINUX_ENTRY=linuxefi
INITRD_ENTRY=initrdefi
;;
aarch64)
BOOTFILE=BOOTAA64.EFI
LINUX_ENTRY=linux
INITRD_ENTRY=initrd
;;
esac

mkdir -p /tmp/efi
cd /tmp/efi

# input is a tarball on stdin with kernel and cmdline in /boot
# output is an iso on stdout

# extract. BSD tar auto recognises compression, unlike GNU tar
# only if stdin is a tty, if so need files volume mounted...
[ -t 0 ] || bsdtar xzf -

CMDLINE="$(cat cmdline)"
rm cmdline

cp /usr/local/share/$BOOTFILE .

CFG="set timeout=0
set gfxpayload=text
menuentry 'LinuxKit ISO Image' {
$LINUX_ENTRY /kernel ${CMDLINE} text
$INITRD_ENTRY /initrd.img
}
"

mkdir -p EFI/BOOT
printf "$CFG" > EFI/BOOT/grub.cfg

# create a ISO with a EFI boot partition
# Stuff it into a FAT filesystem, making it as small as possible. 511KiB
# headroom seems to be enough; (x+31)/32*32 rounds up to multiple of 32.
mkfs.vfat -v -C boot.img \
$(( ($(stat -c %s "${BOOTFILE}") / 1024 + 511) \
/ 32 * 32 )) > /dev/null
echo "mtools_skip_check=1" >> /etc/mtools.conf && \
mmd -i boot.img ::/EFI
mmd -i boot.img ::/EFI/BOOT
mcopy -i boot.img $BOOTFILE ::/EFI/BOOT/

rm $BOOTFILE

xorriso -as mkisofs \
-R -e boot.img -hide boot.img -hide boot.catalog -no-emul-boot -o linuxkit-efi-initrd.iso .

cat linuxkit-efi-initrd.iso

0 comments on commit 860934d

Please sign in to comment.