[yocto] [PATCH] EFI support for IA

Josef Ahmad josef.ahmad at intel.com
Thu Nov 24 00:48:39 PST 2011


Hi Darren,

I'll track your branch to sync our efforts.

I meant to only generate the Grub EFI binary for the target, without
including any tool/library into the root filesystem: I assumed that it's
sufficient to deploy the bootloader onto the top-level image. That's why I
build natively the mkimage tool and run that on the host to get the EFI
executable. Now, as you justly point out, there's a target mismatch:
mkimage incorrectly calls out the host architecture under the -O switch,
whereas it should have been something like ${TARGET_ARCH}-efi.

That said, surely a solution that embodies the GRUB tools into the root
filesystem is desirable.

Feel free to merge my grub config generator into your branch, as well as
any of my contrib you may like. Speaking of grub.bbclass, I named it so as
it's not specifically tied to the EFI mode. It basically builds up the grub
configuration menu, based off machine-specific parameters. I implemented it
among the lines of syslinux.bbclass.

- Josef

On 23 November 2011 15:38, Darren Hart <dvhart at linux.intel.com> wrote:

> Hi Josef,
>
> On 11/23/2011 02:39 AM, Josef Ahmad wrote:
> > Hi all
> >
> > I've been in contact with Darren Hart, who has opened an RFC re:
> > including support for EFI into Yocto.
> > Meanwhile, due to time constraints of my own project, I worked out a
> > patch to enable EFI on IA-based BSPs.
>
> There are various issues I'm currently working through with respect to
> this. See the mail thread on openembedded-core with respect to this:
>
>
> http://lists.linuxtogo.org/pipermail/openembedded-core/2011-November/012972.html
>
> Also, while my tree is not currently ready for use, if you want to get
> an idea about how I'm going about fixing this, you can see it here. Note
> that this tree is a development tree and will be rebased frequently:
>
> http://git.yoctoproject.org/cgit/cgit.cgi/poky-contrib/log/?h=dvhart/efi
>
> More comments inline below...
>
> >
> > The patch makes it possible to deploy a system image that adds EFI boot
> > feature along with the legacy bios boot mode. Hence it does not replace
> > the legacy booting, which is still available on the built image.
> > This solution appears to me conservative enough test without breaking
> > existing features, and makes the following introduction of an EFI/PCBIOS
> > switch relatively straightforward.
> >
> > To check out the feature, it's sufficient to add the following lines to
> > either your local.conf or layer.conf:
> >
> >    # Ensure you build an hddimg
> >    IMAGE_FSTYPES += "live"
> >    # Enable EFI mode
> >    EFI = "1"
>
> We will want to make this part of the MACHINE_FEATURES variables defined
> in the machine config.
>
> >    MACHINE_ESSENTIAL_EXTRA_RDEPENDS += "grub-efi"
> >    # Target-specific boot options (e.g. headless mode)
> >    GRUB_OPTS = "serial --unit=0 --speed=115200 --word=8 --parity=no
> > --stop=1"
> >    GRUB_APPEND = "console=uart8250,io,0x3f8,115200n8 ro"
> >    GRUB_TIMEOUT = "10"
> >
> > This will produce a system image containing the EFI Grub bootloader +
> > boot configuration file.
> >
> > Currently, the patch applies to the meta layer and therefore has global
> > visibility. However, I see from yesterday's meeting minutes that
> > meta-intel has been added as a layer itself. Which comes in handy, as we
> > can narrow the scope of the patch to the Intel targets, which are the
> > only supported machines at the moment.
> >
> > Feedbacks are keenly appreciated. I'm still in ramp-up phase with Yocto,
> > so I might be doing incorrect assumptions, or not complying with common
> > practices.
> >
> > - Josef
> >
> > -----------------------------------
> >
> > From d04ffad92107572f70c06e5692083f285d767c01 Mon Sep 17 00:00:00 2001
> > From: Josef Ahmad <josef.ahmad at intel.com <mailto:josef.ahmad at intel.com>>
> > Date: Thu, 17 Nov 2011 14:57:20 +0000
> > Subject: [PATCH] Add UEFI support to Edison
> >  Add UEFI GRUB support into bootimg.bbclass
> >
> > Add grub-efi recipe
> >
> > Added UEFI GRUB support for system image generation
> >
> > Add switch for EFI mode + automated boot conf generation
> >
> > Fix typo in grub.bbclass comment header
> >
> > x86_64-efi now supported
> > ---
> >  meta/classes/bootimg.bbclass                       |   24 ++++++
> >  meta/classes/grub.bbclass                          |   73
> > ++++++++++++++++++
> >  .../grub-efi/grub-efi-1.99/40_custom               |    9 ++
> >  .../grub-efi/grub-efi-1.99/grub-install.in.patch   |   20 +++++
> >  meta/recipes-devtools/grub-efi/grub-efi.bb <http://grub-efi.bb>
> > |   79 ++++++++++++++++++++
> >  5 files changed, 205 insertions(+), 0 deletions(-)
> >  create mode 100644 meta/classes/grub.bbclass
> >  create mode 100755
> meta/recipes-devtools/grub-efi/grub-efi-1.99/40_custom
> >  create mode 100644
> > meta/recipes-devtools/grub-efi/grub-efi-1.99/grub-install.in.patch
> >  create mode 100644 meta/recipes-devtools/grub-efi/grub-efi.bb
> > <http://grub-efi.bb>
> >
> > diff --git a/meta/classes/bootimg.bbclass b/meta/classes/bootimg.bbclass
> > index 49ee85e..00c70d4 100644
> > --- a/meta/classes/bootimg.bbclass
> > +++ b/meta/classes/bootimg.bbclass
> > @@ -45,7 +45,20 @@ BOOTIMG_EXTRA_SPACE ?= "512"
> >  SYSLINUXCFG  = "${HDDDIR}/syslinux.cfg"
> >  SYSLINUXMENU = "${HDDDIR}/menu"
> >
> > +GRUBCFG = "${HDDDIR}/grub.cfg"
> > +
> >  inherit syslinux
> > +inherit grub
> > +
>
> One thing I'm working on is making it possible to choose which
> bootloader you want to use, and if you want PCBIOS, EFI, or both in your
> live image.
>
> > +def get_grub_imgname(bb, d):
> > +    import re
> > +    host = bb.data.getVar('HOST_SYS', d, 1)
> > +    if re.match('i.86.*-linux', host):
> > +        return "bootia32.efi"
> > +    if re.match('x86.64.*-linux', host):
> > +        return "bootx64.efi"
>
>
> This needs to be based on the TARGET_ARCH, not the HOST_SYS.
>
> > +
> > +GRUB_IMGNAME = "${@get_grub_imgname(bb, d)}"
> >
> >  build_boot_bin() {
> >      install -d ${HDDDIR}
> > @@ -62,6 +75,12 @@ build_boot_bin() {
> >
> >      install -m 444 ${STAGING_LIBDIR}/syslinux/ldlinux.sys
> > ${HDDDIR}/ldlinux.sys
> >
> > +    # TODO locate bootloader under /EFI/boot/ as soon as mkdosfs bug is
> > fixed
> > +
> > +    if [ -n "${EFI}" ]; then
>
> OK, good.
>
> > +        install -m 444 ${STAGING_LIBDIR}/grub/${GRUB_IMGNAME} ${HDDDIR}/
> > +    fi
> > +
> >      # Do a little math, bash style
> >      #BLOCKS=`du -s ${HDDDIR} | cut -f 1`
> >      BLOCKS=`du -bks ${HDDDIR} | cut -f 1`
> > @@ -118,6 +137,11 @@ build_boot_bin() {
> >
> >  python do_bootimg() {
> >      bb.build.exec_func('build_syslinux_cfg', d)
> > +
> > +    efi = bb.data.getVar('EFI', d, 1)
> > +    if efi:
> > +        bb.build.exec_func('build_grub_cfg', d)
> > +
> >      bb.build.exec_func('build_boot_bin', d)
> >  }
> >
> > diff --git a/meta/classes/grub.bbclass b/meta/classes/grub.bbclass
> > new file mode 100644
> > index 0000000..b461fc5
> > --- /dev/null
> > +++ b/meta/classes/grub.bbclass
>
> I've been calling mine grub-efi to distinguish it from the PCBIOS version.
>
> > @@ -0,0 +1,73 @@
> > +# grub.bbclass
> > +# (based off syslinux.bbclass Copyright (C) 2004-2006, Advanced Micro
> > Devices, Inc.)
> > +
> > +python build_grub_cfg () {
> > +    import sys
> > +
> > +    workdir = bb.data.getVar('WORKDIR', d, 1)
> > +    if not workdir:
> > +        bb.error("WORKDIR not defined, unable to package")
> > +        return
> > +
> > +    labels = bb.data.getVar('LABELS', d, 1)
> > +    if not labels:
> > +        bb.debug(1, "LABELS not defined, nothing to do")
> > +        return
> > +
> > +    if labels == []:
> > +        bb.debug(1, "No labels, nothing to do")
> > +        return
> > +
> > +    cfile = bb.data.getVar('GRUBCFG', d, 1)
> > +    if not cfile:
> > +        raise bb.build.FuncFailed('Unable to read GRUBCFG')
> > +
> > +    bb.mkdirhier(os.path.dirname(cfile))
> > +
> > +    try:
> > +         cfgfile = file(cfile, 'w')
> > +    except OSError:
> > +        raise bb.build.funcFailed('Unable to open %s' % (cfile))
> > +
> > +    cfgfile.write('# Automatically created by OE\n')
> > +
> > +    opts = bb.data.getVar('GRUB_OPTS', d, 1)
> > +
> > +    if opts:
> > +        for opt in opts.split(';'):
> > +            cfgfile.write('%s\n' % opt)
> > +
> > +    cfgfile.write('default=%s\n' % (labels.split()[0]))
> > +
> > +    timeout = bb.data.getVar('GRUB_TIMEOUT', d, 1)
> > +    if timeout:
> > +        cfgfile.write('timeout=%s\n' % timeout)
> > +    else:
> > +        cfgfile.write('timeout=50\n')
> > +
> > +        for label in labels.split():
> > +                localdata = bb.data.createCopy(d)
> > +
> > +                overrides = bb.data.getVar('OVERRIDES', localdata, True)
> > +                if not overrides:
> > +                        raise bb.build.FuncFailed('OVERRIDES not
> defined')
> > +
> > +                bb.data.setVar('OVERRIDES', label + ':' + overrides,
> > localdata)
> > +                bb.data.update_data(localdata)
> > +
> > +                cfgfile.write('\nmenuentry \'%s\'{\n' % (label))
> > +                cfgfile.write('linux /vmlinuz ')
> > +
> > +                append = bb.data.getVar('GRUB_APPEND', localdata, 1)
> > +                initrd = bb.data.getVar('INITRD', localdata, 1)
> > +
> > +                if append:
> > +                        cfgfile.write('%s' % (append))
> > +                cfgfile.write('\n')
> > +
> > +                if initrd:
> > +                        cfgfile.write('initrd /initrd')
> > +                cfgfile.write('\n}\n')
> > +
> > +    cfgfile.close()
> > +}
>
> I had not done this part yet, I can roll this into my series and keep it
> attributed to you.
>
> > diff --git a/meta/recipes-devtools/grub-efi/grub-efi-1.99/40_custom
> > b/meta/recipes-devtools/grub-efi/grub-efi-1.99/40_custom
> > new file mode 100755
> > index 0000000..0d80854
> > --- /dev/null
> > +++ b/meta/recipes-devtools/grub-efi/grub-efi-1.99/40_custom
> > @@ -0,0 +1,9 @@
> > +#!/bin/sh
> > +exec tail -n +3 $0
> > +# This file provides an easy way to add custom menu entries.  Simply
> > type the
> > +# menu entries you want to add after this comment.  Be careful not to
> > change
> > +# the 'exec tail' line above.
> > +menuentry "Linux" {
> > +    set root=(hd0,1)
> > +    linux /boot/vmlinuz root=__ROOTFS__ rw __VIDEO_MODE__ __VGA_MODE__
> > quiet
> > +}
> > diff --git
> > a/meta/recipes-devtools/grub-efi/grub-efi-1.99/grub-install.in.patch
> > b/meta/recipes-devtools/grub-efi/grub-efi-1.99/grub-install.in.patch
> > new file mode 100644
> > index 0000000..326951d
> > --- /dev/null
> > +++ b/meta/recipes-devtools/grub-efi/grub-efi-1.99/grub-install.in.patch
> > @@ -0,0 +1,20 @@
> > +Upstream-Status: Inappropriate [embedded specific]
> > +
> > +Our use of grub-install doesn't require the -x option, so we should be
> > +be able make use of grep versions that don't support it.
> > +
> > +Signed-off-by: Tom Zanussi <tom.zanussi at intel.com
> > <mailto:tom.zanussi at intel.com>>
> > +
> > +Index: grub-1.99/util/grub-install.in <http://grub-install.in>
> > +===================================================================
> > +--- grub-1.99.orig/util/grub-install.in <http://grub-install.in>
> > 2011-09-09 22:37:20.093906679 -0500
> > ++++ grub-1.99/util/grub-install.in <http://grub-install.in>
> > 2011-09-09 22:37:30.854737882 -0500
> > +@@ -510,7 +510,7 @@
> > +
> > + if [ "x${devabstraction_module}" = "x" ] ; then
> > +     if [ x"${install_device}" != x ]; then
> > +-      if echo "${install_device}" | grep -qx "(.*)" ; then
> > ++      if echo "${install_device}" | grep -q "(.*)" ; then
> > +         install_drive="${install_device}"
> > +       else
> > +         install_drive="`"$grub_probe" --device-map="${device_map}"
> > --target=drive --device "${install_device}"`" || exit 1
> > diff --git a/meta/recipes-devtools/grub-efi/grub-efi.bb
> > <http://grub-efi.bb> b/meta/recipes-devtools/grub-efi/grub-efi.bb
> > <http://grub-efi.bb>
> > new file mode 100644
> > index 0000000..1310c75
> > --- /dev/null
> > +++ b/meta/recipes-devtools/grub-efi/grub-efi.bb <http://grub-efi.bb>
> > @@ -0,0 +1,79 @@
> > +SUMMARY = "GRUB2 is the next-generation GRand Unified Bootloader"
> > +
> > +DESCRIPTION = "GRUB2 is the next generaion of a GPLed bootloader \
> > +intended to unify bootloading across x86 operating systems. In \
> > +addition to loading the Linux kernel, it implements the Multiboot \
> > +standard, which allows for flexible loading of multiple boot images."
> > +
> > +HOMEPAGE = "http://www.gnu.org/software/grub/"
> > +SECTION = "bootloaders"
> > +PRIORITY = "optional"
> > +
> > +LICENSE = "GPLv3"
> > +LIC_FILES_CHKSUM = "file://COPYING;md5=d32239bcb673463ab874e80d47fae504"
> > +
> > +RDEPENDS_${PN} = "diffutils freetype"
> > +PR = "r1"
> > +PN = "grub-efi"
> > +PV = "1.99"
> > +
> > +
> > +SRC_URI = "ftp://ftp.gnu.org/gnu/grub/grub-${PV}.tar.gz
> > <ftp://ftp.gnu.org/gnu/grub/grub-$%7BPV%7D.tar.gz> \
> > +          file://grub-install.in.patch;apply=yes \
> > +          file://40_custom"
> > +
> > +inherit autotools
> > +inherit gettext
> > +
> > +def set_grub_imgfmt(bb, d):
> > +    import re
> > +    host = bb.data.getVar('HOST_SYS', d, 1)
>
> Same here, needs to be based on TARGET_ARCH
>
> > +    if re.match('i.86.*-linux', host):
> > +        return "i386"
> > +    if re.match('x86.64.*-linux', host):
> > +        return "x86_64"
> > +
> > +GRUB_IMGFMT = "${@set_grub_imgfmt(bb, d)}"
> > +
> > +EXTRA_OECONF = "--target=${GRUB_IMGFMT} --with-platform=efi
> > --enable-grub-mkfont=no \
> > +     --disable-nls --enable-efiemu=no --program-prefix="""
> > +
> > +do_update_unpack_loc () {
> > +    rm -rf grub-efi-1.99
> > +    mv grub-1.99 grub-efi-1.99
> > +}
>
> This is better done by setting the S variable, see my branch linked above:
>
> S = ${WORKDIR}/grub-${PV}
>
> > +
> > +do_unpack_append () {
> > +    bb.build.exec_func('do_update_unpack_loc', d)
> > +}
>
> drop
>
> > +
> > +do_configure() {
> > +    oe_runconf
> > +}
> > +
> > +python __anonymous () {
> > +    import re
> > +    host = bb.data.getVar('HOST_SYS', d, 1)
> > +    if not re.match('x86.64.*-linux', host) and not
> > re.match('i.86.*-linux', host):
> > +        raise bb.parse.SkipPackage("incompatible with host %s" % host)
> > +}
> > +
> > +do_install_append () {
> > +    install -m 0755 ${WORKDIR}/40_custom
> ${D}${sysconfdir}/grub.d/40_custom
> > +
> > +    if [ "${GRUB_IMGFMT}" = "i386" ]
> > +        then GRUB_EFIARCH="ia32"
> > +    else GRUB_EFIARCH="x64"
> > +    fi
> > +
> > +    ./grub-mkimage -p / -d ./grub-core/ -O ${GRUB_IMGFMT}-efi \
>
> And as we discussed (after you had sent this), we need to ensure
> grub-mkimage is a BUILDHOST_ARCH. See the oe-core thread I listed above
> some more context. It's a tough problem. I'm currently leaning towards
> the building a -native package first. In fact, I'm building native now.
> I just need to get access to the real TARGET_ARCH for the --target=
> configure argument and then it works.
>
> > +    -o ./boot${GRUB_EFIARCH}.efi \
> > +    boot linux fat serial part_msdos normal
> > +
> > +    install -d ${STAGING_LIBDIR}/grub/
> > +    install -m 644 ${S}/boot${GRUB_EFIARCH}.efi ${STAGING_LIBDIR}/grub/
> > +}
> > +
> > +FILES_${PN}-doc = "${datadir}"
> > +FILES_${PN} = "/usr /etc"
> > +
> > --
> > 1.7.2.5
> >
>
> Definitely some good bits in here Josef. Let's make sure we are in sync
> so we don't duplicate too much effort here. I will push my changes to
> the dvhart/efi branch linked above more frequently so you can have
> access to that.
>
> Do you have any objection if I lift your grub cfg generator for the
> grub-efi.bbclass? Maintaining your Signed-off-by of course.
>
> --
> Darren Hart
> Intel Open Source Technology Center
> Yocto Project - Linux Kernel
> _______________________________________________
> yocto mailing list
> yocto at yoctoproject.org
> https://lists.yoctoproject.org/listinfo/yocto
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.yoctoproject.org/pipermail/yocto/attachments/20111124/fbb8a11f/attachment.html>


More information about the yocto mailing list