#!/bin/sh -e
# This script is run in a dump capture kernel to save a kernel dump to an
# SD card or HDD.
#
# (C) Copyright 2015 Axis Communications AB, LUND, SWEDEN
# This file is released under the GPL v2.
PATH=/sbin:/bin:/usr/sbin:/usr/bin
DEVPATH=
SD_MOUNT=/tmp/sdcard
max_num_dumps=5
conffile=/etc/sysconfig/crashdump.conf
MODE=${1:-}
greet() {
echo "$0: $*"
}
whine() {
greet "$*" >&2
}
restart() {
[ $# -gt 0 ] && [ "$1" ] && { case $1 in (''|[!01]) ! :; esac; } ||
panic "restart: Invalid argument"
greet "Rebooting"
reboot -ff || whine "Failed to reboot"
sleep 5
exit $1
}
unmount_sd() {
! grep -q $SD_MOUNT /proc/mounts || {
umount $SD_MOUNT || {
whine "Unable to unmount storage;" "attempt remount, read-only"
mount -o remount,ro $SD_MOUNT ||
whine "Unable to remount storage read-only"
}
}
}
checkmount() {
[ $# -eq 2 ] && [ "$1" ] && [ "$2" ] ||
panic "checkmount: invalid arguments"
case "$MOUNTS" in *" $1 $2 "*) :; *) ! :; esac ||
mount -t $2 nodev $1 || panic "Unable to mount $1"
}
panic() {
whine "$*!"
unmount_sd
restart 1
}
greet "Kernel crash dump"
pm=/proc/mounts
[ -r $pm ] || mount -t proc proc /proc || panic "Failed to mount /proc"
MOUNTS=$(cat $pm) && [ "$MOUNTS" ] || panic "Unable to get mounts"
checkmount /sys sysfs
checkmount /dev devtmpfs
checkmount /run tmpfs
checkmount /var/volatile tmpfs
mkdir -p /var/volatile/tmp
echo 600 > /sys/module/self_destruct/parameters/timeout ||
panic "Unable to set self-destruct"
/sbin/fwmgr init || panic "Failed to setup firmware volumes"
[ ! -r $conffile ] || exec /lib/systemd/systemd --unit=crashdump.service
watchdog -T 600 -t 1200 /dev/watchdog || panic "Unable to start watchdog"
[ -d $SD_MOUNT ] || mkdir -p $SD_MOUNT || panic "Failed to create $SD_MOUNT"
sd_activate=/usr/share/temperature_ctrld/sd_activate.sh
[ -f $sd_activate ] && {
$sd_activate force || panic "Unable to activate SD card"
}
modprobe ahci_platform 2>/dev/null || :
[ $(ls /sys/class/mmc_host/ 2>/dev/null | wc -l) -lt 2 ] || {
greet "Waiting for all MMC controllers to stabilize"
sleep 5
}
timeout=10
count=0
while :; do
for dev in mmcblk0p1 mmcblk1p1 mmcblk2p1 sda1; do
[ -b /dev/$dev ] || continue
case $dev in
mmc*)
# Check that the MMC device is an SD card
partsysfs=$(find /sys/devices/ -name $dev | head -1) || continue
read type <$partsysfs/../device/type || continue
[ "$type" = SD ] || continue
trigger=${partsysfs##*mmc_host/}
trigger=${trigger%%/*}
echo $trigger >/sys/class/leds/status:red/trigger 2>/dev/null ||
whine "Unable to write LED trigger $trigger"
;
esac
DEVPATH=/dev/$dev
break
done
[ -z "$DEVPATH" ] || break
[ $count -lt $timeout ] ||
panic "Unable to find storage"
greet "Will wait $(($timeout - $count)) more second(s) for storage"
count=$(($count + 1))
sleep 1
done
greet "Mounting $DEVPATH at $SD_MOUNT"
cryptomount() {
local kw=passphrase=
grep -q $kw /etc/storage/storages.conf || return
greet "Mounting encrypted SD-card"
printf "$(sed -ne "/^$kw/{s///;s/%/%%/g;p;q}" /etc/storage/storages.conf)" >/tmp/key
cryptsetup open $DEVPATH foo --key-file /tmp/key || return
mount /dev/mapper/foo $SD_MOUNT
}
fmtmount() {
case $MODE in storage+format) :; *) ! :; esac || return
greet "Formatting $DEVPATH"
mkfs.ext4 -U 281e9e0e-129d-4cb4-868d-843e7b9d39bd -E hash_seed=9c1b5092-9e76-4791-96e1-c1c4a2ee3447 -F -L AxisDump $DEVPATH || return
mount $DEVPATH $SD_MOUNT
}
mount $DEVPATH $SD_MOUNT || cryptomount || fmtmount ||
panic "Failed to mount $DEVPATH"
dumpsd=$SD_MOUNT/dumps
[ -d $dumpsd ] || mkdir -p $dumpsd || panic "Unable to make dumps directory"
[ $(echo $dumpsd/dump-* | wc -w) -lt $max_num_dumps ] || {
olddumps=$(find $dumpsd -type f -mtime +0) ||
whine "Unable to find old dumps"
[ -z "$olddumps" ] || {
greet "Trying to delete dumps older than 1 day: $olddumps"
rm -f $olddumps || whine "Unable to delete dumps"
}
}
[ $(echo $dumpsd/dump-* | wc -w) -lt $max_num_dumps ] ||
panic "Too many existing dumps"
vmcore=/proc/vmcore
now=$(date +%Y%m%d-%H%M%S)
dumpfile=$dumpsd/dump-$now.elf
if command -v lzop >/dev/null 2>& then
cmd="cat $vmcore | lzop -1 >$dumpfile.lzo"
else
cmd="cp $vmcore $dumpfile"
fi
greet "Running $cmd"
eval $cmd || panic "Unable to save dump"
etb=/dev/*.etb
[ ! -r $etb ] || {
greet "Saving ETB"
cp $etb $dumpsd/etb-$now || whine "Unable to save ETB"
}
greet "Syncing $DEVPATH"
sync || whine "Unable to sync"
greet "Unmounting $DEVPATH"
unmount_sd
greet "Done"
restart 0