Added proper UEFI support. The ISO image can be 'burned' on USB flash drive (dd if=mll.iso of=/dev/xyz) and it works on UEFI systems (tested with QEMU and virtual hdd image). The 'hybrid' support also works and one ISO/hdd can be used on both firmware types.

This commit is contained in:
Ivan Davidov 2017-12-18 01:23:22 +02:00
parent 58e1b5b939
commit 38716fc00d
9 changed files with 382 additions and 72 deletions

View File

@ -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 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 section contains configuration properties #
# # # #
#################################################### ####################################################
# This property is not used at the moment. # This property defines the firmware compatibility, i.e. on which systems MLL
# # will be bootable.
# This property defines the firmware compatibility. You can specify on what
# systems MLL will be bootable.
# #
# bios - the generated ISO image will be compatible with legacy BIOS systems. # 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 # uefi - the generated ISO image will be compatible with UEFI systems. This
# option requires root privileges. # option requires root privileges.

View File

@ -7,11 +7,6 @@ set -e
echo "*** BUILD KERNEL BEGIN ***" 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'. # Change to the kernel source directory which ls finds, e.g. 'linux-4.4.6'.
cd `ls -d $WORK_DIR/kernel/linux-*` cd `ls -d $WORK_DIR/kernel/linux-*`
@ -95,6 +90,11 @@ make \
CFLAGS="$CFLAGS" \ CFLAGS="$CFLAGS" \
bzImage -j $NUM_JOBS 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. # Install the kernel file.
cp arch/x86/boot/bzImage \ cp arch/x86/boot/bzImage \
$KERNEL_INSTALLED/kernel $KERNEL_INSTALLED/kernel

View File

@ -5,19 +5,44 @@ set -e
# Load common properties and functions in the current script. # Load common properties and functions in the current script.
. ./common.sh . ./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 ***" echo "*** GET SYSLINUX BEGIN ***"
# Read the 'SYSLINUX_SOURCE_URL' property from '.config'. # Read the 'FIRMWARE_TYPE' property from '.config'.
DOWNLOAD_URL=`read_property SYSLINUX_SOURCE_URL` FIRMWARE_TYPE=`read_property FIRMWARE_TYPE`
echo "Firmware type is '$FIRMWARE_TYPE'."
# Grab everything after the last '/' character. case $FIRMWARE_TYPE in
ARCHIVE_FILE=${DOWNLOAD_URL##*/} bios)
download
;;
# Download Syslinux source archive in the 'source' directory. both)
download_source $DOWNLOAD_URL $SOURCE_DIR/$ARCHIVE_FILE download
;;
# Extract the Syslinux sources in the 'work/syslinux' directory. uefi)
extract_source $SOURCE_DIR/$ARCHIVE_FILE syslinux 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. # We go back to the main MLL source folder.
cd $SRC_DIR cd $SRC_DIR

50
src/12_get_systemd-boot.sh Executable file
View File

@ -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 ***"

View File

@ -5,59 +5,201 @@ set -e
# Load common properties and functions in the current script. # Load common properties and functions in the current script.
. ./common.sh . ./common.sh
echo "*** PREPARE ISO BEGIN ***"
# Find the Syslinux build directory. # Find the Syslinux build directory.
WORK_SYSLINUX_DIR=`ls -d $WORK_DIR/syslinux/syslinux-*` WORK_SYSLINUX_DIR=`ls -d $WORK_DIR/syslinux/syslinux-*`
# Remove the old ISO generation area if it exists. init() {
echo "Removing old ISO image work area. This may take a while." # Remove the old ISO generation area if it exists.
rm -rf $ISOIMAGE echo "Removing old ISO image work area. This may take a while."
rm -rf $ISOIMAGE
echo "Preparing new ISO image work area." echo "Preparing new ISO image work area."
mkdir -p $ISOIMAGE mkdir -p $ISOIMAGE
}
# This is the folder where we keep legacy BIOS boot artifacts. prepare_mll_bios() {
mkdir -p $ISOIMAGE/boot # This is the folder where we keep legacy BIOS boot artifacts.
mkdir -p $ISOIMAGE/boot
# Now we copy the kernel. # Now we copy the kernel.
cp $KERNEL_INSTALLED/kernel \ cp $KERNEL_INSTALLED/kernel \
$ISOIMAGE/boot/kernel.xz $ISOIMAGE/boot/kernel.xz
# Now we copy the root file system. # Now we copy the root file system.
cp $WORK_DIR/rootfs.cpio.xz \ cp $WORK_DIR/rootfs.cpio.xz \
$ISOIMAGE/boot/rootfs.xz $ISOIMAGE/boot/rootfs.xz
}
# Now we copy the overlay content if it exists prepare_overlay() {
if [ -d $ISOIMAGE_OVERLAY \ # Now we copy the overlay content if it exists.
-a ! "`ls $ISOIMAGE_OVERLAY`" = "" ] ; then if [ -d $ISOIMAGE_OVERLAY \
-a ! "`ls $ISOIMAGE_OVERLAY`" = "" ] ; then
echo "The ISO image will have overlay structure." echo "The ISO image will have overlay structure."
cp -r $ISOIMAGE_OVERLAY/* $ISOIMAGE cp -r $ISOIMAGE_OVERLAY/* $ISOIMAGE
else else
echo "The ISO image will have no overlay structure." echo "The ISO image will have no overlay structure."
fi fi
}
# Add the Syslinux configuration files for legacy BIOS and additional prepare_boot_bios() {
# UEFI startup script. # 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 # The existing UEFI startup script does not guarantee that you can run
# drops you in UEFI shell with support level 1 or above. See UEFI shell # MLL on UEFI systems. This script is invoked only in case your system
# specification 2.2, section 3.1. Depending on your system configuration # drops you in UEFI shell with support level 1 or above. See UEFI shell
# you may not end up with UEFI shell even if your system supports it. # specification 2.2, section 3.1. Depending on your system configuration
# In this case MLL will not boot and you will end up with some kind of # you may not end up with UEFI shell even if your system supports it.
# UEFI error message. # In this case MLL will not boot and you will end up with some kind of
cp -r $SRC_DIR/minimal_boot/bios/* \ # UEFI error message.
$ISOIMAGE 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 cd $SRC_DIR

View File

@ -5,6 +5,58 @@ set -e
# Load common properties and functions in the current script. # Load common properties and functions in the current script.
. ./common.sh . ./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 ***" echo "*** GENERATE ISO BEGIN ***"
if [ ! -d $ISOIMAGE ] ; then if [ ! -d $ISOIMAGE ] ; then
@ -12,19 +64,28 @@ if [ ! -d $ISOIMAGE ] ; then
exit 1 exit 1
fi 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 case $FIRMWARE_TYPE in
# USB flash drive, e.g. 'dd if=minimal_linux_live.iso of=/dev/sdb'. bios)
xorriso -as mkisofs \ bios
-isohybrid-mbr $WORK_DIR/syslinux/syslinux-*/bios/mbr/isohdpfx.bin \ ;;
-c boot/syslinux/boot.cat \
-b boot/syslinux/isolinux.bin \ uefi)
-no-emul-boot \ uefi
-boot-load-size 4 \ ;;
-boot-info-table \
-o $SRC_DIR/minimal_linux_live.iso \ both)
$ISOIMAGE both
;;
*)
echo "Firmware type '$FIRMWARE_TYPE' is not recognized. Cannot continue."
exit 1
;;
esac
cd $SRC_DIR cd $SRC_DIR

28
src/qemu-uefi.sh Executable file
View File

@ -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