On Mon, Nov 20, 2023 at 7:49 AM Dmitry Baryshkov <dbarysh...@gmail.com> wrote: > > On Thu, 7 Sept 2023 at 01:29, Alejandro Hernandez Samaniego > <a...@linux.microsoft.com> wrote: > > > > > > On 9/2/23 00:53, Richard Purdie wrote: > > > On Fri, 2023-09-01 at 23:32 +0000, Michelle Lin wrote: > > >> Currently, there is not a class to support the building of unified kernel > > >> images. Adding a uki.bbclass to support the creation of UKIs. This class > > >> calls > > >> the systemd Ukify tool, which will combine the kernel/initrd/stub > > >> components to > > >> build the UKI. To sign the UKI (i.e. SecureBoot, TPM PCR signing), the > > >> keys/cert > > >> files are to be specified in a separate configuration file, and the path > > >> to the > > >> file is passed to the Ukify tool. UKIs are supported by UEFI and can > > >> improve > > >> security through predicted TPM PCR states, and reduce the build burden > > >> due to > > >> its single PE binary format. > > >> > > >> Signed-off-by: Michelle Lin <michelle.lint...@gmail.com> > > >> --- > > >> meta/classes/uki.bbclass | 140 +++++++++++++++++++++++ > > >> meta/recipes-core/systemd/systemd_254.bb | 23 ++++ > > >> 2 files changed, 163 insertions(+) > > >> create mode 100644 meta/classes/uki.bbclass > > >> > > >> diff --git a/meta/classes/uki.bbclass b/meta/classes/uki.bbclass > > >> new file mode 100644 > > >> index 0000000000..2eff387c75 > > >> --- /dev/null > > >> +++ b/meta/classes/uki.bbclass > > >> @@ -0,0 +1,140 @@ > > >> +# > > >> +# Unified kernel image (UKI) class > > >> +# > > >> +# > > >> +# This bbclass is designed to repack an Overlake image as a UKI, to be > > >> booted on a qemuarm64 with SecureBoot > > >> +# signing and embedded with TPM PCR measurements. > > >> +# > > >> +# The UKI is composed by: > > >> +# - an UEFI stub > > >> +# The linux kernel can generate a UEFI stub, however the one from > > >> systemd-boot can fetch > > >> +# the command line from a separate section of the EFI application, > > >> avoiding the need to > > >> +# rebuild the kernel. > > >> +# - the kernel > > >> +# - an initramfs > > >> +# - other metadata (e.g. PCR measurements) > > >> +# > > >> +# > > >> +# > > >> + > > >> +# List build time dependencies > > >> +DEPENDS += "systemd-native \ > > >> + sbsigntool-native \ > > >> + virtual/${TARGET_PREFIX}binutils \ > > >> + " > > >> + > > >> +REQUIRED_DISTRO_FEATURES += "usrmerge systemd" > > >> + > > >> +inherit features_check > > >> +require ../conf/image-uefi.conf > > >> + > > >> +INITRD_IMAGE ?= "core-image-minimal-initramfs" > > >> + > > >> +INITRD_LIVE ?= "${@ ('${DEPLOY_DIR_IMAGE}/' + d.getVar('INITRD_IMAGE') > > >> + '-${MACHINE}.cpio.gz') if d.getVar('INITRD_IMAGE') else ''}" > > >> + > > >> +UKI_CONFIG_FILE ?= "${WORKDIR}/core-image-minimal-uki.conf" > > >> +UKI_FILENAME ?= "${@ 'UKI.signed.efi' if d.getVar('UKI_CONFIG_FILE') > > >> else 'UKI.unsigned.efi'}" > > >> + > > >> +do_uki[depends] += " \ > > >> + systemd-boot:do_deploy \ > > >> + virtual/kernel:do_deploy \ > > >> + " > > >> + > > >> +# INITRD_IMAGE is added to INITRD_LIVE, which we use to create our > > >> initrd, so depend on it if it is set > > >> +# So we want to generate the initrd image if INITRD_IMAGE exists > > >> +do_uki[depends] += "${@ '${INITRD_IMAGE}:do_image_complete' if > > >> d.getVar('INITRD_IMAGE') else ''}" > > >> + > > >> +# ensure that the build directory is empty everytime we generate a > > >> newly-created uki > > >> +do_uki[cleandirs] = "${B}" > > >> +# influence the build directory at the start of the builds > > >> +do_uki[dirs] = "${B}" > > >> + > > >> +# we want to allow specifying files in SRC_URI, such as for signing the > > >> UKI > > >> +python () { > > >> + d.delVarFlag("do_fetch","noexec") > > >> + d.delVarFlag("do_unpack","noexec") > > >> +} > > >> + > > >> +# main task > > >> +python do_uki() { > > >> + import glob > > >> + import subprocess > > >> + > > >> + # Construct the ukify command > > >> + ukify_cmd = ("ukify build") > > >> + > > >> + # Handle the creation of an initrd image by reading and > > >> concatenating multiple cpio files. > > >> + # If the INITRD_LIVE variable is defined and not empty, it opens > > >> the necessary files, reads their contents, > > >> + # and constructs a list. > > >> + if d.getVar('INITRD_LIVE'): > > >> + initrd_list = "" > > >> + for cpio in d.getVar('INITRD_LIVE').split(): > > >> + # get a list of initrds > > >> + initrd_list += cpio + ' ' > > >> + > > >> + ukify_cmd += " --initrd=%s" % initrd_list > > >> + else: > > >> + bb.fatal("ERROR - Required argument: INITRD") > > >> + > > >> + deploy_dir_image = d.getVar('DEPLOY_DIR_IMAGE') > > >> + > > >> + # Kernel > > >> + if d.getVar('KERNEL_IMAGETYPE'): > > >> + kernel = "%s/%s" % (deploy_dir_image, > > >> d.getVar('KERNEL_IMAGETYPE')) > > >> + kernel_version = d.getVar('KERNEL_VERSION') > > >> + if not os.path.exists(kernel): > > >> + bb.fatal(f"ERROR: cannot find {kernel}.") > > >> + > > >> + ukify_cmd += " --linux=%s --uname %s" % (kernel, kernel_version) > > >> + else: > > >> + bb.fatal("ERROR - Required argument: KERNEL") > > >> + > > >> + # Architecture > > >> + target_arch = d.getVar('EFI_ARCH') > > >> + ukify_cmd += " --efi-arch %s" % target_arch > > >> + > > >> + # Stub > > >> + stub = "%s/linux%s.efi.stub" % (deploy_dir_image, target_arch) > > >> + if not os.path.exists(stub): > > >> + bb.fatal(f"ERROR: cannot find {stub}.") > > >> + ukify_cmd += " --stub %s" % stub > > >> + > > >> + # Add option for dtb > > >> + if d.getVar('KERNEL_DEVICETREE'): > > >> + first_dtb = d.getVar('KERNEL_DEVICETREE').split()[0] > > >> + dtb_path = "%s/%s" % (deploy_dir_image, first_dtb) > > >> + > > >> + if not os.path.exists(dtb_path): > > >> + bb.fatal(f"ERROR: cannot find {dtb_path}.") > > >> + > > >> + ukify_cmd += " --devicetree %s" % dtb_path > > >> + > > >> + # Add option to pass a config file to sign the UKI. > > >> + if os.path.exists(d.getVar('UKI_CONFIG_FILE')): > > >> + ukify_cmd += " --config=%s" % d.getVar('UKI_CONFIG_FILE') > > >> + ukify_cmd += " --tools=%s%s/lib/systemd/tools" % > > >> (d.getVar("RECIPE_SYSROOT_NATIVE"), d.getVar("prefix")) > > >> + bb.note("Pulling keys from config file") > > >> + else: > > >> + bb.note("Generating unsigned UKI") > > >> + > > >> + # Custom UKI name > > >> + output = " --output=%s" % d.getVar('UKI_FILENAME') > > >> + ukify_cmd += " %s" % output > > >> + > > >> + # Set env to determine where bitbake should look for dynamic > > >> libraries > > >> + env = os.environ.copy() # get the env variables > > >> + env['LD_LIBRARY_PATH'] = > > >> d.expand("${RECIPE_SYSROOT_NATIVE}/usr/lib/systemd:${LD_LIBRARY_PATH}") > > >> + > > >> + # Run the ukify command > > >> + subprocess.check_call(ukify_cmd, env=env, shell=True) > > >> +} > > >> + > > >> +inherit deploy > > >> + > > >> +do_deploy () { > > >> + # Copy generated UKI into DEPLOYDIR > > >> + install ${B}/${UKI_FILENAME} ${DEPLOYDIR} > > >> +} > > >> + > > >> +addtask uki before do_deploy do_image after do_rootfs > > >> +addtask deploy before do_build after do_compile > > >> \ No newline at end of file > > >> diff --git a/meta/recipes-core/systemd/systemd_254.bb > > >> b/meta/recipes-core/systemd/systemd_254.bb > > >> index 8d5cf13095..65f132abb8 100644 > > >> --- a/meta/recipes-core/systemd/systemd_254.bb > > >> +++ b/meta/recipes-core/systemd/systemd_254.bb > > >> @@ -6,6 +6,9 @@ PE = "1" > > >> > > >> DEPENDS = "intltool-native gperf-native libcap util-linux > > >> python3-jinja2-native" > > >> > > >> +# The Ukify tool requires this module > > >> +DEPENDS:append:class-native = " python3-pefile-native" > > > Do we need to add this to OE-Core? I think this will cause current > > > builds to fail? > > > > > > I think you are right, there are some dependencies from this that are > > not present in OE-core, this probably belongs in a different layer, at > > least for the time being. > > I think that ukify is useful in OE-core. Having it in another layer > would mean that we can not use it from the BSP layer. >
Can you elaborate on that first point ? That sounds like an internal restriction / rule, so it really doesn't factor into whether or not something needs to be in oe-core or not. The answer itself doesn't matter to me, I just didn't want someone in the future to be searching and think that their BSP layer can only use functionality from oe-core. Bruce > As the ukify is usable even without sbsign and pesign, I think we can > do either of the following things: > > - Mark sbsign and pesign as recomendations instead of dependencies > > - Add PACAKGECONFIG for the signing support. If it is not enabled, > replace sbsign and pesign support with the error message. > > -- > With best wishes > Dmitry > > > -- - Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end - "Use the force Harry" - Gandalf, Star Trek II
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#190877): https://lists.openembedded.org/g/openembedded-core/message/190877 Mute This Topic: https://lists.openembedded.org/mt/101106095/21656 Group Owner: openembedded-core+ow...@lists.openembedded.org Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-