From 04b56f3a0168900ef00197cb2f5ef235e3b2fc7a Mon Sep 17 00:00:00 2001 From: Jeremy Katz Date: Wed, 17 Dec 2008 16:57:43 -0500 Subject: [PATCH] Add some basic functions used for the initramfs Add some functions used by the initramfs generator from Fedora's mkinitrd with bits and pieces stripped out. This needs a closer look to ensure that we're not bringing along any other old baggage --- initrd-functions | 291 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100755 initrd-functions diff --git a/initrd-functions b/initrd-functions new file mode 100755 index 00000000..2323c849 --- /dev/null +++ b/initrd-functions @@ -0,0 +1,291 @@ +#!/bin/bash +# +# functions used by mkinitrd and other tools. +# +# Copyright 2005-2008 Red Hat, Inc. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Authors: +# Peter Jones +# Jeremy Katz +# Jakub Jelinek +# +# + +IF_RTLD="" +IF_dynamic="" +function get_dso_deps() { + local bin="$1" ; shift + + declare -a FILES + declare -a NAMES + + local LDSO=$(echo nash-showelfinterp $bin | /sbin/nash --forcequiet) + [ -z "$LDSO" -o "$LDSO" == "$bin" ] && local LDSO="$IF_RTLD" + [ -z "$LDSO" -o "$LDSO" == "$bin" ] && return 1 + [ -z "$IF_RTLD" ] && IF_RTLD="$LDSO" + + # I hate shell. + declare -i n=0 + while read NAME I0 FILE ADDR I1 ; do + [ "$FILE" == "not" ] && FILE="$FILE $ADDR" + [ "$NAME" == "not" ] && NAME="$NAME $I0" + NAMES[$n]="$NAME" + FILES[$n]="$FILE" + let n++ + done << EOF + $(LD_TRACE_PRELINKING=1 LD_WARN= LD_TRACE_LOADED_OBJECTS=1 \ + $LDSO $bin 2>/dev/null) +EOF + + [ ${#FILES[*]} -eq 0 ] && return 1 + + # we don't want the name of the binary in the list + if [ "${FILES[0]}" == "$bin" ]; then + FILES[0]="" + NAMES[0]="" + [ ${#FILES[*]} -eq 1 ] && return 1 + fi + + declare -i n=0 + while [ $n -lt ${#FILES[*]} ]; do + local FILE="${FILES[$n]}" + local NAME="${NAMES[$n]}" + if [ "$FILE" == "not found" -o "$NAME" == "not found" ]; then + cat 1>&2 < []" + return 1 + fi + local file="$1" ; shift + local root="${1%%/}/" ; shift + local dest="${1##/}" + [ -z "$dest" ] && local dest="${file##/}" + + mkdir -p "$root/$(dirname $dest)" + + local RET=0 + local target="" + [ -L "$file" ] && target=$(readlink "$file") + if [ -n "$target" -a "$dest" != "$target" ]; then + if [ -e "$root$dest" ]; then + RET=0 + else + + ln -sf "$target" "$root$dest" + #inst "$target" "$root" + local BASE=`basename "$target"` + local LIBDIR=`echo "$file" | sed -e 's,\(\(.*\)/\)[^/]\+$,\1,'` + if [ "$LIBDIR" = "$BASE" ]; then + local LIBDIR=`echo "/$dest" | sed -e 's,\(\(.*\)/\)[^/]\+$,\1,'` + fi + + local TLIBDIR=`echo "$target" | sed -e 's,\(^/lib[^/]*\)/.*$,\1/,' \ + -e 's,\(\(.*\)/\)[^/]\+$,\1,'` + if [ "$TLIBDIR" = "$BASE" ]; then + local TLIBDIR=`echo "/$dest" | sed \ + -e 's,\(^/lib[^/]*\)/.*$,\1/,' \ + -e 's,\(\(.*\)/\)[^/]\+$,\1,'` + fi + + inst "$LIBDIR/$BASE" "$root" "$TLIBDIR/$BASE" + RET=$? + return $RET + fi + fi + + local SHEBANG=$(dd if="$file" bs=2 count=1 2>/dev/null) + if [ "$SHEBANG" == '#!' ]; then + # We're intentionally not playing the "what did this moron run + # in his shell script" game. There's nothing but pain in that. + local interp=$(head -1 "$file" | sed 's/^#! *//') + inst "$interp" "$root" + RET=$? + return $RET + fi + + if [ -e "$root$dest" ]; then + RET=0 + else + if [ -n "$target" -a -L "$target" ]; then + inst "$target" "$root" + RET=$? + else + cp -aL "$file" "$root$dest" + + local DEPS=$(get_dso_deps "$file") + if [ -n "$DEPS" ]; then + IF_dynamic="yes" + fi + for x in $DEPS ; do + local TLIBDIR=`echo "$x" | sed 's,\(/lib[^/]*\)/.*$,\1,'` + local BASE=`basename "$x"` + inst "$x" "$root" "$TLIBDIR/$BASE" + done + RET=$? + fi + fi + return $RET +} + +# module dep finding and installation functions +moduledep() { + MPARGS="" + if [ "$1" == "--ignore-install" ]; then + MPARGS="$MPARGS --ignore-install" + shift + fi + vecho -n "Looking for deps of module $1" + deps="" + deps=$(modprobe $MPARGS --set-version $kernel --show-depends $1 2>/dev/null| awk '/^insmod / { print gensub(".*/","","g",$2) }' | while read foo ; do [ "${foo%%.ko}" != "$1" ] && echo -n "${foo%%.ko} " ; done) + [ -n "$deps" ] && vecho ": $deps" || vecho +} + +locatemodule() { + MPARGS="" + if [ "$1" == "--ignore-install" ]; then + MPARGS="$MPARGS --ignore-install" + shift + fi + fmPath=$(modprobe $MPARGS --set-version $kernel --show-depends $1 2>/dev/null | awk '/^insmod / { print $2; }' | tail -1) + if [ -n "$fmPath" -a -f "$fmPath" ]; then + return 0 + fi + for modExt in o.gz o ko ; do + for modDir in /lib/modules/$kernel/updates /lib/modules/$kernel ; do + if [ -d $modDir ]; then + fmPath=$(find $modDir -name $1.ko |awk {'print $1; exit;'}) + if [ -n "$fmPath" -a -f "$fmPath" ]; then + return 0 + fi + fi + done + done + return 1 +} + +resolveAndExpandModules() { + items=$* + + mods=$(expandModules $items) + echo "looking for $mods" + resdeps $mods + echo $resolved +} + +expandModules() { + items=$* + + for m in $items ; do + char=$(echo $m | cut -c1) + if [ $char = '=' ]; then + NAME=$(echo $m | cut -c2-) + if [ "$NAME" = "ata" ]; then + MODS="$MODS $(cat /lib/modules/$kernel/modules.block |egrep '(ata|ahci)' |sed -e 's/.ko//')" + else + # Ignore if group list does not exist + if [ -e /lib/modules/$kernel/modules.$NAME ]; then + MODS="$MODS $(cat /lib/modules/$kernel/modules.$NAME |sed -e 's/.ko//')" + fi + fi + else + MODS="$MODS $m" + fi + done + echo $MODS +} + +installmodule() +{ + MPARGS="" + if [ "$1" == "--ignore-install" ]; then + MPARGS="$MPARGS --ignore-install" + shift + fi + MODULE=$1 + MNTIMAGE=$2 + fmPath="" + locatemodule $MPARGS $MODULE + MODULE=$fmPath + if [ -z "$MODULE" ]; then + return + fi + if [ -x /usr/bin/strip ]; then + /usr/bin/strip -g $MODULE -o $MNTIMAGE/lib/modules/$kernel/$(basename $MODULE) + else + inst "$MODULE" "$MNTIMAGE" "/lib/modules/$kernel/$(basename $MODULE)" + fi + for fw in $(/sbin/modinfo -F firmware $MODULE 2>/dev/null); do + if [ -f /lib/firmware/$fw ]; then + inst "/lib/firmware/$fw" "$MNTIMAGE" "/lib/firmware/$fw" + fi + done +} + +# This loops to make sure it resolves dependencies of dependencies of... +resdeps () { + modlist="$1" + + before=1 + after=2 + + items=$(eval echo \${$modlist}) + while [ $before != $after ]; do + before=$(echo $items | wc -c) + list="" + + for i in $items ; do + deps="" + moduledep $i + list="$list $deps" + done + items=$(for n in $items $list; do echo $n; done | sort -u) + after=`echo $items | wc -c` + done + + resolved="$items" +} + + + +# vim:ts=8:sw=4:sts=4:et