EFI-32 ISO erstellen

Aus wiki.archlinux.de
Version vom 30. Oktober 2020, 23:09 Uhr von Arisinfenix (Diskussion | Beiträge) (Script aktualisiert)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

Auf Geräten die nur ein 32-Bit UEFI besitzen, lässt sich das normale Installations ISO nicht starten. Das offizielle ISO kann jedoch modifiziert werden damit es auch auf 32-Bit UEFI Geräten geladen werden kann. Zum Beispiel mit diesem Script:

#!/bin/bash
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Description: Remaster Arch Linux ISO with 32-bit EFI
# Dependencies:
# 	command             : Arch package
#       --------------------------------------
#	grub-mkstandalone   : grub
#	xorriso             : libisoburn
#	mcopy               : mtools
#
# Example: efi32iso ./archlinux-2020.10.01-x86_64.iso
# Creates: ./archlinux-2020.10.01-x86_64-efi32.iso
#

work_dir="/tmp/efi32iso"

cleanup() {
	umount "${efi_image_dir}" 2>/dev/null
	umount "${iso_dir}"
	rm -r "${work_dir}"
	exit ${1}
}

if ((UID != 0)); then
	printf "This script requires root privileges!\n"
	exit 1
fi

if (($# != 1)); then
	printf "Usage: $(basename "${0}") <input_file>\n"
	exit 1
fi

! type -p grub-mkstandalone >/dev/null &&
	printf "grub-mkstandalone not found\n" &&
	exit 1

! type -p xorriso >/dev/null &&
	printf "xorriso not found\n" &&
	exit 1

! type -p mcopy >/dev/null &&
	printf "mcopy not found\n" &&
	exit 1

# check if we have an Arch iso, pattern tested with 2020.10.01
pattern="ISO 9660 CD-ROM filesystem data (DOS/MBR boot sector) 'ARCH_"
if [[ "$(file -b "${1}")" != "${pattern}"* ]]; then
	printf "Not a valid iso file!\n"
	exit 1
fi

mkdir "${work_dir}" || exit 1

iso_file="${1}"
out_file="${iso_file/.iso/-efi32.iso}"
grub_config="${work_dir}/grub.cfg"
efi32_loader="${work_dir}/bootia32.efi"
efi_image_dir="${work_dir}/efi_image" # mount point for original efiboot image
iso_dir="${work_dir}/archiso" # mount point for original iso
new_iso_dir="${work_dir}/newiso" # working directory for new iso

# create grub config
cat << 'EOF' > "${grub_config}"
insmod part_gpt
insmod part_msdos
insmod fat
insmod efi_gop
insmod efi_uga
insmod video_bochs
insmod video_cirrus
insmod font

if loadfont "${prefix}/fonts/unicode.pf2" ; then
  insmod gfxterm
  set gfxmode="1024x768x32;auto"
  terminal_input console
  terminal_output gfxterm
fi

menuentry "Arch Linux archiso x86_64" {
  set gfxpayload=keep
  search --no-floppy --set=root --label ARCH_YYYYMM
  linux /arch/boot/x86_64/vmlinuz archisobasedir=arch archisolabel=ARCH_YYYYMM add_efi_memmap
  initrd /arch/boot/x86_64/archiso.img
}

menuentry "UEFI Shell x86_64 v2" {
  search --no-floppy --set=root --label ARCH_YYYYMM
  chainloader /EFI/shellx64_v2.efi
}

menuentry "UEFI Shell x86_64 v1" {
  search --no-floppy --set=root --label ARCH_YYYYMM
  chainloader /EFI/shellx64_v1.efi
}
EOF

# extract the iso
mkdir "${iso_dir}"
mount -t iso9660 -o loop "${iso_file}" "${iso_dir}" || cleanup 1
cp -a "${iso_dir}" "${new_iso_dir}" || cleanup 1

# get label and write it to the grub config
label="$(awk -F '=' '/archisolabel/ {print $3}' \
	"${new_iso_dir}/loader/entries/archiso-x86_64-linux.conf")"
sed -i "s/ARCH_YYYYMM/${label}/g" "${grub_config}"

# generate 32-bit EFI loader
grub-mkstandalone \
	-d /usr/lib/grub/i386-efi/ \
	-O i386-efi \
	--modules="part_gpt part_msdos" \
	--fonts="unicode" \
	--locales="en@quot" \
	--themes="" \
	-o "${efi32_loader}" \
	"boot/grub/grub.cfg=${grub_config}" || cleanup 1

# copy 32-bit EFI loader to new iso
cp "${efi32_loader}" "${new_iso_dir}/EFI/BOOT/bootia32.efi" || cleanup 1

# mount origianl efiboot image
mkdir "${efi_image_dir}"
mount -t vfat -o loop "${new_iso_dir}/EFI/archiso/efiboot.img" "${efi_image_dir}" || cleanup 1

# calculate new efiboot image size
new_efiboot_imgsize="$(du -bc \
	"${new_iso_dir}/EFI/archiso/efiboot.img" \
	"${new_iso_dir}/EFI/BOOT/bootia32.efi" \
	2>/dev/null | awk 'function ceil(x){return int(x)+(x>int(x))}
			   function byte_to_kib(x){return x/1024}
			   function mib_to_kib(x){return x*1024}
			   END {print mib_to_kib(ceil((byte_to_kib($1)+1024)/1024))}'
)"

# copy files from original efiboot.img and 32-bit EFI loader to a new image
mkfs.fat -C -n ARCHISO_EFI "${work_dir}/new_efiboot.img" "${new_efiboot_imgsize}" || cleanup 1
mcopy -s -i "${work_dir}/new_efiboot.img" "${efi_image_dir}"/* ::/ || cleanup 1
mcopy -i "${work_dir}/new_efiboot.img" "${efi32_loader}" ::EFI/BOOT || cleanup 1

# copy new efiboot image to new iso
umount "${efi_image_dir}"
cp "${work_dir}/new_efiboot.img" "${new_iso_dir}/EFI/archiso/efiboot.img" || cleanup 1

# create new iso
xorriso -as mkisofs \
	-iso-level 3 \
	-full-iso9660-filenames \
	-volid "${label}" \
	-eltorito-boot isolinux/isolinux.bin \
	-eltorito-catalog isolinux/boot.cat \
	-no-emul-boot \
	-boot-load-size 4 \
	-boot-info-table \
	-isohybrid-mbr "${new_iso_dir}/isolinux/isohdpfx.bin" \
	-eltorito-alt-boot \
	-e EFI/archiso/efiboot.img \
	-no-emul-boot \
	-isohybrid-gpt-basdat \
	-output "${out_file}" \
	"${new_iso_dir}"

cleanup 0