hc
2023-12-06 d38611ca164021d018c1b23eee65bbebc09c63e0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#!/bin/sh
# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
# Copyright (C) 2006 Sam Ravnborg <sam@ravnborg.org>
#
# Released under the terms of the GNU GPL
#
# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
# the cpio archive.
# 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>] [-l <dep_list>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
   -o <file>      Create initramfs file named <file> by using gen_init_cpio
   -l <dep_list>  Create dependency list named <dep_list>
   -u <uid>       User ID to map to user ID 0 (root).
              <uid> is only meaningful if <cpio_source> is a
              directory.  "squash" forces all files to uid 0.
   -g <gid>       Group ID to map to group ID 0 (root).
              <gid> is only meaningful if <cpio_source> is a
              directory.  "squash" forces all files to gid 0.
   <cpio_source>  File list or directory for cpio archive.
              If <cpio_source> is a .cpio file it will be used
              as direct input to initramfs.
 
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
}
 
# awk style field access
# $1 - field number; rest is argument string
field() {
   shift $1 ; echo $1
}
 
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 my_mtime="0"
 
   if [ -e "$1" ]; then
       my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
   fi
 
   echo "# Last modified: ${my_mtime}" >> $cpio_list
   echo "" >> $cpio_list
}
 
list_parse() {
   if [ -z "$dep_list" -o -L "$1" ]; then
       return
   fi
   echo "$1" | sed 's/:/\\:/g; s/$/ \\/' >> $dep_list
}
 
# 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
parse() {
   local location="$1"
   local name="/${location#${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
   [ "$root_uid" = "squash" ] && uid=0 || [ "$uid" -eq "$root_uid" ] && uid=0
   [ "$root_gid" = "squash" ] && gid=0 || [ "$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 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}"
           ;;
       "slink")
           local target=`readlink "${location}"`
           str="${ftype} ${name} ${target} ${str}"
           ;;
       *)
           str="${ftype} ${name} ${str}"
           ;;
   esac
 
   echo "${str}" >> $cpio_list
 
   return 0
}
 
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
}
 
header() {
   printf "\n#####################\n# $1\n" >> $cpio_list
}
 
# process one directory (incl sub-directories)
dir_filelist() {
   header "$1"
 
   srcdir=$(echo "$1" | sed -e 's://*:/:g')
   dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" | LANG=C sort)
 
   # If $dirlist is only one line, then the directory is empty
   if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
       print_mtime "$1"
 
       echo "${dirlist}" | \
       while read x; do
           list_parse $x
           parse $x
       done
   fi
}
 
input_file() {
   source="$1"
   if [ -f "$1" ]; then
       # If a regular file is specified, assume it is in
       # gen_init_cpio format
       header "$1"
       print_mtime "$1" >> $cpio_list
       cat "$1"         >> $cpio_list
       if [ -n "$dep_list" ]; then
               echo "$1 \\"  >> $dep_list
           cat "$1" | while read type dir file perm ; do
               if [ "$type" = "file" ]; then
                   echo "$file \\" >> $dep_list
               fi
           done
       fi
   elif [ -d "$1" ]; then
       # If a directory is specified then add all files in it to fs
       dir_filelist "$1"
   else
       echo "  ${prog}: Cannot open '$1'" >&2
       exit 1
   fi
}
 
prog=$0
root_uid=0
root_gid=0
dep_list=
cpio_list=$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)
output="/dev/stdout"
 
trap "rm -f $cpio_list" EXIT
 
while [ $# -gt 0 ]; do
   arg="$1"
   shift
   case "$arg" in
       "-l")    # files included in initramfs - used by kbuild
           dep_list="$1"
           echo "deps_initramfs := \\" > $dep_list
           shift
           ;;
       "-o")    # generate cpio image named $1
           output="$1"
           shift
           ;;
       "-u")    # map $1 to uid=0 (root)
           root_uid="$1"
           [ "$root_uid" = "-1" ] && root_uid=$(id -u || echo 0)
           shift
           ;;
       "-g")    # map $1 to gid=0 (root)
           root_gid="$1"
           [ "$root_gid" = "-1" ] && root_gid=$(id -g || echo 0)
           shift
           ;;
       "-h")
           usage
           exit 0
           ;;
       *)
           case "$arg" in
               "-"*)
                   unknown_option
                   ;;
               *)    # input file/dir - process it
                   input_file "$arg"
                   ;;
           esac
           ;;
   esac
done
 
# If output_file is set we will generate cpio archive
# we are careful to delete tmp files
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
usr/gen_init_cpio $timestamp $cpio_list > $output