「InitDisk1.sh」の編集履歴(バックアップ)一覧はこちら
「InitDisk1.sh」(2008/02/02 (土) 15:58:58) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
標準Linuxの/usr/local/bin/内にある。
HDDの初期化の役割を担う。
ユーザーの意思次第で、開発用LinuxをHDDに設置したりHDDブートするように設定する。
#contents()
*動作内容
-HDDがマウントされていないことを確認。されていればエラー終了。
-HDDがxfs形式でフォーマットされていないことを確認。されていればエラー終了。
-/mnt/mtdにChangeMeDevHDDがあるかどうかを確認して以下を実行。
&bold(){ある場合}
>-HDDを/dev/sda1、/dev/sda2、/dev/sda3、/dev/sda4の4つのパーティションに切り、それぞれをフォーマットする(マウントはしない)。
>|デバイス|フォーマット形式|
>|/dev/sda1|ext3|
>|/dev/sda2|xfs|
>|/dev/sda3|swap|
>|/dev/sda4|xfs|
>-[[SetupDevEnv.sh]]の実行
>>-/mnt/mtdにhddrootfs.tar.gz、uImage.buffaloがあるかどうかを確認して以下を実行。
>>
>>&bold(){ある場合}
>>>-/mnt/bootディレクトリを作成し、/dev/sda1をext3形式でマウントして、そこにuImage.buffaloをコピーする。
>>>-/mnt/rootfsディレクトリを作成し、/dev/sda2をxfs形式でマウントして、そこにhddrootfs.tar.gzを展開する。
>>>|デバイス|マウントポイント|マウントタイプ|
>>>|/dev/sda1|/mnt/boot|ext3|
>>>|/dev/sda2|/mnt/rootfs|xfs|
>>>-/usr/local/bin/[[kuro_lib]]を/mnt/rootfs/usr/local/binにコピーする。
>>>-ChangeMyUbootEnvがあればU-Boot環境変数を書き換える。なければそのまま終了する。
>>
>>&bold(){ない場合}
>>>-エラー終了させる。
&bold(){ない場合}
>-HDDを/dev/sda1と1つだけの[[パーティション]]に切りxfs形式でフォーマットする。
>|デバイス|フォーマット形式|
>|/dev/sda1|xfs|
>-/dev/sda1を/mnt/disk1にxfs形式でマウントする。
>|デバイス|マウントポイント|マウントタイプ|
>|/dev/sda1|/mnt/disk1|xfs|
>-/mnt/disk1のパーミッションを777にする。
*スクリプト
#!/bin/sh
. /usr/local/bin/kuro_lib
# $1 : Error type {mounted | formatted}
ExitWithError(){
miconapl -a led_set_cpu_mcon diag
miconapl -a led_set_on_off diag
miconapl -a led_set_brink diag
miconapl -a bz_on on3off3
case $1 in
mounted)
echo "disk is already mounted!" > /dev/console
;;
formatted)
echo "disk is already formatted!" > /dev/console
;;
esac
sleep 5
miconapl -a bz_on
miconapl -a led_set_brink off
miconapl -a led_set_on_off off
miconapl -a led_set_cpu_mcon off
exit 1
}
# Check point 1. disk is already mounted or not.
IsMounted ${DISK1_DEV} ; [ $? = 1 ] && ExitWithError mounted
IsMounted ${DISK1_DEV}1 ; [ $? = 1 ] && ExitWithError mounted
IsMounted ${DISK1_DEV}4 ; [ $? = 1 ] && EixtWithError mounted
# Check point 2. disk is already formatted or not.
XFS_FORMATTED=`dd if=${DISK1_DEV} bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] && ExitWithError formatted
XFS_FORMATTED=`dd if=${DISK1_DEV}1 bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] && ExitWithError formatted
XFS_FORMATTED=`dd if=${DISK1_DEV}4 bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] && ExitWithError formatted
# OK! Disk is not mounted and not formatted.
miconapl -a led_set_code_information 28
miconapl -a bz_on button
if [ -e ${CHANGE_TO_DEVHDD_FILE} ] ; then
fdisk ${DISK1_DEV} < /usr/local/bin/PartitionDefinition
Format_EXT3 ${DISK1_DEV}1
Format_XFS ${DISK1_DEV}2
Format_XFS ${DISK1_DEV}4
mkswap ${DISK_DEV}3
/usr/local/sbin/SetupDevEnv.sh
else
fdisk ${DISK1_DEV} < /usr/local/bin/PartitionDefinition1
Format_XFS ${DISK1_DEV}1
MountShare ${DISK1_DEV} ${DISK1_MPT}
fi
miconapl -a led_set_code_information clear
~ #
*スクリプト詳細
ブロックごとに見てみる。
#!/bin/sh
シェルの指定。shを指定している。
. /usr/local/bin/kuro_lib
/usr/local/bin/[[kuro_lib]]をサブシェルで実行している。
この[[kuro_lib]]内の
-InMounted関数
-Format_EXT3関数
-Format_XFS関数
-MountShare関数
-IsHavePartition関数
-DISK1_DEV変数(=/dev/sda)
-DISK1_MPT変数(=/mnt/disk1)
-CHANGE_TO_DEVHDD_FILE変数(=/mnt/mtd/ChangeMeDevHDD)
-HEXDUMP変数(=/usr/bin/hexdump)
を使用するためだ。
**ExitWithError関数
関数の定義が始まる。なお、この項目は関数が以後の命令で呼び出された時に機能する内容であり、スクリプト実行と同時に実行されるわけではない。
# $1 : Error type {mounted | formatted}
ExitWithError(){
第1引数はmountedかformattedというエラータイプだ、と解説されている。
miconapl -a led_set_cpu_mcon diag
miconapl -a led_set_on_off diag
miconapl -a led_set_brink diag
miconapl -a bz_on on3off3
まずはどのタイプのエラーであれ(この関数が呼び出されている時点で何らかのエラーには間違いないため)、[[miconaplコマンド]]でLEDとブザーが共通の操作をされている。
詳しくは[[miconaplコマンド]]で記すが、この4行で
-エラーLEDが点滅
-ブザーがピッピッピと鳴る
という動作になる。
case $1 in
先ほどの第1引数の内容によって以後の処理動作を分けている。
&bold(){第1引数がmountedの場合}
mounted)
echo "disk is already mounted!" > /dev/console
;;
[[echoコマンド]]で「disk is already mounted!」という一文がコンソールデバイスに出力されている。
これだけでこのcase文を抜ける。
&bold(){第1引数がformattedの場合}
formatted)
echo "disk is already formatted!" > /dev/console
;;
[[echoコマンド]]で「disk is already formatted!」という一文がコンソールデバイスに出力されている。
これだけでこのcase文を抜ける。
esac
以上の処理でmountedかformattedか、というcase文は終了する。
sleep 5
miconapl -a bz_on
miconapl -a led_set_brink off
miconapl -a led_set_on_off off
miconapl -a led_set_cpu_mcon off
5秒間一時停止した後に、LEDとブザーの動作を止めている。
exit 1
終了ステータスに異常を表す「1」を指定。
}
ExitWithError関数はここまで。
**スクリプト本文
ここからがいわゆるInitDisk1.shのスクリプト本体だ。
# Check point 1. disk is already mounted or not.
まずはチェックポイント1としてHDDがすでにマウントされているかいないかを以下で調査している。
サブシェルで走らせている/usr/local/bin/[[kuro_lib]]内の関数「IsMounted」を使うことになる。
ここで述べておく方が理解が容易なので、InitDisk1.shスクリプトの内容ではないが/usr/local/bin/[[kuro_lib]]内のIsMounted関数に触れておく。
>***IsMounted関数
>/usr/local/bin/[[kuro_lib]]内の関数であり、引数を1つ付けさせて内容により戻り値として「0」か「1」を返す仕組みのようだ。
> # $1 : device of check target
> # retval
> # 1 : device $1 is mounted.
> # 0 : device $1 is not mounted.
>第1引数はチェック対象のデバイスであり、このIsMounted関数が戻り値1を返せばそのデバイスはマウントされている、0を返せばされていないとする旨の解説だ。
> IsMounted(){
> MOUNTED=`grep $1 /proc/mounts`
>MOUNTEDという変数を用意しそこにgrep $1 /proc/mountsの結果を代入している。
>$1とはIsMounted関数に付けられた第1引数であり、${DISK1_DEV}すなわち/dev/sdaを指す。
>つまり、[[procコマンド]]でマウント状態を調べたとき、/dev/sdaという文字が含まれるものを抽出していることになる。
>その結果がMOUNTEDという変数に代入される。
> if [ "${MOUNTED}" != "" ] ; then
> return 1
> else
> return 0
> fi
>このMOUNTED変数がカラでなければ戻り値1を返しIsMounted関数を終了、そうでなければ(カラであれば)0を返しIsMounted関数を終了する、という内容。
>この作業で、/dev/sdaがマウントされているかどうかが判別できる。
> return 0
>上のいずれにもあてはまらなければ(実際にはあり得ないが)0を返す。
> }
>IsMounted関数はここまで。
ここからまたスクリプト本文の解説に戻る。
IsMounted ${DISK1_DEV} ; [ $? = 1 ] && ExitWithError mounted
IsMounted ${DISK1_DEV}1 ; [ $? = 1 ] && ExitWithError mounted
IsMounted ${DISK1_DEV}4 ; [ $? = 1 ] && EixtWithError mounted
IsMounted関数に${DISK1_DEV}(=/dev/sda)、${DISK1_DEV}1(=/dev/sda1)、${DISK1_DEV}4(=/dev/sda4)という引数をそれぞれ付け、戻り値は0か1が返ってくるのを待ち、返って来た結果(戻り値「$?」)が1ならばExitWithError関数をmountedという引数を付けて実行している。
/dev/sdaもしくは/dev/sda1、/dev/sda4のいずれか一つでもマウントされていればInitDisk1.shはエラー終了してしまう、ということだ。
誤動作防止のためだと思われる。
これでチェックポイント1であるマウントされているかどうかの調査は終了する。
# Check point 2. disk is already formatted or not.
次にチェックポイント2としてHDDがすでにフォーマットされているかいないかを以下で調査している。
XFS_FORMATTED=`dd if=${DISK1_DEV} bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] && ExitWithError formatted
XFS_FORMATTED=`dd if=${DISK1_DEV}1 bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] && ExitWithError formatted
XFS_FORMATTED=`dd if=${DISK1_DEV}4 bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] && ExitWithError formatted
流れとしては
+XFS_FORMATTEDという変数を用意
+そこに対象となるデバイスのフォーマット形式を代入
+それがxfs形式かどうかを判別
+xfs形式ならばExitWithError関数にformatted引数を付けてエラー処理
となる。
デバイスのフォーマットの調べ方だが、ここでは[[ddコマンド]]で行っている。
[[ddコマンド]]のofパラメータは出力先を指すが、今回これは指定しないのですなわち標準出力を指す。
xfs形式でフォーマットされたデバイス([[パーティション]])は、
>dd if=デバイス bs=1 count=3
とすると
>XFS3+0 records in
>3+0 records out
とコンソールには表示されるが、内部的にはXFSの3文字だけが出力されている(of=/mnt/disk1/dd.txtなどで確認してみるとはっきりする)。
ext3ではXFSは表示されないが、XFS形式のものをmkfs.ext3で上書きした場合はXFSと表示されてしまう。
[[パーティション]]の先頭を0で埋めた後、領域を破壊した上でmkfs.ext3を実行しないと機械的にはXFSとみなされるので注意が必要だ。
上の命令は/dev/sda、/dev/sda1、/dev/sda4のいずれかがxfs形式ならばformattedという引数を付けてExitWithError関数を実行(すなわちエラー処理)する、という意味だ。
# OK! Disk is not mounted and not formatted.
以上、2つのチェックポイントを無事通過できると次の処理が待っている。
**デバイスの初期化
miconapl -a led_set_code_information 28
miconapl -a bz_on button
オレンジのLEDを点滅させ、ブザーをピっと鳴らす。
&bold(){/mnt/mtdにChangeMeDevHDDがある場合}
if [ -e ${CHANGE_TO_DEVHDD_FILE} ] ; then
この「-e」という評価式は「存在すれば真」なので、CHANGE_TO_DEVHDD_FILE(/mnt/mtd/にChangeMeDevHDD)が存在すれば以下を実行、という意味になる。
なお、このChangeMeDevHDDとは、附属CD-ROM内にあるもので「HDD[[パーティション]]を開発用に設定するための意思表示ファイル」となっている。中身は何もない。
この条件分岐のためだけにあり、あるかないかが問題なだけだ。
fdisk ${DISK1_DEV} < /usr/local/bin/PartitionDefinition
/usr/local/bin/PartitionDefinitionに記載されている内容に従って/dev/sdaに[[パーティション]]をきっていく。
記載された内容とは
|[[パーティション]]|サイズ|パーティションタイプ|
|/dev/sda1|50MB|Linux|
|/dev/sda2|3GB|Linux|
|/dev/sda3|128MB|swap|
|/dev/sda4|残り|Linux|
となっている。
次に、きられた[[パーティション]]に今度は[[ファイルシステム]]を導入する。
まずは/usr/local/bin/[[kuro_lib]]内の関数「Format_EXT3」を説明する。
>***Format_EXT3関数
>/usr/local/bin/[[kuro_lib]]内の関数であり、引数一つを受け取りそのデバイスをext3形式にフォーマットする関数のようだ。
> # $1 : target device to format
> Format_EXT3(){
>第1引数のデバイスをフォーマット対象とする。
> echo "***** Starting to format $1 *****"
>画面に「***** Starting to format 対象デバイス *****」と表示する。
> mkfs.ext3 $1
>[[mkfs.ext3コマンド]]で第1引数のデバイスをext3形式でフォーマットする。
> if [ $? -eq 0 ] ; then
>$?とは上の[[mkfs.ext3コマンド]]の実行結果の終了ステータスを指しているのだが、これが「0」すなわち成功ならば次を実行、となっている。
> echo "Format is succeeded without error."
>画面に「Format is succeeded without error.」と表示する。つまり「フォーマットはエラーもなく成功した。」と表示している。
> else
>$?が「0」でなければ、つまりフォーマットに失敗しているのならば次を実行。
> return 1
> exit 1
> fi
>return 1とは、関数の戻り値を1に明示的に指定してFormat_EXT3関数を終了しているわけだが、このスクリプト内で戻り値を具体的に利用する様子は見受けられないので意味はないだろう。
>/usr/local/bin/[[kuro_lib]]は様々なスクリプトで利用されているライブラリ的なスクリプトなので、どこかで利用するものかもしれない。
>exit 1も同じような意味合いだが、終了ステータスを「1」(異常)に設定してスクリプト(/usr/local/bin/[[kuro_lib]])を終了するようにしている。
> return 0
>戻り値「0」をセットしFormat_EXT3関数を抜ける。
> }
>Format_EXT3関数はここまで。
次に/usr/local/bin/[[kuro_lib]]内の関数「Format_XFS」を説明する。
>***Format_XFS関数
>/usr/local/bin/[[kuro_lib]]内の関数であり、引数一つを受け取りそのデバイスをxfs形式にフォーマットする関数のようだ。
> # $1 : target device to format.
> Format_XFS(){
>第1引数のデバイスをフォーマット対象とする。
> KEY=`dd if=$1 bs=1 count=3`
>KEYという変数を用意し、そこにdd if=$1 bs=1 count=3の結果を代入する。
>先ほど検証したようにxfs形式のデバイスに対してこのコマンドを使うと「XFS」と出力される。
> if [ "${KEY}" = "XFS" ] ; then
>KEYの値がXFSならば次を実行、という意味だ。つまりここは対象デバイスのフォーマット形式がxfs形式かどうかを条件分岐にしている。
> . /etc/melco/info
>/etc/melco/infoをサブシェルで走らせているが、標準Linuxにはこのファイルは存在しない。
>製品仕様書にも初期化SWの項目に
>>内蔵HDD(/dev/sda)が既にxfs形式でフォーマットされている場合、フォーマットは行われない。但し、/etc/melco/info内、force_format=yesとすることで、xfsでフォーマットされている/いないにかかわらず、フォーマットを行うようにすることができる。
>と記載されている。強制フォーマットの機能を使うのであれば自分で/etc/melco/infoを用意するしかない。
> if [ "${force_format}" = "yes" ] ; then
>/etc/melco/info内の「force_format」項目が「yes」となっていれば以下を実行。
> echo "Disk (or partition) is looks like already formatted."
> echo "If you stop format, Press Ctrl+C in 10 seconds!!!"
>画面に「Disk (or partition) is looks like already formatted.If you stop format, Press Ctrl+C in 10 seconds!!!」と表示。
>「ディスク(あるいは[[パーティション]])は既にフォーマットされているようです。フォーマットを中止する場合は10秒以内にCtrl+Cを押してください」という意味。
> COUNTER=10
>COUNTERという変数を用意し、そこに10を代入。
> echo -n "waiting "
>画面に「waiting」と表示。-nオプションは「テキストの行末で改行しない」という意味。
> while [ ${COUNTER} -gt 0 ]
>COUNTER変数が0より大きければdo~doneの内容を繰り返す。
> do
> echo -n "."
> sleep 1
> COUNTER=$((${COUNTER} - 1))
> done
>「waiting」の行末に「.」を表示し、1秒待った後COUNTER変数から1を引く、という内容。
>先のwhile条件から、1を引いた結果が0よりも大きければ同じことを繰り返す、ということなので、これで結果的に10秒間待機することになる。
>「.」を1秒ごとに表示させるためにwhile文を使ったのだろう。
> echo ""
> echo "OK, go on formatting."
>echoで空白を表示、これは改行させる目的で、次に「OK, go on formatting.」を表示させている。
> else
>/etc/melco/info内の「force_format」項目が「yes」となっていなければ以下を実行。
> return 0
>戻り値を「0」に設定しFormat_XFS関数を抜ける。つまりこの関数内の以後の命令は実行しない。
> fi
> fi
>if [ "${force_format}" = "yes" ]を抜け、すぐ次にif [ "${KEY}" = "XFS" ]も抜けている。
> echo "***** Cleaning Disk partition information *****"
>画面に「***** Cleaning Disk partition information *****」と表示。
> dd if=/dev/zero of=$1 bs=512 count=1
>[[ddコマンド]]を使ってデバイスの先頭から512バイトに「0」を書き込んでいる。
>要するにそのデバイス([[パーティション]])を先頭から512バイト分データを消去している。
> echo "***** Starting to format $1 *****"
>画面に「***** Starting to format 対象デバイス *****」と表示。
> mkfs.xfs $1 -f
>デバイスを[[mkfs.xfsコマンド]]でxfs形式にフォーマットしている。-fは上書きオプション。
> if [ $? -eq 0 ] ; then
>終了ステータスが0であれば、つまり上の[[mkfs.xfsコマンド]]がエラーでなければ以下を実行。
> echo "Format is succeeded without error."
>画面に「Format is succeeded without error.」と表示。
> else
>mkfs.xfsでエラーが発生すれば
> return 1
> exit 1
> fi
>戻り値を1、終了ステータスを1に設定して終了。
> return 0
>戻り値を0に設定しFormat_XFS関数を抜ける。
> }
>Format_XFS関数はここまで。
これら関数を使って[[ファイルシステム]]を導入する命令が以下。
Format_EXT3 ${DISK1_DEV}1
Format_XFS ${DISK1_DEV}2
Format_XFS ${DISK1_DEV}4
mkswap ${DISK_DEV}3
わかりやすく表にすれば
|デバイス|フォーマット形式|
|/dev/sda1|ext3|
|/dev/sda2|xfs|
|/dev/sda3|swap|
|/dev/sda4|xfs|
という意味だが、
>mkswap ${DISK_DEV}3
は上の[[パーティション]]の様子からすると
>mkswap ${DISK1_DEV}3
でなければならないはずだ。開発用Linuxのfstabで/dev/sda3をswapでマウントしようとしても、フォーマットが完了していないため失敗するだろう。
/usr/local/sbin/SetupDevEnv.sh
そして、/usr/local/sbin/[[SetupDevEnv.sh]]を実行する。詳細は[[SetupDevEnv.sh]]の項目で説明する。
その後、miconapl -a led_set_code_information clearを実行してInitDisk1.shを終了する。
&bold(){/mnt/mtdにChangeMeDevHDDがない場合}
else
CHANGE_TO_DEVHDD_FILE(/mnt/mtd/にChangeMeDevHDD)が存在しなければ以下を実行。
fdisk ${DISK1_DEV} < /usr/local/bin/PartitionDefinition1
/dev/sdaを/usr/local/bin/PartitionDefinition1に従って[[パーティション]]分割作業する。
|[[パーティション]]|サイズ|パーティションタイプ|
|/dev/sda1|すべて|Linux|
という内容だ。
Format_XFS ${DISK1_DEV}1
Format_XFS関数で/dev/sda1をxfs形式にフォーマット。
MountShare ${DISK1_DEV} ${DISK1_MPT}
MountShare関数に
|第1引数|/dev/sda|
|第2引数|/mnt/disk1|
という引数を付けて実行させている。
ここで/usr/local/bin/[[kuro_lib]]内のMountShare関数を説明する。
>***MountShare関数
>/usr/local/bin/[[kuro_lib]]内の関数。4つまでの引数に対応し、3つの戻り値を設定できる。
> # $1 : target device to mount.
> # $2 : target mountpoint of $1.
> # $3 : File system of target device(default is xfs).
> # $4 : Mounted device permission(default is 777).
> MountShare(){
>第1引数にマウントする対象デバイス、第2引数に対象デバイスのマウント先、第3引数に対象デバイスの[[ファイルシステム]](初期値はxfs形式)、第4引数にマウントしたデバイスのパーミッション(初期値は777)、という解説。
> # ret 0 : this is no partition disk.
> # ret 1 : this is nand share type partition
> # ret 2 : this is developkit type partition (maybe)
>MountShare関数の戻り値ではない。IsHavePartition関数からの戻り値を説明している。
>戻り値「0」で「[[パーティション]]が存在しないディスクです」、「1」で「NANDフラッシュ共有時(つまり標準Linux時)の[[パーティション]]です」、「2」で「(おそらく)開発用Linux時の[[パーティション]]です」と、それぞれ意味する。
> if [ "$1" = "/dev/sda" -o "$1" = "/dev/sdb" ] ; then
>第1引数が/dev/sdaあるいは/dev/sdbであれば以下を実行。
> IsHavePartition $1
>/usr/local/bin/[[kuro_lib]]内のIsHavePartition関数に第1引数を付けて実行している。
>ここでIsHavePartition関数を説明する。
>>***IsHavePartition関数
>> # $1 : target device to check partition
>>第1引数にパーティション状態をチェックする対象デバイス、という解説。
>> # ret 0 : this is no partition disk.
>> # ret 1 : this is nand share type partition
>> # ret 2 : this is developkit type partition (maybe)
>>戻り値「0」で「[[パーティション]]が存在しないディスクです」、「1」で「NANDフラッシュ共有時(つまり標準Linux時)の[[パーティション]]です」、「2」で「(おそらく)開発用Linux時の[[パーティション]]です」と、それぞれ意味する。
>> IsHavePartition(){
>> if [ -x ${HEXDUMP} ] ; then
>>HEXDUMP変数(=/usr/bin/hexdump)に-xオプションを付けて条件としている。-xオプションは「存在し、かつ実行可能なら真」という意味なので、ここでは「/usr/bin/hexdumpが存在し、かつ実行可能なら次を実行」という意味になる。
>> DISK_1_PART_TAIL=`hexdump -s 446 -n 64 -e '8/1 "%02x " 2/4 "%10d " "\n"' $1 | sed -n "1p"|awk '{print $10}'`
>>DISK_1_PART_TAILという変数を用意し、そこにhexdump -s 446 -n 64 -e '8/1 "%02x " 2/4 "%10d " "\n"' $1 | sed -n "1p"|awk '{print $10}'という内容を代入している。
>>パイプで3つの命令がつながっているが、それぞれに分けて考えてみる。
>>
>>&bold(){hexdump}
>>>hexdump -s 446 -n 64 -e '8/1 "%02x " 2/4 "%10d " "\n"' $1
>>[[hexdumpコマンド]]を使っている。先頭から446バイト読み飛ばした所から64バイト分だけを読み込み、それを「8/1 "%02x " 2/4 "%10d " "\n"」というフォーマットで第1引数のデバイスを表示する、という意味になる。
>>HDDの先頭512バイトはMBR領域となっており、その中の先頭446バイトから64バイトはパーティションテーブルが4エントリ分(1エントリ16バイト)ある。
>>つまりここでは4つのパーティションテーブルを読み込んだことになる。
>>次に、詳細は[[hexdumpコマンド]]で説明するが、「繰り返し回数/バイト数 "フォーマット"」の羅列が[[hexdumpコマンド]]のフォーマット形式なので、この場合は
>>>8回繰り返し/1バイト "フィールド幅2(2桁表示で満たない桁は0で表示)で16進数変換"
>>>2回繰り返し/4バイト "フィールド幅10(10桁表示で満たない桁は空白で表示)で10進数変換"
>>>改行
>>という内容になる。
>>つまり、「1バイトづつ8回、4バイトづつ2回、計16バイトを10回にわけて読み込み、それを4行に出力」という内容だ。
>>パーティションテーブルを1つ読み込んでは改行し、64バイト分すべてを16バイトづつ4行10フィールドで表現している。
>>4つの[[パーティション]]を切ったHDDで試してみると以下の結果を得た。
>>>00 01 01 00 83 fe 3f 06 63 112392
>>>00 00 01 07 83 fe 7f 74 112455 5879790
>>>00 00 41 75 82 fe 7f 85 5992245 273105
>>>00 00 41 86 83 fe ff ff 6265350 150031035
>>
>>&bold(){sed}
>>>sed -n "1p"
>>「-n」オプションで[[hexdumpコマンド]]から受け取った結果の1行目(pが行を表す)だけを抽出している。
>>ここの「1p」が「2p」「3p」「4p」と変化していくのは、それぞれパーティションテーブルを1から4まで読み、該当パーティションテーブル以外を破棄している。
>>先ほどの例で試すと
>>>00 01 01 00 83 fe 3f 06 63 112392
>>という結果を得る。
>>
>>&bold(){awk}
>>>awk '{print $10}'
>>[[sedコマンド]]から受け取った行の第10フィールドの値を出力している。
>>第10フィールドはLBAの[[パーティション]]総セクター数(4バイト)を意味する。
>>つまり、最終的にDISK_1_PART_TAIL変数に代入したい値とは、各[[パーティション]]の総セクター数であることがわかる。これは[[hexdumpコマンド]]で10進数にされている。
>> DISK_2_PART_TAIL=`hexdump -s 446 -n 64 -e '8/1 "%02x " 2/4 "%10d " "\n"' $1 | sed -n "2p"|awk '{print $10}'`
>> DISK_3_PART_TAIL=`hexdump -s 446 -n 64 -e '8/1 "%02x " 2/4 "%10d " "\n"' $1 | sed -n "3p"|awk '{print $10}'`
>> DISK_4_PART_TAIL=`hexdump -s 446 -n 64 -e '8/1 "%02x " 2/4 "%10d " "\n"' $1 | sed -n "4p"|awk '{print $10}'`
>>先ほどと同様な処理を各[[パーティション]]ごとにDISK_パーティション番号_PART_TAILという変数に代入している。
>>例で試すと
>>>112392
>>という結果。
>>総セクター数が0であればその[[パーティション]]は存在しない、という意味になる。
>> if [ "${DISK_1_PART_TAIL}" -ne 0 -a "${DISK_2_PART_TAIL}" -eq 0 -a "${DISK_3_PART_TAIL}" -eq 0 -a "${DISK_4_PART_TAIL}" -eq 0 ] ; then
>>-第1パーティションの総セクター数が0ではない
>>-かつ第2~4パーティションの総セクター数が0
>>の場合に以下を実行する。
>> return 1
>>戻り値「1」を設定し関数を抜ける。
>>つまり「this is nand share type partition」ということになる。
>> elif [ "${DISK_1_PART_TAIL}" -ne 0 -a "${DISK_2_PART_TAIL}" -ne 0 -a "${DISK_3_PART_TAIL}" -ne 0 -a "${DISK_4_PART_TAIL}" -ne 0 ] ; then
>>-第1~4パーティションの総セクター数が0ではない
>>の場合に以下を実行。
>> return 2
>>戻り値「2」を設定し関数を抜ける。
>>つまり「this is developkit type partition (maybe)」ということだ。
>> else
>>それ以外の場合、つまり
>>-第1パーティションの総セクター数が0
>>の場合に以下を実行。
>> return 0
>>戻り値に「0」を設定し関数を抜ける。
>>つまり「this is no partition disk.」ということになる。
>> fi
>>[[パーティション]]総セクター数の条件分岐を終了する。
>> else
>>「/usr/bin/hexdumpが存在し、かつ実行可能」ではない場合は以下を実行、という意味。
>> return 0
>>戻り値に「0」を設定し関数を抜ける。
>>つまり「this is no partition disk.」ということになる。
>> fi
>>「/usr/bin/hexdumpが存在し、かつ実行可能」という条件分岐を終了する。
>> return 0
>>いずれにもあてはまらなかった場合、戻り値に「0」を設定し関数を抜ける。
>>つまり「this is no partition disk.」ということになる。
>> }
>>IsHavePartition関数はここまで。
>ここからまたMountShare関数に戻る。
> RET=$?
>RETという変数を用意し、そこにIsHavePartition関数の戻り値を代入。
> [ "${RET}" -eq 1 ] && TARGET_DEV=${1}1
> [ "${RET}" -eq 2 ] && TARGET_DEV=${1}4
> [ "${RET}" -eq 0 ] && TARGET_DEV=${1}
>-戻り値が1ならば、TARGET_DEV変数にMountShare関数に付けた第1引数(if文の関係上、/dev/sdaか/dev/sdb)の第1[[パーティション]]を代入する。
>-戻り値が2ならば、TARGET_DEV変数にMountShare関数に付けた第1引数(if文の関係上、/dev/sdaか/dev/sdb)の第4[[パーティション]]を代入する。
>-戻り値が0ならば、TARGET_DEV変数にMountShare関数に付けた第1引数(if文の関係上、/dev/sdaか/dev/sdb)を代入する。
>というように処理している。
> else
>MountShare関数に付けた第1引数が/dev/sdaでも/dev/sdbでもなければ以下を実行。
> TARGET_DEV=$1
>TARGET_DEV変数にMountShare関数に付けた第1引数を代入。
> fi
>MountShare関数に付けた第1引数が/dev/sdaか/dev/sdbか、という条件分岐を抜ける。
> IsMounted ${TARGET_DEV}
>IsMounted関数に第1引数としてTARGET_DEV変数を渡す。先ほど説明したとおり、戻り値「1」で「device is mounted.」、戻り値「0」で「device $1 is not mounted.」という意味になる。
> if [ $? = 1 ] ; then
>戻り値が「1」ならば、つまり「device is mounted.」という意味ならば次を実行。
> echo "${TARGET_DEV} is already mounted."
>画面上に「対象デバイス is already mounted.」と表示。
> return 1
>戻り値「1」を設定しMountShare関数を抜ける。
> fi
>IsMounted関数の戻り値による条件分岐を抜ける。
> if [ "$3" = "" ] ; then
>MountShare関数の第3引数が何もなければ以下を実行する。
> FS=xfs
>FSという変数を用意し、そこにxfsを代入する。
> else
>MountShare関数の第3引数に何かあれば以下を実行する。
> FS=$3
>FSという変数を用意し、そこにその第3引数を代入する。
> fi
>MountShare関数の第3引数の有無の条件分岐を抜ける。
> if [ "$4" = "" ] ; then
>MountShare関数の第4引数が何もなければ以下を実行する。
> PERMISSION=777
>PERMISSIONという変数を用意し、そこに777を代入する。
> else
>MountShare関数の第4引数に何かあれば以下を実行する。
> PERMISSION=$4
>PERMISSIONという変数を用意し、そこにその第4引数を代入する。
> fi
>MountShare関数の第4引数の有無の条件分岐を抜ける。
> echo "Mounting ${TARGET_DEV} on $2 as a ${FS} file system."
>画面上に「Mounting 対象デバイス(MountShare関数の第1引数) on マウントポイント( MountShare関数の第2引数) as a ファイルシステムタイプ(MountShare関数の第3引数) file system.」と表示する。
> mount -t ${FS} ${TARGET_DEV} $2
>実際に設定した変数の値をもとに[[mountコマンド]]でマウントする。
> case $? in
>[[mountコマンド]]の終了ステータスをもとに実行内容を変える。
> 0)
>
>&bold(){終了ステータス「0」(正常)の場合}
> chmod ${PERMISSION} $2
> echo "Success."
> ;;
>[[chmodコマンド]]で設定したパーミッションでマウントポイントのデバイスを指定し、画面上に「Success.」と表示してcase文を抜ける。
> *)
>
>&bold(){終了ステータス「1」(異常)の場合}
> echo "Failed."
> return 1
> ;;
>画面上に「Failed.」と表示して、戻り値「1」を設定しMountShare関数を抜ける。
> esac
>case文はここまで。
> echo ""
>
> return 0
>画面上を改行して戻り値「0」を設定しMountShare関数を抜ける。
> }
>MountShare関数はここまで。
fi
CHANGE_TO_DEVHDD_FILE(/mnt/mtd/にChangeMeDevHDD)の有無の条件分岐を抜ける。
miconapl -a led_set_code_information clear
LEDの点滅を止める。
----
標準Linuxの/usr/local/bin/内にある。
HDDの初期化の役割を担う。
ユーザーの意思次第で、開発用LinuxをHDDに設置したりHDDブートするように設定する。
#contents()
*動作内容
-HDDがマウントされていないことを確認。されていればエラー終了。
-HDDがxfs形式でフォーマットされていないことを確認。されていればエラー終了。
-/mnt/mtdにChangeMeDevHDDがあるかどうかを確認して以下を実行。
&bold(){ある場合}
>-HDDを/dev/sda1、/dev/sda2、/dev/sda3、/dev/sda4の4つのパーティションに切り、それぞれをフォーマットする(マウントはしない)。
>|デバイス|フォーマット形式|
>|/dev/sda1|ext3|
>|/dev/sda2|xfs|
>|/dev/sda3|swap|
>|/dev/sda4|xfs|
>-[[SetupDevEnv.sh]]の実行
>>-/mnt/mtdにhddrootfs.tar.gz、uImage.buffaloがあるかどうかを確認して以下を実行。
>>
>>&bold(){ある場合}
>>>-/mnt/bootディレクトリを作成し、/dev/sda1をext3形式でマウントして、そこにuImage.buffaloをコピーする。
>>>-/mnt/rootfsディレクトリを作成し、/dev/sda2をxfs形式でマウントして、そこにhddrootfs.tar.gzを展開する。
>>>|デバイス|マウントポイント|マウントタイプ|
>>>|/dev/sda1|/mnt/boot|ext3|
>>>|/dev/sda2|/mnt/rootfs|xfs|
>>>-/usr/local/bin/[[kuro_lib]]を/mnt/rootfs/usr/local/binにコピーする。
>>>-ChangeMyUbootEnvがあればU-Boot環境変数を書き換える。なければそのまま終了する。
>>
>>&bold(){ない場合}
>>>-エラー終了させる。
&bold(){ない場合}
>-HDDを/dev/sda1と1つだけの[[パーティション]]に切りxfs形式でフォーマットする。
>|デバイス|フォーマット形式|
>|/dev/sda1|xfs|
>-/dev/sda1を/mnt/disk1にxfs形式でマウントする。
>|デバイス|マウントポイント|マウントタイプ|
>|/dev/sda1|/mnt/disk1|xfs|
>-/mnt/disk1のパーミッションを777にする。
*スクリプト
#!/bin/sh
. /usr/local/bin/kuro_lib
# $1 : Error type {mounted | formatted}
ExitWithError(){
miconapl -a led_set_cpu_mcon diag
miconapl -a led_set_on_off diag
miconapl -a led_set_brink diag
miconapl -a bz_on on3off3
case $1 in
mounted)
echo "disk is already mounted!" > /dev/console
;;
formatted)
echo "disk is already formatted!" > /dev/console
;;
esac
sleep 5
miconapl -a bz_on
miconapl -a led_set_brink off
miconapl -a led_set_on_off off
miconapl -a led_set_cpu_mcon off
exit 1
}
# Check point 1. disk is already mounted or not.
IsMounted ${DISK1_DEV} ; [ $? = 1 ] && ExitWithError mounted
IsMounted ${DISK1_DEV}1 ; [ $? = 1 ] && ExitWithError mounted
IsMounted ${DISK1_DEV}4 ; [ $? = 1 ] && EixtWithError mounted
# Check point 2. disk is already formatted or not.
XFS_FORMATTED=`dd if=${DISK1_DEV} bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] && ExitWithError formatted
XFS_FORMATTED=`dd if=${DISK1_DEV}1 bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] && ExitWithError formatted
XFS_FORMATTED=`dd if=${DISK1_DEV}4 bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] && ExitWithError formatted
# OK! Disk is not mounted and not formatted.
miconapl -a led_set_code_information 28
miconapl -a bz_on button
if [ -e ${CHANGE_TO_DEVHDD_FILE} ] ; then
fdisk ${DISK1_DEV} < /usr/local/bin/PartitionDefinition
Format_EXT3 ${DISK1_DEV}1
Format_XFS ${DISK1_DEV}2
Format_XFS ${DISK1_DEV}4
mkswap ${DISK_DEV}3
/usr/local/sbin/SetupDevEnv.sh
else
fdisk ${DISK1_DEV} < /usr/local/bin/PartitionDefinition1
Format_XFS ${DISK1_DEV}1
MountShare ${DISK1_DEV} ${DISK1_MPT}
fi
miconapl -a led_set_code_information clear
~ #
*スクリプト詳細
ブロックごとに見てみる。
#!/bin/sh
シェルの指定。shを指定している。
. /usr/local/bin/kuro_lib
/usr/local/bin/[[kuro_lib]]をサブシェルで実行している。
この[[kuro_lib]]内の
-InMounted関数
-Format_EXT3関数
-Format_XFS関数
-MountShare関数
-IsHavePartition関数
-DISK1_DEV変数(=/dev/sda)
-DISK1_MPT変数(=/mnt/disk1)
-CHANGE_TO_DEVHDD_FILE変数(=/mnt/mtd/ChangeMeDevHDD)
-HEXDUMP変数(=/usr/bin/hexdump)
を使用するためだ。
**ExitWithError関数
関数の定義が始まる。なお、この項目は関数が以後の命令で呼び出された時に機能する内容であり、スクリプト実行と同時に実行されるわけではない。
# $1 : Error type {mounted | formatted}
ExitWithError(){
第1引数はmountedかformattedというエラータイプだ、と解説されている。
miconapl -a led_set_cpu_mcon diag
miconapl -a led_set_on_off diag
miconapl -a led_set_brink diag
miconapl -a bz_on on3off3
まずはどのタイプのエラーであれ(この関数が呼び出されている時点で何らかのエラーには間違いないため)、[[miconaplコマンド]]でLEDとブザーが共通の操作をされている。
詳しくは[[miconaplコマンド]]で記すが、この4行で
-エラーLEDが点滅
-ブザーがピッピッピと鳴る
という動作になる。
case $1 in
先ほどの第1引数の内容によって以後の処理動作を分けている。
&bold(){第1引数がmountedの場合}
mounted)
echo "disk is already mounted!" > /dev/console
;;
[[echoコマンド]]で「disk is already mounted!」という一文がコンソールデバイスに出力されている。
これだけでこのcase文を抜ける。
&bold(){第1引数がformattedの場合}
formatted)
echo "disk is already formatted!" > /dev/console
;;
[[echoコマンド]]で「disk is already formatted!」という一文がコンソールデバイスに出力されている。
これだけでこのcase文を抜ける。
esac
以上の処理でmountedかformattedか、というcase文は終了する。
sleep 5
miconapl -a bz_on
miconapl -a led_set_brink off
miconapl -a led_set_on_off off
miconapl -a led_set_cpu_mcon off
5秒間一時停止した後に、LEDとブザーの動作を止めている。
exit 1
終了ステータスに異常を表す「1」を指定。
}
ExitWithError関数はここまで。
**スクリプト本文
ここからがいわゆるInitDisk1.shのスクリプト本体だ。
# Check point 1. disk is already mounted or not.
まずはチェックポイント1としてHDDがすでにマウントされているかいないかを以下で調査している。
サブシェルで走らせている/usr/local/bin/[[kuro_lib]]内の関数「IsMounted」を使うことになる。
ここで述べておく方が理解が容易なので、InitDisk1.shスクリプトの内容ではないが/usr/local/bin/[[kuro_lib]]内のIsMounted関数に触れておく。
>***IsMounted関数
>/usr/local/bin/[[kuro_lib]]内の関数であり、引数を1つ付けさせて内容により戻り値として「0」か「1」を返す仕組みのようだ。
> # $1 : device of check target
> # retval
> # 1 : device $1 is mounted.
> # 0 : device $1 is not mounted.
>第1引数はチェック対象のデバイスであり、このIsMounted関数が戻り値1を返せばそのデバイスはマウントされている、0を返せばされていないとする旨の解説だ。
> IsMounted(){
> MOUNTED=`grep $1 /proc/mounts`
>MOUNTEDという変数を用意しそこにgrep $1 /proc/mountsの結果を代入している。
>$1とはIsMounted関数に付けられた第1引数であり、${DISK1_DEV}すなわち/dev/sdaを指す。
>つまり、[[procコマンド]]でマウント状態を調べたとき、/dev/sdaという文字が含まれるものを抽出していることになる。
>その結果がMOUNTEDという変数に代入される。
> if [ "${MOUNTED}" != "" ] ; then
> return 1
> else
> return 0
> fi
>このMOUNTED変数がカラでなければ戻り値1を返しIsMounted関数を終了、そうでなければ(カラであれば)0を返しIsMounted関数を終了する、という内容。
>この作業で、/dev/sdaがマウントされているかどうかが判別できる。
> return 0
>上のいずれにもあてはまらなければ(実際にはあり得ないが)0を返す。
> }
>IsMounted関数はここまで。
ここからまたスクリプト本文の解説に戻る。
IsMounted ${DISK1_DEV} ; [ $? = 1 ] && ExitWithError mounted
IsMounted ${DISK1_DEV}1 ; [ $? = 1 ] && ExitWithError mounted
IsMounted ${DISK1_DEV}4 ; [ $? = 1 ] && EixtWithError mounted
IsMounted関数に${DISK1_DEV}(=/dev/sda)、${DISK1_DEV}1(=/dev/sda1)、${DISK1_DEV}4(=/dev/sda4)という引数をそれぞれ付け、戻り値は0か1が返ってくるのを待ち、返って来た結果(戻り値「$?」)が1ならばExitWithError関数をmountedという引数を付けて実行している。
/dev/sdaもしくは/dev/sda1、/dev/sda4のいずれか一つでもマウントされていればInitDisk1.shはエラー終了してしまう、ということだ。
誤動作防止のためだと思われる。
これでチェックポイント1であるマウントされているかどうかの調査は終了する。
# Check point 2. disk is already formatted or not.
次にチェックポイント2としてHDDがすでにフォーマットされているかいないかを以下で調査している。
XFS_FORMATTED=`dd if=${DISK1_DEV} bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] && ExitWithError formatted
XFS_FORMATTED=`dd if=${DISK1_DEV}1 bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] && ExitWithError formatted
XFS_FORMATTED=`dd if=${DISK1_DEV}4 bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] && ExitWithError formatted
流れとしては
+XFS_FORMATTEDという変数を用意
+そこに対象となるデバイスのフォーマット形式を代入
+それがxfs形式かどうかを判別
+xfs形式ならばExitWithError関数にformatted引数を付けてエラー処理
となる。
デバイスのフォーマットの調べ方だが、ここでは[[ddコマンド]]で行っている。
[[ddコマンド]]のofパラメータは出力先を指すが、今回これは指定しないのですなわち標準出力を指す。
xfs形式でフォーマットされたデバイス([[パーティション]])は、
>dd if=デバイス bs=1 count=3
とすると
>XFS3+0 records in
>3+0 records out
とコンソールには表示されるが、内部的にはXFSの3文字だけが出力されている(of=/mnt/disk1/dd.txtなどで確認してみるとはっきりする)。
ext3ではXFSは表示されないが、XFS形式のものをmkfs.ext3で上書きした場合はXFSと表示されてしまう。
[[パーティション]]の先頭を0で埋めた後、領域を破壊した上でmkfs.ext3を実行しないと機械的にはXFSとみなされるので注意が必要だ。
上の命令は/dev/sda、/dev/sda1、/dev/sda4のいずれかがxfs形式ならばformattedという引数を付けてExitWithError関数を実行(すなわちエラー処理)する、という意味だ。
# OK! Disk is not mounted and not formatted.
以上、2つのチェックポイントを無事通過できると次の処理が待っている。
**デバイスの初期化
miconapl -a led_set_code_information 28
miconapl -a bz_on button
オレンジのLEDを点滅させ、ブザーをピっと鳴らす。
&bold(){/mnt/mtdにChangeMeDevHDDがある場合}
if [ -e ${CHANGE_TO_DEVHDD_FILE} ] ; then
この「-e」という評価式は「存在すれば真」なので、CHANGE_TO_DEVHDD_FILE(/mnt/mtd/にChangeMeDevHDD)が存在すれば以下を実行、という意味になる。
なお、このChangeMeDevHDDとは、附属CD-ROM内にあるもので「HDD[[パーティション]]を開発用に設定するための意思表示ファイル」となっている。中身は何もない。
この条件分岐のためだけにあり、あるかないかが問題なだけだ。
fdisk ${DISK1_DEV} < /usr/local/bin/PartitionDefinition
/usr/local/bin/PartitionDefinitionに記載されている内容に従って/dev/sdaに[[パーティション]]をきっていく。
記載された内容とは
|[[パーティション]]|サイズ|パーティションタイプ|
|/dev/sda1|50MB|Linux|
|/dev/sda2|3GB|Linux|
|/dev/sda3|128MB|swap|
|/dev/sda4|残り|Linux|
となっている。
次に、きられた[[パーティション]]に今度は[[ファイルシステム]]を導入する。
まずは/usr/local/bin/[[kuro_lib]]内の関数「Format_EXT3」を説明する。
>***Format_EXT3関数
>/usr/local/bin/[[kuro_lib]]内の関数であり、引数一つを受け取りそのデバイスをext3形式にフォーマットする関数のようだ。
> # $1 : target device to format
> Format_EXT3(){
>第1引数のデバイスをフォーマット対象とする。
> echo "***** Starting to format $1 *****"
>画面に「***** Starting to format 対象デバイス *****」と表示する。
> mkfs.ext3 $1
>[[mkfs.ext3コマンド]]で第1引数のデバイスをext3形式でフォーマットする。
> if [ $? -eq 0 ] ; then
>$?とは上の[[mkfs.ext3コマンド]]の実行結果の終了ステータスを指しているのだが、これが「0」すなわち成功ならば次を実行、となっている。
> echo "Format is succeeded without error."
>画面に「Format is succeeded without error.」と表示する。つまり「フォーマットはエラーもなく成功した。」と表示している。
> else
>$?が「0」でなければ、つまりフォーマットに失敗しているのならば次を実行。
> return 1
> exit 1
> fi
>return 1とは、関数の戻り値を1に明示的に指定してFormat_EXT3関数を終了しているわけだが、このスクリプト内で戻り値を具体的に利用する様子は見受けられないので意味はないだろう。
>/usr/local/bin/[[kuro_lib]]は様々なスクリプトで利用されているライブラリ的なスクリプトなので、どこかで利用するものかもしれない。
>exit 1も同じような意味合いだが、終了ステータスを「1」(異常)に設定してスクリプト(/usr/local/bin/[[kuro_lib]])を終了するようにしている。
> return 0
>戻り値「0」をセットしFormat_EXT3関数を抜ける。
> }
>Format_EXT3関数はここまで。
次に/usr/local/bin/[[kuro_lib]]内の関数「Format_XFS」を説明する。
>***Format_XFS関数
>/usr/local/bin/[[kuro_lib]]内の関数であり、引数一つを受け取りそのデバイスをxfs形式にフォーマットする関数のようだ。
> # $1 : target device to format.
> Format_XFS(){
>第1引数のデバイスをフォーマット対象とする。
> KEY=`dd if=$1 bs=1 count=3`
>KEYという変数を用意し、そこにdd if=$1 bs=1 count=3の結果を代入する。
>先ほど検証したようにxfs形式のデバイスに対してこのコマンドを使うと「XFS」と出力される。
> if [ "${KEY}" = "XFS" ] ; then
>KEYの値がXFSならば次を実行、という意味だ。つまりここは対象デバイスのフォーマット形式がxfs形式かどうかを条件分岐にしている。
> . /etc/melco/info
>/etc/melco/infoをサブシェルで走らせているが、標準Linuxにはこのファイルは存在しない。
>製品仕様書にも初期化SWの項目に
>>内蔵HDD(/dev/sda)が既にxfs形式でフォーマットされている場合、フォーマットは行われない。但し、/etc/melco/info内、force_format=yesとすることで、xfsでフォーマットされている/いないにかかわらず、フォーマットを行うようにすることができる。
>と記載されている。強制フォーマットの機能を使うのであれば自分で/etc/melco/infoを用意するしかない。
> if [ "${force_format}" = "yes" ] ; then
>/etc/melco/info内の「force_format」項目が「yes」となっていれば以下を実行。
> echo "Disk (or partition) is looks like already formatted."
> echo "If you stop format, Press Ctrl+C in 10 seconds!!!"
>画面に「Disk (or partition) is looks like already formatted.If you stop format, Press Ctrl+C in 10 seconds!!!」と表示。
>「ディスク(あるいは[[パーティション]])は既にフォーマットされているようです。フォーマットを中止する場合は10秒以内にCtrl+Cを押してください」という意味。
> COUNTER=10
>COUNTERという変数を用意し、そこに10を代入。
> echo -n "waiting "
>画面に「waiting」と表示。-nオプションは「テキストの行末で改行しない」という意味。
> while [ ${COUNTER} -gt 0 ]
>COUNTER変数が0より大きければdo~doneの内容を繰り返す。
> do
> echo -n "."
> sleep 1
> COUNTER=$((${COUNTER} - 1))
> done
>「waiting」の行末に「.」を表示し、1秒待った後COUNTER変数から1を引く、という内容。
>先のwhile条件から、1を引いた結果が0よりも大きければ同じことを繰り返す、ということなので、これで結果的に10秒間待機することになる。
>「.」を1秒ごとに表示させるためにwhile文を使ったのだろう。
> echo ""
> echo "OK, go on formatting."
>echoで空白を表示、これは改行させる目的で、次に「OK, go on formatting.」を表示させている。
> else
>/etc/melco/info内の「force_format」項目が「yes」となっていなければ以下を実行。
> return 0
>戻り値を「0」に設定しFormat_XFS関数を抜ける。つまりこの関数内の以後の命令は実行しない。
> fi
> fi
>if [ "${force_format}" = "yes" ]を抜け、すぐ次にif [ "${KEY}" = "XFS" ]も抜けている。
> echo "***** Cleaning Disk partition information *****"
>画面に「***** Cleaning Disk partition information *****」と表示。
> dd if=/dev/zero of=$1 bs=512 count=1
>[[ddコマンド]]を使ってデバイスの先頭から512バイトに「0」を書き込んでいる。
>要するにそのデバイス([[パーティション]])を先頭から512バイト分データを消去している。
> echo "***** Starting to format $1 *****"
>画面に「***** Starting to format 対象デバイス *****」と表示。
> mkfs.xfs $1 -f
>デバイスを[[mkfs.xfsコマンド]]でxfs形式にフォーマットしている。-fは上書きオプション。
> if [ $? -eq 0 ] ; then
>終了ステータスが0であれば、つまり上の[[mkfs.xfsコマンド]]がエラーでなければ以下を実行。
> echo "Format is succeeded without error."
>画面に「Format is succeeded without error.」と表示。
> else
>mkfs.xfsでエラーが発生すれば
> return 1
> exit 1
> fi
>戻り値を1、終了ステータスを1に設定して終了。
> return 0
>戻り値を0に設定しFormat_XFS関数を抜ける。
> }
>Format_XFS関数はここまで。
これら関数を使って[[ファイルシステム]]を導入する命令が以下。
Format_EXT3 ${DISK1_DEV}1
Format_XFS ${DISK1_DEV}2
Format_XFS ${DISK1_DEV}4
mkswap ${DISK_DEV}3
わかりやすく表にすれば
|デバイス|フォーマット形式|
|/dev/sda1|ext3|
|/dev/sda2|xfs|
|/dev/sda3|swap|
|/dev/sda4|xfs|
という意味だが、
>mkswap ${DISK_DEV}3
は上の[[パーティション]]の様子からすると
>mkswap ${DISK1_DEV}3
でなければならないはずだ。開発用Linuxのfstabで/dev/sda3をswapでマウントしようとしても、フォーマットが完了していないため失敗するだろう。
/usr/local/sbin/SetupDevEnv.sh
そして、/usr/local/sbin/[[SetupDevEnv.sh]]を実行する。詳細は[[SetupDevEnv.sh]]の項目で説明する。
その後、miconapl -a led_set_code_information clearを実行してInitDisk1.shを終了する。
&bold(){/mnt/mtdにChangeMeDevHDDがない場合}
else
CHANGE_TO_DEVHDD_FILE(/mnt/mtd/にChangeMeDevHDD)が存在しなければ以下を実行。
fdisk ${DISK1_DEV} < /usr/local/bin/PartitionDefinition1
/dev/sdaを/usr/local/bin/PartitionDefinition1に従って[[パーティション]]分割作業する。
|[[パーティション]]|サイズ|パーティションタイプ|
|/dev/sda1|すべて|Linux|
という内容だ。
Format_XFS ${DISK1_DEV}1
Format_XFS関数で/dev/sda1をxfs形式にフォーマット。
MountShare ${DISK1_DEV} ${DISK1_MPT}
MountShare関数に
|第1引数|/dev/sda|
|第2引数|/mnt/disk1|
という引数を付けて実行させている。
ここで/usr/local/bin/[[kuro_lib]]内のMountShare関数を説明する。
>***MountShare関数
>/usr/local/bin/[[kuro_lib]]内の関数。4つまでの引数に対応し、3つの戻り値を設定できる。
> # $1 : target device to mount.
> # $2 : target mountpoint of $1.
> # $3 : File system of target device(default is xfs).
> # $4 : Mounted device permission(default is 777).
> MountShare(){
>第1引数にマウントする対象デバイス、第2引数に対象デバイスのマウント先、第3引数に対象デバイスの[[ファイルシステム]](初期値はxfs形式)、第4引数にマウントしたデバイスのパーミッション(初期値は777)、という解説。
> # ret 0 : this is no partition disk.
> # ret 1 : this is nand share type partition
> # ret 2 : this is developkit type partition (maybe)
>MountShare関数の戻り値ではない。IsHavePartition関数からの戻り値を説明している。
>戻り値「0」で「[[パーティション]]が存在しないディスクです」、「1」で「NANDフラッシュ共有時(つまり標準Linux時)の[[パーティション]]です」、「2」で「(おそらく)開発用Linux時の[[パーティション]]です」と、それぞれ意味する。
> if [ "$1" = "/dev/sda" -o "$1" = "/dev/sdb" ] ; then
>第1引数が/dev/sdaあるいは/dev/sdbであれば以下を実行。
> IsHavePartition $1
>/usr/local/bin/[[kuro_lib]]内のIsHavePartition関数に第1引数を付けて実行している。
>ここでIsHavePartition関数を説明する。
>>***IsHavePartition関数
>> # $1 : target device to check partition
>>第1引数にパーティション状態をチェックする対象デバイス、という解説。
>> # ret 0 : this is no partition disk.
>> # ret 1 : this is nand share type partition
>> # ret 2 : this is developkit type partition (maybe)
>>戻り値「0」で「[[パーティション]]が存在しないディスクです」、「1」で「NANDフラッシュ共有時(つまり標準Linux時)の[[パーティション]]です」、「2」で「(おそらく)開発用Linux時の[[パーティション]]です」と、それぞれ意味する。
>> IsHavePartition(){
>> if [ -x ${HEXDUMP} ] ; then
>>HEXDUMP変数(=/usr/bin/hexdump)に-xオプションを付けて条件としている。-xオプションは「存在し、かつ実行可能なら真」という意味なので、ここでは「/usr/bin/hexdumpが存在し、かつ実行可能なら次を実行」という意味になる。
>> DISK_1_PART_TAIL=`hexdump -s 446 -n 64 -e '8/1 "%02x " 2/4 "%10d " "\n"' $1 | sed -n "1p"|awk '{print $10}'`
>>DISK_1_PART_TAILという変数を用意し、そこにhexdump -s 446 -n 64 -e '8/1 "%02x " 2/4 "%10d " "\n"' $1 | sed -n "1p"|awk '{print $10}'という内容を代入している。
>>パイプで3つの命令がつながっているが、それぞれに分けて考えてみる。
>>
>>&bold(){hexdump}
>>>hexdump -s 446 -n 64 -e '8/1 "%02x " 2/4 "%10d " "\n"' $1
>>[[hexdumpコマンド]]を使っている。先頭から446バイト読み飛ばした所から64バイト分だけを読み込み、それを「8/1 "%02x " 2/4 "%10d " "\n"」というフォーマットで第1引数のデバイスを表示する、という意味になる。
>>HDDの先頭512バイトはMBR領域となっており、その中の先頭446バイトから64バイトはパーティションテーブルが4エントリ分(1エントリ16バイト)ある。
>>つまりここでは4つのパーティションテーブルを読み込んだことになる。
>>次に、詳細は[[hexdumpコマンド]]で説明するが、「繰り返し回数/バイト数 "フォーマット"」の羅列が[[hexdumpコマンド]]のフォーマット形式なので、この場合は
>>>8回繰り返し/1バイト "フィールド幅2(2桁表示で満たない桁は0で表示)で16進数変換"
>>>2回繰り返し/4バイト "フィールド幅10(10桁表示で満たない桁は空白で表示)で10進数変換"
>>>改行
>>という内容になる。
>>つまり、「1バイトづつ8回、4バイトづつ2回、計16バイトを10回にわけて読み込み、それを4行に出力」という内容だ。
>>パーティションテーブルを1つ読み込んでは改行し、64バイト分すべてを16バイトづつ4行10フィールドで表現している。
>>4つの[[パーティション]]を切ったHDDで試してみると以下の結果を得た。
>>>00 01 01 00 83 fe 3f 06 63 112392
>>>00 00 01 07 83 fe 7f 74 112455 5879790
>>>00 00 41 75 82 fe 7f 85 5992245 273105
>>>00 00 41 86 83 fe ff ff 6265350 150031035
>>
>>&bold(){sed}
>>>sed -n "1p"
>>「-n」オプションで[[hexdumpコマンド]]から受け取った結果の1行目(pが行を表す)だけを抽出している。
>>ここの「1p」が「2p」「3p」「4p」と変化していくのは、それぞれパーティションテーブルを1から4まで読み、該当パーティションテーブル以外を破棄している。
>>先ほどの例で試すと
>>>00 01 01 00 83 fe 3f 06 63 112392
>>という結果を得る。
>>
>>&bold(){awk}
>>>awk '{print $10}'
>>[[sedコマンド]]から受け取った行の第10フィールドの値を出力している。
>>第10フィールドはLBAの[[パーティション]]総セクター数(4バイト)を意味する。
>>つまり、最終的にDISK_1_PART_TAIL変数に代入したい値とは、各[[パーティション]]の総セクター数であることがわかる。これは[[hexdumpコマンド]]で10進数にされている。
>> DISK_2_PART_TAIL=`hexdump -s 446 -n 64 -e '8/1 "%02x " 2/4 "%10d " "\n"' $1 | sed -n "2p"|awk '{print $10}'`
>> DISK_3_PART_TAIL=`hexdump -s 446 -n 64 -e '8/1 "%02x " 2/4 "%10d " "\n"' $1 | sed -n "3p"|awk '{print $10}'`
>> DISK_4_PART_TAIL=`hexdump -s 446 -n 64 -e '8/1 "%02x " 2/4 "%10d " "\n"' $1 | sed -n "4p"|awk '{print $10}'`
>>先ほどと同様な処理を各[[パーティション]]ごとにDISK_パーティション番号_PART_TAILという変数に代入している。
>>例で試すと
>>>112392
>>という結果。
>>総セクター数が0であればその[[パーティション]]は存在しない、という意味になる。
>> if [ "${DISK_1_PART_TAIL}" -ne 0 -a "${DISK_2_PART_TAIL}" -eq 0 -a "${DISK_3_PART_TAIL}" -eq 0 -a "${DISK_4_PART_TAIL}" -eq 0 ] ; then
>>-第1パーティションの総セクター数が0ではない
>>-かつ第2~4パーティションの総セクター数が0
>>の場合に以下を実行する。
>> return 1
>>戻り値「1」を設定し関数を抜ける。
>>つまり「this is nand share type partition」ということになる。
>> elif [ "${DISK_1_PART_TAIL}" -ne 0 -a "${DISK_2_PART_TAIL}" -ne 0 -a "${DISK_3_PART_TAIL}" -ne 0 -a "${DISK_4_PART_TAIL}" -ne 0 ] ; then
>>-第1~4パーティションの総セクター数が0ではない
>>の場合に以下を実行。
>> return 2
>>戻り値「2」を設定し関数を抜ける。
>>つまり「this is developkit type partition (maybe)」ということだ。
>> else
>>それ以外の場合、つまり
>>-第1パーティションの総セクター数が0
>>の場合に以下を実行。
>> return 0
>>戻り値に「0」を設定し関数を抜ける。
>>つまり「this is no partition disk.」ということになる。
>> fi
>>[[パーティション]]総セクター数の条件分岐を終了する。
>> else
>>「/usr/bin/hexdumpが存在し、かつ実行可能」ではない場合は以下を実行、という意味。
>> return 0
>>戻り値に「0」を設定し関数を抜ける。
>>つまり「this is no partition disk.」ということになる。
>> fi
>>「/usr/bin/hexdumpが存在し、かつ実行可能」という条件分岐を終了する。
>> return 0
>>いずれにもあてはまらなかった場合、戻り値に「0」を設定し関数を抜ける。
>>つまり「this is no partition disk.」ということになる。
>> }
>>IsHavePartition関数はここまで。
>ここからまたMountShare関数に戻る。
> RET=$?
>RETという変数を用意し、そこにIsHavePartition関数の戻り値を代入。
> [ "${RET}" -eq 1 ] && TARGET_DEV=${1}1
> [ "${RET}" -eq 2 ] && TARGET_DEV=${1}4
> [ "${RET}" -eq 0 ] && TARGET_DEV=${1}
>-戻り値が1ならば、TARGET_DEV変数にMountShare関数に付けた第1引数(if文の関係上、/dev/sdaか/dev/sdb)の第1[[パーティション]]を代入する。
>-戻り値が2ならば、TARGET_DEV変数にMountShare関数に付けた第1引数(if文の関係上、/dev/sdaか/dev/sdb)の第4[[パーティション]]を代入する。
>-戻り値が0ならば、TARGET_DEV変数にMountShare関数に付けた第1引数(if文の関係上、/dev/sdaか/dev/sdb)を代入する。
>というように処理している。
> else
>MountShare関数に付けた第1引数が/dev/sdaでも/dev/sdbでもなければ以下を実行。
> TARGET_DEV=$1
>TARGET_DEV変数にMountShare関数に付けた第1引数を代入。
> fi
>MountShare関数に付けた第1引数が/dev/sdaか/dev/sdbか、という条件分岐を抜ける。
> IsMounted ${TARGET_DEV}
>IsMounted関数に第1引数としてTARGET_DEV変数を渡す。先ほど説明したとおり、戻り値「1」で「device is mounted.」、戻り値「0」で「device $1 is not mounted.」という意味になる。
> if [ $? = 1 ] ; then
>戻り値が「1」ならば、つまり「device is mounted.」という意味ならば次を実行。
> echo "${TARGET_DEV} is already mounted."
>画面上に「対象デバイス is already mounted.」と表示。
> return 1
>戻り値「1」を設定しMountShare関数を抜ける。
> fi
>IsMounted関数の戻り値による条件分岐を抜ける。
> if [ "$3" = "" ] ; then
>MountShare関数の第3引数が何もなければ以下を実行する。
> FS=xfs
>FSという変数を用意し、そこにxfsを代入する。
> else
>MountShare関数の第3引数に何かあれば以下を実行する。
> FS=$3
>FSという変数を用意し、そこにその第3引数を代入する。
> fi
>MountShare関数の第3引数の有無の条件分岐を抜ける。
> if [ "$4" = "" ] ; then
>MountShare関数の第4引数が何もなければ以下を実行する。
> PERMISSION=777
>PERMISSIONという変数を用意し、そこに777を代入する。
> else
>MountShare関数の第4引数に何かあれば以下を実行する。
> PERMISSION=$4
>PERMISSIONという変数を用意し、そこにその第4引数を代入する。
> fi
>MountShare関数の第4引数の有無の条件分岐を抜ける。
> echo "Mounting ${TARGET_DEV} on $2 as a ${FS} file system."
>画面上に「Mounting 対象デバイス(MountShare関数の第1引数) on マウントポイント( MountShare関数の第2引数) as a ファイルシステムタイプ(MountShare関数の第3引数) file system.」と表示する。
> mount -t ${FS} ${TARGET_DEV} $2
>実際に設定した変数の値をもとに[[mountコマンド]]でマウントする。
> case $? in
>[[mountコマンド]]の終了ステータスをもとに実行内容を変える。
> 0)
>
>&bold(){終了ステータス「0」(正常)の場合}
> chmod ${PERMISSION} $2
> echo "Success."
> ;;
>[[chmodコマンド]]で設定したパーミッションでマウントポイントのデバイスを指定し、画面上に「Success.」と表示してcase文を抜ける。
> *)
>
>&bold(){終了ステータス「1」(異常)の場合}
> echo "Failed."
> return 1
> ;;
>画面上に「Failed.」と表示して、戻り値「1」を設定しMountShare関数を抜ける。
> esac
>case文はここまで。
> echo ""
>
> return 0
>画面上を改行して戻り値「0」を設定しMountShare関数を抜ける。
> }
>MountShare関数はここまで。
fi
CHANGE_TO_DEVHDD_FILE(/mnt/mtd/にChangeMeDevHDD)の有無の条件分岐を抜ける。
miconapl -a led_set_code_information clear
LEDの点滅を止める。
----
表示オプション
横に並べて表示:
変化行の前後のみ表示: