1*4882a593Smuzhiyun#!/bin/sh 2*4882a593Smuzhiyun# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org> 3*4882a593Smuzhiyun# Copyright (C) 2006 Sam Ravnborg <sam@ravnborg.org> 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun# Released under the terms of the GNU GPL 6*4882a593Smuzhiyun# 7*4882a593Smuzhiyun# Generate a cpio packed initramfs. It uses gen_init_cpio to generate 8*4882a593Smuzhiyun# the cpio archive. 9*4882a593Smuzhiyun# This script assumes that gen_init_cpio is located in usr/ directory 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun# error out on errors 12*4882a593Smuzhiyunset -e 13*4882a593Smuzhiyun 14*4882a593Smuzhiyunusage() { 15*4882a593Smuzhiyuncat << EOF 16*4882a593SmuzhiyunUsage: 17*4882a593Smuzhiyun$0 [-o <file>] [-l <dep_list>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ... 18*4882a593Smuzhiyun -o <file> Create initramfs file named <file> by using gen_init_cpio 19*4882a593Smuzhiyun -l <dep_list> Create dependency list named <dep_list> 20*4882a593Smuzhiyun -u <uid> User ID to map to user ID 0 (root). 21*4882a593Smuzhiyun <uid> is only meaningful if <cpio_source> is a 22*4882a593Smuzhiyun directory. "squash" forces all files to uid 0. 23*4882a593Smuzhiyun -g <gid> Group ID to map to group ID 0 (root). 24*4882a593Smuzhiyun <gid> is only meaningful if <cpio_source> is a 25*4882a593Smuzhiyun directory. "squash" forces all files to gid 0. 26*4882a593Smuzhiyun <cpio_source> File list or directory for cpio archive. 27*4882a593Smuzhiyun If <cpio_source> is a .cpio file it will be used 28*4882a593Smuzhiyun as direct input to initramfs. 29*4882a593Smuzhiyun 30*4882a593SmuzhiyunAll options except -o and -l may be repeated and are interpreted 31*4882a593Smuzhiyunsequentially and immediately. -u and -g states are preserved across 32*4882a593Smuzhiyun<cpio_source> options so an explicit "-u 0 -g 0" is required 33*4882a593Smuzhiyunto reset the root/group mapping. 34*4882a593SmuzhiyunEOF 35*4882a593Smuzhiyun} 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun# awk style field access 38*4882a593Smuzhiyun# $1 - field number; rest is argument string 39*4882a593Smuzhiyunfield() { 40*4882a593Smuzhiyun shift $1 ; echo $1 41*4882a593Smuzhiyun} 42*4882a593Smuzhiyun 43*4882a593Smuzhiyunfiletype() { 44*4882a593Smuzhiyun local argv1="$1" 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun # symlink test must come before file test 47*4882a593Smuzhiyun if [ -L "${argv1}" ]; then 48*4882a593Smuzhiyun echo "slink" 49*4882a593Smuzhiyun elif [ -f "${argv1}" ]; then 50*4882a593Smuzhiyun echo "file" 51*4882a593Smuzhiyun elif [ -d "${argv1}" ]; then 52*4882a593Smuzhiyun echo "dir" 53*4882a593Smuzhiyun elif [ -b "${argv1}" -o -c "${argv1}" ]; then 54*4882a593Smuzhiyun echo "nod" 55*4882a593Smuzhiyun elif [ -p "${argv1}" ]; then 56*4882a593Smuzhiyun echo "pipe" 57*4882a593Smuzhiyun elif [ -S "${argv1}" ]; then 58*4882a593Smuzhiyun echo "sock" 59*4882a593Smuzhiyun else 60*4882a593Smuzhiyun echo "invalid" 61*4882a593Smuzhiyun fi 62*4882a593Smuzhiyun return 0 63*4882a593Smuzhiyun} 64*4882a593Smuzhiyun 65*4882a593Smuzhiyunprint_mtime() { 66*4882a593Smuzhiyun local my_mtime="0" 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun if [ -e "$1" ]; then 69*4882a593Smuzhiyun my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1) 70*4882a593Smuzhiyun fi 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun echo "# Last modified: ${my_mtime}" >> $cpio_list 73*4882a593Smuzhiyun echo "" >> $cpio_list 74*4882a593Smuzhiyun} 75*4882a593Smuzhiyun 76*4882a593Smuzhiyunlist_parse() { 77*4882a593Smuzhiyun if [ -z "$dep_list" -o -L "$1" ]; then 78*4882a593Smuzhiyun return 79*4882a593Smuzhiyun fi 80*4882a593Smuzhiyun echo "$1" | sed 's/:/\\:/g; s/$/ \\/' >> $dep_list 81*4882a593Smuzhiyun} 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun# for each file print a line in following format 84*4882a593Smuzhiyun# <filetype> <name> <path to file> <octal mode> <uid> <gid> 85*4882a593Smuzhiyun# for links, devices etc the format differs. See gen_init_cpio for details 86*4882a593Smuzhiyunparse() { 87*4882a593Smuzhiyun local location="$1" 88*4882a593Smuzhiyun local name="/${location#${srcdir}}" 89*4882a593Smuzhiyun # change '//' into '/' 90*4882a593Smuzhiyun name=$(echo "$name" | sed -e 's://*:/:g') 91*4882a593Smuzhiyun local mode="$2" 92*4882a593Smuzhiyun local uid="$3" 93*4882a593Smuzhiyun local gid="$4" 94*4882a593Smuzhiyun local ftype=$(filetype "${location}") 95*4882a593Smuzhiyun # remap uid/gid to 0 if necessary 96*4882a593Smuzhiyun [ "$root_uid" = "squash" ] && uid=0 || [ "$uid" -eq "$root_uid" ] && uid=0 97*4882a593Smuzhiyun [ "$root_gid" = "squash" ] && gid=0 || [ "$gid" -eq "$root_gid" ] && gid=0 98*4882a593Smuzhiyun local str="${mode} ${uid} ${gid}" 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun [ "${ftype}" = "invalid" ] && return 0 101*4882a593Smuzhiyun [ "${location}" = "${srcdir}" ] && return 0 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun case "${ftype}" in 104*4882a593Smuzhiyun "file") 105*4882a593Smuzhiyun str="${ftype} ${name} ${location} ${str}" 106*4882a593Smuzhiyun ;; 107*4882a593Smuzhiyun "nod") 108*4882a593Smuzhiyun local dev="`LC_ALL=C ls -l "${location}"`" 109*4882a593Smuzhiyun local maj=`field 5 ${dev}` 110*4882a593Smuzhiyun local min=`field 6 ${dev}` 111*4882a593Smuzhiyun maj=${maj%,} 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun [ -b "${location}" ] && dev="b" || dev="c" 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun str="${ftype} ${name} ${str} ${dev} ${maj} ${min}" 116*4882a593Smuzhiyun ;; 117*4882a593Smuzhiyun "slink") 118*4882a593Smuzhiyun local target=`readlink "${location}"` 119*4882a593Smuzhiyun str="${ftype} ${name} ${target} ${str}" 120*4882a593Smuzhiyun ;; 121*4882a593Smuzhiyun *) 122*4882a593Smuzhiyun str="${ftype} ${name} ${str}" 123*4882a593Smuzhiyun ;; 124*4882a593Smuzhiyun esac 125*4882a593Smuzhiyun 126*4882a593Smuzhiyun echo "${str}" >> $cpio_list 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun return 0 129*4882a593Smuzhiyun} 130*4882a593Smuzhiyun 131*4882a593Smuzhiyununknown_option() { 132*4882a593Smuzhiyun printf "ERROR: unknown option \"$arg\"\n" >&2 133*4882a593Smuzhiyun printf "If the filename validly begins with '-', " >&2 134*4882a593Smuzhiyun printf "then it must be prefixed\n" >&2 135*4882a593Smuzhiyun printf "by './' so that it won't be interpreted as an option." >&2 136*4882a593Smuzhiyun printf "\n" >&2 137*4882a593Smuzhiyun usage >&2 138*4882a593Smuzhiyun exit 1 139*4882a593Smuzhiyun} 140*4882a593Smuzhiyun 141*4882a593Smuzhiyunheader() { 142*4882a593Smuzhiyun printf "\n#####################\n# $1\n" >> $cpio_list 143*4882a593Smuzhiyun} 144*4882a593Smuzhiyun 145*4882a593Smuzhiyun# process one directory (incl sub-directories) 146*4882a593Smuzhiyundir_filelist() { 147*4882a593Smuzhiyun header "$1" 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun srcdir=$(echo "$1" | sed -e 's://*:/:g') 150*4882a593Smuzhiyun dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" | LANG=C sort) 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun # If $dirlist is only one line, then the directory is empty 153*4882a593Smuzhiyun if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then 154*4882a593Smuzhiyun print_mtime "$1" 155*4882a593Smuzhiyun 156*4882a593Smuzhiyun echo "${dirlist}" | \ 157*4882a593Smuzhiyun while read x; do 158*4882a593Smuzhiyun list_parse $x 159*4882a593Smuzhiyun parse $x 160*4882a593Smuzhiyun done 161*4882a593Smuzhiyun fi 162*4882a593Smuzhiyun} 163*4882a593Smuzhiyun 164*4882a593Smuzhiyuninput_file() { 165*4882a593Smuzhiyun source="$1" 166*4882a593Smuzhiyun if [ -f "$1" ]; then 167*4882a593Smuzhiyun # If a regular file is specified, assume it is in 168*4882a593Smuzhiyun # gen_init_cpio format 169*4882a593Smuzhiyun header "$1" 170*4882a593Smuzhiyun print_mtime "$1" >> $cpio_list 171*4882a593Smuzhiyun cat "$1" >> $cpio_list 172*4882a593Smuzhiyun if [ -n "$dep_list" ]; then 173*4882a593Smuzhiyun echo "$1 \\" >> $dep_list 174*4882a593Smuzhiyun cat "$1" | while read type dir file perm ; do 175*4882a593Smuzhiyun if [ "$type" = "file" ]; then 176*4882a593Smuzhiyun echo "$file \\" >> $dep_list 177*4882a593Smuzhiyun fi 178*4882a593Smuzhiyun done 179*4882a593Smuzhiyun fi 180*4882a593Smuzhiyun elif [ -d "$1" ]; then 181*4882a593Smuzhiyun # If a directory is specified then add all files in it to fs 182*4882a593Smuzhiyun dir_filelist "$1" 183*4882a593Smuzhiyun else 184*4882a593Smuzhiyun echo " ${prog}: Cannot open '$1'" >&2 185*4882a593Smuzhiyun exit 1 186*4882a593Smuzhiyun fi 187*4882a593Smuzhiyun} 188*4882a593Smuzhiyun 189*4882a593Smuzhiyunprog=$0 190*4882a593Smuzhiyunroot_uid=0 191*4882a593Smuzhiyunroot_gid=0 192*4882a593Smuzhiyundep_list= 193*4882a593Smuzhiyuncpio_list=$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX) 194*4882a593Smuzhiyunoutput="/dev/stdout" 195*4882a593Smuzhiyun 196*4882a593Smuzhiyuntrap "rm -f $cpio_list" EXIT 197*4882a593Smuzhiyun 198*4882a593Smuzhiyunwhile [ $# -gt 0 ]; do 199*4882a593Smuzhiyun arg="$1" 200*4882a593Smuzhiyun shift 201*4882a593Smuzhiyun case "$arg" in 202*4882a593Smuzhiyun "-l") # files included in initramfs - used by kbuild 203*4882a593Smuzhiyun dep_list="$1" 204*4882a593Smuzhiyun echo "deps_initramfs := \\" > $dep_list 205*4882a593Smuzhiyun shift 206*4882a593Smuzhiyun ;; 207*4882a593Smuzhiyun "-o") # generate cpio image named $1 208*4882a593Smuzhiyun output="$1" 209*4882a593Smuzhiyun shift 210*4882a593Smuzhiyun ;; 211*4882a593Smuzhiyun "-u") # map $1 to uid=0 (root) 212*4882a593Smuzhiyun root_uid="$1" 213*4882a593Smuzhiyun [ "$root_uid" = "-1" ] && root_uid=$(id -u || echo 0) 214*4882a593Smuzhiyun shift 215*4882a593Smuzhiyun ;; 216*4882a593Smuzhiyun "-g") # map $1 to gid=0 (root) 217*4882a593Smuzhiyun root_gid="$1" 218*4882a593Smuzhiyun [ "$root_gid" = "-1" ] && root_gid=$(id -g || echo 0) 219*4882a593Smuzhiyun shift 220*4882a593Smuzhiyun ;; 221*4882a593Smuzhiyun "-h") 222*4882a593Smuzhiyun usage 223*4882a593Smuzhiyun exit 0 224*4882a593Smuzhiyun ;; 225*4882a593Smuzhiyun *) 226*4882a593Smuzhiyun case "$arg" in 227*4882a593Smuzhiyun "-"*) 228*4882a593Smuzhiyun unknown_option 229*4882a593Smuzhiyun ;; 230*4882a593Smuzhiyun *) # input file/dir - process it 231*4882a593Smuzhiyun input_file "$arg" 232*4882a593Smuzhiyun ;; 233*4882a593Smuzhiyun esac 234*4882a593Smuzhiyun ;; 235*4882a593Smuzhiyun esac 236*4882a593Smuzhiyundone 237*4882a593Smuzhiyun 238*4882a593Smuzhiyun# If output_file is set we will generate cpio archive 239*4882a593Smuzhiyun# we are careful to delete tmp files 240*4882a593Smuzhiyuntimestamp= 241*4882a593Smuzhiyunif test -n "$KBUILD_BUILD_TIMESTAMP"; then 242*4882a593Smuzhiyun timestamp="$(date -d"$KBUILD_BUILD_TIMESTAMP" +%s || :)" 243*4882a593Smuzhiyun if test -n "$timestamp"; then 244*4882a593Smuzhiyun timestamp="-t $timestamp" 245*4882a593Smuzhiyun fi 246*4882a593Smuzhiyunfi 247*4882a593Smuzhiyunusr/gen_init_cpio $timestamp $cpio_list > $output 248