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: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
This commit is contained in:
Arnout Vandecappelle (Essensium/Mind) 2011-09-06 23:16:09 +02:00 committed by Peter Korsgaard
parent 3fac21ef8d
commit 13a3afc536
5 changed files with 29 additions and 254 deletions

View File

@ -1,20 +1,21 @@
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

View File

@ -1,203 +0,0 @@
#!/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

View File

@ -1,7 +0,0 @@
#!/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 $*

View File

@ -1,36 +1,23 @@
#############################################################
#
# 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)
define ROOTFS_INITRAMFS_ADD_INIT
if [ ! -e $(TARGET_DIR)/init ]; then \
ln -sf sbin/init $(TARGET_DIR)/init; \
fi
endef
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
ROOTFS_INITRAMFS_PRE_GEN_HOOKS += ROOTFS_INITRAMFS_ADD_INIT
define ROOTFS_INITRAMFS_CMD
$(SHELL) fs/initramfs/gen_initramfs_list.sh -u 0 -g 0 $(TARGET_DIR) > $$@
endef
ROOTFS_INITRAMFS_DEPENDENCIES += rootfs-cpio
ROOTFS_INITRAMFS_POST_TARGETS += linux26-rebuild-with-initramfs
$(eval $(call ROOTFS_TARGET,initramfs))
# The generic fs infrastructure isn't very useful here.
rootfs-initramfs: $(ROOTFS_INITRAMFS_DEPENDENCIES) $(ROOTFS_INITRAMFS_POST_TARGETS)
rootfs-initramfs-show-depends:
@echo $(ROOTFS_INITRAMFS_DEPENDENCIES)
ifeq ($(BR2_TARGET_ROOTFS_INITRAMFS),y)
TARGETS += rootfs-initramfs
endif

View File

@ -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