Since syslinux is only compatible with platforms that use x86-based CPUs, this change allows creation of bootable ISO images for other EFI-compatible platforms by replacing invocation of the isohybrid tool for those platforms with a python script that creates MBR partition table with a single entry that points to a bootable EFI image placed inside the ISO image.
Signed-off-by: Andrey Popov <andrey.po...@yadro.com> --- meta/classes/image-live.bbclass | 124 +++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 32 deletions(-) diff --git a/meta/classes/image-live.bbclass b/meta/classes/image-live.bbclass index 2c948190cf..6feaf8f3ac 100644 --- a/meta/classes/image-live.bbclass +++ b/meta/classes/image-live.bbclass @@ -1,15 +1,15 @@ # Copyright (C) 2004, Advanced Micro Devices, Inc. All Rights Reserved # Released under the MIT license (see packages/COPYING) -# Creates a bootable image using syslinux, your kernel and an optional +# Creates a bootable image using syslinux (for x86), your kernel and an optional # initrd # # End result is two things: # -# 1. A .hddimg file which is an msdos filesystem containing syslinux, a kernel, -# an initrd and a rootfs image. These can be written to harddisks directly and -# also booted on USB flash disks (write them there with dd). +# 1. A .hddimg file which is an msdos filesystem containing syslinux (for x86), +# a kernel, an initrd and a rootfs image. These can be written to harddisks +# directly and also booted on USB flash disks (write them there with dd). # # 2. A CD .iso image @@ -17,6 +17,10 @@ # in syslinux. Actions based on the label are then performed (e.g. installing to # an hdd) +# Since some versions of isohybrid are still looking for the isolinux.bin inside +# the target image, if machine does not have pcbios feature defined we have to +# use our own method to create EFI-bootable MBR. + # External variables (also used by syslinux.bbclass) # ${INITRD} - indicates a list of filesystem images to concatenate and use as an initrd (optional) # ${HDDIMG_ID} - FAT image volume-id @@ -28,8 +32,12 @@ do_bootimg[depends] += "dosfstools-native:do_populate_sysroot \ mtools-native:do_populate_sysroot \ cdrtools-native:do_populate_sysroot \ virtual/kernel:do_deploy \ - ${MLPREFIX}syslinux:do_populate_sysroot \ - syslinux-native:do_populate_sysroot \ + ${@bb.utils.contains('MACHINE_FEATURES', 'pcbios', \ + d.getVar('MLPREFIX') + 'syslinux:do_populate_sysroot \ + syslinux-native:do_populate_sysroot', '', d)} \ + ${@bb.utils.contains('MACHINE_FEATURES', 'efi', \ + bb.utils.contains('MACHINE_FEATURES', 'pcbios', \ + '', 'xorriso-native:do_populate_sysroot', d), '', d)} \ ${@'%s:do_image_%s' % (d.getVar('PN'), d.getVar('LIVE_ROOTFS_TYPE').replace('-', '_')) if d.getVar('ROOTFS') else ''} \ " @@ -65,19 +73,65 @@ COMPACT_ISODIR = "${S}/iso.z" ISOLINUXDIR ?= "/isolinux" ISO_BOOTIMG = "isolinux/isolinux.bin" ISO_BOOTCAT = "isolinux/boot.cat" -MKISOFS_OPTIONS = "-no-emul-boot -boot-load-size 4 -boot-info-table" +MKISOFS_BOOT_OPTIONS = "-no-emul-boot -boot-load-size 4 -boot-info-table" BOOTIMG_VOLUME_ID ?= "boot" BOOTIMG_EXTRA_SPACE ?= "512" +def compute_chs(sector_z): + C = int(sector_z / (63 * 255)) + H = int((sector_z % (63 * 255)) / 63) + # convert zero-based sector to CHS format + S = int(sector_z % 63) + 1 + # munge accord to partition table format + S = (S & 0x3f) | (((C >> 8) & 0x3) << 6) + C = (C & 0xFF) + return (C, H, S) + +def mk_efi_part_table(iso, start, length): + from struct import pack + + # Compute starting and ending CHS addresses for the partition entry. + (s_C, s_H, s_S) = compute_chs(start) + (e_C, e_H, e_S) = compute_chs(start + length - 1) + + # Write the 66 byte partition table to bytes 0x1BE through 0x1FF in + # sector 0 of the .ISO. + # + # See the partition table format here: + # http://en.wikipedia.org/wiki/Master_boot_record#Sector_layout + f = open(iso, 'r+b') + f.seek(0x1BE) + f.write(pack("<8BLL48xH", 0x80, s_H, s_S, s_C, + 0xEF, e_H, e_S, e_C, start, length, 0xAA55)) + f.close() + +def install_efi_part_table(iso_img): + import subprocess + + find_efi_img_cmd = "xorriso -indev %s -find /efi.img \ + -name efi.img -exec report_lba --" % iso_img + ret = subprocess.run(find_efi_img_cmd.split(), capture_output=True) + efi_img_start = -1 + efi_img_length = -1 + for line in ret.stdout.decode(encoding='utf-8').split("\n"): + if "File data lba:" in line and "/efi.img" in line: + file_stat = line[14:].split(',') + efi_img_start = int(file_stat[1].strip()) * 4 + efi_img_length = int(int(file_stat[3].strip()) / 512) + break + if (efi_img_start < 0) or (efi_img_length < 0): + bb.fatal("Failed to determine /efi.img attributes") + mk_efi_part_table(iso_img, efi_img_start, efi_img_length) + populate_live() { - populate_kernel $1 + populate_kernel $1 if [ -s "${ROOTFS}" ]; then install -m 0644 ${ROOTFS} $1/rootfs.img fi } -build_iso() { +build_iso_base() { # Only create an ISO if we have an INITRD and the live or iso image type was selected if [ -z "${INITRD}" ] || [ "${@bb.utils.contains_any('IMAGE_FSTYPES', 'live iso', '1', '0', d)}" != "1" ]; then bbnote "ISO image will not be created." @@ -102,14 +156,6 @@ build_iso() { build_fat_img ${EFIIMGDIR} ${ISODIR}/efi.img fi - # EFI only - if [ "${PCBIOS}" != "1" ] && [ "${EFI}" = "1" ] ; then - # Work around bug in isohybrid where it requires isolinux.bin - # In the boot catalog, even though it is not used - mkdir -p ${ISODIR}/${ISOLINUXDIR} - install -m 0644 ${STAGING_DATADIR}/syslinux/isolinux.bin ${ISODIR}${ISOLINUXDIR} - fi - # We used to have support for zisofs; this is a relic of that mkisofs_compress_opts="-r" @@ -127,26 +173,40 @@ build_iso() { fi fi - if [ "${PCBIOS}" = "1" ] && [ "${EFI}" != "1" ] ; then - # PCBIOS only media - mkisofs -V ${BOOTIMG_VOLUME_ID} \ - -o ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso \ - -b ${ISO_BOOTIMG} -c ${ISO_BOOTCAT} \ - $mkisofs_compress_opts \ - ${MKISOFS_OPTIONS} $mkisofs_iso_level ${ISODIR} + if [ "${PCBIOS}" = "1" ]; then + if [ "${EFI}" = "1" ]; then + # EFI+PCBIOS + mkisofs -A ${BOOTIMG_VOLUME_ID} -V ${BOOTIMG_VOLUME_ID} \ + -o ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso \ + -b ${ISO_BOOTIMG} -c ${ISO_BOOTCAT} \ + $mkisofs_compress_opts ${MKISOFS_BOOT_OPTIONS} $mkisofs_iso_level \ + -eltorito-alt-boot -eltorito-platform efi \ + -b efi.img -no-emul-boot \ + ${ISODIR} + isohybrid_args="-u" + else + # PCBIOS only + mkisofs -V ${BOOTIMG_VOLUME_ID} \ + -o ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso \ + -b ${ISO_BOOTIMG} -c ${ISO_BOOTCAT} \ + $mkisofs_compress_opts \ + ${MKISOFS_BOOT_OPTIONS} $mkisofs_iso_level ${ISODIR} + fi + + isohybrid $isohybrid_args ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso else - # EFI only OR EFI+PCBIOS mkisofs -A ${BOOTIMG_VOLUME_ID} -V ${BOOTIMG_VOLUME_ID} \ - -o ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso \ - -b ${ISO_BOOTIMG} -c ${ISO_BOOTCAT} \ - $mkisofs_compress_opts ${MKISOFS_OPTIONS} $mkisofs_iso_level \ - -eltorito-alt-boot -eltorito-platform efi \ - -b efi.img -no-emul-boot \ + -o ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso \ + $mkisofs_compress_opts $mkisofs_iso_level \ ${ISODIR} - isohybrid_args="-u" fi +} - isohybrid $isohybrid_args ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso +python build_iso() { + bb.build.exec_func("build_iso_base", d) + if d.getVar("PCBIOS") != "1" and d.getVar("EFI") == "1": + install_efi_part_table(d.getVar("IMGDEPLOYDIR") + "/" + \ + d.getVar("IMAGE_NAME") + ".iso") } build_fat_img() { -- 2.34.1
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#191503): https://lists.openembedded.org/g/openembedded-core/message/191503 Mute This Topic: https://lists.openembedded.org/mt/102892311/21656 Group Owner: openembedded-core+ow...@lists.openembedded.org Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-