diff --git a/src/.config b/src/.config index a819bad84..616bf0cb3 100644 --- a/src/.config +++ b/src/.config @@ -33,19 +33,23 @@ BUSYBOX_SOURCE_URL=http://busybox.net/downloads/busybox-1.27.2.tar.bz2 # SYSLINUX_SOURCE_URL=http://kernel.org/pub/linux/utils/boot/syslinux/syslinux-6.03.tar.xz +# You can find the latest 'systemd-boot' source bundles here: +# +# http://github.com/ivandavidov/systemd-boot +# +SYSTEMD-BOOT_SOURCE_URL=https://github.com/ivandavidov/systemd-boot/releases/download/systemd-boot_10-Dec-2017/systemd-boot_10-Dec-2017.tar.xz + #################################################### # # # This section contains configuration properties # # # #################################################### -# This property is not used at the moment. -# -# This property defines the firmware compatibility. You can specify on what -# systems MLL will be bootable. +# This property defines the firmware compatibility, i.e. on which systems MLL +# will be bootable. # # bios - the generated ISO image will be compatible with legacy BIOS systems. -# This is the defaut option and it does not require root privileges +# This is the default option and it does not require root privileges. # # uefi - the generated ISO image will be compatible with UEFI systems. This # option requires root privileges. diff --git a/src/02_build_kernel.sh b/src/02_build_kernel.sh index 8a9be60fa..8599406ad 100755 --- a/src/02_build_kernel.sh +++ b/src/02_build_kernel.sh @@ -7,11 +7,6 @@ set -e echo "*** BUILD KERNEL BEGIN ***" -# Prepare the kernel install area. -echo "Removing old kernel artifacts. This may take a while." -rm -rf $KERNEL_INSTALLED -mkdir $KERNEL_INSTALLED - # Change to the kernel source directory which ls finds, e.g. 'linux-4.4.6'. cd `ls -d $WORK_DIR/kernel/linux-*` @@ -95,6 +90,11 @@ make \ CFLAGS="$CFLAGS" \ bzImage -j $NUM_JOBS +# Prepare the kernel install area. +echo "Removing old kernel artifacts. This may take a while." +rm -rf $KERNEL_INSTALLED +mkdir $KERNEL_INSTALLED + # Install the kernel file. cp arch/x86/boot/bzImage \ $KERNEL_INSTALLED/kernel diff --git a/src/12_get_syslinux.sh b/src/12_get_syslinux.sh index a20e2e620..4038312d0 100755 --- a/src/12_get_syslinux.sh +++ b/src/12_get_syslinux.sh @@ -5,19 +5,44 @@ set -e # Load common properties and functions in the current script. . ./common.sh +download() { + # Read the 'SYSLINUX_SOURCE_URL' property from '.config'. + DOWNLOAD_URL=`read_property SYSLINUX_SOURCE_URL` + + # Grab everything after the last '/' character. + ARCHIVE_FILE=${DOWNLOAD_URL##*/} + + # Download Syslinux source archive in the 'source' directory. + download_source $DOWNLOAD_URL $SOURCE_DIR/$ARCHIVE_FILE + + # Extract the Syslinux sources in the 'work/syslinux' directory. + extract_source $SOURCE_DIR/$ARCHIVE_FILE syslinux +} + echo "*** GET SYSLINUX BEGIN ***" -# Read the 'SYSLINUX_SOURCE_URL' property from '.config'. -DOWNLOAD_URL=`read_property SYSLINUX_SOURCE_URL` +# Read the 'FIRMWARE_TYPE' property from '.config'. +FIRMWARE_TYPE=`read_property FIRMWARE_TYPE` +echo "Firmware type is '$FIRMWARE_TYPE'." -# Grab everything after the last '/' character. -ARCHIVE_FILE=${DOWNLOAD_URL##*/} +case $FIRMWARE_TYPE in + bios) + download + ;; -# Download Syslinux source archive in the 'source' directory. -download_source $DOWNLOAD_URL $SOURCE_DIR/$ARCHIVE_FILE + both) + download + ;; -# Extract the Syslinux sources in the 'work/syslinux' directory. -extract_source $SOURCE_DIR/$ARCHIVE_FILE syslinux + uefi) + echo "Syslinux download has been skipped." + ;; + + *) + echo "Firmware type '$FIRMWARE_TYPE' is not recognized. Cannot continue." + ;; + +esac # We go back to the main MLL source folder. cd $SRC_DIR diff --git a/src/12_get_systemd-boot.sh b/src/12_get_systemd-boot.sh new file mode 100755 index 000000000..fbba98f9d --- /dev/null +++ b/src/12_get_systemd-boot.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +set -e + +# Load common properties and functions in the current script. +. ./common.sh + +download() { + # Read the 'SYSTEMD-BOOT_SOURCE_URL' property from '.config'. + DOWNLOAD_URL=`read_property SYSTEMD-BOOT_SOURCE_URL` + + # Grab everything after the last '/' character. + ARCHIVE_FILE=${DOWNLOAD_URL##*/} + + # Download systemd-boot source archive in the 'source' directory. + download_source $DOWNLOAD_URL $SOURCE_DIR/$ARCHIVE_FILE + + # Extract the 'systemd-boot' sources in the 'work/systemd-boot' directory. + extract_source $SOURCE_DIR/$ARCHIVE_FILE systemd-boot +} + +echo "*** GET SYSTEMD-BOOT BEGIN ***" + +# Read the 'FIRMWARE_TYPE' property from '.config'. +FIRMWARE_TYPE=`read_property FIRMWARE_TYPE` +echo "Firmware type is '$FIRMWARE_TYPE'." + +case $FIRMWARE_TYPE in + uefi) + download + ;; + + both) + download + ;; + + bios) + echo "'systemd-boot' download has been skipped." + ;; + + *) + echo "Firmware type '$FIRMWARE_TYPE' is not recognized. Cannot continue." + ;; + +esac + +# We go back to the main MLL source folder. +cd $SRC_DIR + +echo "*** GET SYSTEMD-BOOT END ***" diff --git a/src/13_prepare_iso.sh b/src/13_prepare_iso.sh index 979b6267f..9446691cd 100755 --- a/src/13_prepare_iso.sh +++ b/src/13_prepare_iso.sh @@ -5,59 +5,201 @@ set -e # Load common properties and functions in the current script. . ./common.sh -echo "*** PREPARE ISO BEGIN ***" - # Find the Syslinux build directory. WORK_SYSLINUX_DIR=`ls -d $WORK_DIR/syslinux/syslinux-*` -# Remove the old ISO generation area if it exists. -echo "Removing old ISO image work area. This may take a while." -rm -rf $ISOIMAGE +init() { + # Remove the old ISO generation area if it exists. + echo "Removing old ISO image work area. This may take a while." + rm -rf $ISOIMAGE -echo "Preparing new ISO image work area." -mkdir -p $ISOIMAGE + echo "Preparing new ISO image work area." + mkdir -p $ISOIMAGE +} -# This is the folder where we keep legacy BIOS boot artifacts. -mkdir -p $ISOIMAGE/boot +prepare_mll_bios() { + # This is the folder where we keep legacy BIOS boot artifacts. + mkdir -p $ISOIMAGE/boot -# Now we copy the kernel. -cp $KERNEL_INSTALLED/kernel \ - $ISOIMAGE/boot/kernel.xz + # Now we copy the kernel. + cp $KERNEL_INSTALLED/kernel \ + $ISOIMAGE/boot/kernel.xz -# Now we copy the root file system. -cp $WORK_DIR/rootfs.cpio.xz \ - $ISOIMAGE/boot/rootfs.xz + # Now we copy the root file system. + cp $WORK_DIR/rootfs.cpio.xz \ + $ISOIMAGE/boot/rootfs.xz +} -# Now we copy the overlay content if it exists -if [ -d $ISOIMAGE_OVERLAY \ - -a ! "`ls $ISOIMAGE_OVERLAY`" = "" ] ; then +prepare_overlay() { + # Now we copy the overlay content if it exists. + if [ -d $ISOIMAGE_OVERLAY \ + -a ! "`ls $ISOIMAGE_OVERLAY`" = "" ] ; then - echo "The ISO image will have overlay structure." - cp -r $ISOIMAGE_OVERLAY/* $ISOIMAGE -else - echo "The ISO image will have no overlay structure." -fi + echo "The ISO image will have overlay structure." + cp -r $ISOIMAGE_OVERLAY/* $ISOIMAGE + else + echo "The ISO image will have no overlay structure." + fi +} -# Add the Syslinux configuration files for legacy BIOS and additional -# UEFI startup script. -# -# The existing UEFI startup script does not guarantee that you can run -# MLL on UEFI systems. This script is invoked only in case your system -# drops you in UEFI shell with support level 1 or above. See UEFI shell -# specification 2.2, section 3.1. Depending on your system configuration -# you may not end up with UEFI shell even if your system supports it. -# In this case MLL will not boot and you will end up with some kind of -# UEFI error message. -cp -r $SRC_DIR/minimal_boot/bios/* \ - $ISOIMAGE +prepare_boot_bios() { + # Add the Syslinux configuration files for legacy BIOS and additional + # UEFI startup script. + # + # The existing UEFI startup script does not guarantee that you can run + # MLL on UEFI systems. This script is invoked only in case your system + # drops you in UEFI shell with support level 1 or above. See UEFI shell + # specification 2.2, section 3.1. Depending on your system configuration + # you may not end up with UEFI shell even if your system supports it. + # In this case MLL will not boot and you will end up with some kind of + # UEFI error message. + cp -r $SRC_DIR/minimal_boot/bios/* \ + $ISOIMAGE + + # Copy the precompiled files 'isolinux.bin' and 'ldlinux.c32'. These files + # are used by Syslinux during the legacy BIOS boot process. + mkdir -p $ISOIMAGE/boot/syslinux + cp $WORK_SYSLINUX_DIR/bios/core/isolinux.bin \ + $ISOIMAGE/boot/syslinux + cp $WORK_SYSLINUX_DIR/bios/com32/elflink/ldlinux/ldlinux.c32 \ + $ISOIMAGE/boot/syslinux +} + +prepare_boot_uefi() { + # Find the build architecture based on the BusyBox executable. + BUSYBOX_ARCH=$(file $ROOTFS/bin/busybox | cut -d' ' -f3) + + # Determine the proper UEFI configuration. The default image file + # names are described in UEFI specification 2.7, section 3.5.1.1. + # Note that the x86_64 UEFI image file name indeed contains small + # letter 'x'. + if [ "$BUSYBOX_ARCH" = "64-bit" ] ; then + MLL_CONF=x86_64 + LOADER=$WORK_DIR/systemd-boot/systemd-boot*/uefi_root/EFI/BOOT/BOOTx64.EFI + else + MLL_CONF=x86 + LOADER=$WORK_DIR/systemd-boot/systemd-boot*/uefi_root/EFI/BOOT/BOOTIA32.EFI + fi + + # Find the kernel size in bytes. + kernel_size=`du -b $KERNEL_INSTALLED/kernel | awk '{print \$1}'` + + # Find the initramfs size in bytes. + rootfs_size=`du -b $WORK_DIR/rootfs.cpio.xz | awk '{print \$1}'` + + loader_size=`du -b $LOADER | awk '{print \$1}'` + + # The EFI boot image is 64KB bigger than the kernel size. + image_size=$((kernel_size + rootfs_size + loader_size + 65536)) + + echo "Creating UEFI boot image file '$WORK_DIR/uefi.img'." + rm -f $WORK_DIR/uefi.img + truncate -s $image_size $WORK_DIR/uefi.img + + echo "Attaching hard disk image file to loop device." + LOOP_DEVICE_HDD=$(losetup -f) + losetup $LOOP_DEVICE_HDD $WORK_DIR/uefi.img + + echo "Formatting hard disk image with FAT filesystem." + mkfs.vfat $LOOP_DEVICE_HDD + + echo "Preparing 'uefi' work area." + rm -rf $WORK_DIR/uefi + mkdir -p $WORK_DIR/uefi + mount $WORK_DIR/uefi.img $WORK_DIR/uefi + +# # Add the configuration files for UEFI boot. +# cp -r $SRC_DIR/minimal_boot/uefi/* \ +# $ISOIMAGE + + echo "Preparing kernel and rootfs." + mkdir -p $WORK_DIR/uefi/minimal/$MLL_CONF + cp $KERNEL_INSTALLED/kernel \ + $WORK_DIR/uefi/minimal/$MLL_CONF/kernel.xz + cp $WORK_DIR/rootfs.cpio.xz \ + $WORK_DIR/uefi/minimal/$MLL_CONF/rootfs.xz + + echo "Preparing 'systemd-boot' UEFI boot loader." + mkdir -p $WORK_DIR/uefi/EFI/BOOT + cp $LOADER \ + $WORK_DIR/uefi/EFI/BOOT + + echo "Preparing 'systemd-boot' configuration." + mkdir -p $WORK_DIR/uefi/loader/entries + cp $SRC_DIR/minimal_boot/uefi/loader/loader.conf \ + $WORK_DIR/uefi/loader + cp $SRC_DIR/minimal_boot/uefi/loader/entries/mll-${MLL_CONF}.conf \ + $WORK_DIR/uefi/loader/entries + + echo "Setting the default UEFI boot entry." + sed -i "s|default.*|default mll-$MLL_CONF|" $WORK_DIR/uefi/loader/loader.conf + + echo "Unmounting UEFI boot image file." + sync + umount $WORK_DIR/uefi + sync + sleep 1 + + # The directory is now empty (mount point for loop device). + rm -rf $WORK_DIR/uefi + + # Make sure the UEFI boot image is readable. + chmod ugo+r $WORK_DIR/uefi.img + + mkdir -p $ISOIMAGE/boot + cp $WORK_DIR/uefi.img \ + $ISOIMAGE/boot +} + +check_root() { + if [ ! "$(id -u)" = "0" ] ; then + cat << CEOF + + ISO image preparation process for UEFI systems requires root permissions + but you don't have such permissions. Restart this script with root + permissions in order to generate UEFI compatible ISO structure. + +CEOF + exit 1 + fi +} + +echo "*** PREPARE ISO BEGIN ***" + +# Read the 'FIRMWARE_TYPE' property from '.config' +FIRMWARE_TYPE=`read_property FIRMWARE_TYPE` +echo "Firmware type is '$FIRMWARE_TYPE'." + +case $FIRMWARE_TYPE in + bios) + init + prepare_boot_bios + prepare_mll_bios + prepare_overlay + ;; + + uefi) + check_root + init + prepare_boot_uefi + prepare_overlay + ;; + + both) + check_root + init + prepare_boot_uefi + prepare_boot_bios + prepare_mll_bios + prepare_overlay + ;; + + *) + echo "Firmware type '$FIRMWARE_TYPE' is not recognized. Cannot continue." + exit 1 + ;; +esac -# Copy the precompiled files 'isolinux.bin' and 'ldlinux.c32'. These files -# are used by Syslinux during the legacy BIOS boot process. -mkdir -p $ISOIMAGE/boot/syslinux -cp $WORK_SYSLINUX_DIR/bios/core/isolinux.bin \ - $ISOIMAGE/boot/syslinux -cp $WORK_SYSLINUX_DIR/bios/com32/elflink/ldlinux/ldlinux.c32 \ - $ISOIMAGE/boot/syslinux cd $SRC_DIR diff --git a/src/14_generate_iso.sh b/src/14_generate_iso.sh index 88dd81149..94791ccb1 100755 --- a/src/14_generate_iso.sh +++ b/src/14_generate_iso.sh @@ -5,6 +5,58 @@ set -e # Load common properties and functions in the current script. . ./common.sh +# Generate ISO image for UEFI based systems. +uefi() { + cd $ISOIMAGE + + # Now we generate 'hybrid' ISO image file which can also be used on + # USB flash drive, e.g. 'dd if=minimal_linux_live.iso of=/dev/sdb'. + xorriso -as mkisofs \ + -isohybrid-mbr $WORK_DIR/syslinux/syslinux-*/bios/mbr/isohdpfx.bin \ + -c boot.cat \ + -e boot/uefi.img \ + -no-emul-boot \ + -isohybrid-gpt-basdat \ + -o $SRC_DIR/minimal_linux_live.iso \ + $ISOIMAGE +} + +# Generate ISO image for BIOS based systems. +bios() { + cd $ISOIMAGE + + # Now we generate 'hybrid' ISO image file which can also be used on + # USB flash drive, e.g. 'dd if=minimal_linux_live.iso of=/dev/sdb'. + xorriso -as mkisofs \ + -isohybrid-mbr $WORK_DIR/syslinux/syslinux-*/bios/mbr/isohdpfx.bin \ + -c boot/syslinux/boot.cat \ + -b boot/syslinux/isolinux.bin \ + -no-emul-boot \ + -boot-load-size 4 \ + -boot-info-table \ + -o $SRC_DIR/minimal_linux_live.iso \ + $ISOIMAGE +} + +# Generate ISO image for both BIOS and UEFI based systems. +both() { + cd $ISOIMAGE + + xorriso -as mkisofs \ + -isohybrid-mbr $WORK_DIR/syslinux/syslinux-*/bios/mbr/isohdpfx.bin \ + -c boot/syslinux/boot.cat \ + -b boot/syslinux/isolinux.bin \ + -no-emul-boot \ + -boot-load-size 4 \ + -boot-info-table \ + -eltorito-alt-boot \ + -e boot/uefi.img \ + -no-emul-boot \ + -isohybrid-gpt-basdat \ + -o $SRC_DIR/minimal_linux_live.iso \ + $ISOIMAGE +} + echo "*** GENERATE ISO BEGIN ***" if [ ! -d $ISOIMAGE ] ; then @@ -12,19 +64,28 @@ if [ ! -d $ISOIMAGE ] ; then exit 1 fi -cd $ISOIMAGE +# Read the 'FIRMWARE_TYPE' property from '.config' +FIRMWARE_TYPE=`read_property FIRMWARE_TYPE` +echo "Firmware type is '$FIRMWARE_TYPE'." -# Now we generate 'hybrid' ISO image file which can also be used on -# USB flash drive, e.g. 'dd if=minimal_linux_live.iso of=/dev/sdb'. -xorriso -as mkisofs \ - -isohybrid-mbr $WORK_DIR/syslinux/syslinux-*/bios/mbr/isohdpfx.bin \ - -c boot/syslinux/boot.cat \ - -b boot/syslinux/isolinux.bin \ - -no-emul-boot \ - -boot-load-size 4 \ - -boot-info-table \ - -o $SRC_DIR/minimal_linux_live.iso \ - $ISOIMAGE +case $FIRMWARE_TYPE in + bios) + bios + ;; + + uefi) + uefi + ;; + + both) + both + ;; + + *) + echo "Firmware type '$FIRMWARE_TYPE' is not recognized. Cannot continue." + exit 1 + ;; +esac cd $SRC_DIR diff --git a/src/qemu.sh b/src/qemu-bios.sh similarity index 100% rename from src/qemu.sh rename to src/qemu-bios.sh diff --git a/src/qemu-uefi.sh b/src/qemu-uefi.sh new file mode 100755 index 000000000..d02b0cf81 --- /dev/null +++ b/src/qemu-uefi.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# Use this script without arguments to run the generated ISO image with QEMU. +# If you pass '-hdd' or '-h' the virtual hard disk 'hdd.img' will be attached. +# Note that this virtual hard disk has to be created in advance. You can use +# the script 'generate_hdd.sh' to generate the hard disk image file. Once you +# have hard disk image, you can use it as overlay device and persist all your +# changes. See the '.config' file for more information on the overlay support. +# +# If you get kernel panic with message "No working init found", then try to +# increase the RAM from 128M to 256M. + +# Location of the local file 'OVMF.fd' which is used as main firmware. You can +# download it here: +# +# https://sourceforge.net/projects/edk2/files/OVMF/ +# +OVMF_LOCATION=~/Downloads/OVMF.fd + +cmd="qemu-system-$(uname -m) -pflash $OVMF_LOCATION -m 128M -cdrom minimal_linux_live.iso -boot d -vga std" + +if [ "$1" = "-hdd" -o "$1" = "-h" ] ; then + echo "Starting QEMU with attached ISO image and hard disk." + $cmd -hda hdd.img > /dev/null 2>&1 & +else + echo "Starting QEMU with attached ISO image." + $cmd > /dev/null 2>&1 & +fi diff --git a/src/test_image.sh b/src/test_docker_image.sh similarity index 100% rename from src/test_image.sh rename to src/test_docker_image.sh