From: Michael Prokop Date: Wed, 7 Jun 2017 21:25:34 +0000 (+0200) Subject: Support EFI on 32-bit systems, increase EFI image size + switch from isohybrid to... X-Git-Tag: v0.30.0~6 X-Git-Url: https://git.grml.org/?p=grml-live.git;a=commitdiff_plain;h=6725bfa1ffc4b823d0413b1fa018776e4f4a432d Support EFI on 32-bit systems, increase EFI image size + switch from isohybrid to xorriso/isohybrid combination EFI on 32-bit systems is a requested feature for Grml-Forensic, since cheap tablets and notebooks (e.g. Intel Atom-based tablets) are out there with only 32-bit EFI support (and UEFI only, so no legacy BIOS support), quoting clairelyclaire from https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1341944: | As of now, Ubuntu and other major Linux distributions do not | support the use of a 32-bit EFI bootloader on UEFI machines. This | has become extremely problematic due to the popularity of Intel | Atom-based tablets and compact laptops. Atom-based devices are | generally limited in storage space (32GB or 64GB eMMC is common), | and as a result these devices almost universally ship with | Windows 8.1 32-bit installed (winsxs consumes a significant | amount of storage space in order to support 32-bit binaries in a | 64-bit environment). By design, UEFI must use the same | architecture used by the bootloader. | | While most modern computers indeed use a 64-bit UEFI | implementation due to the fact that new computers generally ship | with a 64-bit operating system (be it OS X or Windows 8.1), | Atom-based devices do *not* use a 64-bit operating system or UEFI | implementation. This is by design. | | Intel released a new Atom iteration (Bay Trail) in late 2013 and | has indicated that they will continue to develop and release Atom | CPUs due to consumer market demand. At the time of this filing | there are a number of Atom-based tablets and compact | laptops/netbooks being actively sold and marketed by major OEMs | including Dell, HP, ASUS, and Acer. None of these devices have | 64-bit UEFI firmware. It is also important to note that these | Atom CPUs are 64-bit, but explicitly require a 32-bit UEFI | bootloader. | | The current Linux kernel in Ubuntu 14.04 does support booting the | 64-bit signed kernel from a 32-bit Grub EFI bootloader. I can | confirm this on at least two 32-bit UEFI devices, the ASUS | Transformer T100TA and the Acer Aspire Switch 10. Increase EFI image size (previously automatically calculated on-demand, resulting in ~285KB) to 4MB, giving us more flexibility with what we're installing into the image (esp. useful with usage on USB drives). The isohybrid binary doesn't support 32-bit FI systems and fails hard when using `--uefi` on a 32-bit ISO. But xorriso with appropriate options for EFI usage (see $EFI_ARGS) and /usr/lib/ISOLINUX/isohdpfx.bin from the isolinux package seems to provide everything we need. Useful resources for further information: * http://www.syslinux.org/wiki/index.php?title=Isohybrid * https://fedoraproject.org/wiki/Using_UEFI_with_QEMU * https://wiki.archlinux.org/index.php/Remastering_the_Install_ISO For testing the resulting 32-bit ISO with EFI the OVMF.fd file from OVMF-IA32-r15214.zip available from https://sourceforge.net/projects/edk2/files/OVMF/ works via e.g.: | qemu-system-i386 -m 1024 -bios ./OVMF.fd -cdrom grml.iso --- diff --git a/debian/control b/debian/control index 29a09af..f28c684 100644 --- a/debian/control +++ b/debian/control @@ -19,6 +19,7 @@ Depends: bc, bzip2, fai-client (>= 3.4.0), fai-server (>= 3.4.0), + isolinux (>= 3:6.03+dfsg-5+deb8u1~), memtest86+, mksh, moreutils, diff --git a/etc/grml/fai/config/scripts/GRMLBASE/45-grub-images b/etc/grml/fai/config/scripts/GRMLBASE/45-grub-images index 7b66dcb..42ed130 100755 --- a/etc/grml/fai/config/scripts/GRMLBASE/45-grub-images +++ b/etc/grml/fai/config/scripts/GRMLBASE/45-grub-images @@ -7,9 +7,11 @@ ################################################################################ set -e +set -u BOOTX64="${target}/boot/bootx64.efi" +BOOTX32="${target}/boot/bootia32.efi" EFI_IMG="${target}/boot/efi.img" TMP_CONFIG="${target}/tmp/grub_config_efi" @@ -24,6 +26,7 @@ echo "E: Could not find root device!" EOF BOOTX64="${BOOTX64##${target}}" +BOOTX32="${BOOTX32##${target}}" EFI_IMG="${EFI_IMG##${target}}" TMP_CONFIG="${TMP_CONFIG##${target}}" @@ -40,17 +43,21 @@ if ifclass AMD64 ; then echo "/usr/lib/grub/x86_64-efi/moddep.lst could not be found, skipping." echo "NOTE: grub-efi-amd64-bin not installed?" fi +elif ifclass I386 ; then + if [ -r "${target}"/usr/lib/grub/i386-efi/moddep.lst ] ; then + ARCHS+=(i386-efi) + ADDITIONAL_MODULES[i386-efi]="efi_gop efi_uga" + else + echo "/usr/lib/grub/i386-efi/moddep.lst could not be found, skipping." + echo "NOTE: grub-efi-ia32 not installed?" + fi fi -BOOTX64="${BOOTX64##${target}}" -EFI_IMG="${EFI_IMG##${target}}" -TMP_CONFIG="${TMP_CONFIG##${target}}" - for arch in ${ARCHS[@]} ; do -$ROOTCMD grub-mkimage -O $arch -o /boot/$arch.img --prefix=/boot/grub/ --config="$TMP_CONFIG" \ - echo iso9660 part_msdos search_fs_file test \ - fat ext2 reiserfs xfs btrfs squash4 part_gpt lvm \ - ${ADDITIONAL_MODULES[$arch]} + $ROOTCMD grub-mkimage -O $arch -o /boot/$arch.img --prefix=/boot/grub/ --config="$TMP_CONFIG" \ + echo iso9660 part_msdos search_fs_file test \ + fat ext2 reiserfs xfs btrfs squash4 part_gpt lvm \ + ${ADDITIONAL_MODULES[$arch]} done if [ -f "${target}/boot/i386-pc.img" ] ; then @@ -61,27 +68,40 @@ if [ -f "${target}/boot/x86_64-efi.img" ] ; then mv "${target}/boot/x86_64-efi.img" "${target}/${BOOTX64}" fi +if [ -f "${target}/boot/i386-efi.img" ] ; then + mv "${target}/boot/i386-efi.img" "${target}/${BOOTX32}" +fi + if ifclass AMD64 ; then if ! [ -r "${target}/${BOOTX64}" ] ; then - echo "Can not access grub efi image." >&2 + echo "Can not access grub efi image ${BOOTX64}." >&2 exit 1 fi - SIZE=$(du --apparent-size -sk "${target}/${BOOTX64}" | awk -F" " '{print $1}') - SIZE=$(((($SIZE / 32 )+2)*32)) - - dd if=/dev/zero of="${target}/${EFI_IMG}" bs=1k count="$SIZE" 2>/dev/null + dd if=/dev/zero of="${target}/${EFI_IMG}" bs=4M count=1 2>/dev/null $ROOTCMD mkfs.vfat -n GRML "$EFI_IMG" >/dev/null $ROOTCMD mmd -i "$EFI_IMG" ::EFI $ROOTCMD mmd -i "$EFI_IMG" ::EFI/BOOT $ROOTCMD mcopy -i "$EFI_IMG" "$BOOTX64" ::EFI/BOOT/bootx64.efi >/dev/null - echo "Generated EFI image $BOOTX64" - echo "Generated bootx64 image $EFI_IMG" + echo "Generated 64-bit EFI image $BOOTX64" +elif ifclass I386 ; then + if ! [ -r "${target}/${BOOTX32}" ] ; then + echo "Can not access grub efi image ${BOOTX32}." >&2 + exit 1 + fi + + dd if=/dev/zero of="${target}/${EFI_IMG}" bs=4M count=1 2>/dev/null + $ROOTCMD mkfs.vfat -n GRML "$EFI_IMG" >/dev/null + $ROOTCMD mmd -i "$EFI_IMG" ::EFI + $ROOTCMD mmd -i "$EFI_IMG" ::EFI/BOOT + $ROOTCMD mcopy -i "$EFI_IMG" "$BOOTX32" ::EFI/BOOT/bootia32.efi >/dev/null + echo "Generated 32-bit EFI image $BOOTX32" fi +echo "Generated EFI image $EFI_IMG" + rm -f "${target}/${TMP_CONFIG}" echo "Generated Grub images" - ## END OF FILE ################################################################# # vim:ft=sh expandtab ai tw=80 tabstop=4 shiftwidth=2 diff --git a/grml-live b/grml-live index bdefd28..2e7aad7 100755 --- a/grml-live +++ b/grml-live @@ -891,13 +891,23 @@ if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then # EFI boot files if [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootx64.efi" ] ; then - einfo "Moving EFI boot files into ISO path." - log "Moving EFI boot files into ISO path." - RC=$0 - mv "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$? - mkdir -p "${BUILD_OUTPUT}/efi/boot/" || RC=$? - mv "${CHROOT_OUTPUT}/boot/bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi" || RC=$? - eend $? + einfo "Moving 64-bit EFI boot files into ISO path." + log "Moving 64-bit EFI boot files into ISO path." + RC=$0 + mv "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$? + mkdir -p "${BUILD_OUTPUT}/efi/boot/" || RC=$? + mv "${CHROOT_OUTPUT}/boot/bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi" || RC=$? + eend $? + elif [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootia32.efi" ] ; then + einfo "Moving 32-bit EFI boot files into ISO path." + log "Moving 32-bit EFI boot files into ISO path." + RC=$0 + mv "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$? + mkdir -p "${BUILD_OUTPUT}/efi/boot/" || RC=$? + mv "${CHROOT_OUTPUT}/boot/bootia32.efi" "${BUILD_OUTPUT}/efi/boot/bootia32.efi" || RC=$? + eend $? + else + ewarn "No EFI boot files found, skipping." ; eend 0 fi [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates' @@ -999,10 +1009,14 @@ if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/ cp -a "${CHROOT_OUTPUT}"/boot/grub/grub.img "${BUILD_OUTPUT}"/boot/grub/ - # copy modules for UEFI grub + # copy modules for UEFI grub, 64-bit mkdir -p "${BUILD_OUTPUT}"/boot/grub/x86_64-efi/ cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/x86_64-efi/*.{mod,lst} "${BUILD_OUTPUT}"/boot/grub/x86_64-efi/ + # copy modules for UEFI grub, 32-bit + mkdir -p "${BUILD_OUTPUT}"/boot/grub/i386-efi/ + cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/i386-efi/*.{mod,lst} "${BUILD_OUTPUT}"/boot/grub/i386-efi/ + if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then log "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1 @@ -1277,6 +1291,9 @@ fi if [ "$BOOT_METHOD" = "isolinux" ] ; then BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat" + if [ "$HYBRID_METHOD" = "isohybrid" ] ; then + EFI_ARGS="-isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin -eltorito-alt-boot -e boot/efi.img -no-emul-boot -isohybrid-gpt-basdat" + fi elif [ "$BOOT_METHOD" = "grub2" ] ; then BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin" fi @@ -1350,9 +1367,9 @@ else echo 1 16 | mksh "${SCRIPTS_DIRECTORY}/bootgrub.mksh" -B 11 | \ dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null fi - log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ." + log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS $EFI_ARGS -no-pad -o ${ISO_OUTPUT}/${ISO_NAME} ." $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \ - -l -r -J $BOOT_ARGS -no-pad \ + -l -r -J $BOOT_ARGS $EFI_ARGS -no-pad \ -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$? # both of these need core.img there, so it’s easier to write it here if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then @@ -1400,33 +1417,7 @@ else eend $? fi elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then - if ! which isohybrid >/dev/null 2>&1 ; then - bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common/syslinux-utils" - else - log "Creating hybrid ISO file with isohybrid method" - einfo "Creating hybrid ISO file with isohybrid method" - # Notes for consideration: - # "-entry 4 -type 1c" - # * using 4 as the partition number is supposed to help with BIOSes - # that only support USB-Zip boot - # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17 - # (hidden NTFS, IIRC), as the partition type is sometimes needed - # to get the BIOS even look at the partition created by isohybrid - if isohybrid --help | grep -q -- --uefi ; then - if echo $CLASSES | grep -qw I386 ; then - log "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring." - einfo "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring." - else - log "Detected uefi support for isohybrid, enabling" - einfo "Detected uefi support for isohybrid, enabling" - ISOHYBRID_OPTIONS=--uefi - fi - fi - - log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}" - isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}" - eend $? - fi + : # nothing to do, handled via $MKISOFS $EFI_ARGS already else bailout 12 "Unknown HYBRID_METHOD [${HYBRID_METHOD}]. Supported values: disable, isohybrid, grub2, manifold" fi