バグ?
工場出荷時バージョンのファームウェア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オプションでこれを無視するようにした。