kernel.bbclass: initramfs compression

Message ID CANp-EDbYksyDzAfB9YVLyodLwUUhgQ6noJ-3q8u5J7W7vHsLFg@mail.gmail.com
State New
Headers show
Series
  • kernel.bbclass: initramfs compression
Related show

Commit Message

Ralph Siemsen March 27, 2019, 1:55 a.m.
There is a "regression" of sorts when building initramfs with Yocto,
for kernel version 4.10 and later. Am looking for some suggestions on
how best to handle this.

In a nutshell, the behaviour is:
* kernel 4.9 and earlier: initramfs will be compressed, as long as at
least one decompressor algorithm is enabled in the kernel
* kernel 4.10 and later: initramfs will *not* be compressed, unless
some additional Kconfig parameters are set explicitly to select the
compression method

Phrasing it another way:
* in 4.9 and earlier, compression was done automatically based on the
configured decompression algorithm. The latter can be freely selected
in the kernel configuration.
* in 4.10 and later, compression is a Kconfig option that must be
selected explicitly. The compression option is defined conditionally,
only when an initramfs filename has been specified.

This is problematic for kernel.bbclass because it operates in two steps:
1. yocto first configures the kernel, generating a ".config" file with
all the settings. Notably the initramfs is NOT included at this step.
Thus any compression parameters are ignored by Kconfig.
2. subsequently the kernel gets built, including the initramfs, using
CONFIG_INITRAMFS_SOURCE=... on the "make zImage" command. As the
".config" has not been changed, no initramfs compression occurs.

The kernel behaviour change was introduced in linux 4.10, and
underwent a few revisions thereafter:
https://lore.kernel.org/lkml/57EAD77B.7090607@klondike.es/T/

In Yocto, this results in initramfs no longer being compressed for
kernel 4.10 and up. This has largely gone unnoticed, it seems. The
overall size of the zImage grows slightly, but not dramatically,
because another layer of compression occurs for the zImage itself
(typically with LZO rather than gzip). However, the lack of initramfs
compression is problematic for me because the zImage decompressor is
unaware of reserved memory areas (eg. for secure boot), and the
uncompressed initramfs happened to overlap such a region, causing boot
failure.

I should probably mention that in the case where initramfs file has
been specified in defconfig (eg. CONFIG_INITRAMFS_SOURCE is not
empty), then the compression option behaves like it did in kernel 4.9:
the default value is tied to the user-selected decompressor algorithm.
So kernel developers who include an initramfs in their defconfig files
do not see any regression versus 4.9 behaviour.

Some possible solutions:
- kernel side: remove the conditional dependency between initramfs
compression parameter, and initramfs filename. Then defconfig could
store the preferred compression method.
- yocto side: change sernel.bbclass to pass additional compression
parameter, alongside the existing CONFIG_INITRAMFS_SOURCE parameter.
See patch below.
- yocto side: do not decompress the initramfs at all; let it pass
through unchanged by kernel build process. This might cause problems
(double compression) for 4.9 and earlier.

I will bring this up on kernel list, however even if this got fixed in
kernel 5.2, yocto would still have this problem for kernels between
4.10 and 5.1. This range includes the 4.19 long term stable branch of
course, which many people will likely be using. So I think this will
need to be addressed in yocto through some means. I would welcome any
suggestions...

Finally, just as a proof of concept, here is a patch on the yocto
side, that forces GZIP compression. Obviously if this approach were
taken, it would need to handle all the possible compression schemes,
not just assume GZIP. But the principle would be roughly the same.

                kernel_do_compile
                # Restoring kernel image
                for tp in $tmp_path ; do
@@ -310,7 +310,7 @@ kernel_do_compile() {
                # The old style way of copying an prebuilt image and building it
                # is turned on via INTIRAMFS_TASK != ""
                copy_initramfs
-
use_alternate_initrd=CONFIG_INITRAMFS_SOURCE=${B}/usr/${INITRAMFS_IMAGE_NAME}.cpio
+
use_alternate_initrd="CONFIG_INITRAMFS_SOURCE=${B}/usr/${INITRAMFS_IMAGE_NAME}.cpio
CONFIG_INITRAMFS_COMPRESSION=.gz CONFIG_INITRAMFS_COMPRESSION_GZIP=y"
        fi
        cc_extra=$(get_cc_option)
        for typeformake in ${KERNEL_IMAGETYPE_FOR_MAKE} ; do
-- 
2.17.1
-- 
_______________________________________________
Openembedded-core mailing list
Openembedded-core@lists.openembedded.org
http://lists.openembedded.org/mailman/listinfo/openembedded-core

Patch

diff --git a/meta/classes/kernel.bbclass b/meta/classes/kernel.bbclass
index 727851401c..0f38326d8b 100644
--- a/meta/classes/kernel.bbclass
+++ b/meta/classes/kernel.bbclass
@@ -243,7 +243,7 @@  do_bundle_initramfs () {
                                tmp_path=$tmp_path" "$type"##"
                        fi
                done
-
use_alternate_initrd=CONFIG_INITRAMFS_SOURCE=${B}/usr/${INITRAMFS_IMAGE_NAME}.cpio
+
use_alternate_initrd="CONFIG_INITRAMFS_SOURCE=${B}/usr/${INITRAMFS_IMAGE_NAME}.cpio
CONFIG_INITRAMFS_COMPRESSION=.gz CONFIG_INITRAMFS_COMPRESSION_GZIP=y"