xref: /openbmc/linux/usr/gen_initramfs.sh (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
180e715a0SMasahiro Yamada#!/bin/sh
280e715a0SMasahiro Yamada# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
380e715a0SMasahiro Yamada# Copyright (C) 2006 Sam Ravnborg <sam@ravnborg.org>
480e715a0SMasahiro Yamada#
580e715a0SMasahiro Yamada# Released under the terms of the GNU GPL
680e715a0SMasahiro Yamada#
780e715a0SMasahiro Yamada# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
865e00e04SMasahiro Yamada# the cpio archive.
980e715a0SMasahiro Yamada# This script assumes that gen_init_cpio is located in usr/ directory
1080e715a0SMasahiro Yamada
1180e715a0SMasahiro Yamada# error out on errors
1280e715a0SMasahiro Yamadaset -e
1380e715a0SMasahiro Yamada
1480e715a0SMasahiro Yamadausage() {
1580e715a0SMasahiro Yamadacat << EOF
1680e715a0SMasahiro YamadaUsage:
1796680975SMasahiro Yamada$0 [-o <file>] [-l <dep_list>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
1865e00e04SMasahiro Yamada	-o <file>      Create initramfs file named <file> by using gen_init_cpio
1996680975SMasahiro Yamada	-l <dep_list>  Create dependency list named <dep_list>
2080e715a0SMasahiro Yamada	-u <uid>       User ID to map to user ID 0 (root).
2180e715a0SMasahiro Yamada		       <uid> is only meaningful if <cpio_source> is a
2280e715a0SMasahiro Yamada		       directory.  "squash" forces all files to uid 0.
2380e715a0SMasahiro Yamada	-g <gid>       Group ID to map to group ID 0 (root).
2480e715a0SMasahiro Yamada		       <gid> is only meaningful if <cpio_source> is a
2580e715a0SMasahiro Yamada		       directory.  "squash" forces all files to gid 0.
26*7f8256aeSBenjamin Gray	-d <date>      Use date for all file mtime values
2780e715a0SMasahiro Yamada	<cpio_source>  File list or directory for cpio archive.
2880e715a0SMasahiro Yamada		       If <cpio_source> is a .cpio file it will be used
2980e715a0SMasahiro Yamada		       as direct input to initramfs.
3080e715a0SMasahiro Yamada
3180e715a0SMasahiro YamadaAll options except -o and -l may be repeated and are interpreted
3280e715a0SMasahiro Yamadasequentially and immediately.  -u and -g states are preserved across
3380e715a0SMasahiro Yamada<cpio_source> options so an explicit "-u 0 -g 0" is required
3480e715a0SMasahiro Yamadato reset the root/group mapping.
3580e715a0SMasahiro YamadaEOF
3680e715a0SMasahiro Yamada}
3780e715a0SMasahiro Yamada
3880e715a0SMasahiro Yamada# awk style field access
3980e715a0SMasahiro Yamada# $1 - field number; rest is argument string
4080e715a0SMasahiro Yamadafield() {
4180e715a0SMasahiro Yamada	shift $1 ; echo $1
4280e715a0SMasahiro Yamada}
4380e715a0SMasahiro Yamada
4480e715a0SMasahiro Yamadafiletype() {
4580e715a0SMasahiro Yamada	local argv1="$1"
4680e715a0SMasahiro Yamada
4780e715a0SMasahiro Yamada	# symlink test must come before file test
4880e715a0SMasahiro Yamada	if [ -L "${argv1}" ]; then
4980e715a0SMasahiro Yamada		echo "slink"
5080e715a0SMasahiro Yamada	elif [ -f "${argv1}" ]; then
5180e715a0SMasahiro Yamada		echo "file"
5280e715a0SMasahiro Yamada	elif [ -d "${argv1}" ]; then
5380e715a0SMasahiro Yamada		echo "dir"
5480e715a0SMasahiro Yamada	elif [ -b "${argv1}" -o -c "${argv1}" ]; then
5580e715a0SMasahiro Yamada		echo "nod"
5680e715a0SMasahiro Yamada	elif [ -p "${argv1}" ]; then
5780e715a0SMasahiro Yamada		echo "pipe"
5880e715a0SMasahiro Yamada	elif [ -S "${argv1}" ]; then
5980e715a0SMasahiro Yamada		echo "sock"
6080e715a0SMasahiro Yamada	else
6180e715a0SMasahiro Yamada		echo "invalid"
6280e715a0SMasahiro Yamada	fi
6380e715a0SMasahiro Yamada	return 0
6480e715a0SMasahiro Yamada}
6580e715a0SMasahiro Yamada
6680e715a0SMasahiro Yamadaprint_mtime() {
6780e715a0SMasahiro Yamada	local my_mtime="0"
6880e715a0SMasahiro Yamada
6980e715a0SMasahiro Yamada	if [ -e "$1" ]; then
7080e715a0SMasahiro Yamada		my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
7180e715a0SMasahiro Yamada	fi
7280e715a0SMasahiro Yamada
73469e87e8SMasahiro Yamada	echo "# Last modified: ${my_mtime}" >> $cpio_list
74469e87e8SMasahiro Yamada	echo "" >> $cpio_list
7580e715a0SMasahiro Yamada}
7680e715a0SMasahiro Yamada
7780e715a0SMasahiro Yamadalist_parse() {
7896680975SMasahiro Yamada	if [ -z "$dep_list" -o -L "$1" ]; then
7980e715a0SMasahiro Yamada		return
8080e715a0SMasahiro Yamada	fi
8196680975SMasahiro Yamada	echo "$1" | sed 's/:/\\:/g; s/$/ \\/' >> $dep_list
8280e715a0SMasahiro Yamada}
8380e715a0SMasahiro Yamada
8480e715a0SMasahiro Yamada# for each file print a line in following format
8580e715a0SMasahiro Yamada# <filetype> <name> <path to file> <octal mode> <uid> <gid>
8680e715a0SMasahiro Yamada# for links, devices etc the format differs. See gen_init_cpio for details
8780e715a0SMasahiro Yamadaparse() {
8880e715a0SMasahiro Yamada	local location="$1"
8980e715a0SMasahiro Yamada	local name="/${location#${srcdir}}"
9080e715a0SMasahiro Yamada	# change '//' into '/'
9180e715a0SMasahiro Yamada	name=$(echo "$name" | sed -e 's://*:/:g')
9280e715a0SMasahiro Yamada	local mode="$2"
9380e715a0SMasahiro Yamada	local uid="$3"
9480e715a0SMasahiro Yamada	local gid="$4"
9580e715a0SMasahiro Yamada	local ftype=$(filetype "${location}")
9680e715a0SMasahiro Yamada	# remap uid/gid to 0 if necessary
9780e715a0SMasahiro Yamada	[ "$root_uid" = "squash" ] && uid=0 || [ "$uid" -eq "$root_uid" ] && uid=0
9880e715a0SMasahiro Yamada	[ "$root_gid" = "squash" ] && gid=0 || [ "$gid" -eq "$root_gid" ] && gid=0
9980e715a0SMasahiro Yamada	local str="${mode} ${uid} ${gid}"
10080e715a0SMasahiro Yamada
10180e715a0SMasahiro Yamada	[ "${ftype}" = "invalid" ] && return 0
10280e715a0SMasahiro Yamada	[ "${location}" = "${srcdir}" ] && return 0
10380e715a0SMasahiro Yamada
10480e715a0SMasahiro Yamada	case "${ftype}" in
10580e715a0SMasahiro Yamada		"file")
10680e715a0SMasahiro Yamada			str="${ftype} ${name} ${location} ${str}"
10780e715a0SMasahiro Yamada			;;
10880e715a0SMasahiro Yamada		"nod")
10980e715a0SMasahiro Yamada			local dev="`LC_ALL=C ls -l "${location}"`"
11080e715a0SMasahiro Yamada			local maj=`field 5 ${dev}`
11180e715a0SMasahiro Yamada			local min=`field 6 ${dev}`
11280e715a0SMasahiro Yamada			maj=${maj%,}
11380e715a0SMasahiro Yamada
11480e715a0SMasahiro Yamada			[ -b "${location}" ] && dev="b" || dev="c"
11580e715a0SMasahiro Yamada
11680e715a0SMasahiro Yamada			str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"
11780e715a0SMasahiro Yamada			;;
11880e715a0SMasahiro Yamada		"slink")
11980e715a0SMasahiro Yamada			local target=`readlink "${location}"`
12080e715a0SMasahiro Yamada			str="${ftype} ${name} ${target} ${str}"
12180e715a0SMasahiro Yamada			;;
12280e715a0SMasahiro Yamada		*)
12380e715a0SMasahiro Yamada			str="${ftype} ${name} ${str}"
12480e715a0SMasahiro Yamada			;;
12580e715a0SMasahiro Yamada	esac
12680e715a0SMasahiro Yamada
127469e87e8SMasahiro Yamada	echo "${str}" >> $cpio_list
12880e715a0SMasahiro Yamada
12980e715a0SMasahiro Yamada	return 0
13080e715a0SMasahiro Yamada}
13180e715a0SMasahiro Yamada
13280e715a0SMasahiro Yamadaunknown_option() {
13380e715a0SMasahiro Yamada	printf "ERROR: unknown option \"$arg\"\n" >&2
13480e715a0SMasahiro Yamada	printf "If the filename validly begins with '-', " >&2
13580e715a0SMasahiro Yamada	printf "then it must be prefixed\n" >&2
13680e715a0SMasahiro Yamada	printf "by './' so that it won't be interpreted as an option." >&2
13780e715a0SMasahiro Yamada	printf "\n" >&2
13880e715a0SMasahiro Yamada	usage >&2
13980e715a0SMasahiro Yamada	exit 1
14080e715a0SMasahiro Yamada}
14180e715a0SMasahiro Yamada
14280e715a0SMasahiro Yamadaheader() {
143469e87e8SMasahiro Yamada	printf "\n#####################\n# $1\n" >> $cpio_list
14480e715a0SMasahiro Yamada}
14580e715a0SMasahiro Yamada
14680e715a0SMasahiro Yamada# process one directory (incl sub-directories)
14780e715a0SMasahiro Yamadadir_filelist() {
14896680975SMasahiro Yamada	header "$1"
14980e715a0SMasahiro Yamada
15080e715a0SMasahiro Yamada	srcdir=$(echo "$1" | sed -e 's://*:/:g')
15177a88274SMasahiro Yamada	dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" | LC_ALL=C sort)
15280e715a0SMasahiro Yamada
15380e715a0SMasahiro Yamada	# If $dirlist is only one line, then the directory is empty
15480e715a0SMasahiro Yamada	if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
15596680975SMasahiro Yamada		print_mtime "$1"
15680e715a0SMasahiro Yamada
15780e715a0SMasahiro Yamada		echo "${dirlist}" | \
15880e715a0SMasahiro Yamada		while read x; do
15996680975SMasahiro Yamada			list_parse $x
16096680975SMasahiro Yamada			parse $x
16180e715a0SMasahiro Yamada		done
16280e715a0SMasahiro Yamada	fi
16380e715a0SMasahiro Yamada}
16480e715a0SMasahiro Yamada
16580e715a0SMasahiro Yamadainput_file() {
16680e715a0SMasahiro Yamada	source="$1"
16780e715a0SMasahiro Yamada	if [ -f "$1" ]; then
16865e00e04SMasahiro Yamada		# If a regular file is specified, assume it is in
16965e00e04SMasahiro Yamada		# gen_init_cpio format
17096680975SMasahiro Yamada		header "$1"
171469e87e8SMasahiro Yamada		print_mtime "$1" >> $cpio_list
172469e87e8SMasahiro Yamada		cat "$1"         >> $cpio_list
17396680975SMasahiro Yamada		if [ -n "$dep_list" ]; then
17496680975SMasahiro Yamada		        echo "$1 \\"  >> $dep_list
17580e715a0SMasahiro Yamada			cat "$1" | while read type dir file perm ; do
17680e715a0SMasahiro Yamada				if [ "$type" = "file" ]; then
17796680975SMasahiro Yamada					echo "$file \\" >> $dep_list
17880e715a0SMasahiro Yamada				fi
17980e715a0SMasahiro Yamada			done
18080e715a0SMasahiro Yamada		fi
18180e715a0SMasahiro Yamada	elif [ -d "$1" ]; then
18265e00e04SMasahiro Yamada		# If a directory is specified then add all files in it to fs
18380e715a0SMasahiro Yamada		dir_filelist "$1"
18480e715a0SMasahiro Yamada	else
18580e715a0SMasahiro Yamada		echo "  ${prog}: Cannot open '$1'" >&2
18680e715a0SMasahiro Yamada		exit 1
18780e715a0SMasahiro Yamada	fi
18880e715a0SMasahiro Yamada}
18980e715a0SMasahiro Yamada
19080e715a0SMasahiro Yamadaprog=$0
19180e715a0SMasahiro Yamadaroot_uid=0
19280e715a0SMasahiro Yamadaroot_gid=0
19380e715a0SMasahiro Yamadadep_list=
194*7f8256aeSBenjamin Graytimestamp=
195469e87e8SMasahiro Yamadacpio_list=$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)
19680e715a0SMasahiro Yamadaoutput="/dev/stdout"
19780e715a0SMasahiro Yamada
1987168965eSMasahiro Yamadatrap "rm -f $cpio_list" EXIT
1997168965eSMasahiro Yamada
20096680975SMasahiro Yamadawhile [ $# -gt 0 ]; do
20180e715a0SMasahiro Yamada	arg="$1"
20296680975SMasahiro Yamada	shift
20380e715a0SMasahiro Yamada	case "$arg" in
20480e715a0SMasahiro Yamada		"-l")	# files included in initramfs - used by kbuild
20596680975SMasahiro Yamada			dep_list="$1"
20696680975SMasahiro Yamada			echo "deps_initramfs := \\" > $dep_list
20780e715a0SMasahiro Yamada			shift
20880e715a0SMasahiro Yamada			;;
20965e00e04SMasahiro Yamada		"-o")	# generate cpio image named $1
21065e00e04SMasahiro Yamada			output="$1"
21180e715a0SMasahiro Yamada			shift
21280e715a0SMasahiro Yamada			;;
21380e715a0SMasahiro Yamada		"-u")	# map $1 to uid=0 (root)
21480e715a0SMasahiro Yamada			root_uid="$1"
21580e715a0SMasahiro Yamada			[ "$root_uid" = "-1" ] && root_uid=$(id -u || echo 0)
21680e715a0SMasahiro Yamada			shift
21780e715a0SMasahiro Yamada			;;
21880e715a0SMasahiro Yamada		"-g")	# map $1 to gid=0 (root)
21980e715a0SMasahiro Yamada			root_gid="$1"
22080e715a0SMasahiro Yamada			[ "$root_gid" = "-1" ] && root_gid=$(id -g || echo 0)
22180e715a0SMasahiro Yamada			shift
22280e715a0SMasahiro Yamada			;;
223*7f8256aeSBenjamin Gray		"-d")	# date for file mtimes
224*7f8256aeSBenjamin Gray			timestamp="$(date -d"$1" +%s || :)"
225*7f8256aeSBenjamin Gray			if test -n "$timestamp"; then
226*7f8256aeSBenjamin Gray				timestamp="-t $timestamp"
227*7f8256aeSBenjamin Gray			fi
228*7f8256aeSBenjamin Gray			shift
229*7f8256aeSBenjamin Gray			;;
23080e715a0SMasahiro Yamada		"-h")
23180e715a0SMasahiro Yamada			usage
23280e715a0SMasahiro Yamada			exit 0
23380e715a0SMasahiro Yamada			;;
23480e715a0SMasahiro Yamada		*)
23580e715a0SMasahiro Yamada			case "$arg" in
23680e715a0SMasahiro Yamada				"-"*)
23780e715a0SMasahiro Yamada					unknown_option
23880e715a0SMasahiro Yamada					;;
23980e715a0SMasahiro Yamada				*)	# input file/dir - process it
24065e00e04SMasahiro Yamada					input_file "$arg"
24180e715a0SMasahiro Yamada					;;
24280e715a0SMasahiro Yamada			esac
24380e715a0SMasahiro Yamada			;;
24480e715a0SMasahiro Yamada	esac
24580e715a0SMasahiro Yamadadone
24680e715a0SMasahiro Yamada
24765e00e04SMasahiro Yamada# If output_file is set we will generate cpio archive
24880e715a0SMasahiro Yamada# we are careful to delete tmp files
24965e00e04SMasahiro Yamadausr/gen_init_cpio $timestamp $cpio_list > $output
250