バグ?
工場出荷時バージョンのファームウェア1.02から最新版1.15へアップデートすると、「デジカメコピー」と「iobb.net」の機能が増える。後者機能の初期値としてUPnP機能がONになっているのだが、ルーターがUPnPに応答しないとHDL-GSの電源ボタンで電源が切れないことがある。
電源OFFシーケンス中にUPnPでルーターからグローバルIPアドレスを取得しようとするのだが、ルーターのUPnPは切ってあるのでそこで処理が止まるようだ。Webインタフェースが生きている場合はそちらから電源OFFを選べばいい。
電源OFFシーケンス中にUPnPでルーターからグローバルIPアドレスを取得しようとするのだが、ルーターのUPnPは切ってあるのでそこで処理が止まるようだ。Webインタフェースが生きている場合はそちらから電源OFFを選べばいい。
tar2diskのパーティション割当サイズ
新品のHDDをHDL-GSシステム用にするスクリプトが /boot/.landisk/tar2disk である。これは512バイト/セクタを前提としているので、4096バイト/物理セクタのHDDではいまいちよろしくない。実際、物理セクタ一つの破損で2パーティションが影響を受けた。
というわけで、改良版tar2disk
というわけで、改良版tar2disk
#!/bin/sh
#
# tar2disk: tar ball をディスクに展開、指定によりパーティションを切る
# # 2017-04-26
# usage: tar2disk sda [reset|reset_full|none [ignore_smart]]
# sda means:
# /dev/sda like that.
# if it is hdb then it is internal HDD of normal configuration.
# Others is external HDD.
# OPERATION: (option 'none' is default)
# (none) smart_check (if ignore_smart, result ignore)
# (none) partition
# mkswap
# swapon (if internal HDD)
# trap swapoff (if internal HDD)
# --partition 1
# format
# tar
# (none) fw_install
# (reset) set_reset_flag
# --partition 2
# format
# tar
# --partition 5
# (reset) bk_factory_log
# format
# tar
# (reset) restore_factory_log
# --partition 6
# (reset_full)sanitaize
# format
# tar
# END
#
# .landisk/ --- このディレクトリの中から実行しなければならず、以下のファイルとディレクトリを含んでいることが必要
# tar2disk, sd1.tgz, sd2.tgz, sd5.tgz, sd6.tgz
# mnt/
#
# BUG:
# $SCRIPT_PATH の定義がない。mkfs.xfsとsmartctlがある場所を指していなければならない。
# ただし/sbin/mkfs.xfs, /usr/sbin/smartctl があるなら$SCRIPT_PATHが参照されることはない。
#
# 2017-05-02
# /mnt/hda5/factory_logを初期化直後に作成するようにした。
#
START_TIME=`date`
INTERNAL_HDD="hdb"
EXIT() {
local code=$1
echo $2
echo "STARTED: $START_TIME"
echo "END : `date`"
echo --- tar2disk end. code=$code
exit $code
}
#
# パーティションを切る
#
partition() {
echo "--- partition(): Clear MBR for $disk"
dd if=/dev/zero of=/dev/$disk bs=512 count=2 || return 1
echo "--- partition(): pertitioning for HDL-GS"
# Windows等に倣い、MBRを含む先頭1MiB(2048セクタ)を空きブロックとしている。
# 大容量ディスクは4KiB物理セクタなので、512Byte論理セクタで指定する場合8セクタごとの境界にすることが必要。
# 物理セクタサイズが異なる場合は修正必要。
# part1 300MiB(614400) tgzイメージとアップデータの保管場所。現状100MiB使用。追加アップデータに備えて+200MiB
# part2 600MiB(1228800) システム領域。現状実使用200MiB程度。
# part3 128MiB(262144) swap。実メモリ64MiB*2
# part4 拡張領域。EPBRが1論理セクタ分確保されてしまうので、次のpart5は+8の位置にすること
# part5 250MiB(512000) samba等サーバーアプリケーション領域。現状実使用50MiB程度。
# part6 のこり。ユーザーデータ領域。直前にEPBRが1論理セクタ置かれるので、開始位置はpart5+512000+8とする。
sfdisk -uS -f /dev/$disk <<EOF || return 3
2048,614400,L
616448,1228800,L
1845248,262144,S
2107392,,E
2107400,512000,L
2619408,,L
EOF
echo "--- partition(): complete"
return 0
}
#
# format partition
#
format() {
local i=$1
echo "--- format(): formatting $disk$i"
if [ $i -eq 1 ]; then
if [ $flag_reset -eq 1 ]; then
echo "--- SKIP format for $disk$i because of command line parameter."
return 0
fi
mke2fs -b 4096 -j -m1 /dev/$disk$i || return 1
elif [ $i -eq 2 ]; then
mke2fs -j -m1 /dev/$disk$i || return 1
elif [ $i -eq 5 ]; then
mke2fs -j -b 4096 -N 100000 \
-O dir_index,filetype,sparse_super /dev/$disk$i || return 1
elif [ $i -eq 6 ]; then
[ ! -f /sbin/mkfs.xfs ] && cp -a ${SCRIPT_PATH}/mkfs.xfs /sbin/
mkfs.xfs -f /dev/$disk$i || return 1
else
echo "--- SKIP format for $disk$i because of not nessesary"
fi
echo "--- format(): complete"
return 0
}
#
# fw_install
#
fw_install() {
echo "--- fw_install(): copying .tgz archives, etc.."
touch verify_on_boot
cp -a ../sd?.tgz ../tar2disk ./.landisk/
mkdir ./.landisk/mnt
echo "--- fw_install(): complete"
}
#
# 初期化後updateの為にflag fileをtouchする
#
set_reset_flag() {
touch ./.landisk/reset_ok
}
#
# 指定ディスクを 0 クリアする
#
sanitize_disk() {
local i=$1
echo "--- sanitaize_disk(): zero filling $disk$i"
dd if=/dev/zero of=/dev/$disk$i bs=4M || return 1
echo "sanitize_disk(): complete"
}
#
# install_logを 作成する
#
set_install_log() {
echo "--- recording install log"
local end_time
local j
local mac_addr=`/sbin/ifconfig eth0 | sed -n 's/^.*HWaddr \([0-9A-F:]*\)[ ]*$/\1/p'`
local log_dir="$mnt/factory_log"
local install_log="$log_dir/install.log"
mount /dev/${disk}5 $mnt || return 1
if [ ! -d $log_dir ]; then
mkdir $log_dir || return 1
fi
end_time=`date`
echo "Mac Address: $mac_addr" > $install_log
echo "Install Start: $START_TIME" >> $install_log
echo "Install End: $end_time" >> $install_log
for j in 1 2 3 4 5 6 7 8 9 10; do
sync
umount $mnt && break || sleep 1
done
}
#
# partition5 にある factorylog を$topdirへ退避
#
bk_factory_log() {
echo "--- backup factory log"
local factory_tgz=$topdir/factory_log.tar.gz
if [ ! -f $factory_tgz ]; then
mount /dev/${disk}5 $mnt || return 1
tar cpzf $factory_tgz -C $mnt factory_log
umount $mnt
fi
}
#
# $topdirにあるfactorylogをカレントディレクトリへ書き戻して、今の作業をログへ追加
#
restore_factory_log() {
echo "--- restore factory log"
local factory_tgz=$topdir/factory_log.tar.gz
if [ -f $factory_tgz ]; then
tar xpzf $factory_tgz
echo `LANG=C date`: reset_script: >> factory_log/powerlog
rm -f $factory_tgz
fi
}
#
# smartチェックを行う
#
smart_check() {
echo --- smart checking
local RESULT_SMARTCTL=0
local RESULT_SMARTCTL_BIT0=0
local RESULT_SMARTCTL_BIT1=0
local RESULT_SMARTCTL_BIT2=0
local RESULT_SMARTCTL_BIT3=0
[ ! -f /usr/sbin/smartctl ] && cp -a ${SCRIPT_PATH}/smartctl /usr/sbin/
/usr/sbin/smartctl --smart=on --offlineauto=on --saveauto=on /dev/$disk
/usr/sbin/smartctl -a /dev/$disk
RESULT_SMARTCTL=$?
RESULT_SMARTCTL_BIT0=$((${RESULT_SMARTCTL} & 1))
RESULT_SMARTCTL_BIT1=$((${RESULT_SMARTCTL} & 2))
RESULT_SMARTCTL_BIT2=$((${RESULT_SMARTCTL} & 4))
RESULT_SMARTCTL_BIT3=$((${RESULT_SMARTCTL} & 8))
if [ ${RESULT_SMARTCTL_BIT0} -ne 0 ]; then
echo "*** FAILED TO ENABLE S.M.A.R.T. DISK=${disk} ***"
echo "*** COMMAND LINE PARSE ERROR ***"
return 1
fi
if [ ${RESULT_SMARTCTL_BIT1} -ne 0 ]; then
echo "*** FAILED TO ENABLE S.M.A.R.T. DISK=${disk} ***"
echo "*** DEVICE OPEN FAILED ***"
return 1
fi
if [ ${RESULT_SMARTCTL_BIT2} -ne 0 ]; then
echo "*** FAILED TO ENABLE S.M.A.R.T. DISK=${disk} ***"
echo "*** S.M.A.R.T. COMMAND FAILED ***"
return 1
fi
if [ ${RESULT_SMARTCTL_BIT3} -ne 0 ]; then
echo "*** S.M.A.R.T ERROR DETECTED DISK=${disk} ***"
echo "*** STATUS: DISK FAILING ***"
return 1
fi
echo "--- S.M.A.R.T check complete"
return 0
}
#
# メイン
#
disk=$1
mode=$2
ignoresmart=$3
topdir=`pwd`
mnt=./mnt
PATH=$PATH:/sbin
if [ "x$disk" = "x" ]; then
echo "usage: tar2disk sda [reset|reset_full|none [ignore_smart]] 1>&2"
exit -1
fi
if [ "x$mode" = "xreset" ]; then
flag_install=0
flag_reset=1
flag_reset_full=0
elif [ "x$mode" = "xreset_full" ]; then
flag_install=0
flag_reset=1
flag_reset_full=1
else
flag_install=1
flag_reset=0
flag_reset_full=0
fi
for i in 1 2 5 6; do
umount /dev/${disk}$i
done
if [ $flag_install -eq 1 ]; then
smart_check
if [ $? -ne 0 ] && [ "x$ignoresmart" != "xignore_smart" ]; then
EXIT 1 "SMART CHECK FAILED."
else
echo "--- SMART RESULT IGNORED."
fi
partition
fi
mkswap /dev/${disk}3
if [ $disk = $INTERNAL_HDD ]; then
swapon /dev/${disk}3
trap "swapoff /dev/${disk}3" 0
fi
for i in 1 2 5 6; do
cd $topdir
[ $i -eq 6 -a $flag_reset_full -eq 1 ] && sanitize_disk $i
[ $i -eq 5 -a $flag_reset -eq 1 ] && bk_factory_log
format $i || EXIT 1 "FORMAT $disk$i FAILED."
mount /dev/${disk}$i $mnt || EXIT 1 "MOUNT $disk$i FAILED."
cd $mnt || EXIT 1 "CD $mnt FAILED."
echo --- extract tar to $disk$i
tar zxf ../sd$i.tgz || EXIT 1
# 2017-05-02 bug fix for factory_log
[ $i -eq 5 -a ! -d $mnt/factory_log ] && mkdir $mnt/factory_log
[ $i -eq 1 -a $flag_install -eq 1 ] && fw_install
[ $i -eq 1 -a $flag_reset -eq 1 ] && set_reset_flag
[ $i -eq 5 -a $flag_reset -eq 1 ] && restore_factory_log
cd $topdir || EXIT 1 "cd $topdir FAILED."
echo --- unmounting
for j in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
sync
umount $mnt && break || sleep 1
done
[ "$?" -ne 0 ] && EXIT 1 "umount any FAILED."
done
[ $flag_install -eq 1 ] && set_install_log
EXIT 0 "OK."
sfdisk -uM を使ってMiB単位での指定がうまく機能すればいいのだが、EPBRのために1MiBの隙間を空けて次のパーティションの開始位置を指定するとsfdiskが「俺はこんな割当気に入らないね!」といって拒否られる。結局、-uS -fでパーティション開始位置を8の倍数セクタに強制することにした。
あと、/mnt/hda5/factory_logディレクトリがないというバグもここで解決した。
あと、/mnt/hda5/factory_logディレクトリがないというバグもここで解決した。
使い方は、HDL-GSのUSBポートに新品HDDを接続して(/dev/sdaになる)、telnetでHDL-GSの/boot/.landiskに入り、
./tar2disk sda none ignore_smart
とする。USB経由のHDDではSMART情報が採れないことがほとんどなのでignore_smartオプションでこれを無視するようにした。
