[meta-intel] [PATCH] uefi-comboapp.bbclass: support multiple UEFI combo apps + fixes

Cal Sullivan california.l.sullivan at intel.com
Tue Jul 18 13:44:00 PDT 2017



On 07/18/2017 12:26 PM, Patrick Ohly wrote:
> The original code in intel-iot-refkit allows to create more than one
> UEFI combo app and uses that to create one for removable media and one
> for fixed media (after installation), with different boot=PARTUUID=xxx
> parameters. This way, an installed image never ended up booting from
> the install media.
>
> uefi-comboapp.bbclass now supports the same feature, with
> create_uefiapp() as the API function that can be used to create
> additional UEFI apps and create_uefiapps as the method where the call
> can be added.
>
> In addition, several shortcomings are getting addressed:
> - A UEFI combo app must be stored under a name that is specific
>    to the image for which it gets created, otherwise different
>    image recipes end up overwriting (or using) files from other
>    images.
> - Signing must be done after creating the apps and before deploying
>    them, otherwise the unsigned apps get copied to the image when
>    using do_uefiapp_deploy.
> - The common code for deployment is now in uefiapp_deploy_at.
> - $dest is used instead of ${DEST} because the latter might get
>    expanded by bitbake.
> - Because do_uefiapp always had to run anew to produce the
>    clean, unsigned input for do_uefiapp_sign, having two different
>    tasks just added unnecessary complexity. Now all code is in
>    do_uefiapp.
> - Old files matching the output pattern get removed explicitly,
>    because they might not get overwritten when the optional
>    app suffix changes between builds, or when the task fails
>    in the middle.
>
> Signed-off-by: Patrick Ohly <patrick.ohly at intel.com>
> ---
>   classes/uefi-comboapp.bbclass | 71 ++++++++++++++++++++++++------------
>   1 file changed, 48 insertions(+), 23 deletions(-)
>
> diff --git a/classes/uefi-comboapp.bbclass b/classes/uefi-comboapp.bbclass
> index 7719686..fc7e1b6 100644
> --- a/classes/uefi-comboapp.bbclass
> +++ b/classes/uefi-comboapp.bbclass
> @@ -32,12 +32,13 @@ do_uefiapp[depends] += "${@ '${INITRD_IMAGE}:do_image_complete' if d.getVar('INI
>   #   - the kernel
>   #   - an initramfs (optional)
>   
> -python do_uefiapp() {
> +def create_uefiapp(d, uuid=None, app_suffix=''):
>       import glob, re
>       from subprocess import check_call
>   
>       build_dir = d.getVar('B')
>       deploy_dir_image = d.getVar('DEPLOY_DIR_IMAGE')
> +    image_link_name = d.getVar('IMAGE_LINK_NAME')
>   
>       cmdline = '%s/cmdline.txt' % build_dir
>       linux = '%s/%s' % (deploy_dir_image, d.getVar('KERNEL_IMAGETYPE'))
> @@ -45,8 +46,9 @@ python do_uefiapp() {
>   
>       stub_path = '%s/linux*.efi.stub' % deploy_dir_image
>       stub = glob.glob(stub_path)[0]
> -    app = re.sub(r"\S*(ia32|x64)(.efi)\S*", r"boot\1\2", os.path.basename(stub))
> -    executable = '%s/%s' % (deploy_dir_image, app)
> +    m = re.match(r"\S*(ia32|x64)(.efi)\S*", os.path.basename(stub))
> +    app = "boot%s%s%s" % (m.group(1), app_suffix, m.group(2))
> +    executable = '%s/%s.%s' % (deploy_dir_image, image_link_name, app)
>   
>       if d.getVar('INITRD_LIVE'):
>           with open(initrd, 'wb') as dst:
> @@ -57,7 +59,6 @@ python do_uefiapp() {
>       else:
>           initrd_cmd = ""
>   
> -    uuid = d.getVar('DISK_SIGNATURE_UUID')
>       root = 'root=PARTUUID=%s' % uuid if uuid else ''
>   
>       with open(cmdline, 'w') as f:
> @@ -70,21 +71,22 @@ python do_uefiapp() {
>           (cmdline, linux, initrd_cmd, stub, executable)
>   
>       check_call(objcopy_cmd, shell=True)
> -}
>   
> -do_uefiapp[vardeps] += "APPEND DISK_SIGNATURE_UUID INITRD_LIVE KERNEL_IMAGETYPE"
> -
> -do_uefiapp_deploy() {
> -    rm -rf ${IMAGE_ROOTFS}/boot/*
> -    mkdir -p ${IMAGE_ROOTFS}/boot/EFI/BOOT
> -    cp  --preserve=timestamps ${DEPLOY_DIR_IMAGE}/boot*.efi ${IMAGE_ROOTFS}/boot/EFI/BOOT/
> +python create_uefiapps () {
> +    # We must clean up anything that matches the expected output pattern, to ensure that
> +    # the next steps do not accidentally use old files.
> +    import glob
> +    pattern = d.expand('${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.boot*.efi')
> +    for old_efi in glob.glob(pattern):
> +        os.unlink(old_efi)
> +    uuid = d.getVar('DISK_SIGNATURE_UUID')
> +    create_uefiapp(d, uuid=uuid)
>   }
>   
> -do_uefiapp_deploy[depends] += "${PN}:do_uefiapp"
> -
> -do_uefiapp_sign() {
> -    if [ -f ${UEFIAPP_SIGNING_KEY} ] && [ -f ${UEFIAPP_SIGNING_CERT} ]; then
> -        for i in `find ${DEPLOY_DIR_IMAGE}/ -name 'boot*.efi'`; do
> +sign_uefiapps () {
> +    if ${@ bb.utils.contains('IMAGE_FEATURES', 'secureboot', 'true', 'false', d) } &&
> +       [ -f ${UEFIAPP_SIGNING_KEY} ] && [ -f ${UEFIAPP_SIGNING_CERT} ]; then
> +        for i in `find ${DEPLOY_DIR_IMAGE}/ -name '${IMAGE_LINK_NAME}.boot*.efi'`; do
>               sbsign --key ${UEFIAPP_SIGNING_KEY} --cert ${UEFIAPP_SIGNING_CERT} $i
>               sbverify --cert ${UEFIAPP_SIGNING_CERT} $i.signed
>               mv $i.signed $i
> @@ -92,8 +94,35 @@ do_uefiapp_sign() {
>       fi
>   }
>   
> -do_uefiapp_sign[depends] += "${PN}:do_uefiapp_deploy \
> -                             sbsigntool-native:do_populate_sysroot"
> +# This is intentionally split into different parts. This way, derived
> +# classes or images can extend the individual parts. We can also use
> +# whatever language (shell script or Python) is more suitable.
> +python do_uefiapp() {
> +    bb.build.exec_func('create_uefiapps', d)
> +    bb.build.exec_func('sign_uefiapps', d)
> +}
I'd like to move the signing portion to its own flexible bbclass so it 
can be used elsewhere (systemd-boot, kernel, eventually shim). Would 
something like what I sent in my last RFC be flexible enough to suite 
refkit's needs? Adding the signing portion like this would make my goal 
a bit harder.

Besides that, this patch looks fine to me.

---
Cal

> +
> +do_uefiapp[vardeps] += "APPEND DISK_SIGNATURE_UUID INITRD_LIVE KERNEL_IMAGETYPE IMAGE_LINK_NAME"
> +do_uefiapp[depends] += "${@ bb.utils.contains('IMAGE_FEATURES', 'secureboot', 'sbsigntool-native:do_populate_sysroot', '', d) }"
> +
> +uefiapp_deploy_at() {
> +    dest=$1
> +    for i in ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.boot*.efi; do
> +        target=`basename $i`
> +        target=`echo $target | sed -e 's/${IMAGE_LINK_NAME}.//'`
> +        cp  --preserve=timestamps -r $i $dest/$target
> +    done
> +}
> +
> +do_uefiapp_deploy() {
> +    rm -rf ${IMAGE_ROOTFS}/boot/*
> +    dest=${IMAGE_ROOTFS}/boot/EFI/BOOT
> +    mkdir -p $dest
> +    uefiapp_deploy_at $dest
> +}
> +
> +do_uefiapp_deploy[depends] += "${PN}:do_uefiapp"
> +
>   
>   # This decides when/how we add our tasks to the image
>   python () {
> @@ -124,17 +153,13 @@ python () {
>       if initramfs_fstypes not in image_fstypes:
>           bb.build.addtask('uefiapp', 'do_image', 'do_rootfs', d)
>           bb.build.addtask('uefiapp_deploy', 'do_image', 'do_rootfs', d)
> -        # Only sign if secureboot is enabled
> -        if secureboot:
> -            bb.build.addtask('uefiapp_sign', 'do_image', 'do_rootfs', d)
>   }
>   
>   do_uefiapp[vardeps] += "UEFIAPP_SIGNING_CERT_HASH UEFIAPP_SIGNING_KEY_HASH"
>   
>   # Legacy hddimg support below this line
>   efi_hddimg_populate() {
> -    DEST=$1
> -    cp  --preserve=timestamps -r ${DEPLOY_DIR_IMAGE}/boot*.efi ${DEST}/
> +    uefiapp_deploy_at "$1"
>   }
>   
>   build_efi_cfg() {
>
> base-commit: e76947d3ee70171cda00661d6367b0bc982cfe39



More information about the meta-intel mailing list