[OE-core] [PATCH] kernel.bbclass, image.bbclass: Implement kernel INITRAMFS dependency and bundling

Bruce Ashfield bruce.ashfield at windriver.com
Tue Aug 20 16:28:07 UTC 2013


On 13-08-20 11:03 AM, Andrea Adami wrote:
> On Tue, Aug 20, 2013 at 3:51 PM, Bruce Ashfield
> <bruce.ashfield at windriver.com> wrote:
>> On 13-08-19 03:11 PM, Jason Wessel wrote:
>>>
>>> This patch aims to fix the following two cases for the INITRAMFS
>>> generation.
>>>     1) Allow an image recipe to specify a paired INITRAMFS recipe such
>>>        as core-image-minimal-initramfs.  This allows building a base
>>>        image which always generates the needed initramfs image in one step
>>>     2) Allow building a single binary which contains a kernel and
>>>        the initramfs.
>>>
>>> A key requirement of the initramfs is to be able to add kernel
>>> modules.  The current implementation of the INITRAMFS_IMAGE variable
>>> has a circular dependency when using kernel modules in the initramfs
>>> image.bb file that is caused by kernel.bbclass trying to build the
>>> initramfs before the kernel's do_install rule.
>>>
>>> The solution for this problem is to have the kernel's
>>> do_bundle_initramfs_image task depend on the do_rootfs from the
>>> INITRAMFS_IMAGE and not some intermediate point.  The image.bbclass
>>> will also sets up dependencies to make the initramfs creation task run
>>> last.
>>>
>>> The code to bundle the kernel and initramfs together has been added.
>>> At a high level, all it is doing is invoking a second compilation of
>>> the kernel but changing the value of CONFIG_INITRAMFS_SOURCE to point
>>> to the generated initramfs from the image recipe.
>>
>>
>> In case it wasn't obvious with Jason cc'ing me, I've seen the patch
>> before, and I'm good with the change.
>>
>> So definitely: Acked-by: Bruce Ashfield <bruce.ashfield at windriver.com>
>>
>> I'm adding Andrea to the cc list as well, since we've been talking
>> about initramfs creation for years now, and I'd want his opinion on
>> whether this looks good, and would work for meta-handheld.
>>
>> Cheers,
>>
>> Bruce
>>
>>
>>>
>>> Signed-off-by: Jason Wessel <jason.wessel at windriver.com>
>>> ---
>>>    meta/classes/image.bbclass  |   12 ++++++
>>>    meta/classes/kernel.bbclass |   96
>>> +++++++++++++++++++++++++++++++++++++------
>>>    meta/conf/local.conf.sample |   20 +++++++++
>>>    3 files changed, 116 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/meta/classes/image.bbclass b/meta/classes/image.bbclass
>>> index 116bd22..78c25db 100644
>>> --- a/meta/classes/image.bbclass
>>> +++ b/meta/classes/image.bbclass
>>> @@ -140,6 +140,10 @@ python () {
>>>        d.setVar('MULTILIB_VENDORS', ml_vendor_list)
>>>
>>>        check_image_features(d)
>>> +    initramfs_image = d.getVar('INITRAMFS_IMAGE', True) or ""
>>> +    if initramfs_image != "":
>>> +        d.appendVarFlag('do_build', 'depends', " %s:do_bundle_initramfs"
>>> %  d.getVar('PN', True))
>>> +        d.appendVarFlag('do_bundle_initramfs', 'depends', " %s:do_rootfs"
>>> % initramfs_image)
>>>    }
>>>
>>>    #
>>> @@ -614,3 +618,11 @@ do_package_write_deb[noexec] = "1"
>>>    do_package_write_rpm[noexec] = "1"
>>>
>>>    addtask rootfs before do_build
>>> +# Allow the kernel to be repacked with the initramfs and boot image file
>>> as a single file
>>> +do_bundle_initramfs[depends] += "virtual/kernel:do_bundle_initramfs"
>>> +do_bundle_initramfs[nostamp] = "1"
>>> +do_bundle_initramfs[noexec] = "1"
>>> +do_bundle_initramfs () {
>>> +       :
>>> +}
>>> +addtask bundle_initramfs after do_rootfs
>>> diff --git a/meta/classes/kernel.bbclass b/meta/classes/kernel.bbclass
>>> index e039dfc..8cf66ce 100644
>>> --- a/meta/classes/kernel.bbclass
>>> +++ b/meta/classes/kernel.bbclass
>>> @@ -9,6 +9,7 @@ INHIBIT_DEFAULT_DEPS = "1"
>>>    KERNEL_IMAGETYPE ?= "zImage"
>>>    INITRAMFS_IMAGE ?= ""
>>>    INITRAMFS_TASK ?= ""
>>> +INITRAMFS_IMAGE_BUNDLE ?= ""
>>>
>>>    python __anonymous () {
>>>        kerneltype = d.getVar('KERNEL_IMAGETYPE', True) or ''
>>> @@ -19,7 +20,15 @@ python __anonymous () {
>>>
>>>        image = d.getVar('INITRAMFS_IMAGE', True)
>>>        if image:
>>> -        d.setVar('INITRAMFS_TASK', '${INITRAMFS_IMAGE}:do_rootfs')
>>> +        d.appendVarFlag('do_bundle_initramfs', 'depends', '
>>> ${INITRAMFS_IMAGE}:do_rootfs')
>>> +
>>> +    # NOTE: setting INITRAMFS_TASK is for backward compatibility
>>> +    #       The preferred method is to set INITRAMFS_IMAGE, because
>>> +    #       this INITRAMFS_TASK has circular dependency problems
>>> +    #       if the initramfs requires kernel modules
>>> +    image_task = d.getVar('INITRAMFS_TASK', True)
>>> +    if image_task:
>>> +        d.appendVarFlag('do_configure', 'depends', ' ${INITRAMFS_TASK}')
>>>    }
>>>
>>>    inherit kernel-arch deploy
>>> @@ -72,9 +81,82 @@ KERNEL_SRC_PATH = "/usr/src/kernel"
>>>
>>>    KERNEL_IMAGETYPE_FOR_MAKE = "${@(lambda s: s[:-3] if s[-3:] == ".gz"
>>> else s)(d.getVar('KERNEL_IMAGETYPE', True))}"
>>>
>>> +copy_initramfs() {
>>> +       echo "Copying initramfs into ./usr ..."
>>> +       # Find and use the first initramfs image archive type we find
>>> +       rm -f ${B}/usr/${INITRAMFS_IMAGE}-${MACHINE}.cpio
>>> +       for img in cpio.gz cpio.lzo cpio.lzma cpio.xz; do
>>> +               if [ -e
>>> "${DEPLOY_DIR_IMAGE}/${INITRAMFS_IMAGE}-${MACHINE}.$img" ]; then
>>> +                       cp
>>> ${DEPLOY_DIR_IMAGE}/${INITRAMFS_IMAGE}-${MACHINE}.$img ${B}/usr/.
>>> +                       case $img in
>>> +                       *gz)
>>> +                               echo "gzip decompressing image"
>>> +                               gunzip -f
>>> ${B}/usr/${INITRAMFS_IMAGE}-${MACHINE}.$img
>>> +                               break
>>> +                               ;;
>>> +                       *lzo)
>>> +                               echo "lzo decompressing image"
>>> +                               lzop -df
>>> ${B}/usr/${INITRAMFS_IMAGE}-${MACHINE}.$img
>>> +                               break
>>> +                               ;;
>>> +                       *lzma)
>>> +                               echo "lzma decompressing image"
>>> +                               lzmash -df
>>> ${B}/usr/${INITRAMFS_IMAGE}-${MACHINE}.$img
>>> +                               break
>>> +                               ;;
>>> +                       *xz)
>>> +                               echo "xz decompressing image"
>>> +                               xz -df
>>> ${B}/usr/${INITRAMFS_IMAGE}-${MACHINE}.$img
>>> +                               break
>>> +                               ;;
>>> +                       esac
>>> +               fi
>>> +       done
>>> +       echo "Finished copy of initramfs into ./usr"
>>> +}
>>> +
>>> +INITRAMFS_BASE_NAME =
>>> "${KERNEL_IMAGETYPE}-initramfs-${PV}-${PR}-${MACHINE}-${DATETIME}"
>>> +INITRAMFS_BASE_NAME[vardepsexclude] = "DATETIME"
>>> +do_bundle_initramfs () {
>>> +       if [ ! -z "${INITRAMFS_IMAGE}" -a x"${INITRAMFS_IMAGE_BUNDLE}" =
>>> x1 ]; then
>>> +               echo "Creating a kernel image with a bundled initramfs..."
>>> +               copy_initramfs
>>> +               if [ -e ${KERNEL_OUTPUT} ] ; then
>>> +                       mv -f ${KERNEL_OUTPUT} ${KERNEL_OUTPUT}.bak
>>> +               fi
>>> +
>>> use_alternate_initrd=CONFIG_INITRAMFS_SOURCE=${B}/usr/${INITRAMFS_IMAGE}-${MACHINE}.cpio
>>> +               kernel_do_compile
>>> +               mv -f ${KERNEL_OUTPUT} ${KERNEL_OUTPUT}.initramfs
>>> +               mv -f ${KERNEL_OUTPUT}.bak ${KERNEL_OUTPUT}
>>> +               # Update install area
>>> +               echo "There is kernel image bundled with initramfs:
>>> ${B}/${KERNEL_OUTPUT}.initramfs"
>>> +               install -m 0644 ${B}/${KERNEL_OUTPUT}.initramfs
>>> ${D}/boot/${KERNEL_IMAGETYPE}-initramfs-${MACHINE}.bin
>>> +               echo "${B}/${KERNEL_OUTPUT}.initramfs"
>>> +               cd ${B}
>>> +               # Update deploy directory
>>> +               if [ -e "${KERNEL_OUTPUT}.initramfs" ]; then
>>> +                       echo "Copying deploy kernel-initramfs image and
>>> setting up links..."
>>> +                       initramfs_base_name=${INITRAMFS_BASE_NAME}
>>> +
>>> initramfs_symlink_name=${KERNEL_IMAGETYPE}-initramfs-${MACHINE}
>>> +                       install -m 0644 ${KERNEL_OUTPUT}.initramfs
>>> ${DEPLOY_DIR_IMAGE}/${initramfs_base_name}.bin
>>> +                       cd ${DEPLOY_DIR_IMAGE}
>>> +                       ln -sf ${initramfs_base_name}.bin
>>> ${initramfs_symlink_name}.bin
>>> +               fi
>>> +       fi
>>> +}
>>> +do_bundle_initramfs[nostamp] = "1"
>>> +addtask bundle_initramfs after do_compile
>>> +
>>>    kernel_do_compile() {
>>>          unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS MACHINE
>>> -       oe_runmake ${KERNEL_IMAGETYPE_FOR_MAKE} ${KERNEL_ALT_IMAGETYPE}
>>> CC="${KERNEL_CC}" LD="${KERNEL_LD}" ${KERNEL_EXTRA_ARGS}
>>> +       # The $use_alternate_initrd is only set from
>>> +       # do_bundle_initramfs() This variable is specifically for the
>>> +       # case where we are making a second pass at the kernel
>>> +       # compilation and we want to force the kernel build to use a
>>> +       # different initramfs image.  The way to do that in the kernel
>>> +       # is to specify:
>>> +       # make ...args...
>>> CONFIG_INITRAMFS_SOURCE=some_other_initramfs.cpio
>>> +       oe_runmake ${KERNEL_IMAGETYPE_FOR_MAKE} ${KERNEL_ALT_IMAGETYPE}
>>> CC="${KERNEL_CC}" LD="${KERNEL_LD}" ${KERNEL_EXTRA_ARGS}
>>> $use_alternate_initrd
>>>          if test "${KERNEL_IMAGETYPE_FOR_MAKE}.gz" = "${KERNEL_IMAGETYPE}";
>>> then
>>>                  gzip -9c < "${KERNEL_IMAGETYPE_FOR_MAKE}" >
>>> "${KERNEL_OUTPUT}"
>>>          fi
>>> @@ -219,18 +301,8 @@ kernel_do_configure() {
>>>                  cp "${WORKDIR}/defconfig" "${B}/.config"
>>>          fi
>>>          yes '' | oe_runmake oldconfig
>>> -
>>> -       if [ ! -z "${INITRAMFS_IMAGE}" ]; then
>>> -               for img in cpio.gz cpio.lzo cpio.lzma cpio.xz; do
>>> -               if [ -e
>>> "${DEPLOY_DIR_IMAGE}/${INITRAMFS_IMAGE}-${MACHINE}.$img" ]; then
>>> -                       cp
>>> "${DEPLOY_DIR_IMAGE}/${INITRAMFS_IMAGE}-${MACHINE}.$img" initramfs.$img
>>> -               fi
>>> -               done
>>> -       fi
>>>    }
>>>
>>> -do_configure[depends] += "${INITRAMFS_TASK}"
>>> -
>>>    do_savedefconfig() {
>>>          oe_runmake savedefconfig
>>>    }
>>> diff --git a/meta/conf/local.conf.sample b/meta/conf/local.conf.sample
>>> index 2b078d0..17733ab 100644
>>> --- a/meta/conf/local.conf.sample
>>> +++ b/meta/conf/local.conf.sample
>>> @@ -146,6 +146,26 @@ EXTRA_IMAGE_FEATURES = "debug-tweaks"
>>>    USER_CLASSES ?= "buildstats image-mklibs image-prelink"
>>>
>>>    #
>>> +# Kernel image features
>>> +#
>>> +# The INITRAMFS_IMAGE image variable will cause an additional recipe to
>>> +# be built as a dependency to the what ever rootfs recipe you might be
>>> +# using such as core-image-sato.  The initramfs might be needed for
>>> +# the initial boot of of the target system such as to load kernel
>>> +# modules prior to mounting the root file system.
>>> +#
>>> +# INITRAMFS_IMAGE_BUNDLE variable controls if the image recipe
>>> +# specified by the INITRAMFS_IMAGE will be run through an extra pass
>>> +# through the kernel compilation in order to build a single binary
>>> +# which contains both the kernel image and the initramfs.  The
>>> +# combined binary will be deposited into the tmp/deploy directory.
>>> +# NOTE: You can set INITRAMFS_IMAGE in an image recipe, but
>>> +#       INITRAMFS_IMAGE_BUNDLE can only be set in a conf file.
>>> +#
>>> +#INITRAMFS_IMAGE = "core-image-minimal-initramfs"
>>> +#INITRAMFS_IMAGE_BUNDLE = "1"
>>> +
>>> +#
>>>    # Runtime testing of images
>>>    #
>>>    # The build system can test booting virtual machine images under qemu
>>> (an emulator)
>>>
>>
>
> I plan to test this as soon as possible.
>
> Though, it seems to me a bit too special-cased: you only change
> CONFIG_INITRAMFS_SOURCE=some_other_initramfs.cpio.
> I mean, our necessity is to have a *different* second kernel embedding
> the initramfs and in fact we have linux-yocto as standard kernel and a
> linux-yocto-tiny derived special-purpose kernel+cpio.

This is exactly what I was hoping to hear as feedback, and yes,
this solution does stop short of the kexec solution or a two
kernel variant. It does allow you to have a kernel module for a
driver in your initramfs, and a unique filesystem for that
initramfs.

Your document/steps are one of the cases that I had in mind, it
would be nice to make it simpler as well .. if possible.

>
> (in case you missed it:
> http://kexecboot.org/documentation/crosscompiling/oe-yocto )
>
> About building all in one-pass, well, we were there and we did step back.
> It was preferred to build only the 'production' kernel when building
> images and to build separately the special kernel+cpio.
> The logic was to create a dummy recipe and let the option to build it
> automatically i.e. adding it as # EXTRA_IMAGEDEPENDS += "dummy" in
> your machine.conf or another conf file

Remind me on this part. When you assemble and include that second
kernel into the production kernel's initramfs, how are the build
artifacts shared ? i.e. it's just a second build with a shared
deploy directory ? (your my-installer.bb recipe) ?

Cheers,

Bruce

>
> I'll test soon anyway, thx.
>
> Cheers
>
> Andrea
>




More information about the Openembedded-core mailing list