ASUS IPMI EXPANSION CARD

ASUS IPMI EXPANSION CARDBIOSTAR B550GTAに挿してみたところ普通に使えたので備忘録。

用意するのはマザーボードに内部USB 2.0ポートの空きが一つ、マザーボードと筐体の電源・リセットピンをIPMI EXPANSION CARDに接続するためのケーブル。

ハードウェアのセットアップなどはマニュアルに記載されているとおりなので略。

BMC LANはデフォルトではDHCPIPv4アドレスを取得しようとするのでtcpdumpを使うなりDHCPサーバを参照するなりしてBMC LANのIPv4アドレスを確認する。IPv6もデフォルト有効になっているのでそちらを使うのでも良い。 マニュアルを見るとジャンパピンでBMC LANのIPv4アドレスを10.10.10.10に固定する設定もあるようだが試したことは無い。

電源にケーブルを挿して電源のスイッチをオンにした後、一分程度待ってからブラウザでBMCにHTTPSで接続するとWeb UIにアクセスできる。 注意:このときに筐体の電源ボタンで本体の電源をオンにしないこと。筐体の電源ボタンを押して電源を入れようとすると電源が入らない、且つBMCの電源制御が失敗するようになる気がする。謎。

試したこと:

  • NetBSDの起動。起動した。ただしipmi(4)は認識していない。
  • Remote Control
    • H5Viewer
      • キーボード。動作した、ただしシフトキーを押しているのに効いていない
  • Power Control
    • Power Cycle。動作した。
    • ACPI Shutdown。動作した。
  • ipmitool
    • マニュアルに記載されているView BMC informationを取得するコマンドを試してみたところ動作した。

2022/10/10時点の問題: * Firefoxを使ったときにH5Viewerでシフトキーの入力が効かない。Chromeなどで同様の問題が発生するかは不明。 * 筐体の電源ボタンを押して電源を入れようとすると電源が入らない、且つBMCの電源制御が失敗するようになる気がする。

NetBSD dmesg抜粋

pci3 at ppb2 bus 3
pci3: i/o space, memory space enabled, rd/line, wr/inv ok
ppb3 at pci3 dev 0 function 0: ASPEED Technology AST1150 PCIe-to-PCI bridge (rev. 0x06)
ppb3: PCI Express capability version 2 <PCI-E to PCI/PCI-X Bridge>
pci4 at ppb3 bus 4
pci4: i/o space, memory space enabled, rd/line, wr/inv ok
genfb0 at pci4 dev 0 function 0: ASPEED Technology ASPEED Graphics Family (rev. 0x52)
genfb0: framebuffer at 0xe8000000, size 1024x768, depth 32, stride 4096
genfb0: shadow framebuffer enabled, size 3072 KB
wsdisplay0 at genfb0 kbdmux 1: console (default, vt100 emulation)
wsmux1: connecting to wsdisplay0
drm at genfb0 not configured
ASPEED Technology product 2402 (IPMI serial bus, keyboard, revision 0x01) at pci4 dev 1 function 0 not configured
...
uhub6 at uhub1 port 10: American Megatrends Inc. (0x046b) Virtual Hub (0xff01), class 9/0, rev 2.00/1.00, addr 1
uhub6: single transaction translator
uhub6: 7 ports with 7 removable, self powered
cdce0 at uhub6 port 3 configuration 2 interface 0
cdce0: American Megatrends Inc. (0x046b) Virtual Ethernet. (0xffb0), rev 2.00/1.00, addr 2
cdce0: Ethernet address XX:XX:XX:XX:XX:XX
uhidev0 at uhub6 port 4 configuration 1 interface 0
uhidev0: American Megatreds Inc. (0x046b) Virtual Keyboard and Mouse Gadget (0xff10), rev 2.00/5.04, addr 3, iclass 3/1
ums0 at uhidev0: 3 buttons and Z dir
wsmouse0 at ums0 mux 0
uhidev1 at uhub6 port 4 configuration 1 interface 1
uhidev1: American Megatreds Inc. (0x046b) Virtual Keyboard and Mouse Gadget (0xff10), rev 2.00/5.04, addr 3, iclass 3/1
ukbd0 at uhidev1
wskbd0 at ukbd0: console keyboard, using wsdisplay0

Twitter投稿へのリンク:

nvme(4) ベンチマーク

人から Intel SSD 750 400GB や Intel SSD 750 800GB を二枚借りたり、自分でも既に SAMSUNG SM951 NVMe 128GB を持っているのに SAMSUNG SM950 PRO 256GB と SAMSUNG SM951 NVMe 256GB を買ったりしたので、ベンチマークを取ってみたり。

注意

この記事はディスクのベンチマークですが、残念ながら水晶雫さんは登場いたしません。

環境

パーツ 品名
CPU Intel Core i7-6700
M/B Shuttle SH170R6
OS NetBSD/amd64 HEAD (20160507)

Shuttle SH170R6 は PCIe 3.0 x16、PCIe 3.0 x4 スロット各一本と M.2 (PCIe 3.0 x4) スロットが一つあります。

チップセットは H170 なので PCIe 3.0 x16 は CPU 直結、それ以外の PCIe 3.0 x4 と M.2 はチップセット側のものだと思われます。

dmesg は http://dmesgd.nycbug.org/index.cgi?do=view&id=2966 を参照。

ベンチマーク結果

面倒なので同じベンチマークを何回も実行していません。一発勝負です。

dd

if, of 以外のパラメータは dd bs=1g count=100

SSD Slot Read Write 備考
Intel SSD 750 400GB PCIe 3.0 x16 2213718093 (2111MB/s) 933794101 (890MB/s)
Intel SSD 750 400GB PCIe 3.0 x4 2209572639 (2107MB/s) 937765785 (894MB/s)
SAMSUNG SM951 256GB M.2 2479715997 (2364MB/s) 1056073710 (1007MB/s)
SAMSUNG SM951 128GB M.2 (PCIe 2.0 x 2) 835018410 (796MB/s) 601738300 (573MB/s) Mouse LB-J300X

その他

このベンチマークもやってくれとかありましたらコメントなり Twitter の @nonakap にお願いします。

Xnp2 更新

Xnp2 ver.0.85 をリリースしました。

ver.0.85 更新内容

X11 依存部
  • 環境によってサウンドの設定を変更した後にリセットするとプログラムがクラッシュする不具合を修正
  • SDL 2.0 サポート追加
    SDL 2.0 → SDL 1.2 の順番でライブラリを検索するので SDL 1.2 を明示的に使用したい場合には configure のオプションに --disable-sdl2 を指定する必要があります。
  • SDL audio のバックエンドとして PulseAudio を使用している場合に音が正常に鳴らない不具合を修正
  • SPFM Light、C86BOX サポート追加。SPFM Light+Re:birth(RE1-YM2608) と C86BOX+PC-9801-86 の組み合わせで動作確認済みです。
    なお、C86BOX を使用するには libusb 1.0 が必要です。

とりあえず ver.0.84 リリース時に書いたリストの半分は実現できたのでよしとしましょう(棒

次のリリースでは GTK+ 2.x と SDL 1.2 のサポートを切りたいと思います、思っています、出来たら良いなぁ…。

NetBSD で USB デバイスを強制的に ugen(4) として attach したい

通常は uftdi(4) とか uhid(4) として認識される USB デバイスを ugen(4) として認識させたい事ってありませんか?

そうですか、ありませんか…。

はじめに

これは「NetBSD でも YubiKey を使って二要素認証したい」の以下の文章を説明するための記事です。

ここで ukbd(4) が attach されていないと動作モードの変更が必要になるのですが、素の NetBSD カーネルだと動作モードの変更が難しいので後述することにします、しないかもしれません。

なんで ugen(4) にしたいの?

まずは libusb のソースを見てもらおうか。話はそれからだ。

int
netbsd_get_device_list(struct libusb_context * ctx,
    struct discovered_devs **discdevs)
{
    struct libusb_device *dev;
    struct device_priv *dpriv;
    struct usb_device_info di;
    unsigned long session_id;
    char devnode[16];
    int fd, err, i;

    usbi_dbg("");

    /* Only ugen(4) is supported */
    for (i = 0; i < USB_MAX_DEVICES; i++) {
        /* Control endpoint is always .00 */
        snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i);

libusb を使えばデバイスドライバを書かなくてもユーザーランドプログラムから USB デバイスを制御できるのですが、残念ながら NetBSD 上では libusb は上記ソースに記載されている通り ugen(4) として認識されている USB デバイスしか扱えないのです。

そんな訳で uhid(4) や ukbd(4) として認識されている YubiKey 4 を libusb 経由で YubiKey を制御する ykpersonalize や ykinfo といったプログラムは制御する以前にそもそも YubiKey デバイスを見つけられません。

nonaka@koharu$ dmesg
(snip...)
uhidev2 at uhub2 port 1 configuration 1 interface 0
uhidev2: Yubico Yubikey NEO OTP+U2F, rev 2.00/3.43, addr 6, iclass 3/1
ukbd1 at uhidev2: 8 modifier keys, 6 key codes
wskbd2 at ukbd1 mux 1
wskbd2: connecting to wsdisplay0
uhidev3 at uhub2 port 1 configuration 1 interface 1
uhidev3: Yubico Yubikey NEO OTP+U2F, rev 2.00/3.43, addr 6, iclass 3/0
uhid0 at uhidev3: input=64, output=64, feature=0
nonaka@koharu$ sudo ykinfo -v
Yubikey core error: no yubikey present

本来ならば ukbd(4) などの USB デバイスドライバはすべからく ugen(4) として振る舞えるべき、もしくはインタフェースを持つべきだとは思うのですが、それを実現するにはちょっと長い道のりとなります。

なのでここではデバイスドライバの match/attach 処理に小細工をして、USB デバイスを接続した際に正しいデバイスドライバではなく ugen(4) として認識させようとします。

デバイスドライバ match/attach 処理

もの凄くざっくりとした説明

NetBSD ではあるバス(PCI とか USB とか)に接続されているデバイスドライバを attach する際には、該当バスに接続できるすべてのデバイスドライバの match 関数を呼び出します。

match 関数は PCI や USB であれば Vendor ID, Product ID といったバス固有の情報を受け取り、その情報から該当デバイスドライバで取り扱うデバイスであると判断したら match 関数の戻り値として 1 以上の整数値を返します。

全てのデバイスドライバの match 関数を呼び終わった後で 0 では無い一番大きな値を返したデバイスドライバの attach 関数を呼び出してデバイスドライバを attach します。

まあ、要するに ugen(4) として attach してほしいデバイスには ugen(4) の match 関数で他のデバイスドライバよりも大きな値を戻り値として返せば良いだけです。

USB スタック固有事情

実は USB スタックでは この match 関数で返すべき値が用意されています。

/* Match codes. */
#define UMATCH_HIGHEST                 15
/* First five codes is for a whole device. */
#define UMATCH_VENDOR_PRODUCT_REV          14
#define UMATCH_VENDOR_PRODUCT              13
#define UMATCH_VENDOR_DEVCLASS_DEVPROTO            12
#define UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO       11
#define UMATCH_DEVCLASS_DEVSUBCLASS            10
/* Next six codes are for interfaces. */
#define UMATCH_VENDOR_PRODUCT_REV_CONF_IFACE        9
#define UMATCH_VENDOR_PRODUCT_CONF_IFACE        8
#define UMATCH_VENDOR_IFACESUBCLASS_IFACEPROTO      7
#define UMATCH_VENDOR_IFACESUBCLASS             6
#define UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO  5
#define UMATCH_IFACECLASS_IFACESUBCLASS             4
#define UMATCH_IFACECLASS               3
#define UMATCH_IFACECLASS_GENERIC           2
/* Generic driver */
#define UMATCH_GENERIC                  1
/* No match */
#define UMATCH_NONE                     0

という訳で他のデバイスとして attach して貰いたくない場合には ugen(4) で該当デバイスの場合に UMATCH_HIGHEST を返すようにすれば良いという事になります。

ugen(4) match 関数

それでは ugen(4) の match 関数である ugen_match() 関数を見てみましょう。

/* toggle to control attach priority. -1 means "let autoconf decide" */
int ugen_override = -1;

int
ugen_match(device_t parent, cfdata_t match, void *aux)
{
    struct usb_attach_arg *uaa = aux;
    int override;

    if (ugen_override != -1)
        override = ugen_override;
    else
        override = match->cf_flags & 1;

    if (override)
        return (UMATCH_HIGHEST);
    else if (uaa->usegeneric)
        return (UMATCH_GENERIC);
    else
        return (UMATCH_NONE);
}

既に UMATCH_HIGHEST を返すコードがありますね。

struct usb_attach_arg が先ほど説明したバス固有のデバイス情報になります。

struct usb_attach_arg {
    int            port;
    int            vendor;
    int            product;
    int            release;
    usbd_device_handle  device; /* current device */
    int            class, subclass, proto;
    int            usegeneric;
};

struct usb_attach_arg に接続されたデバイスの Vendor ID と Product ID があるので、この二つが ugen(4) として attach したいデバイスの値と一致したら UMATCH_HIGHEST を返すコードを追加すれば良いですかね。

後は ugen(4) として attach したいデバイスの Vendor ID と Product ID をどうやって指定するかという事になります。

Linux であれば /proc 経由で良いのでしょうが、NetBSD では何年前かはまで知りませんが今時は sysctl(8) 経由でユーザランドから設定できるようにするらしいです。

完成

良くあるように実際の処理よりもユーザインタフェース部分の方が処理が多い差分になりました。仕方ないね

USB デバイスの Vendor ID と Product ID はデバイスを接続した状態で usbdevs -v で表示されます。

nonaka@koharu$ sudo usbdevs -v
Controller /dev/usb0:
addr 0: high speed, self powered, config 1, xHCI Root Hub(0x0000), NetBSD(0x0000), rev 1.00
 port 1 powered
 port 2 powered
 port 3 powered
 port 4 powered
 port 5 powered
 port 6 powered
 port 7 powered
 port 8 powered
 port 9 powered
Controller /dev/usb1:
addr 1: high speed, self powered, config 1, EHCI root hub(0x0000), Intel(0x8086), rev 1.00
 port 1 addr 2: high speed, self powered, config 1, product 8000(0x8000), Intel(0x8087), rev 0.04
  port 1 addr 6: full speed, power 30 mA, config 1, Yubikey NEO OTP+U2F(0x0114), Yubico(0x1050), rev 3.43
  port 2 powered
  port 3 powered
  port 4 powered
  port 5 addr 3: full speed, self powered, config 1, product 0a2a(0x0a2a), Intel(0x8087), rev 0.01
  port 6 addr 4: high speed, power 200 mA, config 1, BisonCam, NB Pro(0x024b), vendor 5986(0x5986), rev 6.08
  port 7 addr 5: full speed, power 100 mA, config 1, ThinkPad Compact USB Keyboard with TrackPoint(0x6047), Lenovo(0x17ef), rev 3.00
  port 8 powered
 port 2 powered

実際に使ってみた

$ dmesg
(snip...)
uhidev2 at uhub2 port 1 configuration 1 interface 0
uhidev2: Yubico Yubikey NEO OTP+U2F, rev 2.00/3.43, addr 6, iclass 3/1
ukbd1 at uhidev2: 8 modifier keys, 6 key codes
wskbd2 at ukbd1 mux 1
wskbd2: connecting to wsdisplay0
uhidev3 at uhub2 port 1 configuration 1 interface 1
uhidev3: Yubico Yubikey NEO OTP+U2F, rev 2.00/3.43, addr 6, iclass 3/0
uhid0 at uhidev3: input=64, output=64, feature=0
$ sysctl hw.ugen
hw.ugen.override = -1
hw.ugen.forced_attach.vendor = 65535
hw.ugen.forced_attach.product = 65535
hw.ugen.forced_attach.addr = -1
hw.ugen.forced_attach.add = 0
hw.ugen.forced_attach.delete = 0
hw.ugen.forced_attach.clear = 0
hw.ugen.forced_attach.list = 
$ sudo sysctl -w hw.ugen.forced_attach.vendor=0x1050
hw.ugen.forced_attach.vendor: 65535 -> 4176
$ sudo sysctl -w hw.ugen.forced_attach.product=0x114
hw.ugen.forced_attach.product: 65535 -> 276
$ sudo sysctl -w hw.ugen.forced_attach.add=1
hw.ugen.forced_attach.add: 0 -> 1
$ sysctl hw.ugen
hw.ugen.override = -1
hw.ugen.forced_attach.vendor = 65535
hw.ugen.forced_attach.product = 65535
hw.ugen.forced_attach.addr = -1
hw.ugen.forced_attach.add = 0
hw.ugen.forced_attach.delete = 0
hw.ugen.forced_attach.clear = 0
hw.ugen.forced_attach.list = [0x1050 0x0114 -1]
(ここでデバイスを一旦抜いてから接続しなおす)
$ dmesg
(snip...)
wskbd2: disconnecting from wsdisplay0
wskbd2: detached
ukbd1: detached
uhidev2: detached
uhidev2: at uhub2 port 1 (addr 6) disconnected
uhid0: detached
uhidev3: detached
uhidev3: at uhub2 port 1 (addr 6) disconnected
ugen0 at uhub2 port 1
ugen0: Yubico Yubikey NEO OTP+U2F, rev 2.00/3.43, addr 6
$ sudo ykinfo -v
version: 3.4.3

使い方

デバイス追加
$ sudo sysctl -w hw.ugen.forced_attach.vendor=0x1050
hw.ugen.forced_attach.vendor: 65535 -> 4176
$ sudo sysctl -w hw.ugen.forced_attach.product=0x114
hw.ugen.forced_attach.product: 65535 -> 276
$ sudo sysctl -w hw.ugen.forced_attach.add=1
hw.ugen.forced_attach.add: 0 -> 1
$ sysctl hw.ugen
hw.ugen.override = -1
hw.ugen.forced_attach.vendor = 65535
hw.ugen.forced_attach.product = 65535
hw.ugen.forced_attach.addr = -1
hw.ugen.forced_attach.add = 0
hw.ugen.forced_attach.delete = 0
hw.ugen.forced_attach.clear = 0
hw.ugen.forced_attach.list = [0x1050 0x0114 -1]
デバイス削除
$ sudo sysctl -w hw.ugen.forced_attach.vendor=0x1050
hw.ugen.forced_attach.vendor: 65535 -> 4176
$ sudo sysctl -w hw.ugen.forced_attach.product=0x114
hw.ugen.forced_attach.product: 65535 -> 276
$ sudo sysctl -w hw.ugen.forced_attach.delete=1
hw.ugen.forced_attach.delete: 0 -> 1
デバイス全削除
$ sudo sysctl -w hw.ugen.forced_attach.clear=1
hw.ugen.forced_attach.clear: 0 -> 1

課題など

USB スタックにも設定がおかしな USB デバイスが接続された場合の振る舞いを変更するための quirk を決定する処理が実は既に存在しています。

Cross Reference: /src/sys/dev/usb/usb_quirks.c

何故これを使わなかったのかと言えば、動的にデバイスの追加・削除をするのが面倒だったのと Vendor ID と Product ID 以外でも指定したかったからです。現在のパッチでは Vendor ID と Product ID の他に addr が指定できます。これは同じ Vendor ID と Product ID を持っているけれど特定のデバイスだけ ugen(4) として使いたいという要求があったからです。

後で usbdevs -v の出力を見て気付いたのですが、addr だけでは controller だか bus が違う場合にも適用されてしまうのでもう細かく少し指定できる必要がありそうです。それを修正するのは後の課題としたいと思います。

パッチ

GitHubnetbsd-src リポジトリの nonakap-catfood ブランチでパッチは保守しているのでそちらを参照して貰った方が良いかもしれません。

nonakap/netbsd-src at nonakap-catfood · GitHub

続きを読む