gen_initramfs_list.sh 7.38 KB
Newer Older
1
#!/bin/sh
Linus Torvalds's avatar
Linus Torvalds committed
2
# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
3
# Copyright (C) 2006 Sam Ravnborg <sam@ravnborg.org>
Linus Torvalds's avatar
Linus Torvalds committed
4
#
5
# Released under the terms of the GNU GPL
Linus Torvalds's avatar
Linus Torvalds committed
6
#
7
# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
8
# the cpio archive, and then compresses it.
9 10 11 12 13 14 15 16 17 18
# The script may also be used to generate the inputfile used for gen_init_cpio
# This script assumes that gen_init_cpio is located in usr/ directory

# error out on errors
set -e

usage() {
cat << EOF
Usage:
$0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
19 20
	-o <file>      Create compressed initramfs file named <file> using
		       gen_init_cpio and compressor depending on the extension
21
	-u <uid>       User ID to map to user ID 0 (root).
22 23
		       <uid> is only meaningful if <cpio_source> is a
		       directory.  "squash" forces all files to uid 0.
24
	-g <gid>       Group ID to map to group ID 0 (root).
25 26
		       <gid> is only meaningful if <cpio_source> is a
		       directory.  "squash" forces all files to gid 0.
27
	<cpio_source>  File list or directory for cpio archive.
28
		       If <cpio_source> is a .cpio file it will be used
29 30 31 32 33 34 35 36 37 38
		       as direct input to initramfs.
	-d             Output the default cpio list.

All options except -o and -l may be repeated and are interpreted
sequentially and immediately.  -u and -g states are preserved across
<cpio_source> options so an explicit "-u 0 -g 0" is required
to reset the root/group mapping.
EOF
}

39 40 41 42 43 44
# awk style field access
# $1 - field number; rest is argument string
field() {
	shift $1 ; echo $1
}

45 46 47 48
list_default_initramfs() {
	# echo usr/kinit/kinit
	:
}
Linus Torvalds's avatar
Linus Torvalds committed
49 50

default_initramfs() {
51
	cat <<-EOF >> ${output}
Linus Torvalds's avatar
Linus Torvalds committed
52 53 54 55 56
		# 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
57 58
		# file /kinit usr/kinit/kinit 0755 0 0
		# slink /init kinit 0755 0 0
Linus Torvalds's avatar
Linus Torvalds committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
	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
}

84 85 86 87
list_print_mtime() {
	:
}

Linus Torvalds's avatar
Linus Torvalds committed
88 89 90
print_mtime() {
	local my_mtime="0"

91 92
	if [ -e "$1" ]; then
		my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
Linus Torvalds's avatar
Linus Torvalds committed
93
	fi
94 95 96 97 98 99

	echo "# Last modified: ${my_mtime}" >> ${output}
	echo "" >> ${output}
}

list_parse() {
100
	[ ! -L "$1" ] && echo "$1 \\" || :
Linus Torvalds's avatar
Linus Torvalds committed
101 102
}

103 104 105
# for each file print a line in following format
# <filetype> <name> <path to file> <octal mode> <uid> <gid>
# for links, devices etc the format differs. See gen_init_cpio for details
Linus Torvalds's avatar
Linus Torvalds committed
106 107
parse() {
	local location="$1"
108
	local name="/${location#${srcdir}}"
Linus Torvalds's avatar
Linus Torvalds committed
109
	# change '//' into '/'
110
	name=$(echo "$name" | sed -e 's://*:/:g')
Linus Torvalds's avatar
Linus Torvalds committed
111 112 113 114 115
	local mode="$2"
	local uid="$3"
	local gid="$4"
	local ftype=$(filetype "${location}")
	# remap uid/gid to 0 if necessary
116 117
	[ "$root_uid" = "squash" ] && uid=0 || [ "$uid" -eq "$root_uid" ] && uid=0
	[ "$root_gid" = "squash" ] && gid=0 || [ "$gid" -eq "$root_gid" ] && gid=0
Linus Torvalds's avatar
Linus Torvalds committed
118 119
	local str="${mode} ${uid} ${gid}"

120 121
	[ "${ftype}" = "invalid" ] && return 0
	[ "${location}" = "${srcdir}" ] && return 0
Linus Torvalds's avatar
Linus Torvalds committed
122 123 124 125 126 127

	case "${ftype}" in
		"file")
			str="${ftype} ${name} ${location} ${str}"
			;;
		"nod")
128 129 130 131 132 133 134 135
			local dev=`LC_ALL=C ls -l "${location}"`
			local maj=`field 5 ${dev}`
			local min=`field 6 ${dev}`
			maj=${maj%,}

			[ -b "${location}" ] && dev="b" || dev="c"

			str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"
Linus Torvalds's avatar
Linus Torvalds committed
136 137
			;;
		"slink")
138
			local target=`readlink "${location}"`
Linus Torvalds's avatar
Linus Torvalds committed
139 140 141 142 143 144 145
			str="${ftype} ${name} ${target} ${str}"
			;;
		*)
			str="${ftype} ${name} ${str}"
			;;
	esac

146
	echo "${str}" >> ${output}
Linus Torvalds's avatar
Linus Torvalds committed
147 148 149 150

	return 0
}

151 152 153 154 155 156 157 158 159 160 161
unknown_option() {
	printf "ERROR: unknown option \"$arg\"\n" >&2
	printf "If the filename validly begins with '-', " >&2
	printf "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
}

list_header() {
162
	:
163 164 165 166 167 168 169 170 171 172 173
}

header() {
	printf "\n#####################\n# $1\n" >> ${output}
}

# process one directory (incl sub-directories)
dir_filelist() {
	${dep_list}header "$1"

	srcdir=$(echo "$1" | sed -e 's://*:/:g')
174
	dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n")
175 176 177 178 179 180 181 182 183 184

	# If $dirlist is only one line, then the directory is empty
	if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
		${dep_list}print_mtime "$1"

		echo "${dirlist}" | \
		while read x; do
			${dep_list}parse ${x}
		done
	fi
Linus Torvalds's avatar
Linus Torvalds committed
185 186
}

187 188 189 190 191 192 193
# if only one file is specified and it is .cpio file then use it direct as fs
# if a directory is specified then add all files in given direcotry to fs
# if a regular file is specified assume it is in gen_initramfs format
input_file() {
	source="$1"
	if [ -f "$1" ]; then
		${dep_list}header "$1"
194
		is_cpio="$(echo "$1" | sed 's/^.*\.cpio\(\..*\)\?/cpio/')"
195
		if [ $2 -eq 0 -a ${is_cpio} = "cpio" ]; then
196
			cpio_file=$1
197
			echo "$1" | grep -q '^.*\.cpio\..*' && is_cpio_compressed="compressed"
198 199 200 201 202 203
			[ ! -z ${dep_list} ] && echo "$1"
			return 0
		fi
		if [ -z ${dep_list} ]; then
			print_mtime "$1" >> ${output}
			cat "$1"         >> ${output}
Linus Torvalds's avatar
Linus Torvalds committed
204
		else
205
		        echo "$1 \\"
206
			cat "$1" | while read type dir file perm ; do
207
				if [ "$type" = "file" ]; then
208 209 210
					echo "$file \\";
				fi
			done
Linus Torvalds's avatar
Linus Torvalds committed
211
		fi
212 213
	elif [ -d "$1" ]; then
		dir_filelist "$1"
Linus Torvalds's avatar
Linus Torvalds committed
214
	else
215
		echo "  ${prog}: Cannot open '$1'" >&2
Linus Torvalds's avatar
Linus Torvalds committed
216 217 218 219
		exit 1
	fi
}

220
prog=$0
Linus Torvalds's avatar
Linus Torvalds committed
221 222
root_uid=0
root_gid=0
223 224 225 226 227
dep_list=
cpio_file=
cpio_list=
output="/dev/stdout"
output_file=""
228
is_cpio_compressed=
Michal Marek's avatar
Michal Marek committed
229
compr="gzip -n -9 -f"
Linus Torvalds's avatar
Linus Torvalds committed
230

231 232 233 234
arg="$1"
case "$arg" in
	"-l")	# files included in initramfs - used by kbuild
		dep_list="list_"
235
		echo "deps_initramfs := $0 \\"
236 237
		shift
		;;
238
	"-o")	# generate compressed cpio image named $1
239 240 241 242
		shift
		output_file="$1"
		cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
		output=${cpio_list}
Michal Marek's avatar
Michal Marek committed
243
		echo "$output_file" | grep -q "\.gz$" && compr="gzip -n -9 -f"
244 245
		echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f"
		echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f"
246 247
		echo "$output_file" | grep -q "\.xz$" && \
				compr="xz --check=crc32 --lzma2=dict=1MiB"
248
		echo "$output_file" | grep -q "\.lzo$" && compr="lzop -9 -f"
249
		echo "$output_file" | grep -q "\.cpio$" && compr="cat"
250 251 252
		shift
		;;
esac
Linus Torvalds's avatar
Linus Torvalds committed
253 254 255 256
while [ $# -gt 0 ]; do
	arg="$1"
	shift
	case "$arg" in
257
		"-u")	# map $1 to uid=0 (root)
Linus Torvalds's avatar
Linus Torvalds committed
258 259 260
			root_uid="$1"
			shift
			;;
261
		"-g")	# map $1 to gid=0 (root)
Linus Torvalds's avatar
Linus Torvalds committed
262 263 264
			root_gid="$1"
			shift
			;;
265
		"-d")	# display default initramfs list
Linus Torvalds's avatar
Linus Torvalds committed
266
			default_list="$arg"
267
			${dep_list}default_initramfs
Linus Torvalds's avatar
Linus Torvalds committed
268 269 270 271 272 273 274 275
			;;
		"-h")
			usage
			exit 0
			;;
		*)
			case "$arg" in
				"-"*)
276
					unknown_option
Linus Torvalds's avatar
Linus Torvalds committed
277
					;;
278 279
				*)	# input file/dir - process it
					input_file "$arg" "$#"
Linus Torvalds's avatar
Linus Torvalds committed
280 281 282 283 284 285
					;;
			esac
			;;
	esac
done

286
# If output_file is set we will generate cpio archive and compress it
Lucas De Marchi's avatar
Lucas De Marchi committed
287
# we are careful to delete tmp files
288 289
if [ ! -z ${output_file} ]; then
	if [ -z ${cpio_file} ]; then
290 291 292 293 294 295 296
		timestamp=
		if test -n "$KBUILD_BUILD_TIMESTAMP"; then
			timestamp="$(date -d"$KBUILD_BUILD_TIMESTAMP" +%s || :)"
			if test -n "$timestamp"; then
				timestamp="-t $timestamp"
			fi
		fi
297
		cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
298
		usr/gen_init_cpio $timestamp ${cpio_list} > ${cpio_tfile}
299 300 301 302
	else
		cpio_tfile=${cpio_file}
	fi
	rm ${cpio_list}
303 304 305
	if [ "${is_cpio_compressed}" = "compressed" ]; then
		cat ${cpio_tfile} > ${output_file}
	else
306 307
		(cat ${cpio_tfile} | ${compr}  - > ${output_file}) \
		|| (rm -f ${output_file} ; false)
308
	fi
309 310
	[ -z ${cpio_file} ] && rm ${cpio_tfile}
fi
Linus Torvalds's avatar
Linus Torvalds committed
311
exit 0