From 282d5852b682af8d60d8e062854cdb062cac236e Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 21 Feb 2021 14:19:26 +0000 Subject: [PATCH] image: allow building FIT and uImage with ramdisk Instead of embedding the initrd cpio archive into the kernel, allow for having an external ramdisk added to the FIT or uImage. This is useful to overcome kernel size limitations present in many stock bootloaders, as the ramdisk is then loaded seperately and doesn't add to the kernel size. Hence we can have larger ramdisks to host ie. installers with all binaries to flash included (or a web-based firmware selector). In terms of performance and total size the differences are neglectible. Signed-off-by: Daniel Golle Signed-off-by: Tianling Shen --- config/Config-images.in | 21 ++++++++++---- include/image-commands.mk | 57 ++++++++++++++++++++++++++++---------- include/kernel-defaults.mk | 26 +++++++++++++++++ scripts/mkits.sh | 28 ++++++++++++++++++- scripts/target-metadata.pl | 1 + target/Config.in | 3 ++ 6 files changed, 115 insertions(+), 21 deletions(-) diff --git a/config/Config-images.in b/config/Config-images.in index f641d12079..2a3fc2cf3e 100644 --- a/config/Config-images.in +++ b/config/Config-images.in @@ -36,9 +36,11 @@ menu "Target Images" bool "lzma" config TARGET_INITRAMFS_COMPRESSION_LZO + depends on !TARGET_ROOTFS_INITRAMFS_SEPERATE bool "lzo" config TARGET_INITRAMFS_COMPRESSION_LZ4 + depends on !TARGET_ROOTFS_INITRAMFS_SEPERATE bool "lz4" config TARGET_INITRAMFS_COMPRESSION_XZ @@ -57,11 +59,20 @@ menu "Target Images" Kernel uses specified external cpio as INITRAMFS_SOURCE. config TARGET_INITRAMFS_FORCE - bool "Force" - depends on TARGET_ROOTFS_INITRAMFS - default n - help - Ignore the initramfs passed by the bootloader. + bool "Force" + depends on TARGET_ROOTFS_INITRAMFS + default n + help + Ignore the initramfs passed by the bootloader. + + config TARGET_ROOTFS_INITRAMFS_SEPERATE + bool "seperate ramdisk" + depends on TARGET_ROOTFS_INITRAMFS && !TARGET_INITRAMFS_FORCE + default y if USES_SEPERATE_INITRAMFS + help + Generate seperate initrd.cpio instead of embedding it. + This is useful for generating images with a dedicated + ramdisk e.g. in U-Boot's uImage and uImage.FIT formats. comment "Root filesystem archives" diff --git a/include/image-commands.mk b/include/image-commands.mk index 7508ff4d5a..36fc2fefa6 100644 --- a/include/image-commands.mk +++ b/include/image-commands.mk @@ -11,21 +11,6 @@ define rootfs_align $(patsubst %-256k,0x40000,$(patsubst %-128k,0x20000,$(patsubst %-64k,0x10000,$(patsubst squashfs%,0x4,$(patsubst root.%,%,$(1)))))) endef -define Build/uImage - mkimage \ - -A $(LINUX_KARCH) \ - -O linux \ - -T kernel \ - -C $(word 1,$(1)) \ - -a $(KERNEL_LOADADDR) \ - -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \ - -n '$(if $(UIMAGE_NAME),$(UIMAGE_NAME),$(call toupper,$(LINUX_KARCH)) $(VERSION_DIST) Linux-$(LINUX_VERSION))' \ - $(if $(UIMAGE_MAGIC),-M $(UIMAGE_MAGIC)) \ - $(wordlist 2,$(words $(1)),$(1)) \ - -d $@ $@.new - mv $@.new $@ -endef - define Build/buffalo-enc $(eval product=$(word 1,$(1))) $(eval version=$(word 2,$(1))) @@ -191,11 +176,22 @@ define Build/install-dtb ) endef +define Build/initrd_compression + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_BZIP2),.bzip2) \ + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_GZIP),.gzip) \ + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZMA),.lzma) \ + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_XZ),.xz) \ + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_ZSTD),.zstd) +endef + define Build/fit $(TOPDIR)/scripts/mkits.sh \ -D $(DEVICE_NAME) -o $@.its -k $@ \ $(if $(word 2,$(1)),-d $(word 2,$(1))) -C $(word 1,$(1)) \ $(if $(findstring with-rootfs,$(word 3,$(1))),-r $(IMAGE_ROOTFS)) \ + $(if $(findstring with-initrd,$(word 3,$(1))), \ + $(if $(CONFIG_TARGET_ROOTFS_INITRAMFS_SEPERATE), \ + -i $(KERNEL_BUILD_DIR)/initrd.cpio$(strip $(call Build/initrd_compression)))) \ -a $(KERNEL_LOADADDR) -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \ $(if $(DEVICE_FDT_NUM),-n $(DEVICE_FDT_NUM)) \ -c $(if $(DEVICE_DTS_CONFIG),$(DEVICE_DTS_CONFIG),"config@1") \ @@ -435,6 +431,37 @@ metadata_json = \ } \ }' +define Build/uImage + mkimage \ + -A $(LINUX_KARCH) \ + -O linux \ + -T kernel \ + -C $(word 1,$(1)) \ + -a $(KERNEL_LOADADDR) \ + -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \ + -n '$(if $(UIMAGE_NAME),$(UIMAGE_NAME),$(call toupper,$(LINUX_KARCH)) $(VERSION_DIST) Linux-$(LINUX_VERSION))' \ + $(if $(UIMAGE_MAGIC),-M $(UIMAGE_MAGIC)) \ + $(wordlist 2,$(words $(1)),$(1)) \ + -d $@ $@.new + mv $@.new $@ +endef + +define Build/uImage-with-ramdisk + mkimage \ + -A $(LINUX_KARCH) \ + -O linux \ + -T kernel \ + -C $(word 1,$(1)) \ + -a $(KERNEL_LOADADDR) \ + -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \ + -i $(KERNEL_BUILD_DIR)/initrd.cpio.$(strip $(call Build/initrd_compression)) \ + -n '$(if $(UIMAGE_NAME),$(UIMAGE_NAME),$(call toupper,$(LINUX_KARCH)) $(VERSION_DIST) Linux-$(LINUX_VERSION))' \ + $(if $(UIMAGE_MAGIC),-M $(UIMAGE_MAGIC)) \ + $(wordlist 2,$(words $(1)),$(1)) \ + -d $@ $@.new + mv $@.new $@ +endef + define Build/append-metadata $(if $(SUPPORTED_DEVICES),-echo $(call metadata_json,$(SUPPORTED_DEVICES)) | fwtool -I - $@) [ ! -s "$(BUILD_KEY)" -o ! -s "$(BUILD_KEY).ucert" -o ! -s "$@" ] || { \ diff --git a/include/kernel-defaults.mk b/include/kernel-defaults.mk index 8293956f6b..4b39296f8c 100644 --- a/include/kernel-defaults.mk +++ b/include/kernel-defaults.mk @@ -48,6 +48,13 @@ else endif ifeq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),y) + ifeq ($(CONFIG_TARGET_ROOTFS_INITRAMFS_SEPERATE),y) + define Kernel/SetInitramfs/PreConfigure + grep -v -e CONFIG_BLK_DEV_INITRD $(LINUX_DIR)/.config.old > $(LINUX_DIR)/.config + echo 'CONFIG_BLK_DEV_INITRD=y' >> $(LINUX_DIR)/.config + echo 'CONFIG_INITRAMFS_SOURCE=""' >> $(LINUX_DIR)/.config + endef + else ifeq ($(strip $(CONFIG_EXTERNAL_CPIO)),"") define Kernel/SetInitramfs/PreConfigure grep -v -e INITRAMFS -e CONFIG_RD_ -e CONFIG_BLK_DEV_INITRD $(LINUX_DIR)/.config.old > $(LINUX_DIR)/.config @@ -60,14 +67,19 @@ ifeq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),y) echo 'CONFIG_INITRAMFS_SOURCE="$(call qstrip,$(CONFIG_EXTERNAL_CPIO))"' >> $(LINUX_DIR)/.config endef endif +endif define Kernel/SetInitramfs rm -f $(LINUX_DIR)/.config.prev mv $(LINUX_DIR)/.config $(LINUX_DIR)/.config.old $(call Kernel/SetInitramfs/PreConfigure) + ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS_SEPERATE),y) echo 'CONFIG_INITRAMFS_ROOT_UID=$(shell id -u)' >> $(LINUX_DIR)/.config echo 'CONFIG_INITRAMFS_ROOT_GID=$(shell id -g)' >> $(LINUX_DIR)/.config echo "$(if $(CONFIG_TARGET_INITRAMFS_FORCE),CONFIG_INITRAMFS_FORCE=y,# CONFIG_INITRAMFS_FORCE is not set)" >> $(LINUX_DIR)/.config + else + echo "# CONFIG_INITRAMFS_FORCE is not set" >> $(LINUX_DIR)/.config + endif echo "$(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_NONE),CONFIG_INITRAMFS_COMPRESSION_NONE=y,# CONFIG_INITRAMFS_COMPRESSION_NONE is not set)" >> $(LINUX_DIR)/.config echo -e "$(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_GZIP),CONFIG_INITRAMFS_COMPRESSION_GZIP=y\nCONFIG_RD_GZIP=y,# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set\n# CONFIG_RD_GZIP is not set)" >> $(LINUX_DIR)/.config echo -e "$(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_BZIP2),CONFIG_INITRAMFS_COMPRESSION_BZIP2=y\nCONFIG_RD_BZIP2=y,# CONFIG_INITRAMFS_COMPRESSION_BZIP2 is not set\n# CONFIG_RD_BZIP2 is not set)" >> $(LINUX_DIR)/.config @@ -147,6 +159,20 @@ define Kernel/CompileImage/Initramfs $(CP) $(GENERIC_PLATFORM_DIR)/other-files/init $(TARGET_DIR)/init $(if $(SOURCE_DATE_EPOCH),touch -hcd "@$(SOURCE_DATE_EPOCH)" $(TARGET_DIR)/init) rm -rf $(KERNEL_BUILD_DIR)/linux-$(LINUX_VERSION)/usr/initramfs_data.cpio* +ifeq ($(CONFIG_TARGET_ROOTFS_INITRAMFS_SEPERATE),y) +ifeq ($(CONFIG_EXTERNAL_CPIO),y) + $(CP) $(CONFIG_EXTERNAL_CPIO) $(KERNEL_BUILD_DIR)/initrd.cpio +else + ( cd $(TARGET_DIR); find . | cpio -o -H newc -R root:root > $(KERNEL_BUILD_DIR)/initrd.cpio ) +endif + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_BZIP2),bzip2 -9 -c < $(KERNEL_BUILD_DIR)/initrd.cpio > $(KERNEL_BUILD_DIR)/initrd.cpio.bzip2) + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_GZIP),gzip -f -S .gzip -9n $(KERNEL_BUILD_DIR)/initrd.cpio) + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZMA),$(STAGING_DIR_HOST)/bin/lzma e -lc1 -lp2 -pb2 $(KERNEL_BUILD_DIR)/initrd.cpio $(KERNEL_BUILD_DIR)/initrd.cpio.lzma) +# ? $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZO),) + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_XZ),$(STAGING_DIR_HOST)/bin/xz -9 -fz --check=crc32 $(KERNEL_BUILD_DIR)/initrd.cpio) +# ? $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_LZ4),) + $(if $(CONFIG_TARGET_INITRAMFS_COMPRESSION_ZSTD),$(STAGING_DIR_HOST)/bin/zstd -T0 -f -o $(KERNEL_BUILD_DIR)/initrd.cpio.zstd $(KERNEL_BUILD_DIR)/initrd.cpio) +endif +$(KERNEL_MAKE) $(KERNEL_MAKEOPTS_IMAGE) $(if $(KERNELNAME),$(KERNELNAME),all) $(call Kernel/CopyImage,-initramfs) endef diff --git a/scripts/mkits.sh b/scripts/mkits.sh index 59ff3a2d15..ecaba8e965 100755 --- a/scripts/mkits.sh +++ b/scripts/mkits.sh @@ -24,6 +24,7 @@ usage() { printf "\n\t-a ==> set load address to 'addr' (hex)" printf "\n\t-e ==> set entry point to 'entry' (hex)" printf "\n\t-f ==> set device tree compatible string" + printf "\n\t-i ==> include initrd Blob 'initrd'" printf "\n\t-v ==> set kernel version to 'version'" printf "\n\t-k ==> include kernel image 'kernel'" printf "\n\t-D ==> human friendly Device Tree Blob 'name'" @@ -37,10 +38,11 @@ usage() { FDTNUM=1 ROOTFSNUM=1 +INITRDNUM=1 HASH=sha1 LOADABLES= -while getopts ":A:a:c:C:D:d:e:f:k:n:o:v:r:S" OPTION +while getopts ":A:a:c:C:D:d:e:f:i:k:n:o:v:r:S" OPTION do case $OPTION in A ) ARCH=$OPTARG;; @@ -51,6 +53,7 @@ do d ) DTB=$OPTARG;; e ) ENTRY_ADDR=$OPTARG;; f ) COMPATIBLE=$OPTARG;; + i ) INITRD=$OPTARG;; k ) KERNEL=$OPTARG;; n ) FDTNUM=$OPTARG;; o ) OUTPUT=$OPTARG;; @@ -96,6 +99,27 @@ if [ -n "${DTB}" ]; then FDT_PROP="fdt = \"fdt@$FDTNUM\";" fi +if [ -n "${INITRD}" ]; then + INITRD_NODE=" + initrd@$INITRDNUM { + description = \"${ARCH_UPPER} OpenWrt ${DEVICE} initrd\"; + ${COMPATIBLE_PROP} + data = /incbin/(\"${INITRD}\"); + type = \"ramdisk\"; + arch = \"${ARCH}\"; + os = \"linux\"; + hash@1 { + algo = \"crc32\"; + }; + hash@2 { + algo = \"${HASH}\"; + }; + }; +" + INITRD_PROP="ramdisk=\"initrd@${INITRDNUM}\";" +fi + + if [ -n "${ROOTFS}" ]; then dd if="${ROOTFS}" of="${ROOTFS}.pagesync" bs=4096 conv=sync ROOTFS_NODE=" @@ -141,6 +165,7 @@ DATA="/dts-v1/; algo = \"$HASH\"; }; }; +${INITRD_NODE} ${FDT_NODE} ${ROOTFS_NODE} }; @@ -153,6 +178,7 @@ ${ROOTFS_NODE} ${FDT_PROP} ${LOADABLES:+loadables = ${LOADABLES};} ${COMPATIBLE_PROP} + ${INITRD_PROP} }; }; };" diff --git a/scripts/target-metadata.pl b/scripts/target-metadata.pl index 0ea66ebaa6..42d80959de 100755 --- a/scripts/target-metadata.pl +++ b/scripts/target-metadata.pl @@ -33,6 +33,7 @@ sub target_config_features(@) { /^fpu$/ and $ret .= "\tselect HAS_FPU\n"; /^spe_fpu$/ and $ret .= "\tselect HAS_SPE_FPU\n"; /^ramdisk$/ and $ret .= "\tselect USES_INITRAMFS\n"; + /^seperate_ramdisk$/ and $ret .= "\tselect USES_INITRAMFS\n\tselect USES_SEPERATE_INITRAMFS\n"; /^powerpc64$/ and $ret .= "\tselect powerpc64\n"; /^nommu$/ and $ret .= "\tselect NOMMU\n"; /^mips16$/ and $ret .= "\tselect HAS_MIPS16\n"; diff --git a/target/Config.in b/target/Config.in index 7744a34174..9f9620bc2d 100644 --- a/target/Config.in +++ b/target/Config.in @@ -52,6 +52,9 @@ config USES_DEVICETREE config USES_INITRAMFS bool +config USES_SEPERATE_INITRAMFS + bool + config USES_SQUASHFS bool