From 8a187e29d31692ae88984417159cf2c16197e0f3 Mon Sep 17 00:00:00 2001 From: NTTdocomo Date: Mon, 23 Jul 2012 13:07:27 +0900 Subject: [PATCH] initial commit --- phy-mkinitrd.sh | 127 +++++++++++++++++++++++ scripts/d/init-func | 179 +++++++++++++++++++++++++++++++++ scripts/init | 157 +++++++++++++++++++++++++++++ udev/firmware.sh | 30 ++++++ udev/rules.d/50-firmware.rules | 1 + udev/rules.d/80-drivers.rules | 11 ++ 6 files changed, 505 insertions(+) create mode 100755 phy-mkinitrd.sh create mode 100755 scripts/d/init-func create mode 100644 scripts/init create mode 100755 udev/firmware.sh create mode 100644 udev/rules.d/50-firmware.rules create mode 100644 udev/rules.d/80-drivers.rules diff --git a/phy-mkinitrd.sh b/phy-mkinitrd.sh new file mode 100755 index 00000000..156e13ad --- /dev/null +++ b/phy-mkinitrd.sh @@ -0,0 +1,127 @@ +#!/bin/bash + +# Copyright (c) 2012 NTT DOCOMO, INC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +if [ $# -lt 2 ]; then + cat <&2 + echo "Please set environment variable BUSYBOX to path to busybox executable" 1>&2 + exit 1 +fi + +function fullpath() { + local f=$1 + if [ "${f#/}" = "$f" ]; then + echo `pwd`/"$f" + else + echo "$f" + fi +} + +DIR=`dirname "$0"` +INIT="$DIR/scripts/init" +FUNCTIONS_D="$DIR/scripts/d" +LIB_UDEV="$DIR/udev" + +DEST=`fullpath "$1"` +KERNEL_VERSION=$2 +MODULE_ROOT=${3:-""} +MODULE_DIR=$MODULE_ROOT/lib/modules/$KERNEL_VERSION +FIRMWARE_DIR=$MODULE_ROOT/lib/firmware + +if [ ! -d "$MODULE_DIR" ]; then + echo "ERROR: kernel module directory not found at $MODULE_DIR" + return 1 +fi + +INITRD_DIR=`mktemp -t -d phy-mkinitrd.XXXXXXXX` +if [ $? -ne 0 ]; then + exit 1 +fi +function cleanup() { + rm -r "$INITRD_DIR" +} +trap cleanup EXIT +echo "working in $INITRD_DIR" + +mkdir -p "$INITRD_DIR/bin" +ln -s bin "$INITRD_DIR/sbin" +mkdir -p "$INITRD_DIR/lib" +ln -s lib "$INITRD_DIR/lib64" +mkdir -p "$INITRD_DIR/lib/modules" +mkdir -p "$INITRD_DIR/etc" +mkdir -p "$INITRD_DIR/etc/udev" + +cp -a "$LIB_UDEV" "$INITRD_DIR/lib/udev" + +mkdir -p "$INITRD_DIR/etc/modprobe.d" +echo "blacklist evbug" > "$INITRD_DIR/etc/modprobe.d/blacklist.conf" + +mkdir -p "$INITRD_DIR/etc/udev" +cat >"$INITRD_DIR/etc/udev/udev.conf" </dev/null; then + continue + fi + path=`which $i 2>/dev/null` || path=$i + if ! [ -x "$path" ]; then + echo "$i is not found in PATH" 2>&1 + exit 1 + fi + cp -L "$path" "$INITRD_DIR/bin/" + if l=`ldd "$path"`; then + l=$( echo "$l" | grep '/' | tr "\t" " " ) + l=$( echo "$l" | sed 's/^.* => \([^ ]*\).*$/\1/' ) + l=$( echo "$l" | sed 's/^ *\([^ ]*\) *(0x[0-9a-f]*)/\1/' ) + l=$( echo "$l" | tr " " "\n" ) + libs=$( printf "%s\n%s\n" "$l" "$libs" | sort | uniq ) + fi +done +cp $libs "$INITRD_DIR/lib/" + +for i in $( "$BUSYBOX" --list ); do + if [ -f "$INITRD_DIR/bin/$i" ]; then + echo "skip $i" + continue + fi + ln -s busybox "$INITRD_DIR/bin/$i" +done + +cp -a "$MODULE_DIR" "$INITRD_DIR/lib/modules/$KERNEL_VERSION" + +cp -a "$FIRMWARE_DIR" "$INITRD_DIR/lib/firmware" + +cp "$INIT" "$INITRD_DIR/init" +chmod +x $INITRD_DIR/init +for F in "$FUNCTIONS_D"/* ; do + cp "$F" "$INITRD_DIR" +done + +(cd "$INITRD_DIR"; find . | cpio -o -H newc | gzip > "$DEST" ) + diff --git a/scripts/d/init-func b/scripts/d/init-func new file mode 100755 index 00000000..7491767d --- /dev/null +++ b/scripts/d/init-func @@ -0,0 +1,179 @@ +# Copyright (c) 2012 NTT DOCOMO, INC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +function get_kernel_parameter() { + local name=$1 + for i in `cat /proc/cmdline`; do + case "$i" in + ${name}=*) + echo "${i#${name}=}" + return 0 + ;; + ${name}) + echo "" + return 0 + ;; + *) + ;; + esac + done + echo "" + return 1 +} + +function load_modules_by_udev() { + depmod + udevadm trigger --action=add + udevadm settle +} + +function strip_dev() { + echo "$1" | sed -e 's:^/dev/::' +} + +function prepend_dev() { + case "$1" in + /dev/*) + echo "$1" + ;; + *) + echo "/dev/$1" + ;; + esac +} + +function whole_disk_name() { + local dev=`prepend_dev "$1"` + case "$dev" in + /dev/sd*|/dev/hd*) + echo "$dev" | sed -e 's/[0-9]*$//' + ;; + /dev/cciss/*) + echo "$dev" | sed -e 's/p[0-9]*$//' + ;; + *) + echo "" + return 1 + ;; + esac +} + +function partition_name() { + local dev=`prepend_dev "$1"` + local part=$2 + case "$dev" in + /dev/sd*|/dev/hd*) + echo "${dev}${part}" + ;; + /dev/cciss/*) + echo "${dev}p${part}" + ;; + *) + echo "" + return 1 + ;; + esac +} + +function find_interface() { + local mac=$1 + eth=`ifconfig -a | grep -i "$mac" | awk {' print $1 '} | head -n 1` + if [ -n "$eth" ]; then + echo "$eth" + return 0 + else + return 1 + fi +} + +function set_mac() { + local dev=$1 + local mac=$2 + ip link set "$dev" address "$mac" +} + +function swap_ifname() { + local dev=$1 + local dev2=$2 + if [ "$dev" = "$dev2" ]; then + return + fi + if ip link show "$dev2" >/dev/null; then + # dev2 exists + # swap device name + ip link set "$dev" name "_$dev" + ip link set "$dev2" name "$dev" + ip link set "_$dev" name "$dev2" + else + ip link set "$dev" name "$dev2" + fi +} + +function partition_exists() { + local dev=$1 + dev=`strip_dev "$dev"` + if tail -n +3 /proc/partitions | grep "$dev" >/dev/null; then + return 0 + else + return 1 + fi +} + +function find_disk() { + local disks=$1 + local dev + + # find device + local OLD_IFS=$IFS + IFS=, + for i in $disks; do + dev=`whole_disk_name "$i"` + if partition_exists "$dev"; then + dev=`prepend_dev "$dev"` + break + fi + dev="" + done + IFS=$OLD_IFS + + if [ -z "$dev" ]; then + return 1 + fi + echo "$dev" + return 0 +} + +function start_iscsi_target() { + local iqn=$1 + local dev=$2 + local cli=$3 + + # used by tgtd + mkdir -p /var/run + + tgtd + + tgtadm --lld iscsi --mode target --op new --tid 1 --targetname "$iqn" + tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 1 --backing-store "$dev" + tgtadm --lld iscsi --mode target --op bind --tid 1 --initiator-address "$cli" +} + +function stop_iscsi_target() { + tgtadm --lld iscsi --mode logicalunit --op delete --tid 1 --lun 1 + tgtadm --lld iscsi --mode target --op delete --tid 1 + killall tgtd +} + + diff --git a/scripts/init b/scripts/init new file mode 100644 index 00000000..492088dc --- /dev/null +++ b/scripts/init @@ -0,0 +1,157 @@ +#!/bin/bash + +# Copyright (c) 2012 NTT DOCOMO, INC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +echo "init" + +source /init-func + +PATH=/sbin:/bin:/usr/bin:/usr/sbin +export PATH + +mkdir -p /proc +mkdir -p /sys +mkdir -p /dev +mkdir -p /boot +mkdir -p /etc +mkdir -p /mnt +mkdir -p /lib/modules + +mount -t proc proc /proc + +readonly _BOOTIF_=$(get_kernel_parameter BOOTIF) +readonly _IP_=$(get_kernel_parameter ip) +readonly BOOT_MAC_ADDRESS=$(echo "$_BOOTIF_" | sed -e "s/-/:/g" | sed -e "s/^01://g" | tr 'a-f' 'A-F') +readonly BOOT_IP_ADDRESS=$(echo "$_IP_" | cut -d':' -f1) +readonly BOOT_SERVER=$(echo "$_IP_" | cut -d':' -f2) +readonly BOOT_NETMASK=$(echo "$_IP_" | cut -d':' -f4) + +readonly DISK=$(get_kernel_parameter disk) + +readonly DEPLOYMENT_ID=$(get_kernel_parameter deployment_id) +readonly DEPLOYMENT_KEY=$(get_kernel_parameter deployment_key) +readonly ISCSI_TARGET_IQN=$(get_kernel_parameter iscsi_target_iqn) + +if [ -z "$ISCSI_TARGET_IQN" ]; then + echo "iscsi_target_iqn is not defined" + echo "Starting troubleshooting shell." + bash +fi + +mount -t sysfs none /sys +mount -t tmpfs none /dev +ln -sf /proc/self/fd /dev/fd +mknod /dev/null c 1 3 +mknod /dev/zero c 1 5 +mknod /dev/random c 1 8 +mknod /dev/urandom c 1 9 +mknod /dev/tty0 c 4 0 +mknod /dev/tty1 c 4 1 +mknod /dev/tty2 c 4 2 +mknod /dev/tty3 c 4 3 +mknod /dev/tty4 c 4 4 +mknod /dev/tty5 c 4 5 +mknod /dev/tty6 c 4 6 +mknod /dev/tty7 c 4 7 +mknod /dev/tty8 c 4 8 +mknod /dev/tty9 c 4 9 +mknod /dev/tty c 5 0 +mknod -m 0600 /dev/console c 5 1 +mknod -m 0666 /dev/ptmx c 5 2 +mkdir -p /dev/.udev +mkdir -p /dev/.udev/data + +echo "starting syslogd" + +echo '*.* /initlog' > /etc/syslog.conf +syslogd +klogd + +echo "starting udevd" +udevd --daemon --resolve-names=never + +echo "load modules" +load_modules_by_udev + +echo "starting network $BOOT_MAC_ADDRESS" +t=0 +while ! BOOT_INTERFACE=$(find_interface "$BOOT_MAC_ADDRESS"); do + t=`expr "$t" + 5` + if [ "$t" -gt 10 ]; then + break + fi + sleep 5 +done +if [ -z "$BOOT_INTERFACE" ]; then + echo "could not find an interface owns MAC=$BOOT_MAC_ADDRESS" + echo "Starting troubleshooting shell." + bash +fi + +readonly BOOT_INTERFACE + +ifconfig lo 127.0.0.1 up +ifconfig "$BOOT_INTERFACE" up +if [ $? -ne 0 ]; then + sleep 10 + ifconfig "$BOOT_INTERFACE" up + if [ $? -ne 0 ]; then + echo "Failed to up $BOOT_INTERFACE" + echo "Starting troubleshooting shell." + bash + fi +fi +ifconfig "$BOOT_INTERFACE" "$BOOT_IP_ADDRESS" netmask "$BOOT_NETMASK" + +echo "pinging to boot server $BOOT_SERVER" +w=30 +while [ $w -gt 0 ]; do + ping -c 5 -q "$BOOT_SERVER" > /dev/null + if [ $? -eq 0 ]; then + break + fi + sleep 1 + w=`expr $w - 5` +done + +echo "network ready" + +target_disk=`find_disk "$DISK"` +echo "start iSCSI target on $target_disk" +start_iscsi_target "$ISCSI_TARGET_IQN" "$target_disk" ALL +if [ $? -ne 0 ]; then + echo "Could not find disk to use." + echo "Starting troubleshooting shell." + bash +fi + +echo "request boot server to deploy image" +d="i=$DEPLOYMENT_ID&k=$DEPLOYMENT_KEY&a=$BOOT_IP_ADDRESS&n=$ISCSI_TARGET_IQN" +wget --post-data "$d" "http://$BOOT_SERVER:10000" + +echo "waiting for notice of complete" +nc -l -p 10000 + +echo "stop iSCSI target on $target_disk" + +stop_iscsi_target + +echo "rebooting" +reboot -f + +echo "failed to reboot" +echo "Starting troubleshooting shell." +bash diff --git a/udev/firmware.sh b/udev/firmware.sh new file mode 100755 index 00000000..1a13e5f7 --- /dev/null +++ b/udev/firmware.sh @@ -0,0 +1,30 @@ +#!/bin/sh -e + +FIRMWARE_DIRS="/lib/firmware/updates/$(uname -r) /lib/firmware/updates \ + /lib/firmware/$(uname -r) /lib/firmware" + +err() { + echo "$@" >&2 + logger -t "${0##*/}[$$]" "$@" 2>/dev/null || true +} + +if [ ! -e /sys$DEVPATH/loading ]; then + err "udev firmware loader misses sysfs directory" + exit 1 +fi + +for DIR in $FIRMWARE_DIRS; do + [ -e "$DIR/$FIRMWARE" ] || continue + echo 1 > /sys$DEVPATH/loading + cat "$DIR/$FIRMWARE" > /sys$DEVPATH/data + echo 0 > /sys$DEVPATH/loading + exit 0 +done + +echo -1 > /sys$DEVPATH/loading +err "Cannot find firmware file '$FIRMWARE'" +mkdir -p /dev/.udev/firmware-missing +file=$(echo "$FIRMWARE" | sed 's:/:\\x2f:g') +ln -s -f "$DEVPATH" /dev/.udev/firmware-missing/$file +exit 1 + diff --git a/udev/rules.d/50-firmware.rules b/udev/rules.d/50-firmware.rules new file mode 100644 index 00000000..2fbebb0e --- /dev/null +++ b/udev/rules.d/50-firmware.rules @@ -0,0 +1 @@ +SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware.sh" diff --git a/udev/rules.d/80-drivers.rules b/udev/rules.d/80-drivers.rules new file mode 100644 index 00000000..caf1be44 --- /dev/null +++ b/udev/rules.d/80-drivers.rules @@ -0,0 +1,11 @@ +ACTION!="add", GOTO="drivers_end" + +DRIVER!="?*", ENV{MODALIAS}=="?*", RUN+="/sbin/modprobe $env{MODALIAS}" +SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="SD", RUN+="/sbin/modprobe tifm_sd" +SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="MS", RUN+="/sbin/modprobe tifm_ms" +SUBSYSTEM=="memstick", RUN+="/sbin/modprobe --all ms_block mspro_block" +SUBSYSTEM=="i2o", RUN+="/sbin/modprobe i2o_block" +SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", TEST!="[module/sg]", RUN+="/sbin/modprobe sg" +SUBSYSTEM=="module", KERNEL=="parport_pc", RUN+="/sbin/modprobe ppdev" + +LABEL="drivers_end"