浏览代码

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 <[email protected]>
Daniel Golle 4 年之前
父节点
当前提交
330bd380e8
共有 6 个文件被更改,包括 100 次插入6 次删除
  1. 16 5
      config/Config-images.in
  2. 27 0
      include/image-commands.mk
  3. 26 0
      include/kernel-defaults.mk
  4. 27 1
      scripts/mkits.sh
  5. 1 0
      scripts/target-metadata.pl
  6. 3 0
      target/Config.in

+ 16 - 5
config/Config-images.in

@@ -35,9 +35,11 @@ menu "Target Images"
 				bool "lzma"
 				bool "lzma"
 
 
 			config TARGET_INITRAMFS_COMPRESSION_LZO
 			config TARGET_INITRAMFS_COMPRESSION_LZO
+				depends on !TARGET_ROOTFS_INITRAMFS_SEPERATE
 				bool "lzo"
 				bool "lzo"
 
 
 			config TARGET_INITRAMFS_COMPRESSION_LZ4
 			config TARGET_INITRAMFS_COMPRESSION_LZ4
+				depends on !TARGET_ROOTFS_INITRAMFS_SEPERATE
 				bool "lz4"
 				bool "lz4"
 
 
 			config TARGET_INITRAMFS_COMPRESSION_XZ
 			config TARGET_INITRAMFS_COMPRESSION_XZ
@@ -56,11 +58,20 @@ menu "Target Images"
 			  Kernel uses specified external cpio as INITRAMFS_SOURCE.
 			  Kernel uses specified external cpio as INITRAMFS_SOURCE.
 
 
 		config TARGET_INITRAMFS_FORCE
 		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"
 	comment "Root filesystem archives"
 
 

+ 27 - 0
include/image-commands.mk

@@ -196,11 +196,22 @@ define Build/eva-image
 	mv [email protected] $@
 	mv [email protected] $@
 endef
 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
 define Build/fit
 	$(TOPDIR)/scripts/mkits.sh \
 	$(TOPDIR)/scripts/mkits.sh \
 		-D $(DEVICE_NAME) -o [email protected] -k $@ \
 		-D $(DEVICE_NAME) -o [email protected] -k $@ \
 		$(if $(word 2,$(1)),-d $(word 2,$(1))) -C $(word 1,$(1)) \
 		$(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-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)) \
 		-a $(KERNEL_LOADADDR) -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \
 		$(if $(DEVICE_FDT_NUM),-n $(DEVICE_FDT_NUM)) \
 		$(if $(DEVICE_FDT_NUM),-n $(DEVICE_FDT_NUM)) \
 		-c $(if $(DEVICE_DTS_CONFIG),$(DEVICE_DTS_CONFIG),"config@1") \
 		-c $(if $(DEVICE_DTS_CONFIG),$(DEVICE_DTS_CONFIG),"config@1") \
@@ -450,6 +461,22 @@ define Build/uImage
 	mv [email protected] $@
 	mv [email protected] $@
 endef
 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 $@ [email protected]
+	mv [email protected] $@
+endef
+
 define Build/xor-image
 define Build/xor-image
 	$(STAGING_DIR_HOST)/bin/xorimage -i $@ -o [email protected] $(1)
 	$(STAGING_DIR_HOST)/bin/xorimage -i $@ -o [email protected] $(1)
 	mv [email protected] $@
 	mv [email protected] $@

+ 26 - 0
include/kernel-defaults.mk

@@ -48,6 +48,13 @@ else
 endif
 endif
 
 
 ifeq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),y)
 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)),"")
   ifeq ($(strip $(CONFIG_EXTERNAL_CPIO)),"")
     define Kernel/SetInitramfs/PreConfigure
     define Kernel/SetInitramfs/PreConfigure
 	grep -v -e INITRAMFS -e CONFIG_RD_ -e CONFIG_BLK_DEV_INITRD $(LINUX_DIR)/.config.old > $(LINUX_DIR)/.config
 	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
 	echo 'CONFIG_INITRAMFS_SOURCE="$(call qstrip,$(CONFIG_EXTERNAL_CPIO))"' >> $(LINUX_DIR)/.config
     endef
     endef
   endif
   endif
+endif
 
 
   define Kernel/SetInitramfs
   define Kernel/SetInitramfs
 	rm -f $(LINUX_DIR)/.config.prev
 	rm -f $(LINUX_DIR)/.config.prev
 	mv $(LINUX_DIR)/.config $(LINUX_DIR)/.config.old
 	mv $(LINUX_DIR)/.config $(LINUX_DIR)/.config.old
 	$(call Kernel/SetInitramfs/PreConfigure)
 	$(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_UID=$(shell id -u)' >> $(LINUX_DIR)/.config
 	echo 'CONFIG_INITRAMFS_ROOT_GID=$(shell id -g)' >> $(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
 	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 "$(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_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
 	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
 	$(CP) $(GENERIC_PLATFORM_DIR)/other-files/init $(TARGET_DIR)/init
 	$(if $(SOURCE_DATE_EPOCH),touch -hcd "@$(SOURCE_DATE_EPOCH)" $(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*
 	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)
 	+$(KERNEL_MAKE) $(KERNEL_MAKEOPTS_IMAGE) $(if $(KERNELNAME),$(KERNELNAME),all)
 	$(call Kernel/CopyImage,-initramfs)
 	$(call Kernel/CopyImage,-initramfs)
 endef
 endef

+ 27 - 1
scripts/mkits.sh

@@ -24,6 +24,7 @@ usage() {
 	printf "\n\t-a ==> set load address to 'addr' (hex)"
 	printf "\n\t-a ==> set load address to 'addr' (hex)"
 	printf "\n\t-e ==> set entry point to 'entry' (hex)"
 	printf "\n\t-e ==> set entry point to 'entry' (hex)"
 	printf "\n\t-f ==> set device tree compatible string"
 	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-v ==> set kernel version to 'version'"
 	printf "\n\t-k ==> include kernel image 'kernel'"
 	printf "\n\t-k ==> include kernel image 'kernel'"
 	printf "\n\t-D ==> human friendly Device Tree Blob 'name'"
 	printf "\n\t-D ==> human friendly Device Tree Blob 'name'"
@@ -37,10 +38,11 @@ usage() {
 
 
 FDTNUM=1
 FDTNUM=1
 ROOTFSNUM=1
 ROOTFSNUM=1
+INITRDNUM=1
 HASH=sha1
 HASH=sha1
 LOADABLES=
 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
 do
 	case $OPTION in
 	case $OPTION in
 		A ) ARCH=$OPTARG;;
 		A ) ARCH=$OPTARG;;
@@ -51,6 +53,7 @@ do
 		d ) DTB=$OPTARG;;
 		d ) DTB=$OPTARG;;
 		e ) ENTRY_ADDR=$OPTARG;;
 		e ) ENTRY_ADDR=$OPTARG;;
 		f ) COMPATIBLE=$OPTARG;;
 		f ) COMPATIBLE=$OPTARG;;
+		i ) INITRD=$OPTARG;;
 		k ) KERNEL=$OPTARG;;
 		k ) KERNEL=$OPTARG;;
 		n ) FDTNUM=$OPTARG;;
 		n ) FDTNUM=$OPTARG;;
 		o ) OUTPUT=$OPTARG;;
 		o ) OUTPUT=$OPTARG;;
@@ -96,6 +99,27 @@ if [ -n "${DTB}" ]; then
 	FDT_PROP="fdt = \"fdt@$FDTNUM\";"
 	FDT_PROP="fdt = \"fdt@$FDTNUM\";"
 fi
 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
 if [ -n "${ROOTFS}" ]; then
 	dd if="${ROOTFS}" of="${ROOTFS}.pagesync" bs=4096 conv=sync
 	dd if="${ROOTFS}" of="${ROOTFS}.pagesync" bs=4096 conv=sync
 	ROOTFS_NODE="
 	ROOTFS_NODE="
@@ -141,6 +165,7 @@ DATA="/dts-v1/;
 				algo = \"$HASH\";
 				algo = \"$HASH\";
 			};
 			};
 		};
 		};
+${INITRD_NODE}
 ${FDT_NODE}
 ${FDT_NODE}
 ${ROOTFS_NODE}
 ${ROOTFS_NODE}
 	};
 	};
@@ -153,6 +178,7 @@ ${ROOTFS_NODE}
 			${FDT_PROP}
 			${FDT_PROP}
 			${LOADABLES:+loadables = ${LOADABLES};}
 			${LOADABLES:+loadables = ${LOADABLES};}
 			${COMPATIBLE_PROP}
 			${COMPATIBLE_PROP}
+			${INITRD_PROP}
 		};
 		};
 	};
 	};
 };"
 };"

+ 1 - 0
scripts/target-metadata.pl

@@ -33,6 +33,7 @@ sub target_config_features(@) {
 		/^fpu$/ and $ret .= "\tselect HAS_FPU\n";
 		/^fpu$/ and $ret .= "\tselect HAS_FPU\n";
 		/^spe_fpu$/ and $ret .= "\tselect HAS_SPE_FPU\n";
 		/^spe_fpu$/ and $ret .= "\tselect HAS_SPE_FPU\n";
 		/^ramdisk$/ and $ret .= "\tselect USES_INITRAMFS\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";
 		/^powerpc64$/ and $ret .= "\tselect powerpc64\n";
 		/^nommu$/ and $ret .= "\tselect NOMMU\n";
 		/^nommu$/ and $ret .= "\tselect NOMMU\n";
 		/^mips16$/ and $ret .= "\tselect HAS_MIPS16\n";
 		/^mips16$/ and $ret .= "\tselect HAS_MIPS16\n";

+ 3 - 0
target/Config.in

@@ -51,6 +51,9 @@ config USES_DEVICETREE
 config USES_INITRAMFS
 config USES_INITRAMFS
 	bool
 	bool
 
 
+config USES_SEPERATE_INITRAMFS
+	bool
+
 config USES_SQUASHFS
 config USES_SQUASHFS
 	bool
 	bool