aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Ravnborg <sam@mars.ravnborg.org>2006-04-11 07:24:32 -0400
committerSam Ravnborg <sam@mars.ravnborg.org>2006-04-11 07:24:32 -0400
commitd39a206bc35d46a3b2eb98cd4f34e340d5e56a50 (patch)
treec11cac2d3051264accc36dee7ef9a735f4420659
parentd9df92e22aca939857c5bc9ecb130ef22307ccc1 (diff)
kbuild: rebuild initramfs if content of initramfs changes
initramfs.cpio.gz being build in usr/ and included in the kernel was not rebuild when the included files changed. To fix this the following was done: - let gen_initramfs.sh generate a list of files and directories included in the initramfs - gen_initramfs generate the gzipped cpio archive so we could simplify the kbuild file (Makefile) - utilising the kbuild infrastructure so when uid/gid root mapping changes the initramfs will be rebuild With this change we have a much more robust initramfs generation. Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
-rw-r--r--scripts/gen_initramfs_list.sh225
-rw-r--r--usr/Makefile91
2 files changed, 189 insertions, 127 deletions
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index 6d411169bfa6..56b3bed1108f 100644
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -1,22 +1,55 @@
1#!/bin/bash 1#!/bin/bash
2# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org> 2# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
3# Released under the terms of the GNU GPL 3# Copyright (c) 2006 Sam Ravnborg <sam@ravnborg.org>
4#
5# Generate a newline separated list of entries from the file/directory
6# supplied as an argument.
7#
8# If a file/directory is not supplied then generate a small dummy file.
9# 4#
10# The output is suitable for gen_init_cpio built from usr/gen_init_cpio.c. 5# Released under the terms of the GNU GPL
11# 6#
7# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
8# the cpio archive, and gzip to pack it.
9# The script may also be used to generate the inputfile used for gen_init_cpio
10# This script assumes that gen_init_cpio is located in usr/ directory
11
12# error out on errors
13set -e
14
15usage() {
16cat << EOF
17Usage:
18$0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
19 -o <file> Create gzipped initramfs file named <file> using
20 gen_init_cpio and gzip
21 -u <uid> User ID to map to user ID 0 (root).
22 <uid> is only meaningful if <cpio_source>
23 is a directory.
24 -g <gid> Group ID to map to group ID 0 (root).
25 <gid> is only meaningful if <cpio_source>
26 is a directory.
27 <cpio_source> File list or directory for cpio archive.
28 If <cpio_source> is a .cpio file it will be used
29 as direct input to initramfs.
30 -d Output the default cpio list.
31
32All options except -o and -l may be repeated and are interpreted
33sequentially and immediately. -u and -g states are preserved across
34<cpio_source> options so an explicit "-u 0 -g 0" is required
35to reset the root/group mapping.
36EOF
37}
38
39list_default_initramfs() {
40 # echo usr/kinit/kinit
41 :
42}
12 43
13default_initramfs() { 44default_initramfs() {
14 cat <<-EOF 45 cat <<-EOF >> ${output}
15 # This is a very simple, default initramfs 46 # This is a very simple, default initramfs
16 47
17 dir /dev 0755 0 0 48 dir /dev 0755 0 0
18 nod /dev/console 0600 0 0 c 5 1 49 nod /dev/console 0600 0 0 c 5 1
19 dir /root 0700 0 0 50 dir /root 0700 0 0
51 # file /kinit usr/kinit/kinit 0755 0 0
52 # slink /init kinit 0755 0 0
20 EOF 53 EOF
21} 54}
22 55
@@ -42,18 +75,28 @@ filetype() {
42 return 0 75 return 0
43} 76}
44 77
78list_print_mtime() {
79 :
80}
81
45print_mtime() { 82print_mtime() {
46 local argv1="$1"
47 local my_mtime="0" 83 local my_mtime="0"
48 84
49 if [ -e "${argv1}" ]; then 85 if [ -e "$1" ]; then
50 my_mtime=$(find "${argv1}" -printf "%T@\n" | sort -r | head -n 1) 86 my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
51 fi 87 fi
52 88
53 echo "# Last modified: ${my_mtime}" 89 echo "# Last modified: ${my_mtime}" >> ${output}
54 echo 90 echo "" >> ${output}
91}
92
93list_parse() {
94 echo "$1 \\"
55} 95}
56 96
97# for each file print a line in following format
98# <filetype> <name> <path to file> <octal mode> <uid> <gid>
99# for links, devices etc the format differs. See gen_init_cpio for details
57parse() { 100parse() {
58 local location="$1" 101 local location="$1"
59 local name="${location/${srcdir}//}" 102 local name="${location/${srcdir}//}"
@@ -99,80 +142,112 @@ parse() {
99 ;; 142 ;;
100 esac 143 esac
101 144
102 echo "${str}" 145 echo "${str}" >> ${output}
103 146
104 return 0 147 return 0
105} 148}
106 149
107usage() { 150unknown_option() {
108 printf "Usage:\n" 151 printf "ERROR: unknown option \"$arg\"\n" >&2
109 printf "$0 [ [-u <root_uid>] [-g <root_gid>] [-d | <cpio_source>] ] . . .\n" 152 printf "If the filename validly begins with '-', " >&2
110 printf "\n" 153 printf "then it must be prefixed\n" >&2
111 printf -- "-u <root_uid> User ID to map to user ID 0 (root).\n" 154 printf "by './' so that it won't be interpreted as an option." >&2
112 printf " <root_uid> is only meaningful if <cpio_source>\n" 155 printf "\n" >&2
113 printf " is a directory.\n" 156 usage >&2
114 printf -- "-g <root_gid> Group ID to map to group ID 0 (root).\n" 157 exit 1
115 printf " <root_gid> is only meaningful if <cpio_source>\n" 158}
116 printf " is a directory.\n" 159
117 printf "<cpio_source> File list or directory for cpio archive.\n" 160list_header() {
118 printf " If <cpio_source> is not provided then a\n" 161 echo "deps_initramfs := \\"
119 printf " a default list will be output.\n" 162}
120 printf -- "-d Output the default cpio list. If no <cpio_source>\n" 163
121 printf " is given then the default cpio list will be output.\n" 164header() {
122 printf "\n" 165 printf "\n#####################\n# $1\n" >> ${output}
123 printf "All options may be repeated and are interpreted sequentially\n" 166}
124 printf "and immediately. -u and -g states are preserved across\n" 167
125 printf "<cpio_source> options so an explicit \"-u 0 -g 0\" is required\n" 168# process one directory (incl sub-directories)
126 printf "to reset the root/group mapping.\n" 169dir_filelist() {
170 ${dep_list}header "$1"
171
172 srcdir=$(echo "$1" | sed -e 's://*:/:g')
173 dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
174
175 # If $dirlist is only one line, then the directory is empty
176 if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
177 ${dep_list}print_mtime "$1"
178
179 echo "${dirlist}" | \
180 while read x; do
181 ${dep_list}parse ${x}
182 done
183 fi
127} 184}
128 185
129build_list() { 186# if only one file is specified and it is .cpio file then use it direct as fs
130 printf "\n#####################\n# $cpio_source\n" 187# if a directory is specified then add all files in given direcotry to fs
131 188# if a regular file is specified assume it is in gen_initramfs format
132 if [ -f "$cpio_source" ]; then 189input_file() {
133 print_mtime "$cpio_source" 190 source="$1"
134 cat "$cpio_source" 191 if [ -f "$1" ]; then
135 elif [ -d "$cpio_source" ]; then 192 ${dep_list}header "$1"
136 srcdir=$(echo "$cpio_source" | sed -e 's://*:/:g') 193 is_cpio="$(echo "$1" | sed 's/^.*\.cpio/cpio/')"
137 dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null) 194 if [ $2 -eq 0 -a ${is_cpio} == "cpio" ]; then
138 195 cpio_file=$1
139 # If $dirlist is only one line, then the directory is empty 196 [ ! -z ${dep_list} ] && echo "$1"
140 if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then 197 return 0
141 print_mtime "$cpio_source" 198 fi
142 199 if [ -z ${dep_list} ]; then
143 echo "${dirlist}" | \ 200 print_mtime "$1" >> ${output}
144 while read x; do 201 cat "$1" >> ${output}
145 parse ${x}
146 done
147 else 202 else
148 # Failsafe in case directory is empty 203 grep ^file "$1" | cut -d ' ' -f 3
149 default_initramfs
150 fi 204 fi
205 elif [ -d "$1" ]; then
206 dir_filelist "$1"
151 else 207 else
152 echo " $0: Cannot open '$cpio_source'" >&2 208 echo " ${prog}: Cannot open '$1'" >&2
153 exit 1 209 exit 1
154 fi 210 fi
155} 211}
156 212
157 213prog=$0
158root_uid=0 214root_uid=0
159root_gid=0 215root_gid=0
216dep_list=
217cpio_file=
218cpio_list=
219output="/dev/stdout"
220output_file=""
160 221
222arg="$1"
223case "$arg" in
224 "-l") # files included in initramfs - used by kbuild
225 dep_list="list_"
226 shift
227 ;;
228 "-o") # generate gzipped cpio image named $1
229 shift
230 output_file="$1"
231 cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
232 output=${cpio_list}
233 shift
234 ;;
235esac
161while [ $# -gt 0 ]; do 236while [ $# -gt 0 ]; do
162 arg="$1" 237 arg="$1"
163 shift 238 shift
164 case "$arg" in 239 case "$arg" in
165 "-u") 240 "-u") # map $1 to uid=0 (root)
166 root_uid="$1" 241 root_uid="$1"
167 shift 242 shift
168 ;; 243 ;;
169 "-g") 244 "-g") # map $1 to gid=0 (root)
170 root_gid="$1" 245 root_gid="$1"
171 shift 246 shift
172 ;; 247 ;;
173 "-d") 248 "-d") # display default initramfs list
174 default_list="$arg" 249 default_list="$arg"
175 default_initramfs 250 ${dep_list}default_initramfs
176 ;; 251 ;;
177 "-h") 252 "-h")
178 usage 253 usage
@@ -181,23 +256,27 @@ while [ $# -gt 0 ]; do
181 *) 256 *)
182 case "$arg" in 257 case "$arg" in
183 "-"*) 258 "-"*)
184 printf "ERROR: unknown option \"$arg\"\n" >&2 259 unknown_option
185 printf "If the filename validly begins with '-', then it must be prefixed\n" >&2
186 printf "by './' so that it won't be interpreted as an option." >&2
187 printf "\n" >&2
188 usage >&2
189 exit 1
190 ;; 260 ;;
191 *) 261 *) # input file/dir - process it
192 cpio_source="$arg" 262 input_file "$arg" "$#"
193 build_list
194 ;; 263 ;;
195 esac 264 esac
196 ;; 265 ;;
197 esac 266 esac
198done 267done
199 268
200# spit out the default cpio list if a source hasn't been specified 269# If output_file is set we will generate cpio archive and gzip it
201[ -z "$cpio_source" -a -z "$default_list" ] && default_initramfs 270# we are carefull to delete tmp files
202 271if [ ! -z ${output_file} ]; then
272 if [ -z ${cpio_file} ]; then
273 cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
274 usr/gen_init_cpio ${cpio_list} > ${cpio_tfile}
275 else
276 cpio_tfile=${cpio_file}
277 fi
278 rm ${cpio_list}
279 cat ${cpio_tfile} | gzip -f -9 - > ${output_file}
280 [ -z ${cpio_file} ] && rm ${cpio_tfile}
281fi
203exit 0 282exit 0
diff --git a/usr/Makefile b/usr/Makefile
index e2129cb570bb..19d74e6f2685 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -1,65 +1,48 @@
1#
2# kbuild file for usr/ - including initramfs image
3#
1 4
2obj-y := initramfs_data.o 5klibcdirs:;
3
4hostprogs-y := gen_init_cpio
5 6
6clean-files := initramfs_data.cpio.gz initramfs_list 7# Generate builtin.o based on initramfs_data.o
8obj-y := initramfs_data.o
7 9
8# initramfs_data.o contains the initramfs_data.cpio.gz image. 10# initramfs_data.o contains the initramfs_data.cpio.gz image.
9# The image is included using .incbin, a dependency which is not 11# The image is included using .incbin, a dependency which is not
10# tracked automatically. 12# tracked automatically.
11$(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE 13$(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE
12 14
13ifdef CONFIG_INITRAMFS_ROOT_UID 15#####
14gen_initramfs_args += -u $(CONFIG_INITRAMFS_ROOT_UID) 16# Generate the initramfs cpio archive
15endif 17
16 18hostprogs-y := gen_init_cpio
17ifdef CONFIG_INITRAMFS_ROOT_GID 19initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh
18gen_initramfs_args += -g $(CONFIG_INITRAMFS_ROOT_GID) 20ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
19endif 21 $(CONFIG_INITRAMFS_SOURCE),-d)
20 22ramfs-args := \
21# The $(shell echo $(CONFIG_INITRAMFS_SOURCE)) is to remove the 23 $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \
22# gratuitous begin and end quotes from the Kconfig string type. 24 $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) \
23# Internal, escaped quotes in the Kconfig string will loose the 25 $(ramfs-input)
24# escape and become active quotes. 26
25quotefixed_initramfs_source := $(shell echo $(CONFIG_INITRAMFS_SOURCE)) 27# .initramfs_data.cpio.gz.d is used to identify all files included
26 28# in initramfs and to detect if any files are added/removed.
27filechk_initramfs_list = $(CONFIG_SHELL) \ 29# Removed files are identified by directory timestamp being updated
28 $(srctree)/scripts/gen_initramfs_list.sh $(gen_initramfs_args) $(quotefixed_initramfs_source) 30# The dependency list is generated by gen_initramfs.sh -l
29 31ifneq ($(wildcard $(obj)/.initramfs_data.cpio.gz.d),)
30$(obj)/initramfs_list: $(obj)/Makefile FORCE 32 include $(obj)/.initramfs_data.cpio.gz.d
31 $(call filechk,initramfs_list)
32
33quiet_cmd_cpio = CPIO $@
34 cmd_cpio = ./$< $(obj)/initramfs_list > $@
35
36
37# Check if the INITRAMFS_SOURCE is a cpio archive
38ifneq (,$(findstring .cpio,$(quotefixed_initramfs_source)))
39
40# INITRAMFS_SOURCE has a cpio archive - verify that it's a single file
41ifneq (1,$(words $(quotefixed_initramfs_source)))
42$(error Only a single file may be specified in CONFIG_INITRAMFS_SOURCE (="$(quotefixed_initramfs_source)") when a cpio archive is directly specified.)
43endif
44# Now use the cpio archive directly
45initramfs_data_cpio = $(quotefixed_initramfs_source)
46targets += $(quotefixed_initramfs_source)
47
48else
49
50# INITRAMFS_SOURCE is not a cpio archive - create one
51$(obj)/initramfs_data.cpio: $(obj)/gen_init_cpio \
52 $(initramfs-y) $(obj)/initramfs_list FORCE
53 $(call if_changed,cpio)
54
55targets += initramfs_data.cpio
56initramfs_data_cpio = $(obj)/initramfs_data.cpio
57
58endif 33endif
59 34
60 35quiet_cmd_initfs = GEN $@
61$(obj)/initramfs_data.cpio.gz: $(initramfs_data_cpio) FORCE 36 cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
62 $(call if_changed,gzip) 37
63 38targets := initramfs_data.cpio.gz
64targets += initramfs_data.cpio.gz 39$(deps_initramfs): klibcdirs
40# We rebuild initramfs_data.cpio.gz if:
41# 1) Any included file is newer then initramfs_data.cpio.gz
42# 2) There are changes in which files are included (added or deleted)
43# 3) If gen_init_cpio are newer than initramfs_data.cpio.gz
44# 4) arguments to gen_initramfs.sh changes
45$(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
46 $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d
47 $(call if_changed,initfs)
65 48