FRU情報領域の復旧方法

# はじめに

多数のノードをipmiで管理する場合、シリアル番号や型番などをipmitoolやipmiutilで取得する場面は多々あると思います。しかし、なんらかの障害で正しくFRUの情報が取得できない場合、直接書き込むことが可能です。(保守がある場合はベンダーにBMC等の交換を依頼しましょう)

# ipmiutilを使用する場合

コマンドラインオプションの、`-a`, `-s` もしくは、`-v` などを使用することで、一部の情報を書き込むことができます。

```
$ ipmiutil fru --help
ipmiutil ver 3.01
ifru: version 3.01
fru: invalid option -- '-'
Usage: ifru [-bceikmtvx -a asset_tag -s ser_num -NUPREFTVY]
   -a tag   Sets the Product Asset Tag
   -b       Only show Baseboard FRU data
   -c       show canonical, delimited output
   -d file  Dump the binary FRU data to a file
   -e       walk Every child FRU, for blade MCs
   -i 00    Get a specific FRU ID
   -k       Kontron setsn, setmfgdate
   -m002000 specific MC (bus 00,sa 20,lun 00)
   -s snum  Sets the Product Serial Number
   -v pver  Sets the Product Version Number
   -x       Display extra debug messages
       -N node  Nodename or IP address of target system
       -U user  Username for remote node
       -P/-R pswd  Remote Password
       -E   use password from Environment IPMI_PASSWORD
       -F   force driver type (e.g. imb, lan2)
       -J 0 use lanplus cipher suite 0: 0 thru 14, 3=default
       -T 1 use auth Type: 1=MD2, 2=MD5(default), 4=Pswd
       -V 2 use priVilege level: 2=user(default), 4=admin
       -Y   prompt for remote password
       -Z   set slave address of local MC
ipmiutil fru, usage or help requested
```

一般的に、FRUの情報自体に不整合が無い場合は、上記のコマンドだけで十分でしょう。ただし、FRU情報領域のヘッダ等が破損している場合は厄介です。
以下のように ipmitool では表示すらできません。

```
$ ipmitool -U admin -P admin -H xxx.xxx.xxx.xxx fru print 0
 Unknown FRU header version 0x1a
```

ipmiutil では、もう少し情報が取得できますが、オーバーフローや一部文字化けなどを起こして、破損していることがわかります。

```
$ ipmiutil fru -U admin -P admin -N xxx.xxx.xxx.xxx -J 1
ipmiutil ver 3.01
ifru: version 3.01
Opening lanplus connection to node xxx.xxx.xxx.xxx ...
-- BMC version 1.22, IPMI version 2.0
--- Scanning SDR Repository for 60 SDRs ---
SDR[0000] IPMB 20 00 00 01 AST2300
[Baseboard,20,00] Baseboard FRU Size  : 256
[Baseboard,20,00] Chassis Type        : Laptop
  ERROR - FRU Buffer Overflow (547 >= 256), last len=0
[Baseboard,20,00] Board Mfg DateTime  : Mon Jan  1 00:00:00 1996
[Baseboard,20,00] Board Manufacturer  :
[Baseboard,20,00] Board Product Name  :
[Baseboard,20,00] Board Serial Number :
[Baseboard,20,00] Board Part Number   :
[Baseboard,20,00] Board FRU File ID   :
[Baseboard,20,00] Board OEM Field     :
[Baseboard,20,00] Product Manufacturer:
[Baseboard,20,00] Product Name        :
[Baseboard,20,00] Product Part Number :
[Baseboard,20,00] Product Version     :
[Baseboard,20,00] Product Serial Num  : #ｯGFX355367789990396ﾋ31S
[Baseboard,20,00] Product Asset Tag   : xxxxxxxxxxxxxxxxxxxxxxxxxx
[Baseboard,20,00] Product FRU File ID : 3415012
[Baseboard,20,00] Product OEM Field   : 0000c13600000xxxxxxxxxx000000
```

その場合、ipmiutil に含まれる、`ifruset` コマンドで修復できる可能性があります。`ifruset` は通常はインストールされません。手動でmakeする必要があります。

```bash
tar xvf ipmiutil-3.0.1.tar.gz
cd ipmiutil-3.0.1
make && make install

cd util
make ifruset
```

これで準備は完了しました。実行ファイルが生成されているかと思います。

```
$ ls -la ifruset
-rwxr-xr-x 1 root root 648926 Jun  8 10:15 ifruset
```

`ifruset` でも、個々のフィールドのアップデートは可能ですが、既にヘッダ領域が破損していると、オフセットが正しく計算できず、書き込みに失敗してしまいます(実際には、事前チェックではじかれます)。そのため、FRUの情報領域（256Byte）をまるごとダンプ・リストアすることで復旧します。

FRU領域の詳細は、IntelのWebサイトに仕様書がありますので、そちらを参考にします。”FRU intel spec”などで検索すると、pdfが見つかると思います。

まずは、コマンドの詳細を確認しましょう。
`-u/-n/-p/-v` などのコマンド以外に、`-d`(ダンプ) および `-r` (リストア) が使用可能です。

```
$ ./ifruset -h
ifruset: version 3.01
./ifruset: option requires an argument -- 'h'
Usage: ifruset [-bcimx -unpvsafo -NUPREFTVY]
   -u manu  Sets Product Manufacturer (0)
   -n name  Sets Product Name         (1)
   -p part  Sets Product Part Number  (2)
   -v vers  Sets Product Version      (3)
   -s snum  Sets Product Serial Num   (4)
   -a tag   Sets Product Asset Tag    (5)
   -f fru   Sets Product FRU File ID  (6)
   -o oem   Sets Product OEM Field    (7)
   -b       Only show Baseboard FRU data
   -c       show Canonical, delimited output
   -d       Dump FRU to a file
   -r       Restore FRU from a file
   -i 00    Get/Set a specific FRU ID
   -m002000 specific MC (bus 00,sa 20,lun 00)
   -x       Display extra debug messages
       -N node  Nodename or IP address of target system
       -U user  Username for remote node
       -P/-R pswd  Remote Password
       -E   use password from Environment IPMI_PASSWORD
       -F   force driver type (e.g. imb, lan2)
       -J 0 use lanplus cipher suite 0: 0 thru 14, 3=default
       -T 1 use auth Type: 1=MD2, 2=MD5(default), 4=Pswd
       -V 2 use priVilege level: 2=user(default), 4=admin
       -Y   prompt for remote password
       -Z   set slave address of local MC
ifruset, usage or help requested
```

仕様書によると、FRU領域の先頭8バイトは以下のようになっています。

```
1バイト目: 共通ヘッダ領域のバージョン（上位4bitは0000bで固定、下位4bitがバージョン番号）
2バイト目: 内部使用領域のオフセットを8で割った値（00は未使用を意味する）
3バイト目: シャーシ情報領域のオフセットを8で割った値（00は未使用を意味する）
4バイト目: ボード情報領域のオフセットを8で割った値（00は未使用を意味する）
5バイト目: 製品情報領域のオフセットを8で割った値（00は未使用を意味する）
6バイト目: マルチレコード情報領域のオフセットを8で割った値（00は未使用を意味する）
7バイト目: 00h 固定
8バイト目: ゼロチェックサム（8バイトの合計が00になる）
```

では、破損したFRUのダンプを見てみましょう。

```
$ od -t x1 /tmp/fru.bin
0000000 1a 00 44 1e 03 13 00 00 00 00 00 00 00 00 00 00
0000020 20 43 68 61 73 73 69 73 c1 00 00 c0 c0 c0 c0 e1
```

1バイト目から、完全に仕様書と異なることがわかります。0x44では8倍すると、256バイトを超えてしまい、オフセットエラーが発生します。当然、シリアル番号等を書き込もうも、エラーとなります。

以下は正常なFRUのダンプです。チェックサムも当然正常です。

```
0000000 01 00 01 04 0b 00 00 ef 01 03 17 00 00 ca 58 33
0000020 20 43 68 61 73 73 69 73 c1 00 00 00 00 00 00 e1

# チェックサムの確認（00になること）
$ echo "01 00 01 04 0b 00 00 ef" | tr " " "\n" | awk '{ s += strtonum("0x"$1) } END { printf "%02x\n", s % 256 } '
00
```

あとは、何らかの方法で各種情報を復旧し、`-r` でリストアすれば復旧完了です。一番簡単なのは、正常なノードからダンプした情報を書き込むことですが、シリアル番号などが同じになっていまうので、書き換えが必要になります。また、チェックサムも計算しなおす必要があります。
各領域の最後の１バイトがチェックサムになっているので、仕様書を参考にしながらリストア用のバイナリファイルを作成すると良いでしょう。

# さいごに
このような状態になるのは非常に稀なことです。保守がある場合はサポートを受けましょう。逆に、上記のような書き換えを実施すると、保守を受けられなくなる可能性が高いでしょう。くれぐれも自己責任でお願いします。