#!/bin/bash
#
# Description: universal (distro independent) generator for initial
# ramdisks for linux diskless clients
#
# Author(s): Dirk von Suchodoletz <dirk@goe.net>, 16-01-2006
# Blabla
# Blub
#
# Copyright: (c) 2003 - 2006 - RZ Universitaet Freiburg
DEBUG=1
COMETCEXCL="XF86Config*\nissue*\nmtab*\nfstab*\n"
COMDIRINDXS="/tmp/scratch /var/lib/nobody"
# distro specific settings read from configuration file
# D_SYSCONFDIR - system wide configuration settings in /etc - sysconfig in
# SuSE and RedHat, default in Debian and Ubuntu, conf.d in Gentoo
# D_ETCEXCL - list of files, wildcards to be excluded from /etc when using
# bind mounts
# D_DIRINBINDMNT - lists of directories to be created in bind mounted rw
# part of the client filesystem
# D_RODIRSINRW - ReadOnly Directories in RW part of filesystem to save on
# TempFS usage
# D_DIRINDXS - directories in client filesystem which should be present
# anyhow
# D_BINDMNT - any code which is specific in bind mount environment
# D_RCDIRS - runlevel directories relative to /etc
D_SYSCONFDIR="<set in ~/distro-config/distro file>"
D_ETCEXCL="<set in ~/distro-config/distro file>"
D_BINDMPTS="<set in ~/distro-config/distro file>"
D_DIRINBINDMNT="<set in ~/distro-config/distro file>"
D_RODIRSINRW="<set in ~/distro-config/distro file>"
D_DIRINDXS="<set in ~/distro-config/distro file>"
D_BINDMNT="<set in ~/distro-config/distro file>"
D_INITDIR="<set in ~/distro-config/distro file>"
D_INITBOOTD="<set in ~/distro-config/distro file>"
D_RCDIRS="<set in ~/distro-config/distro file>"
D_RCDIRSINRW="<set in ~/distro-config/distro file>"
D_INITSCRIPTS="<set in ~/distro-config/distro file>"
D_XF86CONFFILE="<set in ~/distro-config/distro file>"
D_XFONTPATH="<set in ~/distro-config/distro file>"
D_DEFAULTCOUNTRY="<set in ~/distro-config/distro file>"
#########################################################################
# End of global variable declaration, nothing needed to be changed at
# default below that line
# copy some binary to given destination. Takes binary in $1 and
# destination in $2
cobi()
{
local DEST=$2
local FPTB=`which $1`
if [ -z ${FPTB} ] ; then
return 1;
else
cp ${ROOTDIR}/${FPTB} ${INSTDIR}/${DEST}
fi
}
# replace copy
repco()
{
local FILENAME=$1
# do not forget to define all variables which should be replaced within
# the start and configuration scripts
sed -e "s,@@@INSTDIR@@@,${INSTDIR},g" \
-e "s,@@@NWMODULES@@@,${NWMODULES},g" \
-e "s,@@@KERNVER@@@,${KERNVER},g" \
-e "s,@@@COMDIRINDXS@@@,${COMDIRINDXS},g" \
-e "s,@@@COMETCEXCL@@@,${COMETCEXCL},g" \
-e "s,@@@DISTRO@@@,${DISTRO},g" \
-e "s,@@@NETIF@@@,${NET_IF},g"
${FILENAME} >> ${INSTDIR}/${FILENAME}
}
# Resolve dynamic library dependencies. Returns a list of symbolic links
# to shared objects and shared object files for the binaries in $*.
# stolen from SuSE mkinitrd
shared_object_files() {
local LDD CHROOT initrd_libs lib_files lib_links lib link
LDD=`which ldd`
if [ ! -x $LDD ]; then
error 2 "I need execution permission on ldd ($LDD)."
fi
initrd_libs=( $(
$LDD "$@" \
| sed -ne 's:\t\(.* => \)\?\(/.*\) (0x[0-9a-f]*):\2:p'
) )
# Evil hack: On some systems we have generic as well as optimized
# libraries, but the optimized libraries may not work with all
# kernel versions (e.g., the NPTL glibc libraries don't work with
# a 2.4 kernel). Use the generic versions of the libraries in the
# initrd (and guess the name).
local n optimized
for ((n=0; $n<${#initrd_libs[@]}; n++)); do
lib=${initrd_libs[$n]}
optimized="$(echo "$lib" | sed -e 's:.*/\([^/]\+/\)[^/]\+$:\1:')"
lib=${lib/$optimized/}
if [ "${optimized:0:3}" != "lib" -a -f "$lib" ]; then
#echo "[Using $lib instead of ${initrd_libs[$n]}]" >&2
initrd_libs[$n]="${lib/$optimized/}"
fi
done
for lib in "${initrd_libs[@]}"; do
case "$lib" in
linux-gate*)
# This library is mapped into the process by the kernel
# for vsyscalls (i.e., syscalls that don't need a user/
# kernel address space transition) in 2.6 kernels.
continue ;;
/*)
lib="${lib:1}" ;;
*)
# Library could not be found.
echo "Dynamic library $lib not found"
continue ;;
esac
while [ -L "/$lib" ]; do
echo $lib
link="$(readlink "/$lib")"
if [ x"${link:0:1}" == x"/" ]; then
lib=${link#/}
else
lib="${lib%/*}/$link"
fi
done
echo $lib
done \
| sort -u
}
# Resolve module dependencies and parameters. Returns a list of modules and
# their parameters.
resolve_modules() {
local kernel_version=$1 module
shift
for module in "$@"; do
local with_modprobe_conf
module=${module%.o} # strip trailing ".o" just in case.
module=${module%.ko} # strip trailing ".ko" just in case.
if [ -e /etc/modprobe.conf ]; then
with_modprobe_conf="-C /etc/modprobe.conf"
fi
module_list=$(/sbin/modprobe $with_modprobe_conf \
--set-version $kernel_version --ignore-install \
--show-depends $module 2> /dev/null \
| sed -ne 's:.*insmod /\?::p' )
if [ -z "$module_list" ]; then
echo "Cannot determine dependencies of module $module." \
"Is modules.dep up to date?"
fi
echo "$module_list"
done \
| awk ' # filter duplicates: we must not reorder modules here!
NF == 0 { next }
$1 in seen { next }
{ seen[$1]=1
print
}
'
rm -f $temp
}
#########################################################################
# End of function declaration
while getopts :hgk:i:r:o:s:f:n:Sut:d:I:V:a: a ; do
case $a in
\:|\?) case $OPTARG in
k) echo "-k requires kernel version parameter"
;;
i) echo "-i requires initrd path parameter"
;;
f) echo "-f requires file system module list parameter"
;;
n) echo "-n requires network module list parameter"
;;
r) echo "-r requires root dir parameter"
;;
s) echo "-s requires image size(s)"
;;
t) echo "-t requires tmp dir parameter"
;;
d) echo "-d requires linux distribution name"
;;
I) echo "-I requires network interface parameter"
;;
a) echo "-a requires a DSDT parameter"
;;
V) echo "-V requires an executable to run inside linuxrc"
;;
*) echo "Unknown option: -$OPTARG"
echo "Try mkinitrd -h"
;;
esac
exit 1
;;
g) use_glibc=1
;;
k) KERNVER=$OPTARG
;;
i) INITRD_PATH=$OPTARG
;;
f) FSMODULES=$OPTARG
;;
n) NWMODULES=$OPTARG
;;
r) ROOTDIR=$OPTARG
;;
s) SPLASH=$OPTARG
;;
t) INSTDIR=$OPTARG
;;
d) DISTRO=$OPTARG
;;
I) NET_IF=$OPTARG
;;
a) acpi_dsdt="$OPTARG"
;;
S) use_selinux=1
;;
V) vendor_init_script="$OPTARG"
;;
R) mkinit_type="rd"
;;
u) sysfs_root=1
use_udev=
;;
h) usage
;;
esac
done
shift $(expr $OPTIND - 1)
#########################################################################
# End of parameter, argument interpretation
if [ -z $INSTDIR ] ; then
INSTDIR=/tmp/dxs-instrd
fi
rm -rf ${INSTDIR}
mkdir -p ${INSTDIR}/{dev,proc,tmp,mnt,root,bin,sbin,sys,lib}
mkdir -p ${INSTDIR}/usr/share
# needed for KNOPPIX hwsetup not to confuse with ${D_SYSCONFDIR}
mkdir -p ${INSTDIR}/etc/sysconfig
# source configuration file for the distribution used
#DISTRO=debian
if [ -z $DISTRO ] ; then
for i in ${ROOTDIR}/bin/lsb_release ${ROOTDIR}/usr/bin/lsb_release; do
if [ -e $i ] ; then
DISTRO = `. $i -a | grep "Distributor" | sed "s/.*\t//"`
DISTRO_VER = `. $i -a | grep "Release:" | sed "s/.*\t//"`
break
fi
done
fi
if [ -z $DISTRO ] ; then
if [ -e ${ROOTDIR}/etc/SuSE-release ] ; then
DISTRO=suse
DISTRO_VER=`grep "VERSION" /etc/SuSE-release | sed "s/.*= //"`
fi
fi
if [ -z $DISTRO ] ; then
if [ -e ${ROOTDIR}/etc/debian-version ] ; then
DISTRO=debian
DISTRO_VER=`cat ${ROOTDIR}/etc/debian-version`
fi
fi
case "${DISTRO}" in
SuSE*|suse*|Suse*|SuSe*)
case "${DISTRO_VER}" in
9*)
DISTRO=suse-9.3
;;
*)
DISTRO=suse-10.0
;;
esac
# hotplug/udev style and stuff
cp -a /etc/udev /etc/hotplug ${INSTDIR}/etc
#cp -a /etc/sysconfig/{hardware,network} ${INSTDIR}/etc/sysconfig
;;
Debian*|debian*|Sarge*|sarge*)
DISTRO=debian
;;
Ubuntu*|ubuntu*)
DISTRO=ubuntu
;;
Gentoo*|gentoo*)
DISTRO=gentoo
;;
esac
cp distro-specs/${DISTRO}/config ${INSTDIR}/etc/sysconfig
cp distro-specs/${DISTRO}/functions-${DISTRO} ${INSTDIR}/etc/distro-functions
cp -a distro-specs/${DISTRO}/files ${INSTDIR}/etc/sysconfig
#case ${DEBUG}
#if no klibc
for bbins in ash bash sh; do
if cobi ${bbins} bin ; then
LRCSH=/bin/${bbins}
ln -fs /bin/${bbins} ${INSTDIR}/bin/sh
[ "${bbins}" != "bash" ] && ln -fs /bin/${bbins} ${INSTDIR}/bin/bash
break
else echo "Binary not found (${bbins})"; fi
done
# if no klibc
for bbins in ip ifconfig; do
if cobi ${bbins} bin
then
LRCIP=/bin/${bbins}
[ "${LRCIP}" = "ifconfig" ] && cobi route bin
break
else echo "Binary not found"; fi
done
# copy and replace variable names
find initrd-stuff -exec repco {} \;
# distro dependet stuff for etc, booting !?
# needed standard binaries
for bbins in \
cat chmod chown chroot cp expr killall ln mkdir modprobe \
mount portmap pivot_root rmmod sed tar umount
do
cobi ${bbins} bin || echo "Program ${bbins} not found"
done
# one of the dhcp clients
for dhcp in dhclient dhcpcd pump ipconfig ; do
which $dhcp && break;
done
cobi $dhcp bin
mkdir -p ${INSTDIR}/var/{lib,run}
# debug binaries
for bbins in \
date ls lsmod lsof ps rm strace time
do
cobi ${bbins} bin || echo "Program ${bbins} not found"
done
# style of hotplug/udev/dev (for etc directories see above!!)
for bbins in udev udevstart
do
cobi ${bbins} bin || echo "Program ${bbins} not found"
done
# if nfs
mkdir -p ${INSTDIR}/var/lib/nfs/state
# if nbd
# cobi nbd-client bin
#if nfs - dann modul suchen, kopieren
case "${DISTRO}" in
debian*)
cp /lib/libnss_compat.so.2 ${INSTDIR}/lib;;
esac
# add needed libraries depending on choosen binaries
for lib in `shared_object_files ${INSTDIR}/bin/*` ; do
baselib=`basename ${lib}`
test -e ${INSTDIR}/lib/${baselib} || \
cp -a /${lib} ${INSTDIR}/lib
done
# add kernel modules and dependency files
if [ -z $KERNVER ] ; then
KERNVER=`ls -l ${ROOTDIR}/boot/vmlinuz | grep vmlinuz | sed "s/.*vmlinuz-//"`
fi
if [ -z $KERNVER ] ; then
KERNVER=`ls -l ${ROOTDIR}/vmlinuz | grep vmlinuz | sed "s/.*vmlinuz-//"`
fi
#KERNVER=2.6.12-10-386
if [ -z $NWMODULES ] ; then
NWMODULES="e100 tg3 via-rhine r8169"
fi
if [ -z $FSMODULES ] ; then
FSMODULES="nbd nfs"
fi
if [ -z $INITRD_PATH ] ; then
INITRD_PATH="/tmp/dxsinitrd.gz"
fi
for module in `resolve_modules ${KERNVER} af_packet ${NWMODULES} ${FSMODULES}`; do
mpath=${INSTDIR}/${module%/*}
mkdir -p ${mpath}
cp /$module ${mpath}
done
cp /lib/modules/${KERNVER}/modules.* ${INSTDIR}/lib/modules/${KERNVER}
#repco initrd-stuff/init ${INSTDIR}/init
chmod 755 ${INSTDIR}/init ${INSTDIR}/bin/servconfig \
${INSTDIR}/bin/hwautocfg ${INSTDIR}/bin/dhcpmkconfig
#repco initrd-stuff/etc/functions ${INSTDIR}/etc/functions
#########################################################################
# End of file copy procedures
# finally create the compressed initial ramdisk cpio archive
pushd . > /dev/null 2>&1
cd ${INSTDIR}
find . ! -name "*~" | cpio -H newc --create | gzip -9 > $INITRD_PATH
popd > /dev/null 2>&1