Commit 13a3afc5 authored by Arnout Vandecappelle (Essensium/Mind)'s avatar Arnout Vandecappelle (Essensium/Mind) Committed by Peter Korsgaard
Browse files

fs/initramfs: refactor with fs/cpio



An initramfs is in fact the same as a cpio archive, but embedded in
the kernel.  So instead of duplicating the cpio infrastructure,
we can simply build images/rootfs.cpio and link that into the
kernel.

Signed-off-by: default avatarArnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
Signed-off-by: default avatarPeter Korsgaard <jacmet@sunsite.dk>
parent 3fac21ef
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
config BR2_TARGET_ROOTFS_INITRAMFS
	bool "initramfs for initial ramdisk of linux kernel"
	depends on BR2_LINUX_KERNEL
	select BR2_TARGET_ROOTFS_CPIO
	help
	  Integrate the root filesystem generated by Buildroot as an
	  initramfs inside the kernel image. This integration will
	  take place automatically.

	  The rootfs.initramfs file generated in the images/ directory
	  is only a text file describing the contents of the initramfs
	  in a format understood by the CONFIG_INITRAMFS_SOURCE kernel
	  configuration option.
	  A rootfs.cpio file will be generated in the images/ directory.
	  This is the archive that will be included in the kernel image.
	  The rootfs in the kernel will always be gzip'ed, regardless
	  of how buildroot's cpio archive is configured.

	  Note that enabling initramfs together with other filesystem
	  Note that enabling initramfs together with another filesystem
	  formats doesn't make sense: you would end up having two
	  identical root filesystems, one embedded inside the kernel
	  image, and one separatly.
	  image, and one separately.

comment "initramfs requires a Linux kernel to be built"
	depends on !BR2_LINUX_KERNEL
+0 −203
Original line number Diff line number Diff line
#!/bin/sh
# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
# Released under the terms of the GNU GPL
#
# Generate a newline separated list of entries from the file/directory
# supplied as an argument.
#
# If a file/directory is not supplied then generate a small dummy file.
#
# The output is suitable for gen_init_cpio built from usr/gen_init_cpio.c.
#

default_initramfs() {
	cat <<-EOF
		# This is a very simple, default initramfs

		dir /dev 0755 0 0
		nod /dev/console 0600 0 0 c 5 1
		dir /root 0700 0 0
	EOF
}

filetype() {
	local argv1="$1"

	# symlink test must come before file test
	if [ -L "$argv1" ]; then
		echo "slink"
	elif [ -f "$argv1" ]; then
		echo "file"
	elif [ -d "$argv1" ]; then
		echo "dir"
	elif [ -b "$argv1" -o -c "$argv1" ]; then
		echo "nod"
	elif [ -p "$argv1" ]; then
		echo "pipe"
	elif [ -S "$argv1" ]; then
		echo "sock"
	else
		echo "invalid"
	fi
	return 0
}

print_mtime() {
	local argv1="$1"
	local mymtime="0"

	if [ -e "$argv1" ]; then
		mymtime=$(find "$argv1" -printf "%T@\n" | sort -r | head -n 1)
	fi
	
	echo "# Last modified: $mymtime"
	echo
}

parse() {
	local location="$1"
	local name=$(echo "$location" | sed -e "s,$srcdir,,")
	# change '//' into '/'
	name=$(echo $name | sed -e 's,/[/]*,/,g')
	local mode="$2"
	local uid="$3"
	local gid="$4"
	local ftype=$(filetype "$location")
	# remap uid/gid to 0 if necessary
	[ "x$uid" != "x" ] && [ $uid -eq $root_uid ] && uid=0
	[ "x$gid" != "x" ] && [ $gid -eq $root_gid ] && gid=0
	local str="$mode $uid $gid"

	[ "$ftype" = "invalid" ] && return 0
	[ "$location" = "$srcdir" ] && return 0

	case "$ftype" in
		"file")
			str="$ftype $name $location $str"
			;;
		"nod")
			local devtype=
			local maj=$(LC_ALL=C ls -l "$location" | \
					awk '{sub(/,/, "", $5); print $5}')
			local min=$(LC_ALL=C ls -l "$location" | \
					awk '{print $6}')

			if [ -b "$location" ]; then
				devtype="b"
			else
				devtype="c"
			fi
			str="$ftype $name $str $devtype $maj $min"
			;;
		"slink")
			local target=$(LC_ALL=C ls -l "$location" | \
					awk '{print $11}')
			str="$ftype $name $target $str"
			;;
		*)
			str="$ftype $name $str"
			;;
	esac

	echo "$str"

	return 0
}

usage() {
	printf    "Usage:\n"
	printf    "$0 [ [-u <root_uid>] [-g <root_gid>] [-d | <cpio_source>] ] . . .\n"
	printf    "\n"
	printf -- "-u <root_uid>  User ID to map to user ID 0 (root).\n"
	printf    "               <root_uid> is only meaningful if <cpio_source>\n"
	printf    "               is a directory.\n"
	printf -- "-g <root_gid>  Group ID to map to group ID 0 (root).\n"
	printf    "               <root_gid> is only meaningful if <cpio_source>\n"
	printf    "               is a directory.\n"
	printf    "<cpio_source>  File list or directory for cpio archive.\n"
	printf    "               If <cpio_source> is not provided then a\n"
	printf    "               a default list will be output.\n"
	printf -- "-d             Output the default cpio list.  If no <cpio_source>\n"
	printf    "               is given then the default cpio list will be output.\n"
	printf    "\n"
	printf    "All options may be repeated and are interpreted sequentially\n"
	printf    "and immediately.  -u and -g states are preserved across\n"
	printf    "<cpio_source> options so an explicit \"-u 0 -g 0\" is required\n"
	printf    "to reset the root/group mapping.\n"
}

build_list() {
	printf "\n#####################\n# $cpio_source\n"

	if [ -f "$cpio_source" ]; then
		print_mtime "$cpio_source"
		cat "$cpio_source"
	elif [ -d "$cpio_source" ]; then
		srcdir=$(echo "$cpio_source" | sed -e 's://*:/:g;s:/$::')
		dirlist=$(find "$srcdir" -printf "%p %m %U %G\n" 2>/dev/null)

		# If $dirlist is only one line, then the directory is empty
		if [  "$(echo "$dirlist" | wc -l)" -gt 1 ]; then
			print_mtime "$cpio_source"
		
			echo "$dirlist" | \
			while read x; do
				parse $x
			done
		else
			# Failsafe in case directory is empty
			default_initramfs
		fi
	else
		echo "  $0: Cannot open '$cpio_source'" >&2
		exit 1
	fi
}


root_uid=0
root_gid=0

while [ $# -gt 0 ]; do
	arg="$1"
	shift
	case "$arg" in
		"-u")
			root_uid="$1"
			shift
			;;
		"-g")
			root_gid="$1"
			shift
			;;
		"-d")
			default_list="$arg"
			default_initramfs
			;;
		"-h")
			usage
			exit 0
			;;
		*)
			case "$arg" in
				"-"*)
					printf "ERROR: unknown option \"$arg\"\n" >&2
					printf "If the filename validly begins with '-', then it must be prefixed\n" >&2
					printf "by './' so that it won't be interpreted as an option." >&2
					printf "\n" >&2
					usage >&2
					exit 1
					;;
				*)
					cpio_source="$arg"
					build_list
					;;
			esac
			;;
	esac
done

# spit out the default cpio list if a source hasn't been specified
[ -z "$cpio_source" -a -z "$default_list" ] && default_initramfs

exit 0

fs/initramfs/init

deleted100755 → 0
+0 −7
Original line number Diff line number Diff line
#!/bin/sh
# devtmpfs does not get automounted for initramfs
/bin/mount -t devtmpfs devtmpfs /dev
exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console
exec /sbin/init $*
+11 −24
Original line number Diff line number Diff line
#############################################################
#
# Make a initramfs_list file to be used by gen_init_cpio
# gen_init_cpio is part of the 2.6 linux kernels to build an
# initial ramdisk filesystem based on cpio
# Build a kernel with an integrated initial ramdisk
# filesystem based on cpio.
#
#############################################################

ifeq ($(BR2_ROOTFS_DEVICE_CREATION_STATIC),y)
ROOTFS_INITRAMFS_DEPENDENCIES += rootfs-cpio

define ROOTFS_INITRAMFS_ADD_INIT
	if [ ! -e $(TARGET_DIR)/init ]; then \
		ln -sf sbin/init $(TARGET_DIR)/init; \
	fi
endef
ROOTFS_INITRAMFS_POST_TARGETS += linux26-rebuild-with-initramfs

else
# devtmpfs does not get automounted when initramfs is used.
# Add a pre-init script to mount it before running init
define ROOTFS_INITRAMFS_ADD_INIT
	if [ ! -e $(TARGET_DIR)/init ]; then \
		$(INSTALL) -m 0755 fs/initramfs/init $(TARGET_DIR)/init; \
	fi
endef

endif # BR2_ROOTFS_DEVICE_CREATION_STATIC
# The generic fs infrastructure isn't very useful here.

ROOTFS_INITRAMFS_PRE_GEN_HOOKS += ROOTFS_INITRAMFS_ADD_INIT
rootfs-initramfs: $(ROOTFS_INITRAMFS_DEPENDENCIES) $(ROOTFS_INITRAMFS_POST_TARGETS)

define ROOTFS_INITRAMFS_CMD
	$(SHELL) fs/initramfs/gen_initramfs_list.sh -u 0 -g 0 $(TARGET_DIR) > $$@
endef
rootfs-initramfs-show-depends:
	@echo $(ROOTFS_INITRAMFS_DEPENDENCIES)

ROOTFS_INITRAMFS_POST_TARGETS += linux26-rebuild-with-initramfs
ifeq ($(BR2_TARGET_ROOTFS_INITRAMFS),y)
TARGETS += rootfs-initramfs
endif
$(eval $(call ROOTFS_TARGET,initramfs))
+7 −10
Original line number Diff line number Diff line
@@ -126,13 +126,13 @@ define LINUX_CONFIGURE_CMDS
		$(call KCONFIG_ENABLE_OPT,CONFIG_AEABI,$(@D)/.config),
		$(call KCONFIG_DISABLE_OPT,CONFIG_AEABI,$(@D)/.config))
	# As the kernel gets compiled before root filesystems are
	# built, we create a fake initramfs file list. It'll be
	# replaced later by the real list, and the kernel will be
	# built, we create a fake cpio file. It'll be
	# replaced later by the real cpio archive, and the kernel will be
	# rebuilt using the linux26-rebuild-with-initramfs target.
	$(if $(BR2_TARGET_ROOTFS_INITRAMFS),
		touch $(BINARIES_DIR)/rootfs.initramfs
		touch $(BINARIES_DIR)/rootfs.cpio
		$(call KCONFIG_ENABLE_OPT,CONFIG_BLK_DEV_INITRD,$(@D)/.config)
		$(call KCONFIG_SET_OPT,CONFIG_INITRAMFS_SOURCE,\"$(BINARIES_DIR)/rootfs.initramfs\",$(@D)/.config)
		$(call KCONFIG_SET_OPT,CONFIG_INITRAMFS_SOURCE,\"$(BINARIES_DIR)/rootfs.cpio\",$(@D)/.config)
		$(call KCONFIG_SET_OPT,CONFIG_INITRAMFS_ROOT_UID,0,$(@D)/.config)
		$(call KCONFIG_SET_OPT,CONFIG_INITRAMFS_ROOT_GID,0,$(@D)/.config)
		$(call KCONFIG_DISABLE_OPT,CONFIG_INITRAMFS_COMPRESSION_NONE,$(@D)/.config)
@@ -190,13 +190,10 @@ linux-savedefconfig linux26-savedefconfig: dirs $(LINUX_DIR)/.stamp_configured
	$(MAKE) $(LINUX_MAKE_FLAGS) -C $(LINUX_DIR) \
		$(subst linux-,,$(subst linux26-,,$@))

# Support for rebuilding the kernel after the initramfs file list has
# been generated in $(BINARIES_DIR)/rootfs.initramfs.
$(LINUX_DIR)/.stamp_initramfs_rebuilt: $(LINUX_DIR)/.stamp_target_installed $(LINUX_DIR)/.stamp_images_installed $(BINARIES_DIR)/rootfs.initramfs
# Support for rebuilding the kernel after the cpio archive has
# been generated in $(BINARIES_DIR)/rootfs.cpio.
$(LINUX_DIR)/.stamp_initramfs_rebuilt: $(LINUX_DIR)/.stamp_target_installed $(LINUX_DIR)/.stamp_images_installed $(BINARIES_DIR)/rootfs.cpio
	@$(call MESSAGE,"Rebuilding kernel with initramfs")
	# Remove the previously generated initramfs which was empty,
	# to make sure the kernel will actually regenerate it.
	$(RM) -f $(@D)/usr/initramfs_data.cpio*
	# Build the kernel.
	$(TARGET_MAKE_ENV) $(MAKE) $(LINUX_MAKE_FLAGS) -C $(@D) $(LINUX_IMAGE_NAME)
	# Copy the kernel image to its final destination