2017年の25日間のまとめ

この記事は、 NetBSD Advent Calendat 2017 の25日目の記事です。 もうすっかり遅くなりましたが、勝手にまとめを書きます。

まとめ

自分の書いた記事は、とりあえず置いておいて、 簡単に振り返っておきたいと思います。

1日目は、furandon_pigさんの記事です。 /usr/share/examples/asmディレクトリー内にアセンブリ言語での Hello, World!を皮切りに、各アーキテクチャー向けの アセンブリプログラミングについて紹介していただきました。

2日目もfurandon_pigさんの記事です。 キングジムPomera DM20の内部ストレージをsd(4)として見てみる話を紹介して いただきました。

3日目は、ebijunさんの記事です。 Open Source Conferenceに1年間を通じて参加するのに合わせて、 Raspberry Pi向けのSDカードイメージファイルを作成され、 動作確認をされた話をご紹介いただきました。

7日目は、furandon_pigさんの記事です。 NetBSDでのnilfsというログ構造化ファイルのサポートについて ご紹介いただきました。

14日目は、jr9qnjさんの記事です。 Raspberry PiSCSIデバイスにするRaSCSIについて、 X68000の実機に接続し、NetBSD/x68kで使えるように された功績をご紹介いただきました。 ぜひNetBSD-currentに入れて欲しいです。

16日目は、nullnilakiさんの記事です。 bintime_add(9)をコメントアウトするところから始め、 カーネル内のタイマーについてご紹介いただきました。

19日目は、tisiharaさんの記事です。 pkg_rolling-replaceを使って便利にpkgsrcからインストールした パッケージをアップデートする方法をご紹介いただきました。

20日目は、610tさんの記事です。 SUNXIカーネルを、NanoPi NEO2で動かすと、現状どのようになるかを ご紹介いただきました。 早く本格的にNanoPi NEO2がサポートされると嬉しいですね。

21日目は、oshimyjaさんの記事です。 NetBSD/amd64でのUEFIブートについてご紹介いただきました。 もう何年かすると、UEFIしかなくなってしまうようですので、 早めに移行していかないといけないようですね。

22日目は、furandon_pigさんの記事です。 uuidgen(1)コマンドの実装について、ご紹介いただきました。 uuid_generate(2)というシステムコールがあるという話で、 大変おもしろいです。

まとめ

勝手にまとめさせていただきます。 ご執筆、ご閲覧いただきましたみなさまありがとうございました。 2018年もよろしくお願いいたします。

2018年に実現して欲しいことを夢想してみる

この記事は、NetBSD Advent Calendar 2017の23日目の記事です。 代わりに投稿できるようになっているので、勝手に投稿してしまいます。 すみません。 間に合っていませんが…

2018年に実現して欲しいこと

一ユーザーとして、あったらうれしいものを挙げておきます。

NetBSD

  • Amazon Web Service EC2のElastic Network Adaptorのサポート (FreeBSDで言うena(4))
  • Microsoft Hyper-Vサポート (第1世代の仮想マシン、第2世代の仮想マシン)
  • UEFIでの光学ディスクからの起動ができるように
  • もっと多くのArmのボードでfdt(4))対応が進むこと
  • MicroBlazeやNios2、RISC-VのようなFPGAに実装されるCPUへの移植
  • qemuのエミュレートする各種ボードへの移植
  • UEFIでのブートがもっと多くのマシンでできるように(少なくとも私の常用するdynabook R63/PSは駄目なので…)
  • VMware Workstation Playerの共有フォルダーをマウントできるように
  • VirtualBoxの共有フォルダーをマウントできるように
  • cramfsをマウントできるように
  • fdt(4)をMIPSにも
  • NFS 4/4.1対応
  • ugen(4)が常に使えるように
  • evdevの追加
  • VirtualBoxをNetBSD上で動かせるように
  • アイソクロナス転送をehci/xhciで可能にする

私はカーネルのこととかは分かりませんが、来年は良く勉強して上述の うち1つでも自分でできればと思ってはいます。

pkgsrc

  • GNU Hurdへの移植
  • ia16クロスツールチェーンのパッケージの作成
  • The pkgsrc guideのEPUB3版を用意する
  • pkg-vulnerabilitiesの効率的な作成を補助するツールを作成する
  • openSUSE 42.3ベースのcompat_linux用パッケージを作成する
  • Rump kernelの活用ができないか
  • Rust for earm
  • Chromiumウェブブラウザーの移植
  • mingw64に移植
  • Widevine CDMをwww/firefoxで使えるようにする
  • input/fcitxのアップデートとmozcを使えるように

どこまでできるか分かりませんが、進めていきたいと思います。

Cubieboard2でpkgsrcの開発をする際に気を付けていること

この記事は、NetBSD Advent Calendar 2017の24日目の記事です。 代わりに投稿できるようになっているので、勝手に投稿してしまいます。 もう25日ですし。

はじめに

ArmアーキテクチャーのNetBSD用のパッケージをpkgsrcで作ることが あります。

大抵のArmのCPUの載ったボードは、SDカードやmicroSDカードを ルートファイルシステムにしています。 SDカード等には、ウェアレベリングの機能などありませんから、 何かを長時間ビルドすると、書き込み回数が多くて、壊れてしまいます。 今回は、いつもビルドに使っているCubieborad2の場合に、この問題に 対処すべくやっていることを書いておきます。

スワップ領域の問題

スワップ領域は、ダウンロードして来たarmv7.imgにも設定 されていますが、非常に小さく役に立ちません。 Cubieboard2ですと、SATAの端子があって、SATAのSSDやHDDを接続できますので、 そちらのファイルシステム内に、スワップ領域を作っておきます。


# dd if=/dev/zero of=/home/ryoon/swapfile bs=1m count=4096
# chmod 600 /home/ryoon/swapfile
# swapctl -a -p 0 /home/ryoon/swapfile
その上で、従来のmicroSDカード上のスワップを無効にし、 これを常に使うようにしてしまいます。/etc/fstab以下のように 置き換えます。

/home/ryoon/swapfile none swap sw 0 0

一時ファイルの置き場所をSSD/HDDにする

これは、TMP環境変数を定義し直すのでも良いのかもしれませんが、 /tmpにSSD/HDDのパーティションの1つを割り当ててしまいます。 以下のように/etc/fstabを変更します。


/dev/wd0e sw,log 1 1
その上で、マシンをリブートさせます。 mount -aで良いように思われるかもしれませんが、 既にディレクトリーやUNIXドメインソケット等が作成されているかもしれませんので、 再起動をお勧めします。

まとめ

簡単ですが、pkgsrcの開発をする際に、SDカード等を破損させないために 私がしていることを紹介しました。 でもまだ壊れることがあるので、何か足りないことがあるのかもしれません。

NetBSDマシンをソフトウェアトークンとして使いqiitaに二段階認証でログインできるようにする

この記事は、NetBSD Advent Calendar 2017の12日目の記事です。 すっかり遅くなっていますが、代わりに投稿できるようになっていたので、 勝手に投稿してしまいます。 あまりNetBSDにもpkgsrcにも直接関係ないような気もしますが…。

はじめに

Two Factor Authenticationは、二段階認証と日本語訳されているようです。 qiitaでも、この二段階認証を使ってログインできるようになっています。

普通は、Google Authenticatorのようなスマートフォンで使用できる ソフトウェアを使って、二段階認証のワンタイムパスワードを 生成すると思います。 しかし、pkgsrcにもsecurity/2faと言う パッケージで、コマンドラインのプログラムが用意されています。 これは、https://github.com/rsc/2fa で公開されているものをパッケージにしたものです。 Go言語で書かれています。 これを使ってqiitaにログインしてみました。

2faコマンドのインストール

Goコンパイラーが動くアーキテクチャーである必要があります。 私はNetBSD/amd64を使っているので、無事にビルドできました。 以下のように操作します。


$ cd /usr/pkgsrc/security/2fa
$ make install
これで/usr/pkg/bin/2faというコマンドがインストールされました。

二段階認証を設定する

二段階認証の設定ページより、QRコードの代わりに、テキストでキーを表示させます、 ここでは、abc123と表示されたと仮定します。


$ 2fa -add qiita
2fa key for qiita: abc123
これで、準備は整いました。 初回のワンタイムパスワードを生成してみます。 ここで、qiitaは時間ベースのワンタイムパスワード(TOTP)を受け付けて くれるようです。

$ 2fa qiita
123456
これで、123456と言うワンタイムパスワードが得られました。 これを、qiitaのページに入力します。

二段階認証でログインする

一度ログアウトして、二段階認証を使ってログインしてみます。 ユーザーIDとパスワードを入力した後、ワンタイムパスワードが求められる ようになっています。


$ 2fa qiita
234567
のように実行し、この例であれば、234567を入力してください。

まとめ

qiitaで、時間ベースのワンタイムパスワードを使用して二段階認証でログインしました。 ワンタイムパスワードはNetBSDの環境で生成することができました。

時間ベースのワンタイムパスワードの生成に限りませんが、端末の時刻はNTP等で 合わせておくようにしましょう。

NanoPi NEOでNetBSDを使ってみる

この記事は、NetBSD Advent Calendar 2017の11日目の記事です。 すっかり遅くなっていますが、代わりに投稿できるようになっていたので、 勝手に投稿してしまいます。 とは言っても、小ネタですが…。

はじめに

オープンソースカンファレンス2017 Chibaに行った際に、えびはらさんに、 NanoPi NEOを紹介いただきました。 Allwinner H3と言うsun8iアーキテクチャーのArm Cortex-A7の4コアのCPUと、 512MBのメインメモリーを搭載しています。 ビデオ出力はありません。シリアルコンソールでの接続になります。 また、Gigabit EthernetとUSB 2.0のポートを1つずつ持っています。 私は、秋月電子通商 のウェブサイトで購入しました。

microSDカードを準備する

lNetBSD/evbearmv7hf-elのSUNXIカーネルが使用できます。 NetBSD/evbarm on Allwinner Technology SoCsにある通りですが、 まずはhttp://nycdn.netbsd.org/pub/NetBSD-daily/HEAD/から、 evbarm-earmv7hf/binary/gzimg/armv7.img.gzをダウンロードします。

次に、これを2GB以上のmicroSDカードに書き込みます。 以下のように実行します。


# gzcat armv7.img.gz | dd of=/dev/ld0d bs=1m

AllwinnerのSoCを搭載したマシンで起動させるには、u-bootを使用する必要 があります。 以下のようにして、u-bootのバイナリーを作成します。


$ cd /usr/pkgsrc/sysutils/u-boot-nanopi-neo
$ make install
これで、/usr/pkg/share/u-boot/nanopi-neo/u-boot-sunxi-with-spl.bin にu-bootのバイナリーが作成できました。

このu-bootバイナリーをmicroSDカードに書き込みます。 以下のように操作します。


# dd if=/usr/pkg/share/u-boot/nanopi-neo/u-boot-sunxi-with-spl.bin of=/dev/rld0d bs=1k seek=8 conv=sync
これで、起動する準備ができました。

起動させる

NanoPi NEOのmicroSDカードスロットに挿入し、シリアルコンソールとUTPケーブル も接続してmicro USBケーブルで電源を接続します。

シリアルコンソールで接続するNetBSDマシンでは、以下のように実行して 出力を待っておきます。


$ cu -s 115200 -l /dev/ttyU0
rootユーザーでは、sshでログインできませんので、 特にmicroSDカードの内容を先に変更しておくのでなければ、シリアルコンソールは 必須です。

カーネルの起動メッセージは以下のようになります。


Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
    The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 8.99.9 (SUNXI) #0: Fri Dec 22 11:22:37 UTC 2017
 mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/evbarm/compile/SUNXI
total memory = 512 MB
avail memory = 499 MB
timecounter: Timecounters tick every 10.000 msec
armfdt0 (root)
fdt0 at armfdt0: FriendlyARM NanoPi NEO
fdt1 at fdt0
fdt2 at fdt0
fdt3 at fdt0
cpus0 at fdt0
cpu0 at cpus0: Cortex-A7 r0p5 (Cortex V7A core)
cpu0: DC enabled IC enabled WB disabled EABT branch prediction enabled
cpu0: 32KB/32B 2-way L1 VIPT Instruction cache
cpu0: 32KB/64B 4-way write-back-locking-C L1 PIPT Data cache
cpu0: 512KB/64B 8-way write-through L2 PIPT Unified cache
vfp0 at cpu0: NEON MPE (VFP 3.0+), rounding, NaN propagation, denormals
cpufreqdt0 at cpu0
cpu1 at cpus0
cpu2 at cpus0
cpu3 at cpus0
gic0 at fdt1: GIC
armgic0 at gic0: Generic Interrupt Controller, 160 sources (150 valid)
armgic0: 16 Priorities, 128 SPIs, 7 PPIs, 15 SGIs
fclock0 at fdt2: 24000000 Hz fixed clock
fclock1 at fdt2: 32768 Hz fixed clock
fclock2 at fdt2: 16000000 Hz fixed clock
gtmr0 at fdt0: Generic Timer
gtmr0: interrupting on GIC irq 27
armgtmr0 at gtmr0: ARMv7 Generic 64-bit Timer (24000 kHz)
timecounter: Timecounter "armgtmr0" frequency 24000000 Hz quality 500
sun8ih3ccu0 at fdt1: H3 CCU
sun8ih3rccu0 at fdt1: H3 PRCM CCU
sunxigpio0 at fdt1: PIO
gpio0 at sunxigpio0: 94 pins
sunxigpio0: interrupting on GIC irq 43
sunxigpio1 at fdt1: PIO
gpio1 at sunxigpio1: 12 pins
sunxigpio1: interrupting on GIC irq 77
fregulator0 at fdt0: vcc3v3
gregulator0 at fdt0: cpux-supply
fregulator1 at fdt0: vcc3v0
fregulator2 at fdt0: vcc5v0
sunxisid0 at fdt1: Security ID EFUSE
sunxiusbphy0 at fdt1: USB PHY
/soc/syscon@1c00000 at fdt1 not configured
sunxiemac0 at fdt1: EMAC
sunxiemac0: interrupting on GIC irq 114
ukphy0 at sunxiemac0 phy 1: OUI 0x0088a0, model 0x0000, rev. 0
ukphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
sun6idma0 at fdt1: DMA controller (12 channels)
sun6idma0: interrupting on GIC irq 82
h3codec0 at fdt1: H3 Audio Codec (analog part)
psci0 at fdt0: PSCI 0.1
gpioleds0 at fdt0: nanopi:blue:status nanopi:green:pwr
gpiokeys0 at fdt0: k1
sunximmc0 at fdt1: SD/MMC controller
sunximmc0: interrupting on GIC irq 92
ehci0 at fdt1: EHCI
ehci0: interrupting on GIC irq 110
ehci0: EHCI version 1.0
ehci0: 1 companion controller, 1 port
usb0 at ehci0: USB revision 2.0
ohci0 at fdt1: OHCI
ohci0: interrupting on GIC irq 111
ohci0: OHCI version 1.0
usb1 at ohci0: USB revision 1.0
sunxitimer0 at fdt1: Timer
timecounter: Timecounter "Timer 2" frequency 24000000 Hz quality 200
sunxiwdt0 at fdt1: Watchdog
sunxiwdt0: default watchdog period is 16 seconds
com0 at fdt1: ns16550a, working fifo
com0: console
com0: interrupting on GIC irq 32
sunxirtc0 at fdt1: RTC
sunxithermal0 at fdt1: Thermal sensor controller
sunxithermal0: interrupting on GIC irq 63
sunxithermal0: cpu: alarm 90C hyst 15C shut 105C
timecounter: Timecounter "clockinterrupt" frequency 100 Hz quality 0
cpu2: Cortex-A7 r0p5 (Cortex V7A core)
cpu2: DC enabled IC enabled WB disabled EABT branch prediction enabled
cpu2: 32KB/32B 2-way L1 VIPT Instruction cache
cpu2: 32KB/64B 4-way write-back-locking-C L1 PIPT Data cache
cpu2: 512KB/64B 8-way write-through L2 PIPT Unified cache
vfp2 at cpu2: NEON MPE (VFP 3.0+), rounding, NaN propagation, denormals
cpu1: Cortex-A7 r0p5 (Cortex V7A core)
cpu1: DC enabled IC enabled WB disabled EABT branch prediction enabled
cpu1: 32KB/32B 2-way L1 VIPT Instruction cache
cpu1: 32KB/64B 4-way write-back-locking-C L1 PIPT Data cache
cpu1: 512KB/64B 8-way write-through L2 PIPT Unified cache
vfp1 at cpu1: NEON MPE (VFP 3.0+), rounding, NaN propagation, denormals
cpu3: Cortex-A7 r0p5 (Cortex V7A core)
cpu3: DC enabled IC enabled WB disabled EABT branch prediction enabled
cpu3: 32KB/32B 2-way L1 VIPT Instruction cache
cpu3: 32KB/64B 4-way write-back-locking-C L1 PIPT Data cache
cpu3: 512KB/64B 8-way write-through L2 PIPT Unified cache
vfp3 at cpu3: NEON MPE (VFP 3.0+), rounding, NaN propagation, denormals
cpufreqdt0: 1008.000 MHz, 1300000 uV
cpufreqdt0: 816.000 MHz, 1100000 uV
cpufreqdt0: 480.000 MHz, 1100000 uV
sdmmc0 at sunximmc0
uhub0 at usb0: Generic (0000) EHCI root hub (0000), class 9/0, rev 2.00/1.00, addr 1
uhub0: 1 port with 1 removable, self powered
uhub1 at usb1: Generic (0000) OHCI root hub (0000), class 9/0, rev 1.00/1.00, addr 1
uhub1: 1 port with 1 removable, self powered
IPsec: Initialized Security Association Processing.
sdmmc0: SD card status: 4-bit, C10, U1
ld0 at sdmmc0: <0x03:0x5344:SL32G:0x80:0x61532365:0x0f3>
ld0: 29476 MB, 7486 cyl, 128 head, 63 sec, 512 bytes/sect x 60367872 sectors
ld0: 4-bit width, High-Speed/SDR25, 50.000 MHz
boot device: ld0
root on ld0a dumps on ld0b
root file system type: ffs
kern.module.path=/stand/evbarm/8.99.9/modules
これで、emac0と言うネットワークインターフェイスが 使用できます。

まとめ

Friendly ElecのNanoPi NEOで、NetBSD/evbearmv7hf-elのSUNXIカーネルを 起動させ、ネットワーク機能を使うことができました。 ヒートシンクを付けていますが、それなりに暖かくなります。 CPUはコア数も多く速いようなので、USB接続のSSDを付けてpkgsrcの開発に 使用するのが良さそうです。

pkgsrcでRELROを有効にしてビルドしてみる

この記事は、NetBSD Advent Calendar 2017のすっかり遅くなった18日目の記事です。

はじめに

pkgsrcはmk.confファイルに設定しておくことで、 挙動を変更することができます。 その中に、以前より試してみたかったオプションが3つあります。

  • PKGSRC_USE_RELRO
  • PKGSRC_MKPIE
  • PKGSRC_MKREPRO
の3つです。

その中でも、PKGSRC_MKREPROに一番興味があったのですが、 どうやら今は循環依存になってしまい、リーフパッケージでないと ビルドできない状態のようです。

今回は、PKGSRC_USE_RELROを有効にして、自分のいつも使っている パッケージをビルドして使ってみました。

RELROとは何か

RELROは、RElocation Read-Onlyの略だそうです。 私はセキュリティー機能の専門家ではないので、詳しく説明はできませんが、 メモリーの一部の領域を読み出し専用にして、メモリーの破壊を防止する ことで、安全性を高める手法と理解しています。

設定方法

mk.confに設定できる内容は、pkgsrc/mk/defaults/mk.conf に既定値が設定されており、コメントも付記されています。 RELROについては、以下のように記載されています。


PKGSRC_USE_RELRO?= no
# Link with RELRO by default (on supported platforms). This makes the
# exploitation of some security vulnerabilities more difficult in some cases.
# Possible values:
#       no:      Do not pass any flags for RELRO
#       partial: Pass -Wl,-z,relro
#       full:    Pass -Wl,-z,relro -Wl,-z,now
#
# Keywords: relro

のように記載されています。この内容は、任意のパッケージのディレクトリーで 以下のように実行することで読むこともできます。

$ make help topic=relro
===> mk/defaults/mk.conf (keywords: relro no PKGSRC_USE_RELRO full partial):
PKGSRC_USE_RELRO?= no
# Link with RELRO by default (on supported platforms). This makes the
# exploitation of some security vulnerabilities more difficult in some cases.
# Possible values:
#       no:      Do not pass any flags for RELRO
#       partial: Pass -Wl,-z,relro
#       full:    Pass -Wl,-z,relro -Wl,-z,now
#

これによると、PKGSRC_USE_RELROの既定値はnoで、 有効にするには、partialfullのいずれかを 設定することが必要と分かります。 また、コンパイラーにLDFLAGS経由で渡されるオプションについても記載されています。

今回は、fullを指定したいと思います。Got overwriteが防止 できるようになるようです。

RELROを有効にして

上述したように、コンパイラーにオプションが渡されます。 これによって、RELROが有効になったバイナリーができるはずですが、 pkgsrcでは、RELROが有効になってバイナリーが本当に生成されたかを readelfコマンドで確認するようになっています。 ですので、LDFLAGSを尊重しないようになっているビルドメカニズムである パッケージについて、RELROを有効にしてビルドしたつもりになって しまうのを防止することができます。

私の使っているパッケージのビルドでは、converters/qkc 以外はLDFLAGSを尊重しているようで、RELROを有効にしたバイナリーを 作成することができました。 editors/emacs25www/firefoxも 特に支障なく動いているようです。

まとめ

RELROを有効にして、pkgsrcのパッケージをビルドしてみました。

Hyper-V第1世代の仮想マシンでレガシーネットワークアダプターが使えるようになった

この記事は、NetBSD Advent Calendar 2017のすっかり遅くなった17日目の記事です。

はじめに

PR kern/49323という2014年10月に send-prして何もできないままになっていた、Hyper-V第1世代の仮想マシンで レガシーネットワークアダプターが使えない問題が、2017年11月にnakayama@さん によって修正されました。

これによって、100 Mbpsではありますが、支障なくネットワーク接続できるように なったので、私は大変喜んでいます。 nakayama@さんありがとうございます。

Hyper-VとBSD

私は大変喜んではいるのですが、Hyper-Vのサポートについては、 FreeBSDやOpenBSDでは既に準仮想化デバイスも含め、 順調にサポートが進んでいるようです。

私も仕事でHyper-Vを使わないといけない場合には、 FreeBSD/amd64を使っています。 でも、Hyper-V第2世代仮想マシンは、FreeBSD/amd64 11.1のISOイメージを 起動させることはできませんでした。

NetBSDと言うと、Google Summer of Codeで課題になったことはあったようですが、 進まなかったのか、結果がsrcツリーにcommitされてはいません。

いつものように、世界で自分しか困っていないパターンなのかもしれません…。

Hyper-V仮想マシンの様子

Hyper-V第1世代の仮想マシンを用意し、ネットワークアダプターを削除して、 レガシーネットワークアダプターを追加するだけです。 acpicpu0の後で、fd0を初期化する辺りで なかなか進まず、気分的にあきらめそうになりますが、 我慢して待ては進みます。 カーネルのブートメッセージは以下のようになります。


Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
    The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 8.99.9 (GENERIC) #0: Sun Dec 17 17:49:04 UTC 2017
 mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/amd64/compile/GENERIC
total memory = 1023 MB
avail memory = 971 MB
WARNING: module error: module `cd9660' pushed by boot loader already exists
timecounter: Timecounters tick every 10.000 msec
Kernelized RAIDframe activated
running cgd selftest aes-xts-256 aes-xts-512 done
timecounter: Timecounter "i8254" frequency 1193182 Hz quality 100
Microsoft Corporation Virtual Machine (7.0)
mainbus0 (root)
ACPI: RSDP 0x00000000000F5BF0 000014 (v00 ACPIAM)
ACPI: RSDT 0x000000003FFF0000 000040 (v01 VRTUAL MICROSFT 06001702 MSFT 00000097)
ACPI: FACP 0x000000003FFF0200 000081 (v02 VRTUAL MICROSFT 06001702 MSFT 00000097)
ACPI: DSDT 0x000000003FFF1D24 003CBE (v01 MSFTVM MSFTVM02 00000002 INTL 02002026)
ACPI: FACS 0x000000003FFFF000 000040
ACPI: WAET 0x000000003FFF1A80 000028 (v01 VRTUAL MICROSFT 06001702 MSFT 00000097)
ACPI: SLIC 0x000000003FFF1AC0 000176 (v01 VRTUAL MICROSFT 06001702 MSFT 00000097)
ACPI: OEM0 0x000000003FFF1CC0 000064 (v01 VRTUAL MICROSFT 06001702 MSFT 00000097)
ACPI: SRAT 0x000000003FFF0800 0000E0 (v02 VRTUAL MICROSFT 00000001 MSFT 00000001)
ACPI: APIC 0x000000003FFF0300 000452 (v01 VRTUAL MICROSFT 06001702 MSFT 00000097)
ACPI: OEMB 0x000000003FFFF040 000064 (v01 VRTUAL MICROSFT 06001702 MSFT 00000097)
ACPI: 1 ACPI AML tables successfully acquired and loaded
ioapic0 at mainbus0 apid 0: pa 0xfec00000, version 0x11, 24 pins
cpu0 at mainbus0 apid 0
cpu0: Intel(R) Core(TM) i3-2348M CPU @ 2.30GHz, id 0x206a7
cpu0: package 0, core 0, smt 0
acpi0 at mainbus0: Intel ACPICA 20171110
acpi0: X/RSDT: OemId , AslId 
LNKA: ACPI: Found matching pin for 0.8.INTA at func 0: 11
LNKA: ACPI: Found matching pin for 0.10.INTA at func 0: 11
acpi0: SCI interrupting at int 9
timecounter: Timecounter "ACPI-Safe" frequency 3579545 Hz quality 900
attimer1 at acpi0 (TMR, PNP0100): io 0x40-0x43 irq 0
pckbc1 at acpi0 (PS2K, PNP0303) (kbd port): io 0x60,0x64 irq 1
pckbc2 at acpi0 (PS2M, PNP0F03) (aux port): irq 12
pcppi1 at acpi0 (SPKR, PNP0800): io 0x61
spkr0 at pcppi1: PC Speaker
wsbell at spkr0 not configured
midi0 at pcppi1: PC speaker
sysbeep0 at pcppi1
UAR1 (PNP0501) at acpi0 not configured
UAR2 (PNP0501) at acpi0 not configured
FDC (PNP0700) at acpi0 not configured
SYSR (PNP0C02) at acpi0 not configured
OSYS (PNP0C02) at acpi0 not configured
VMB8 (VMBUS) at acpi0 not configured
SYSM (PNP0C01) at acpi0 not configured
GENC (HYPER_V_GEN_COUNTER_V1) at acpi0 not configured
ACPI: Enabled 1 GPEs in block 00 to 0F
pckbd0 at pckbc1 (kbd slot)
pckbc1: using irq 1 for kbd slot
wskbd0 at pckbd0: console keyboard
pms0 at pckbc1 (aux slot)
pckbc1: using irq 12 for aux slot
wsmouse0 at pms0 mux 0
attimer1: attached to pcppi1
pci0 at mainbus0 bus 0: configuration mode 1
pci0: This pci host supports neither MSI nor MSI-X.
pci0: i/o space, memory space enabled, rd/line, rd/mult, wr/inv ok
pchb0 at pci0 dev 0 function 0: vendor 8086 product 7192 (rev. 0x03)
pcib0 at pci0 dev 7 function 0: vendor 8086 product 7110 (rev. 0x01)
piixide0 at pci0 dev 7 function 1: Intel 82371AB IDE controller (PIIX4) (rev. 0x01)
piixide0: bus-master DMA support present
piixide0: primary channel wired to compatibility mode
piixide0: primary channel interrupting at ioapic0 pin 14
atabus0 at piixide0 channel 0
piixide0: secondary channel wired to compatibility mode
piixide0: secondary channel interrupting at ioapic0 pin 15
atabus1 at piixide0 channel 1
piixpm0 at pci0 dev 7 function 3: vendor 8086 product 7113 (rev. 0x02)
timecounter: Timecounter "piixpm0" frequency 3579545 Hz quality 900
piixpm0: 24-bit timer
piixpm0: SMBus disabled
vga0 at pci0 dev 8 function 0: vendor 1414 product 5353 (rev. 0x00)
wsdisplay0 at vga0 kbdmux 1: console (80x25, vt100 emulation), using wskbd0
wsmux1: connecting to wsdisplay0
drm at vga0 not configured
tlp0 at pci0 dev 10 function 0: DECchip 21140A Ethernet, pass 2.0
tlp0: interrupting at ioapic0 pin 11
tlp0: Ethernet address 00:15:5d:00:7d:01
tlp0: 100baseTX, 100baseTX-FDX
isa0 at pcib0
com0 at isa0 port 0x3f8-0x3ff irq 4: ns16550a, working fifo
com1 at isa0 port 0x2f8-0x2ff irq 3: ns16550a, working fifo
fdc0 at isa0 port 0x3f0-0x3f7 irq 6 drq 2
acpicpu0 at cpu0: ACPI CPU
acpicpu0: C1: HLT, lat   0 us, pow     0 mW
timecounter: Timecounter "clockinterrupt" frequency 100 Hz quality 0
fd0 at fdc0 drive 0: 1.44MB, 80 cyl, 2 head, 18 sec
wd0 at atabus0 drive 0
wd0: &t;Virtual HD>
wd0: drive supports 128-sector PIO transfers, LBA48 addressing
wd0: 127 GB, 264224 cyl, 16 head, 63 sec, 512 bytes/sect x 266338304 sectors
IPsec: Initialized Security Association Processing.
wd0: 32-bit data port
wd0: drive supports PIO mode 4, DMA mode 2, WRITE DMA FUA
wd0(piixide0:0:0): using PIO mode 4, DMA mode 2 (using DMA), WRITE DMA FUA EXT
atapibus0 at atabus1: 2 targets
cd0 at atapibus0 drive 0: <Virtual CD, , > cdrom removable
cd0: 32-bit data port
cd0: drive supports PIO mode 4, DMA mode 2
cd0(piixide0:1:0): using PIO mode 4, DMA mode 2 (using DMA)
boot device: cd0
root on cd0a dumps on cd0b
root file system type: cd9660
kern.module.path=/stand/amd64/8.99.9/modules
tlp0としてレガシーネットワークアダプターが認識されました。

以下のようにdhcpcd(8)を使ってアドレスを取得しましたが、 以前のようにエラーにはならず、その後のftpでのダウンロードも 問題なくできました。


# dhcpcd tlp0
# ifconfig tlp0
tlp0: flags=0x8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        ec_capabilities=1<VLAN_MTU>
        ec_enabled=0
        address: 00:15:5d:00:7d:01
        media: Ethernet 100baseTX
        status: active
        inet 172.17.248.236/28 broadcast 172.17.248.239 flags 0x0
        inet6 fe80::79e6:af53:6f8e:e91%tlp0/64 flags 0x0 scopeid 0x1

まとめ

Hyper-V第1世代の仮想マシンでレガシーネットワークアダプターを NetBSDから使えるようになりました。

ですが、レガシーでない方のネットワークアダプター、 Hyper-V第2世代の仮想マシンのサポートなどやるべきことはたくさんありそうです。

NetBSDでWacom Intuos 2ペンタブレットを使う

この記事は、NetBSD Advent Calendar 2017のすっかり遅くなった15日目の記事です。

はじめに

Wacom Intuos 2 A4 XD-0912-Uと言うペンタブレットを入手した。 残念ながら絵心はないのだが、NetBSDで使えないのはもったいないので、 使えるようにしてみた。

XD-0912-Uは、A4サイズのペンタブレットで、ペンは傾きも検出できるもので、 売られていた当時は、旗艦モデルだったような気がする。 ただし、今はWindows 7までしか対応しておらず、Windows 10では使用できないので Windowsでは使用は難しいかもしれない。

NetBSDのペンタブレットサポートを考える

ペンタブレットは、マウスとは違い、絶対的な位置情報を発信する必要がある。 NetBSDの既存の仕組みを見てみると、絶対的な位置情報を扱うものとして、 uts(4)というUSB接続タッチパネルの仕組みがあるが、 ペンタブレットをフル活用するには、筆圧、ペンの傾きをサポートする必要がある。 wsmouse(4)の仕組みも、筆圧やペンの傾きの情報を扱えるようには 設計されていないようだ。

と言うことで、uhid(4)を使っている既存の仕組みを改造してサポートする のが現実的だ。 デバイスの初期化はNetBSDカーネルで行い、 OpenBSD用のX windows systemであるXenocaraに含まれている xf86-input-usbtabletを改造して、 対応することにした。

NetBSDカーネルでの初期化

初期化は、基本的には既存のWacom製のペンタブレットと同じで、インターフェイスに 0x0202というデータを送ることで初期化できる。 Wacom Intuos 2は、0x0202による初期化をしないと、相対的な位置情報を USBマウスのように発信してくる。 USBマウスとして動かなくなったら正しく初期化できたと分かる。

uhid(4)の出力を解析する

LinuxのWacom用のデバイスドライバーに関連する資料などを 見ながら、実際にペンを動かして確認してみることにする。


$ cat /dev/uhid0 | od -x
のように実行した上で、ペンタブレット上でペンを動かして出力される データを確認して行く。 ですが、結局はデータの最初の部分がどのようになるかを把握する以上の ことはできなかった。

仕方がないのでLinuxのソースコードを読んでみることにした。。 主には、 drivers/input/tablet/wacom_wac.c を見れば良かった。 LinuxのWacomサポートは、evdevの仕組みで出力すると言うことのようなので、 出力は参考にならないが、ペンタブレットからの入力をデコードする部分の 必要な演算は分かる。 中身自体は、どこで切って入力値にするかと言うだけなので、 あまり面白みはなかった。

本当は、X.orgのインプットモジュールを書く方法について、 きちんとまとめておきたいのだが、今回は割愛して、実際の使用方法に移る。

使い方

以下のようにソースコードを取得し、ビルドし、配置する。 ここで、X.orgはNetBSDのxsrcを使っているので、pkgsrcから導入した場合には、 /usr/pkg以下に配置する必要があるだろう。


$ git clone git@github.com:ryoon/xf86-input-usbtablet.git
$ cd xf86-input-usbtablet
$ ./configure
$ make
# cp src/.libs/usbtablet_drv.so /usr/X11R7/lib/modules/drivers

残念ながら自動的にこのxf86-input-usbtabletドライバーを使用してくれるような ことはない。 以下のように/etc/X11/xorg.confに追加しておく必要がある。 赤字の部分が重要である。


Section "ServerLayout"
 Identifier     "X.org Configured"
 Screen      0  "Screen0" 0 0
 Screen      1  "Screen1" RightOf "Screen0"
 InputDevice    "Mouse0" "CorePointer"
 InputDevice    "Keyboard0" "CoreKeyboard"

 InputDevice    "w_stylus" "SendCoreEvents"
 InputDevice    "w_eraser" "SendCoreEvents" 

EndSection

Section "Files"
 ModulePath   "/usr/X11R7/lib/modules"
 FontPath     "/usr/X11R7/lib/X11/fonts/misc/"
 FontPath     "/usr/X11R7/lib/X11/fonts/TTF/"
 FontPath     "/usr/X11R7/lib/X11/fonts/Type1/"
 FontPath     "/usr/X11R7/lib/X11/fonts/75dpi/"
 FontPath     "/usr/X11R7/lib/X11/fonts/100dpi/"
 FontPath     "/usr/pkg/share/fonts/X11/TTF/"
 FontPath     "/usr/pkg/share/fonts/X11/local/"
EndSection

Section "Module"
 Load  "dbe"
# Load  "dri"
# Load  "dri2"
 Load  "extmod"
 Load  "glx"
 Load  "record"
 Load  "shadow"
EndSection

Section "InputDevice"
 Identifier  "Keyboard0"
 Driver      "kbd"
EndSection

Section "InputDevice"
 Identifier  "Mouse0"
 Driver      "mouse"
 Option     "Protocol" "wsmouse"
 Option     "Device" "/dev/wsmouse"
 Option     "ZAxisMapping" "4 5 6 7"
 Option     "Emulate3Buttons" "on"
EndSection


Section "InputDevice"
 Identifier "w_stylus"
 Driver "usbtablet"
 Option "Type" "stylus"
 Option "Device" "/dev/uhid0"
 Option "Mode" "Absolute"
 Option "Threshold" "10"
# Option "DebugLevel" "99"
EndSection

Section "InputDevice"
 Identifier "w_eraser"
 Driver "usbtablet"
 Option "Type" "eraser"
 Option "Device" "/dev/uhid0"
 Option "Mode" "Absolute"
# Option "DebugLevel" "99"
EndSection


Section "Monitor"
 Identifier   "Monitor0"
 VendorName   "Monitor Vendor"
 ModelName    "Monitor Model"
EndSection

Section "Monitor"
 Identifier   "Monitor1"
 VendorName   "Monitor Vendor"
 ModelName    "Monitor Model"
EndSection

Section "Device"
  Option     "NoAccel" "True"
        #Option     "AccelMethod"
        #Option     "Backlight"
        Option     "DRI" "False"
        #Option     "ColorKey"
        #Option     "VideoKey"
        #Option     "Tiling"
        #Option     "LinearFramebuffer"
        #Option     "SwapbuffersWait"
        #Option     "TripleBuffer"
        #Option     "XvPreferOverlay"
        #Option     "HotPlug"
        #Option     "ReprobeOutputs"
        #Option     "XvMC"
        #Option     "ZaphodHeads"
        #Option     "TearFree"
        #Option     "PerCrtcPixmaps"
        #Option     "FallbackDebug"
        #Option     "DebugFlushBatches"
        #Option     "DebugFlushCaches"
        #Option     "DebugWait"
        #Option     "BufferCache"
 Identifier  "Card0"
# Option     "AccelMethod" "SNA"
# Option     "AccelMethod" "UXA"
 Driver      "intel"
 BusID       "PCI:0:2:0"
EndSection

Section "Screen"
 Identifier "Screen0"
 Device     "Card0"
 Monitor    "Monitor0"
 SubSection "Display"
  Viewport   0 0
  Depth     1
 EndSubSection
 SubSection "Display"
  Viewport   0 0
  Depth     4
 EndSubSection
 SubSection "Display"
  Viewport   0 0
  Depth     8
 EndSubSection
 SubSection "Display"
  Viewport   0 0
  Depth     15
 EndSubSection
 SubSection "Display"
  Viewport   0 0
  Depth     16
 EndSubSection
 SubSection "Display"
  Viewport   0 0
  Depth     24
 EndSubSection
EndSection

Section "Screen"
 Identifier "Screen1"
 Device     "Card1"
 Monitor    "Monitor1"
 SubSection "Display"
  Viewport   0 0
  Depth     1
 EndSubSection
 SubSection "Display"
  Viewport   0 0
  Depth     4
 EndSubSection
 SubSection "Display"
  Viewport   0 0
  Depth     8
 EndSubSection
 SubSection "Display"
  Viewport   0 0
  Depth     15
 EndSubSection
 SubSection "Display"
  Viewport   0 0
  Depth     16
 EndSubSection
 SubSection "Display"
  Viewport   0 0
  Depth     24
 EndSubSection
EndSection

これで、pkgsrc/graphics/gimpでペンと消しゴムが使用できる。

一応、今も売っているはずのでIntuos Art CTH-690/K0でも動くのだが、 uhid(4)の何かのバグに突き当たっているようなので、お勧めはしない。

まとめ

Wacom Intuos 2をNetBSDで動くようにできた。 私は絵心は皆無なので、実際にこれを使って絵を描いてみると、致命的な 間違いをしていることが分かるかもしれない。特にペンの傾きは不安である。

ついでに、Wacom Favoで、ペンの傾きを正しく無視するようにしたので、 Wacom Favoユーザーにも使ってもらえると良いかもしれない。 Gimpがsegfaultで終了しなくなる。

NetBSD/evbearmでfdt(4)対応した環境を試してみる

この記事は、NetBSD Advent Calendar 2017のすっかり遅くなった13日目の記事です。

はじめに

最近、NetBSD/armでは、fdt(4)に対応するのが進んでいる。 fdtとはFlattened Device Treeの略で、dtbファイルを用意しておけば、 各機種ごとにカーネルを用意しなくても、NetBSD/i386やNetBSD/amd64における GENERICカーネルのようなものを用意できるもののようだ。

fdt(4)に対応すると、カーネルのブートメッセージがどのように変化するか 自分で確認しておきたかったので、今回試してみた。

今回使用した機種は、Cubieboard2というAllwinner A20というSoCを搭載した ものです。これはsun7iという名前で呼ばれているアーキテクチャーである。 これは、SATAでHDDやSSDを接続できるため、pkgsrc/www/firefoxをビルド するのに使用していた。 今は、pkgsrc/lang/rustがNetBSD/armではビルドできないので お休み中である、

fdt(4)に対応する前のCUBIEBOARDカーネルのカーネルのブートメッセージは、 えびはらさんが https://github.com/ebijun/NetBSD/blob/master/allwinner/dmesgに 掲載してくれている。

どのカーネルを使用すれば良いか

GENERICカーネル的なものを作成できると書いたが、 現状ではAllwinnerのsun?iアーキテクチャーのSoCを使った機種は、 SUNXIカーネルを使うことになっているようだ。

ディスクイメージファイルを生成する

Cubieboard2に対しては、NetBSD/evbearmv7hf-elが リトルエンディアンでは最適なアーキテクチャーだと考えられる。

NetBSD-currentのソースコードが/usr/srcに、 X window systemのソースコードが/usr/xsrcに それぞれ配置されているとすると、 以下のようにして、ディスクイメージファイルの生成まで一括して 実行することができる。


$ cd /usr/src
$ ./build.sh -U -O /usr/world/8.99/evbearmv7hf-el/obj \
-T /usr/world/8.99/evbearmv7hf-el/tools \
-D /usr/world/8.99/evbearmv7hf-el/destdir \
-R /usr/world/8.99/evbearmv7hf-el/release -x -j 5 -m evbearmv7hf-el release
私は、NetBSD/arm64 8.0_BETAの環境で実行したが、POSIXにある程度準拠した環境で あれば、どこでも同じようにビルドできるはずである。 私の環境では、ほぼ2時間で完了した。

以上のように実行すると、/usr/world/8.99/evbearmv7hf-el/release/evbarm/binary/gzimg/armv7.img.gz のように、gzipで圧縮されたディスクイメージファイルが作成される。

ディスクイメージファイルをmicroSDカードに書き込む

Cubieboard2には、microSDカードを挿入できるようになっている。 以下のようにして、dynabook R73/PS上のNetBSD/amd64でmicroSDカードに書き込んだ。 dynabook R73/PSには、SDカードスロットがあり、そこに挿入された SDカードは、ld(4)デバイスとして認識されるが、 USB接続のメモリーカードリーダー/ライターであれば、 sd(4)になるだろう。 NetBSD/amd64かNetBSD/i386でなければ、書き込み先は/dev/rld0d のようにdではないかもしれない。


$ gzcat armv7.img.gz| sudo dd of=/dev/rld0d bs=1m
ここでは、pkgsrc/security/sudoを使ってみた。

ディスクにu-bootブートローダーのプログラムを書き込む

Cuboeboard2でのブートはu-bootを使う。 Cubieboard用のu-bootのバイナリーは、以下のようにしてpkgsrcの枠組みの中で 作成することができる。


$ cd /usr/pkgsrc/sysutils/u-boot-cubieboard2
$ make install
これで、/usr/pkg/share/u-boot/cubieboard2/u-boot-sunxi-with-spl.bin にCubieboard2用のu-bootイメージを得ることができた。 以下のようにして書き込む。

# dd if=/usr/pkg/share/u-boot/cubieboard2/u-boot-sunxi-with-spl.bin of=/dev/rld0d bs=1k seek=8 conv=sync

HDMI接続でブートメッセージが見えるようにする

Cubieboard2は、HDMIでディスプレイを接続し、X window systemも使用できるが、 armv7imgディスクイメージファイルでSUNXIカーネルの対応する環境には、 シリアルコンソールしかない機種もある。 そのためか、armv7.imgディスクイメージファイルでは、 Cubieboard2であってもシリアルコンソールを使用するようになっている。 そこで、HDMI接続されたディスプレイにカーネルのブートメッセージを表示し、 操作できるように設定しておくことにする。

まずは、u-bootのブートコマンドを書き換え、バイナリーを再生成する。 ここでは、NetBSD/amd64の環境で実行するとする。


# mount_msdos /dev/ld0a /mnt
$ cd /mnt
$ vi boot.cmd (赤字の部分を追加する)
if test "${soc}" = "sunxi" ; then
        setenv kernel netbsd-SUNXI.ub
        setenv bootargs root=ld0a console=fb
        setenv mmcpart 0:1
        setenv use_fdt 1
fi
if test "${soc}" = "tegra" ; then
        setenv kernel netbsd-TEGRA.ub
        setenv bootargs root=ld1a
        setenv mmcpart 1:1
        setenv use_fdt 1
fi
if test "${board}" = "am335x" ; then
        setenv kernel netbsd-BEAGLEBONE.ub
        setenv mmcpart 0:1
        setenv bootargs root=ld0a
fi

if test "${kernel}" = "" ; then
        echo '>>>'
        echo '>>> Target device is not supported by this script.'
        echo '>>>'
        exit
fi

if test "${use_fdt}" = "1" ; then
        fatload mmc ${mmcpart} ${kernel_addr_r} ${kernel}
        fatload mmc ${mmcpart} ${fdt_addr_r} ${fdtfile}
        fdt addr ${fdt_addr_r}
        bootm ${kernel_addr_r} - ${fdt_addr_r}
else
        fatload mmc ${mmcpart} ${kernel_addr_r} ${kernel}
        bootm ${kernel_addr_r} ${bootargs}
fi
$ mkubootimage -A arm -C none -O linux -T script -a 0 -n "NetBSD sunxi boot" boot.cmd boot.scr
$ cd ~
# umount /mnt
これで準備は完了した。

起動してカーネルのブートメッセージを確認する

後は、microSDカードをCubieboard2に挿入して、HDMIケーブルとUSBキーボードを つなぎ、電源をつなげば起動する。

初回は、microSDカードいっぱいまで使用可能領域を伸長させる処理があるので、 何もできない。 自動的に再起動した後にログインできる。 この時点では、ユーザーIDはroot、パスワードは設定なしでログインできる。 以下のようなカーネルのブートメッセージが表示できた。 いたる所にfdtと入っている。


Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
    The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 8.99.9 (SUNXI) #0: Sat Dec 16 00:35:22 JST 2017
 ryoon@datesquare:/usr/world/8.99/evbearmv7hf-el/obj/sys/arch/evbarm/compile/SUNXI
total memory = 1016 MB
avail memory = 998 MB
timecounter: Timecounters tick every 10.000 msec
armfdt0 (root)
fdt0 at armfdt0: Cubietech Cubieboard2
fdt1 at fdt0
fdt2 at fdt0
fdt3 at fdt0
cpus0 at fdt0
cpu0 at cpus0: Cortex-A7 r0p4 (Cortex V7A core)
cpu0: DC enabled IC enabled WB disabled EABT branch prediction enabled
cpu0: 32KB/32B 2-way L1 VIPT Instruction cache
cpu0: 32KB/64B 4-way write-back-locking-C L1 PIPT Data cache
cpu0: 256KB/64B 8-way write-through L2 PIPT Unified cache
vfp0 at cpu0: NEON MPE (VFP 3.0+), rounding, NaN propagation, denormals
cpufreqdt0 at cpu0
cpu1 at cpus0
gic0 at fdt1: GIC
armgic0 at gic0: Generic Interrupt Controller, 160 sources (150 valid)
armgic0: 16 Priorities, 128 SPIs, 7 PPIs, 15 SGIs
fclock0 at fdt2: 25000000 Hz fixed clock
fclock1 at fdt2: 125000000 Hz fixed clock
fclock2 at fdt2: 24000000 Hz fixed clock
fclock3 at fdt2: 32768 Hz fixed clock
gtmr0 at fdt0: Generic Timer
gtmr0: interrupting on GIC irq 27
armgtmr0 at gtmr0: ARMv7 Generic 64-bit Timer (24000 kHz)
timecounter: Timecounter "armgtmr0" frequency 24000000 Hz quality 500
sun4ia10ccu0 at fdt1: A20 CCU
sunxigmacclk0 at fdt2: GMAC MII/RGMII clock mux
sunxigpio0 at fdt1: PIO
gpio0 at sunxigpio0: 175 pins
sunxigpio0: interrupting on GIC irq 60
sunxisramc0 at fdt1: SRAM Controller
sunxisramc0: area: SRAM A3/A4
sunxisramc0: area: SRAM D
fregulator0 at fdt0: vcc3v3
fregulator1 at fdt0: usb1-vbus
fregulator2 at fdt0: usb2-vbus
fregulator3 at fdt0: ahci-5v
fregulator4 at fdt0: vcc3v0
fregulator5 at fdt0: vcc5v0
sunxisid0 at fdt1: Security ID EFUSE
sunxiusbphy0 at fdt1: USB PHY
sunxitwi0 at fdt1: Marvell TWSI controller
sunxitwi0: interrupting on GIC irq 39
iic0 at sunxitwi0: I2C bus
axp20x0 at iic0 addr 0x34: AC used
axp20x0: DCDC2 1400mV
axp20x0: DCDC3 1250mV
axp20x0: LDO2 3000mV, LDO4 3300mV
axp20x0: LDO3 2800mV
axp20xreg0 at axp20x0: dcdc2 (vdd-cpu)
axp20xreg1 at axp20x0: dcdc3 (vdd-int-dll)
sunxits0 at fdt1: Touch Screen Controller
sunxits0: interrupting on GIC irq 61
/soc@1c00000/display-frontend@1e00000 at fdt1 not configured
/soc@1c00000/display-frontend@1e20000 at fdt1 not configured
sun4idma0 at fdt1: DMA controller
sun4idma0: interrupting on GIC irq 59
/soc@1c00000/display-backend@1e60000 at fdt1 not configured
/soc@1c00000/display-backend@1e40000 at fdt1 not configured
/soc@1c00000/hdmi@1c16000 at fdt1 not configured
/soc@1c00000/lcd-controller@1c0c000 at fdt1 not configured
/soc@1c00000/lcd-controller@1c0d000 at fdt1 not configured
/hdmi-connector at fdt0 not configured
/soc@1c00000/interrupt-controller@1c00030 at fdt1 not configured
awge0 at fdt1: GMAC
awge0: interrupting on GIC irq 117
awge0: Ethernet address: 02:0d:0b:82:26:14
rlphy0 at awge0 phy 1: RTL8201L 10/100 media interface, rev. 1
rlphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
psci0 at fdt0: PSCI 0.1
/pmu at fdt0 not configured
/display-engine at fdt0 not configured
gpioleds0 at fdt0: cubieboard2:blue:usr cubieboard2:green:usr
sunximmc0 at fdt1: SD/MMC controller
sunximmc0: interrupting on GIC irq 64
motg0 at fdt1: 'otg' mode not supported
ehci0 at fdt1: EHCI
ehci0: interrupting on GIC irq 71
ehci0: EHCI version 1.0
ehci0: 1 companion controller, 1 port
usb0 at ehci0: USB revision 2.0
ohci0 at fdt1: OHCI
ohci0: interrupting on GIC irq 96
ohci0: OHCI version 1.0
usb1 at ohci0: USB revision 1.0
/soc@1c00000/crypto-engine@1c15000 at fdt1 not configured
ahcisata0 at fdt1: SATA
ahcisata0: interrupting on GIC irq 88
ahcisata0: ignoring broken port multiplier support
ahcisata0: AHCI revision 1.10, 1 port, 32 slots, CAP 0x6f24ff80
atabus0 at ahcisata0 channel 0
ehci1 at fdt1: EHCI
ehci1: interrupting on GIC irq 72
ehci1: EHCI version 1.0
ehci1: 1 companion controller, 1 port
usb2 at ehci1: USB revision 2.0
ohci1 at fdt1: OHCI
ohci1: interrupting on GIC irq 97
ohci1: OHCI version 1.0
usb3 at ohci1: USB revision 1.0
sunxitimer0 at fdt1: Timer
sunxiwdt0 at fdt1: Watchdog
sunxiwdt0: default watchdog period is 16 seconds
sunxirtc0 at fdt1: RTC
/soc@1c00000/ir@1c21800 at fdt1 not configured
sunxicodec0 at fdt1: A10 Audio Codec
audio0 at sunxicodec0: full duplex, playback, capture, mmap, independent
sunxicodec0: Virtual format configured - Format SLINEAR, precision 16, channels 2, frequency 48000
sunxicodec0: Latency: 256 milliseconds
spkr0 at audio0: PC Speaker (synthesized)
wsbell at spkr0 not configured
com0 at fdt1: ns16550a, working fifo
com0: interrupting on GIC irq 33
sunxitwi1 at fdt1: Marvell TWSI controller
sunxitwi1: interrupting on GIC irq 40
iic1 at sunxitwi1: I2C bus
/soc@1c00000/hstimer@1c60000 at fdt1 not configured
genfb0 at fdt3: Simple Framebuffer (1920x1080 32-bpp @ 0x7f817000)
genfb0: switching to framebuffer console
genfb0: framebuffer at 0x7f817000, size 1920x1080, depth 32, stride 7680
wsdisplay0 at genfb0 kbdmux 1: console (default, vt100 emulation)
wsmux1: connecting to wsdisplay0
wsdisplay0: screen 1-3 added (default, vt100 emulation)
timecounter: Timecounter "clockinterrupt" frequency 100 Hz quality 0
cpu1: Cortex-A7 r0p4 (Cortex V7A core)
cpu1: DC enabled IC enabled WB disabled EABT branch prediction enabled
cpu1: 32KB/32B 2-way L1 VIPT Instruction cache
cpu1: 32KB/64B 4-way write-back-locking-C L1 PIPT Data cache
cpu1: 256KB/64B 8-way write-through L2 PIPT Unified cache
vfp1 at cpu1: NEON MPE (VFP 3.0+), rounding, NaN propagation, denormals
cpufreqdt0: 960.000 MHz, 1400000 uV
cpufreqdt0: 912.000 MHz, 1400000 uV
cpufreqdt0: 864.000 MHz, 1300000 uV
cpufreqdt0: 720.000 MHz, 1200000 uV
cpufreqdt0: 528.000 MHz, 1100000 uV
cpufreqdt0: 312.000 MHz, 1000000 uV
cpufreqdt0: 144.000 MHz, 1000000 uV
sdmmc0 at sunximmc0
uhub0 at usb1: Generic (0000) OHCI root hub (0000), class 9/0, rev 1.00/1.00, addr 1
uhub0: 1 port with 1 removable, self powered
uhub1 at usb0: Generic (0000) EHCI root hub (0000), class 9/0, rev 2.00/1.00, addr 1
uhub1: 1 port with 1 removable, self powered
uhub2 at usb3: Generic (0000) OHCI root hub (0000), class 9/0, rev 1.00/1.00, addr 1
uhub2: 1 port with 1 removable, self powered
uhub3 at usb2: Generic (0000) EHCI root hub (0000), class 9/0, rev 2.00/1.00, addr 1
uhub3: 1 port with 1 removable, self powered
IPsec: Initialized Security Association Processing.
sdmmc0: SD card status: 4-bit, C10, U1
ld0 at sdmmc0: <0x03:0x5344:SL32G:0x80:0x61532365:0x0f3>
ld0: 29476 MB, 7486 cyl, 128 head, 63 sec, 512 bytes/sect x 60367872 sectors
ld0: 4-bit width, High-Speed/SDR25, 50.000 MHz
ehci0: handing over low speed device on port 1 to companion controller
boot device: ld0
root on ld0a dumps on ld0b
root file system type: ffs
kern.module.path=/stand/evbarm/8.99.9/modules
WARNING: preposterous TOD clock time
WARNING: using filesystem time
WARNING: CHECK AND RESET THE DATE!
uhidev0 at uhub0 port 1 configuration 1 interface 0
uhidev0: Dell (0x413c) Dell USB Keyboard (0x2003), rev 1.10/2.00, addr 2, iclass 3/1
ukbd0 at uhidev0: 8 Variable keys, 6 Array codes
wskbd0 at ukbd0: console keyboard, using wsdisplay0
wsdisplay0: screen 4 added (default, vt100 emulation)
cpu0cpu1が離れているのがおもしろい。

まとめ

fdt(4)を使ったNetBSD/evbarmの環境を体験することができた。

Slack代替のMattermostをNetBSD/amd64で使う(セットアップ編)

NetBSD Advent Calendar 2017の10日目の記事です。

はじめに

前回は、Slack代替のチャットプラットフォームである Mattermostの配布用アーカイブファイルを作成するところまでを説明した。

今回は、その配布用アーカイブファイルを使って、インストールし、 日本語のメッセージを全文検索できるようにするまでを説明する。

データベースサーバーの選択とインストール

Mattermostは、MySQLとPostgreSQLをバックエンドのデータベースサーバーとして 選択することができる。 しかし、日本語の全文検索が簡単にできるようになるのは、MySQL 5.7を使用 した場合のみである。 MySQL 5.7で新たに搭載された ngram full-text parserを使用するのである。

pkgsrcでは、MySQL 5.7.20を簡単に導入することができる。 以下のように実行すれば良い。


# cd /usr/pkgsrc/databases/mysql57-server
# make install
# cp /usr/pkg/share/examples/rc.d/mysqld /etc/rc.d
# echo "mysqld=YES" >> /etc/rc.conf

MySQL 5.7の下準備

MySQL 5.7では、データベースサーバーの初回起動時に、一時パスワードを 提示されるようになっている。


# vi /usr/pkg/etc/my.cnf
[mysqld]
ngram_token_size=2

# /etc/rc.d/mysqld start
Initializing MySQL database system tables.
2017-12-09T05:44:23.256256Z 0 [Warning] Changed limits: max_open_files: 3404 (requested 5000)
2017-12-09T05:44:23.258372Z 0 [Warning] Changed limits: table_open_cache: 1621 (requested 2000)
2017-12-09T05:44:23.260654Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2017-12-09T05:44:23.277197Z 0 [ERROR] Failed to create event (errno= 9).
2017-12-09T05:44:23.277217Z 0 [ERROR] Failed to start timer notify thread.
2017-12-09T05:44:23.277226Z 0 [ERROR] Failed to initialize timer component (errno 9).
2017-12-09T05:44:25.731713Z 0 [Warning] InnoDB: New log files created, LSN=45790
2017-12-09T05:44:25.995569Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.
2017-12-09T05:44:26.111703Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 043062cf-dca4-11e7-b252-940764e13c88.
2017-12-09T05:44:26.117750Z 0 [Warning] Gtid table is not ready to be used. Table 'mysql.gtid_executed' cannot be opened.
2017-12-09T05:44:27.029478Z 0 [Warning] CA certificate ca.pem is self signed.
2017-12-09T05:44:27.189609Z 1 [Note] A temporary password is generated for root@localhost: zPLeg5>afD/k
Starting mysqld.
ここでは、zPLeg5>afD/kがMySQLのrootユーザーの一時パスワードである。

一時パスワードは、変更しないと、以降の操作をすることはできない。 以下のように変更する。


$ mysql --user='root' --password='zPLeg5>afD/k'
mysql> alter user 'root'@'localhost' identified by 'root-password';

その上で、Mattermost用のユーザーmmuserを追加する。


$ mysql --user='root' --password='root-password'
mysql> create user 'mmuser'@'localhost' identified by 'mm-user-password';

Mattermost用のデータベースmattermostを追加し、 mmuserユーザーに操作権限を付与する。 Mattermostサーバーの初回起動時にテーブルの作成等を自動的に実行するので、 それに必要な操作権限がないといけない。 ここでは、mmusermattermostデータベースに関する全権限を付与した。


mysql> create database mattermost;
mysql> grant all on mattermost.* to 'mmuser'@'localhost';

Mattermostサーバーを配置する

MattermostはGo言語で生成されたバイナリーファイルであり、 配置する場所を選ばない。 ここでは、/opt/mattermostディレクトリーに配置することにする。


# mkdir /opt
# cd /opt
# tar zxvf /home/ryoon/go/src/github.com/mattermost/mattermost-server/dist/mattermost-team-netbsd-amd64.tar.gz
これにより、Mattermostサーバーは/opt/mattermost/bin/platform ファイルとして配置される。

Mattermostサーバーを起動する

単純に/opt/mattermost/bin/platformを起動すれば良いだけである。 永続的に使用するのであれば、いずれ/etc.rc.localで起動 するようにしておけば良い。 初回起動時には、/opt/mattermost/config/config.jsonファイルが 設定ファイルの雛形として生成される。 一度起動し、データベースが見つからないと 出たらCtrl-cで停止させ、/opt/mattermost/config/config.json 設定ファイルを編集しよう。 ここでは、ウェブ画面の標準の言語を日本語にする変更も実施しておく。 各ユーザーで指定できるが、最初の初期設定画面を日本語化しておくためである。


# /opt/mattermost/bin/platform
(省略)
(Ctrl-c押下)
# vi /opt/mattermost/config/config.json
(省略)
    "SqlSettings": {
        "DriverName": "mysql",
        "DataSource": "mmuser:mm-user-password@tcp(localhost:3306)/mattermost?charset=utf8mb4,utf8\u0026readTimeout=30s\u0026writeTimeout=30s",
        "DataSourceReplicas": [],
        "DataSourceSearchReplicas": [],
        "MaxIdleConns": 20,
        "MaxOpenConns": 300,
        "Trace": false,
        "AtRestEncryptKey": "zhk8pfcexaxsubwguc8eqqu8c75j4a9p",
        "QueryTimeout": 30
    },
(省略)
        "DefaultClientLocale": "ja",
(省略)
# /opt/mattermost/bin/platform
(Ctrl-c押下)
これで、必要なテーブルやインデックスが作成される。

日本語の全文検索を有効にする

MySQL 5.7のbgram full-text parserを使ったインデックスを チャットの投稿メッセージに対して作成し直す必要がある。 以下のように操作する。


$ mysql --user='mmuser' --password='mm-user-password' mattermost
mysql> alter table Posts drop index idx_posts_message_txt;                      
mysql> alter table Posts add fulltext index idx_posts_message_txt (`Message`) with parser ngram;

Mattermostサーバーを起動する

以下のように実行すれば良い。


# /opt/mattermost/bin/platform &

Mattermostのウェブ画面を開く

標準では、http://localhost:8065/で表示できるようになっている。 サブディレクトリーに配置する設定は存在しない。 pkgsrc/www/firefoxで動作を確認できる。 日本語のメッセージを投稿して、2文字以上であれば全文検索できることを確認する。

まとめ

NetBSD/amd64で、Mattermostサーバーを立ち上げ、MySQL 5.7を使って ngram full-text parserを利用した全文検索ができるようにした。

Slack代替のMattermostをNetBSD/amd64で使う(ビルド編)

NetBSD Advent Calendar 2017の9日目の記事です。

はじめに

Mattermostと言う チャットプラットフォームがある。これのCommunity Editionは LDAP認証機能がないなどちょっと使いにくい部分はあるのだが、 Linuxでは良い感じに動くのを確認していた。 日本語ユーザーインターフェイスもベータ扱いではあるが、 ほぼ翻訳できていると思う。

Mattermostは、サーバーはGo言語で書かれており、 ビルドにはnode.jsも必要となる。 どちらもGo 1.8以降、node.js 8以降が必要で、 例えばDebian GNU/Linux 9で動かそうとすると、 標準のパッケージマネジメントシステムに収録されている Goとnode.jsはこれよりずっと古いので、ディストリビューションのリポジトリー 以外から新しいバージョンをインストールしなくてはいけない。 その点、pkgsrcであれば、Goは新しいし、node,jsも新しいものを選べる。

また、Mattermostの開発環境には、dockerが必要なように思われるかもしれないが、 別になくてもちゃんと動かすことができる。

以下では、NetBSD/amd64 current上でMattermostのサーバーと ウェブアプリケーションをビルドするまでを紹介する。 実際に動かすまでは、次回に紹介したい。

ビルドに必要なツールを用意する

サーバーはGo言語で書かれているため、 pkgsrc/lang/goを インストールする。 以下のように操作すれば良い。


# cd /usr/pkgsrc/lang/go
# make install
この記事を書いている時点では、go-1.9.2というパッケージがインストールされる。

ウェブアプリケーションは、node.jsでビルドするため、以下のように最新のnode.jsを インストールしておく。


# cd /usr/pkgsrc/lang/nodejs
# make install
この記事を書いている時点では、nodejs-9.2.0nb1というパッケージがインストールされる。

ウェブアプリケーションのビルドの途中で、node.jsのmozjpegモジュールを インストールすることになる。 このモジュールは、Linuxであれば、コマンドのバイナリーファイルを 提供してくれるのだが、NetBSD用など当然ないので、バイナリーファイルを ビルドしないといけない。 そのためには、以下のパッケージが必要になる。 ちなみに、Debian GNU/Linux 9の場合にもlibpng12.soが提供 されていないため、mozjpegを使おうとする箇所で失敗する。

  • pkgsrc/devel/pkgconf
  • pkgsrc/devel/libtool-base
  • pkgsrc/graphics/png
もしかしたら、他にも必要かもしれない。 ここまで用意しておけば、mozjpegをローカルでビルドしようと試みるように なるので、エラーメッセージを見れば分かるはずである。

ウェブアプリケーションをビルドするには、 yarnというパッケージマネジメント システムが必要である。 yarnのインストール手順によると、以下のようにnpmコマンドを 使ってのインストールは推奨されていないようであるが、一番簡単な方法であり、 このためにしか使わないので、これを採用してしまう。


$ mkdir ~/yarn
$ cd ~/yarn
$ npm install yarn
$ set PATH=~/yarn/node_module/yarn/bin:$PATH

また、GNU makeも必要なので、インストールしておく。どこかで、gmakeをmakeとして呼び出しているようなので、シンボリックリンクも作っておく。


# cd /usr/pkgsrc/deve/gmake
# make install
$ ln -s /usr/pkg/bin/gmake ~/yarn/node_modeule/yarn/bin/make

ソースコードを配置する

Compiling Mattermostのウェブページにあるように配置していく。


$ mkdir -p ~/go/src/github.com/mattermost
$ cd ~/go/src/github.com/mattermost
$ git clone https://github.com/mattermost/mattermost-server.git
$ git clone https://github.com/mattermost/mattermost-webapp.git

配置したソースコードの場所を、環境変数に設定する。


$ set GOPATH=$HOME/go
$ export GOPATH
$ set PATH=$PATH:$GOPATH/bin

ビルドに必要なパッチを当てる

残念ながら、MattermostのMakefileは、あまり移植性を考慮していないようである。 また、開発用にはdockerを使うので、配布用のアーカイブファイルを作成する 部分について、最近は忘れられているようである。

どう直すのが適当であるかは明確ではないが、配布用のアーカイブファイルを 作成するには以下のようなパッチが必要である。 config/config.jsonファイルは、なければ自動的に生成されるので 用意しておく必要はないはずである。


diff --git a/build/release.mk b/build/release.mk
index 5eaee8022..285dcadac 100644
--- a/build/release.mk
+++ b/build/release.mk
@@ -36,16 +36,6 @@ package:
  cp -RL templates $(DIST_PATH)
  cp -RL i18n $(DIST_PATH)
 
- @# Disable developer settings
- sed -i'' -e 's|"ConsoleLevel": "DEBUG"|"ConsoleLevel": "INFO"|g' $(DIST_PATH)/config/config.json
- sed -i'' -e 's|"SiteURL": "http://localhost:8065"|"SiteURL": ""|g' $(DIST_PATH)/config/config.json
-
- @# Reset email sending to original configuration
- sed -i'' -e 's|"SendEmailNotifications": true,|"SendEmailNotifications": false,|g' $(DIST_PATH)/config/config.json
- sed -i'' -e 's|"FeedbackEmail": "test@example.com",|"FeedbackEmail": "",|g' $(DIST_PATH)/config/config.json
- sed -i'' -e 's|"SMTPServer": "dockerhost",|"SMTPServer": "",|g' $(DIST_PATH)/config/config.json
- sed -i'' -e 's|"SMTPPort": "2500",|"SMTPPort": "",|g' $(DIST_PATH)/config/config.json
-
  @# Package webapp
  mkdir -p $(DIST_PATH)/client
  cp -RL $(BUILD_WEBAPP_DIR)/dist/* $(DIST_PATH)/client

また、Go言語で書かれたサーバーをNetBSD/amd64向けにビルドするための ターゲットが必要である。 以下のように追加する。


diff --git a/Makefile b/Makefile
index a0cf74f1c..ff4bb8149 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-.PHONY: build package run stop run-client run-server stop-client stop-server restart restart-server restart-client start-docker clean-dist clean nuke check-style check-client-style check-server-style check-unit-tests test dist setup-mac prepare-enteprise run-client-tests setup-run-client-tests cleanup-run-client-tests test-client build-linux build-osx build-windows internal-test-web-client vet run-server-for-web-client-tests
+.PHONY: build package run stop run-client run-server stop-client stop-server restart restart-server restart-client start-docker clean-dist clean nuke check-style check-client-style check-server-style check-unit-tests test dist setup-mac prepare-enteprise run-client-tests setup-run-client-tests cleanup-run-client-tests test-client build-linux build-osx build-windows build-netbsd internal-test-web-client vet run-server-for-web-client-tests
 
 ROOT := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
 
diff --git a/build/release.mk b/build/release.mk
index 5eaee8022..c551e3ad0 100644
--- a/build/release.mk
+++ b/build/release.mk
@@ -13,6 +13,10 @@ build-windows:
  @echo Build Windows amd64
  env GOOS=windows GOARCH=amd64 $(GO) install $(GOFLAGS) $(GO_LINKER_FLAGS) ./cmd/platform
 
+build-netbsd:
+ @echo Build NetBSD amd64
+ env GOOS=netbsd GOARCH=amd64 $(GO) install $(GOFLAGS) $(GO_LINKER_FLAGS) ./cmd/platform
+
 build: build-linux build-windows build-osx
 
 build-client:

配布用のアーカイブファイルを作成する部分は、LinuxとmacOS、Windows用の全てを 用意するようになっているので、NetBSD用だけを用意するように変更してしまう。


diff --git a/build/release.mk b/build/release.mk
index 5eaee8022..0105cf681 100644
--- a/build/release.mk
+++ b/build/release.mk
@@ -61,38 +61,9 @@ endif
 
  @# ----- PLATFORM SPECIFIC -----
 
- @# Make osx package
  @# Copy binary
-ifeq ($(BUILDER_GOOS_GOARCH),"darwin_amd64")
  cp $(GOPATH)/bin/platform $(DIST_PATH)/bin # from native bin dir, not cross-compiled
-else
- cp $(GOPATH)/bin/darwin_amd64/platform $(DIST_PATH)/bin # from cross-compiled bin dir
-endif
- @# Package
- tar -C dist -czf $(DIST_PATH)-$(BUILD_TYPE_NAME)-osx-amd64.tar.gz mattermost
- @# Cleanup
- rm -f $(DIST_PATH)/bin/platform
-
- @# Make windows package
- @# Copy binary
-ifeq ($(BUILDER_GOOS_GOARCH),"windows_amd64")
- cp $(GOPATH)/bin/platform.exe $(DIST_PATH)/bin # from native bin dir, not cross-compiled
-else
- cp $(GOPATH)/bin/windows_amd64/platform.exe $(DIST_PATH)/bin # from cross-compiled bin dir
-endif
- @# Package
- cd $(DIST_ROOT) && zip -9 -r -q -l mattermost-$(BUILD_TYPE_NAME)-windows-amd64.zip mattermost && cd ..
- @# Cleanup
- rm -f $(DIST_PATH)/bin/platform.exe
-
- @# Make linux package
- @# Copy binary
-ifeq ($(BUILDER_GOOS_GOARCH),"linux_amd64")
- cp $(GOPATH)/bin/platform $(DIST_PATH)/bin # from native bin dir, not cross-compiled
-else
- cp $(GOPATH)/bin/linux_amd64/platform $(DIST_PATH)/bin # from cross-compiled bin dir
-endif
  @# Package
- tar -C dist -czf $(DIST_PATH)-$(BUILD_TYPE_NAME)-linux-amd64.tar.gz mattermost
+ tar -C dist -czf $(DIST_PATH)-$(BUILD_TYPE_NAME)-netbsd-amd64.tar.gz mattermost
  @# Don't clean up native package so dev machines will have an unzipped package available
  @#rm -f $(DIST_PATH)/bin/platform

ビルドする

これで、ビルドする準備はできたので、後はウェブアプリケーションとサーバーを ビルドし、配布用アーカイブファイルを作成すれば良い。 node.js、Goともにネットワーク経由でファイルを取得する。

まずはウェブアプリケーションをビルドする。以下のように実行すれば良い。 mattermost-serverディレクトリーの中で実行しているが、実際には mattermost-webapp内でビルドがされる。


$ cd ~/go/src/github.com/mattermost/mattermost-server
$ gmake build-client

次に、サーバーをビルドする。以下のように実行する。


$ cd ~/go/src/github.com/mattermost/mattermost-server
$ gmake build-netbsd

最後に、配布用アーカイブファイルを作成する。


$ cd ~/go/src/github.com/mattermost/mattermost-server
$ gmake package

まとめ

ここまでで、Mattermostのウェブアプリケーションとサーバーを含んだ mattermost-team-netbsd-amd64.tar.gzファイルが、 ~/go/src/github.com/mattermost/mattermost-server/dist ディレクトリーに生成される。

次回は、このmattermost-team-netbsd-amd64.tar.gzファイルを 使って、日本語のメッセージ検索が可能な環境を構築する。

NetBSD/amd64 8.0_BETAをConoHa VPSにインストールする

NetBSD Advent Calendar 2017の8日目の記事です。

はじめに

2015年5月17日以前にConoHaにアカウントを作っていたので、 新しくなったConoHaのVPSを試していなかった。 NetBSDに関しては、NetBSD/amd64 7.1のテンプレートが用意されているようだ。 しかし、NetBSD 8.0_BETAが試せるので、NetBSD/amd64 8.0_BETAを インストールしたいと言うのが人情だと思う。

ConoHa VPSではOpenStackをインフラストラクチャーとして使用しているとのことで、 OpenStack APIを使用することができる。 こう書くと便利なようだが、OpenStack APIを使わないとISOイメージの持ち込みも できないので、逆に不便な気もする。

多数の仮想マシンを展開する場合には、何でもAPIで実行できるのは意味が あると思うのだが、今回はAPIが必要でないものにはAPIを使用しないようにする。

手順を想定する

仮想マシンでないハードウェアにインストールする場合と変わることはないと 思うが、以下のような順序でインストールすることにする。

  1. ISOイメージを用意する
  2. ISOイメージをマウントする
  3. ISOイメージから起動させる
  4. インストールする
  5. シャットダウンする
  6. ISOイメージをアンマウントする
  7. 起動させる

OpenStack APIを調べてみる

それぞれのステップに必要なAPIや操作を調べてみる。

ISOイメージを用意する

ISOイメージダウンロードが使用できる。 http等で拡張子.isoのISOイメージファイルのみダウンロードできるとのこと。

ISOイメージをマウントする

ISOイメージの挿入(mount) が使用できる。 仮想マシンが停止中のみマウント可能であるとのこと。

ISOイメージから起動させる

仮想マシンの起動は、コントロールパネルのウェブページから可能である。 APIでもできるだろうが、ウェブページからできるので、APIは使用しない。

インストールする

インストールは、APIの関係するものではないので、APIは使用しない。

シャットダウンする

仮想マシンのシャットダウンは、NetBSDでshutdown -p nowを 実行すれば良いはずなので、APIは使用しない。

ISOイメージをアンマウントする

ISOイメージの排出(unmount) が使用できる。 仮想マシンが停止中のみ可能であるとのこと。

起動させる

「ISOイメージから起動させる」と同じであるので、コントロールパネルの ウェブページで起動可能である。APIを使用する必要はない。

APIを操作する

実際には、JSONをHTTPSで送ることによって操作する。 ConoHaのページには、 curlを 使う例が出ているのだが、そのまま使ってもおもしろくない。 なので、Firefox 57で動く拡張機能である RESTEDを使うことにする。

早速ISOイメージをダウンロードしようとしたのだが、認証のためのトークンが 必要であった。 APIを使用するためのトークンを取得するにあるようにしないといけない。 具体的にはテナントIDをウェブページに表示させ、 それを使ってIdentity Serviceでトークンを取得する。 下図のようにして、トークンを取得する。


無事にaccess.token.idでトークンが取得できたので、 トークンの期限が切れないうちに先に進めよう。

ISOイメージを用意する

以下のようにISOイメージをダウンロードする。 cdn.NetBSD.orgからダウンロードすることにする。

やはり、ダウンロードした結果を確認しないと不安である。

確かにダウンロードされたようである。スクリーンショットをとっている時間内にダウンロードは完了してしまったようである。 ちなみにISOイメージを消す機能はない。だがある程度時間が経つと、自動的に削除されるようである。

ISOイメージをマウントする

サーバーを用意し、サーバーのUUIDを確認しておく。 サーバーは停止しておく。

ISOイメージをアンマウントする

サーバーは停止しておく。

おわりに

NetBSD/amd64 8.0_BETAは特に問題なく稼動している。

安価なPostScriptレーザープリンターLexmark MS312dnをNetBSDから使う(lpd(8)編)

NetBSD Advent Calendar 2017の6日目の記事です。

はじめに

最近は安価にレーザープリンターを購入できるが、さすがにPostScriptレーザープリンターは、なかなか安くは購入できない。 NTT-X Storeで安価にPostScript白黒レーザープリンターであるLexmark MS312dnが8,800円(税込)で購入できた。 ちなみに、これを書いている時点で在庫は残り3台である。

NetBSDからこのレーザープリンターを使ってみた。 lpd(8)を使った場合について書く。 いずれCUPSを使った場合について書きたい。

lpd(8)とlp(1)の使い方

NetBSDに限らず、lpd(8)lp(1)を使う話になってしまうかもしれない。

lpd(8)で印刷する対象として登録する

lpd(8)の設定ファイルは、 printcap(5)であり、 編集すべきファイルは、/etc/printcapである。

Lexmark社のウェブサイトから、Lexmark-ADS-PPD-Files.tar.Zをダウンロードし、 展開した内容のうち、 Lexmark_MS310_Series.ppdを、 /opt/share/print/Lexmark_MS310_Series.ppdのように配置しておく。

その上で、/etc/printcapに、以下のように追加する。


lp|lmprinter:\
        :lp=:sh:sd=/var/spool/lpd/lp:\
        :rm=lmprinter:\
        :lf=/var/log/lpd-errs:mx#0:\
        :af=/opt/share/print/Lexmark_MS310_Series.ppd:
ここで、lmprinterはネットワーク接続されたLexmark MS312dnのホスト名である。 我が家では、 pkgsrc/net/isc-dhcpd4 とNetBSD/amd64 7のbaseに収録されているbindで dynamic DNSを設定しているのだが、Lexmark MS312dnにはうまくホスト名を割り当て できなかった。 そのため、固定でIPv4のアドレスを割り当ててある。

lpd(8)を起動する

lpd(8)をデーモンとして起動しておく必要がある。 /etc/rc.confにlpd(8)を起動するように設定しておく。


# vi /etc/rc.conf
(以下を追加する)
lpd=YES
その上で、初回は手動で起動させる。

# /etc/rc.d/lpd start
もし、/var/spool/lpd/lpディレクトリーがない場合には、 以下のようにして作成しておく。

# mkdir -p /var/spool/lpd/lp

印刷する

lpd(8)にPostScriptファイルをlp(1)コマンドを使って送信する。 GhostScript をインストールしてあれば、 虎の絵が/usr/pkg/share/ghostscript/9.06/examples/tiger.epsに 格納されている。 これを印刷するのであれば、以下のように実行する。


$ cat /usr/pkg/share/ghostscript/9.06/examples/tiger.eps | lp -d lp
ここで、lpと言うのが、/etc/printcapに設定してある Lexmark MX312dnの名前である。

NetBSDでは、Mozilla FirefoxやxpdfでPostScriptファイルを生成できるので、 これでWindows環境に頼ることなく、自由に印刷できる。

NetBSD/i386用のRust言語のブートストラップキットを作成する

NetBSD Advent Calendar 2017の5日目の記事です。

はじめに

新しいMozilla Firefoxのビルドには、Rustプログラミング言語のコンパイラーであるrustcと、パッケージ管理プログラムのcargoが必要となっている。 jakllschさんがNetBSD/amd64には移植してくれているので、RustのアップストリームがNetBSD/amd64 7向けのブートストラップキットはビルドしてくれている。 だが、NetBSD/i386 7向けがないと、Mozilla FirefoxをNetBSD/i386でビルドできない。

私はhttps://deuterium.ryoon.net/pub/rust/でnetBSD/i386 7用のブートストラップキット を公開しているが、信頼できるか分からない人の作ったコンパイラーなど使うべきではない。 ここにブートストラップキットの作り方を書いておくので、自分のためのブートストラップキットを作って使って欲しい。

# RustのアップストリームにどうやってNetBSD/i386用をビルドしてもらうように交渉すれば良いのか…。

NetBSD/amd64の環境を用意する

NetBSD/amd64 7.0以降の環境を用意する。Rustのアップストリームのビルドしているブートストラップキットが動けばNetBSD/amd64のバージョンは問わない。 ここでは、NetBSD/amd64 7.1の環境があったので、それを使用することにした。

ところで、原理的にはNetBSD/amd64である必要もない。 ある程度POSIX準拠なオペレーティングシステムで、Rustがサポートしブートストラップキットを提供しているアーキテクチャーであれば良い。 次に説明するNetBSD/i386のクロスツールチェインはそこでビルドできるはずである。

NetBSD/i386 7用のクロスツールチェインとユーザーランドをビルドする

NetBSDはクロスツールチェインを簡単に生成でき、クロスコンパイルをする準備が簡単にできるのが良い所である。 まず、以下のように実行してクロスコンパイラーなどのツールチェインを作成する。 これは、NetBSD/i386のユーザーランドをビルドするのに使用するだけでなく、Rustブートストラップキットをビルドするのにも使用する。 ここで、/usr/srcにnetbsd-7のツリーを用意してあるとする。


$ cd /usr/src
$ ./build.sh -m i386 -U -T /usr/world/7/i386/tools -O /usr/world/7/i386/obj -D /usr/world/7/i386/destdir tools
$ ./build.sh -m i386 -U -T /usr/world/7/i386/tools -O /usr/world/7/i386/obj -D /usr/world/7/i386/destdir build
これで、/usr/world/7/i386/tools以下にクロスツールチェインが用意され、 それを使って/usr/world/7/i386/destdir以下にユーザーランドがビルドされインストールされた。

クロスツールチェインを改造する

Rustブートストラップキットに使用するクロスコンパイラーのgccとg++には、いくつかのコマンドライン引数を与えて動かす必要があるのだが、 Rustのブートストラップメカニズムはそのようなコマンドライン引数を与えてgcc/g++を呼び出してはくれない。 なので、必要なコマンドライン引数をあらかじめ指定したシェルスクリプトを用意し、それをクロスコンパイラーの代わりに使用することにする。 以下のようにi486--netbsdelf-g++-sysrooti486--netbsdelf-gcc-sysrootを用意しておく。


$ cat /usr/world/7/i386/tools/bin/i486--netbsdelf-g++-sysroot
#! /bin/sh
/usr/world/7/i386/tools/bin/i486--netbsdelf-g++ --sysroot=/usr/world/7/i386/destdir -march=i586 "$@"

$ cat /usr/world/7/i386/tools/bin/i486--netbsdelf-gcc-sysroot
#! /bin/sh
/usr/world/7/i386/tools/bin/i486--netbsdelf-gcc --sysroot=/usr/world/7/i386/destdir "$@"
ここで、-march=i586は、atomic ops関連の関数がundefined referenceにならないために必要だったはずである。

NetBSD/i386のユーザーランドに必要なパッケージをインストールする

/usr/world/7/i386/destdirにユーザーランドが用意されているが、Rustブートストラップキットをビルドするには、 pkgsrc/lang/rustが必要としているような ライブラリーが必要になる。 llvm関係はRustのソースコードに含まれているので、それ以外を/usr/world/7/i386/destdirにインストールしておく。 NetBSD/amd64では、NetBSD/i386のバイナリーを実行できるので、ここではchroot(8)コマンドを使って、ライブラリーを準備してしまった。 これは安直な方法なので、例えば今後NetBSD/earm向けのRustブートストラップキットを作ろうと言う場合には、この方法は採用できない。 必要なライブラリーをクロスビルドして配置するか、NetBSD/earmでビルドとインストールしたユーザーランドをコピーして来る必要があるだろう。


# chroot /usr/world/7/i386/destdir /bin/ksh
# pkg_add libgit2-0.26.0nb1.tgz
; 手作業でlibhttp_parser.aをビルドし、/usr/libに配置する。
; 合わせて、http_parser.hを/usr/includeに配置する。
# exit
ここで、http-parserは、 /usr/pkg以下にあってはビルドに失敗した。 面倒だったので/usr以下に配置したが、本来であればRustで書かれたRustのビルドメカニズムを修正すべきであろう。

NetBSD/amd64 7用のRustをビルドできるようにする

この先、NetBSD/amd64用のrustcやcargoをビルドし、それを使ってNetBSD/i386 7用のrustcやcargoをビルドしていくのである。 当然だが、NetBSD/amd64向けにpkgsrc/lang/rust が必要とするライブラリー等が用意されている必要がある。 以下のように実行すれば、/usr/pkg以下にインストールされる。 ついでに、Rustブートストラップキットが必要とするGNU coreutilsOpenSSL用のルート証明書ninjaもインストールしてしまおう。 ninjaは、lllvmの部分をパラレルビルドするのに必要となる。


# cd /usr/pkgsrc/lang/rust
# make depends
# cd /usr/pkgsrc/sysutils/coreutils
# make install
# cd /usr/pkgsrc/security/mozilla-rootcerts-openssl
# make install

Rustブートストラップキットを展開する

基本的には、一つ前のリリースのブートストラップキットを使って、最新のリリースのブートストラップキットを作るのだと思う。 ここでは、Rust 1.22.1をNetBSD/i386 7でビルドしようとしているので、1.21.0のブートストラップキットを作ることになる。 その1.21.0のブートストラップキットをビルドするために使用するRustアップストリームのブートストラップキットは、1.20.0となる。 以下のように展開しておく。


$ mkdir ~/tmp
$ cd ~/tmp
$ ftp http://static.rust-lang.org/dist/rust-1.21.0-x86_64-unknown-netbsd.tar.gz
$ ftp http://static.rust-lang.org/dist/rust-std-1.20.0-i686-unknown-netbsd.tar.gz
$ tar zxvf rust-1.21.0-x86_64-unknown-netbsd.tar.gz
$ tar zxvf rust-std-1.20.0-i686-unknown-netbsd.tar.gz
$ mv rust-std-1.20.0-x86_64-unknown-netbsd/rust-std-x86_64-unknown-netbsd/lib/rustlib/x86_64-unknown-netbsd \
rust-1.20.0-x86_64-unknown-netbsd/rustc/lib/rustlib/
$ rm -r rust-std-1.20.0-x86_64-unknown-netbsd

NetBSD/i386のためのパッチを適用する

NetBSD/i386のRustブートストラップキットをビルドするのに必要なパッチを適用する。 そのパッチは以下のようである。


--- src/bootstrap/native.rs
+++ src/bootstrap/native.rs
@@ -407,6 +407,7 @@ impl Step for Openssl {
             "i686-unknown-freebsd" => "BSD-x86-elf",
             "i686-unknown-linux-gnu" => "linux-elf",
             "i686-unknown-linux-musl" => "linux-elf",
+            "i686-unknown-netbsd" => "BSD-x86-elf",
             "mips-unknown-linux-gnu" => "linux-mips32",
             "mips64-unknown-linux-gnuabi64" => "linux64-mips64",
             "mips64el-unknown-linux-gnuabi64" => "linux64-mips64",

NetBSD/amd64 7のためのパッチを適用する

NetBSD/amd64 7で動くllvmのバイナリーを得るには、以下のパッチが必要であった。NetBSD/amd64 8以降では不要らしい。


--- src/llvm/cmake/modules/AddLLVM.cmake
+++ src/llvm/cmake/modules/AddLLVM.cmake
@@ -1422,7 +1422,7 @@ function(llvm_setup_rpath name)
     set(_install_name_dir INSTALL_NAME_DIR "@rpath")
     set(_install_rpath "@loader_path/../lib" ${extra_libdir})
   elseif(UNIX)
-    set(_install_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir})
+#    set(_install_rpath "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}" ${extra_libdir})
     if(${CMAKE_SYSTEM_NAME} MATCHES "(FreeBSD|DragonFly)")
       set_property(TARGET ${name} APPEND_STRING PROPERTY
                    LINK_FLAGS " -Wl,-z,origin ")

config.tomlにビルド条件を設定する

以下のようにi686-unknown-netbsdブートストラップキットを作ること、その他のコマンドのパス等々を設定する。


# Sample TOML configuration file for building Rust.
#
# To configure rustbuild, copy this file to the directory from which you will be
# running the build, and name it config.toml.
#
# All options are commented out by default in this file, and they're commented
# out with their default values. The build system by default looks for
# `config.toml` in the current directory of a build for build configuration, but
# a custom configuration file can also be specified with `--config` to the build
# system.

# =============================================================================
# Tweaking how LLVM is compiled
# =============================================================================
[llvm]

# Indicates whether rustc will support compilation with LLVM
# note: rustc does not compile without LLVM at the moment
#enabled = true

# Indicates whether the LLVM build is a Release or Debug build
#optimize = true

# Indicates whether an LLVM Release build should include debug info
#release-debuginfo = false

# Indicates whether the LLVM assertions are enabled or not
#assertions = false

# Indicates whether ccache is used when building LLVM
#ccache = false
# or alternatively ...
#ccache = "/path/to/ccache"

# If an external LLVM root is specified, we automatically check the version by
# default to make sure it's within the range that we're expecting, but setting
# this flag will indicate that this version check should not be done.
#version-check = true

# Link libstdc++ statically into the librustc_llvm instead of relying on a
# dynamic version to be available.
static-libstdcpp = true

# Tell the LLVM build system to use Ninja instead of the platform default for
# the generated build system. This can sometimes be faster than make, for
# example.
ninja = true

# LLVM targets to build support for.
# Note: this is NOT related to Rust compilation targets. However, as Rust is
# dependent on LLVM for code generation, turning targets off here WILL lead to
# the resulting rustc being unable to compile for the disabled architectures.
# Also worth pointing out is that, in case support for new targets are added to
# LLVM, enabling them here doesn't mean Rust is automatically gaining said
# support. You'll need to write a target specification at least, and most
# likely, teach rustc about the C ABI of the target. Get in touch with the
# Rust team and file an issue if you need assistance in porting!
#targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon"

# LLVM experimental targets to build support for. These targets are specified in
# the same format as above, but since these targets are experimental, they are
# not built by default and the experimental Rust compilation targets that depend
# on them will not work unless the user opts in to building them. Possible
# experimental LLVM targets include WebAssembly for the
# wasm32-experimental-emscripten Rust target.
#experimental-targets = ""

# Cap the number of parallel linker invocations when compiling LLVM.
# This can be useful when building LLVM with debug info, which significantly
# increases the size of binaries and consequently the memory required by
# each linker process.
# If absent or 0, linker invocations are treated like any other job and
# controlled by rustbuild's -j parameter.
#link-jobs = 0

# When invoking `llvm-config` this configures whether the `--shared` argument is
# passed to prefer linking to shared libraries.
#link-shared = false

# =============================================================================
# General build configuration options
# =============================================================================
[build]

# Build triple for the original snapshot compiler. This must be a compiler that
# nightlies are already produced for. The current platform must be able to run
# binaries of this build triple and the nightly will be used to bootstrap the
# first compiler.
build = "x86_64-unknown-netbsd"    # defaults to your host platform

# In addition to the build triple, other triples to produce full compiler
# toolchains for. Each of these triples will be bootstrapped from the build
# triple and then will continue to bootstrap themselves. This platform must
# currently be able to run all of the triples provided here.
host = ["i686-unknown-netbsd"]   # defaults to just the build triple

# In addition to all host triples, other triples to produce the standard library
# for. Each host triple will be used to produce a copy of the standard library
# for each target triple.
target = ["i686-unknown-netbsd"] # defaults to just the build triple

# Instead of downloading the src/stage0.txt version of Cargo specified, use
# this Cargo binary instead to build all Rust code
cargo = "/home/ryoon/tmp/rust-1.20.0-x86_64-unknown-netbsd/cargo/bin/cargo"

# Instead of downloading the src/stage0.txt version of the compiler
# specified, use this rustc binary instead as the stage0 snapshot compiler.
rustc = "/home/ryoon/tmp/rust-1.20.0-x86_64-unknown-netbsd/rustc/bin/rustc"

# Flag to specify whether any documentation is built. If false, rustdoc and
# friends will still be compiled but they will not be used to generate any
# documentation.
docs = true

# Indicate whether the compiler should be documented in addition to the standard
# library and facade crates.
compiler-docs = true

# Indicate whether submodules are managed and updated automatically.
#submodules = true

# The path to (or name of) the GDB executable to use. This is only used for
# executing the debuginfo test suite.
#gdb = "gdb"

# The node.js executable to use. Note that this is only used for the emscripten
# target when running tests, otherwise this can be omitted.
#nodejs = "node"

# Python interpreter to use for various tasks throughout the build, notably
# rustdoc tests, the lldb python interpreter, and some dist bits and pieces.
# Note that Python 2 is currently required.
python = "/usr/pkg/bin/python2.7"

# Force Cargo to check that Cargo.lock describes the precise dependency
# set that all the Cargo.toml files create, instead of updating it.
#locked-deps = false

# Indicate whether the vendored sources are used for Rust dependencies or not
vendor = true

# Typically the build system will build the rust compiler twice. The second
# compiler, however, will simply use its own libraries to link against. If you
# would rather to perform a full bootstrap, compiling the compiler three times,
# then you can set this option to true. You shouldn't ever need to set this
# option to true.
full-bootstrap = false

# Enable a build of the extended rust tool set which is not only the compiler
# but also tools such as Cargo. This will also produce "combined installers"
# which are used to install Rust and Cargo together. This is disabled by
# default.
extended = true

# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
#verbose = 0

# Build the sanitizer runtimes
#sanitizers = false

# Build the profiler runtime
#profiler = false

# Indicates whether the OpenSSL linked into Cargo will be statically linked or
# not. If static linkage is specified then the build system will download a
# known-good version of OpenSSL, compile it, and link it to Cargo.
openssl-static = true

# Run the build with low priority, by setting the process group's "nice" value
# to +10 on Unix platforms, and by using a "low priority" job object on Windows.
#low-priority = false

# Arguments passed to the `./configure` script, used during distcheck. You
# probably won't fill this in but rather it's filled in by the `./configure`
# script.
#configure-args = []

# Indicates that a local rebuild is occurring instead of a full bootstrap,
# essentially skipping stage0 as the local compiler is recompiling itself again.
#local-rebuild = false

# =============================================================================
# General install configuration options
# =============================================================================
[install]

# Instead of installing to /usr/local, install to this path instead.
#prefix = "/usr/local"

# Where to install system configuration files
# If this is a relative path, it will get installed in `prefix` above
#sysconfdir = "/etc"

# Where to install documentation in `prefix` above
#docdir = "share/doc/rust"

# Where to install binaries in `prefix` above
#bindir = "bin"

# Where to install libraries in `prefix` above
#libdir = "lib"

# Where to install man pages in `prefix` above
#mandir = "share/man"

# Where to install data in `prefix` above (currently unused)
#datadir = "share"

# Where to install additional info in `prefix` above (currently unused)
#infodir = "share/info"

# Where to install local state (currently unused)
# If this is a relative path, it will get installed in `prefix` above
#localstatedir = "/var/lib"

# =============================================================================
# Options for compiling Rust code itself
# =============================================================================
[rust]

# Indicates that the build should be optimized for debugging Rust. Note that
# this is typically not what you want as it takes an incredibly large amount of
# time to have a debug-mode rustc compile any code (notably libstd). If this
# value is set to `true` it will affect a number of configuration options below
# as well, if unconfigured.
#debug = false

# Whether or not to optimize the compiler and standard library
# Note: the slowness of the non optimized compiler compiling itself usually
#       outweighs the time gains in not doing optimizations, therefore a
#       full bootstrap takes much more time with optimize set to false.
#optimize = true

# Number of codegen units to use for each compiler invocation. A value of 0
# means "the number of cores on this machine", and 1+ is passed through to the
# compiler.
#codegen-units = 1

# Whether or not debug assertions are enabled for the compiler and standard
# library. Also enables compilation of debug! and trace! logging macros.
#debug-assertions = false

# Whether or not debuginfo is emitted
#debuginfo = false

# Whether or not line number debug information is emitted
#debuginfo-lines = false

# Whether or not to only build debuginfo for the standard library if enabled.
# If enabled, this will not compile the compiler with debuginfo, just the
# standard library.
#debuginfo-only-std = false

# Whether or not jemalloc is built and enabled
#use-jemalloc = true

# Whether or not jemalloc is built with its debug option set
#debug-jemalloc = false

# Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
#backtrace = true

# The default linker that will be hard-coded into the generated compiler for
# targets that don't specify linker explicitly in their target specifications.
# Note that this is not the linker used to link said compiler.
#default-linker = "cc"

# The "channel" for the Rust build to produce. The stable/beta channels only
# allow using stable features, whereas the nightly and dev channels allow using
# nightly features
channel = "stable"

# By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix
# platforms to ensure that the compiler is usable by default from the build
# directory (as it links to a number of dynamic libraries). This may not be
# desired in distributions, for example.
#rpath = true

# Suppresses extraneous output from tests to ensure the output of the test
# harness is relatively clean.
#quiet-tests = false

# Flag indicating whether tests are compiled with optimizations (the -O flag) or
# with debuginfo (the -g flag)
#optimize-tests = true
#debuginfo-tests = true

# Flag indicating whether codegen tests will be run or not. If you get an error
# saying that the FileCheck executable is missing, you may want to disable this.
#codegen-tests = true

# Flag indicating whether git info will be retrieved from .git automatically.
# Having the git information can cause a lot of rebuilds during development.
# Note: If this attribute is not explicity set (e.g. if left commented out) it
# will default to true if channel = "dev", but will default to false otherwise.
#ignore-git = true

# When creating source tarballs whether or not to create a source tarball.
#dist-src = false

# Whether to also run the Miri tests suite when running tests.
# As a side-effect also generates MIR for all libraries.
#test-miri = false

# =============================================================================
# Options for specific targets
#
# Each of the following options is scoped to the specific target triple in
# question and is used for determining how to compile each target.
# =============================================================================
[target.i686-unknown-netbsd]

# C compiler to be used to compiler C code. Note that the
# default value is platform specific, and if not specified it may also depend on
# what platform is crossing to what platform.
#cc = "cc"

# C++ compiler to be used to compiler C++ code (e.g. LLVM and our LLVM shims).
# This is only used for host targets.
#cxx = "c++"

# Archiver to be used to assemble static libraries compiled from C/C++ code.
# Note: an absolute path should be used, otherwise LLVM build will break.
#ar = "ar"

# Linker to be used to link Rust code. Note that the
# default value is platform specific, and if not specified it may also depend on
# what platform is crossing to what platform.
#linker = "cc"

# Path to the `llvm-config` binary of the installation of a custom LLVM to link
# against. Note that if this is specifed we don't compile LLVM at all for this
# target.
#llvm-config = "../path/to/llvm/root/bin/llvm-config"

# Path to the custom jemalloc static library to link into the standard library
# by default. This is only used if jemalloc is still enabled above
#jemalloc = "/path/to/jemalloc/libjemalloc_pic.a"

# If this target is for Android, this option will be required to specify where
# the NDK for the target lives. This is used to find the C compiler to link and
# build native code.
#android-ndk = "/path/to/ndk"

# Force static or dynamic linkage of the standard library for this target. If
# this target is a host for rustc, this will also affect the linkage of the
# compiler itself. This is useful for building rustc on targets that normally
# only use static libraries. If unset, the target's default linkage is used.
#crt-static = false

# The root location of the MUSL installation directory. The library directory
# will also need to contain libunwind.a for an unwinding implementation. Note
# that this option only makes sense for MUSL targets that produce statically
# linked binaries
#musl-root = "..."

# Used in testing for configuring where the QEMU images are located, you
# probably don't want to use this.
#qemu-rootfs = "..."

# =============================================================================
# Distribution options
#
# These options are related to distribution, mostly for the Rust project itself.
# You probably won't need to concern yourself with any of these options
# =============================================================================
[dist]

# This is the folder of artifacts that the build system will sign. All files in
# this directory will be signed with the default gpg key using the system `gpg`
# binary. The `asc` and `sha256` files will all be output into the standard dist
# output folder (currently `build/dist`)
#
# This folder should be populated ahead of time before the build system is
# invoked.
#sign-folder = "path/to/folder/to/sign"

# This is a file which contains the password of the default gpg key. This will
# be passed to `gpg` down the road when signing all files in `sign-folder`
# above. This should be stored in plaintext.
#gpg-password-file = "path/to/gpg/password"

# The remote address that all artifacts will eventually be uploaded to. The
# build system generates manifests which will point to these urls, and for the
# manifests to be correct they'll have to have the right URLs encoded.
#
# Note that this address should not contain a trailing slash as file names will
# be appended to it.
#upload-addr = "https://example.com/folder"

# Whether to build a plain source tarball to upload
# We disable that on Windows not to override the one already uploaded on S3
# as the one built on Windows will contain backslashes in paths causing problems
# on linux
#src-tarball = true

Rustブートストラップキットをビルドする

ここまで来れば、後は実行してしばらく待つだけである。私のところのマシンでは正確には把握していないが数時間は必要だった。 以下のように実行すれば良い。


$ mkdir ~/tmp/rust
$ cd ~/tmp/rust
$ LD_LIBRARY_PATH=/home/ryoon/tmp/rust-1.20.0-x86_64-unknown-netbsd/rustc/lib OPENSSL_DIR=/usr CC_i686_unknown_netbsd=i486--netbsdelf-gcc-sysroot CXX_i686_unknown_netbsd=i486--netbsdelf-g++-sysroot PATH=/usr/world/7/i386/tools/bin:/usr/pkg/gnu/bin:$PATH python2.7 ../rustc-1.21.0-src/x.py dist
エラーなく完了したら、以下のようにブートストラップキットができているはずである。

$ cd ~/tmp/rust
$ ls build/dist
(snip)
build/dist/rust-1.19.0-i686-unknown-netbsd.tar.gz
(snip)
build/dist/rust-std-1.19.0-i686-unknown-netbsd.tar.gz
(snip)
これをDISTDIRに置いて、pkgsrc/lang/rustをNetBSD/i386でビルドするのに使えば良い。

bta2dpd(8)を使って、NetBSDでBluetoothヘッドフォンを使う

NetBSD Advent Calendar 2017の4日目の記事です。

English version is here.

はじめに

Bluetoothでオーディオを再生するには、以前はbtsco(4)しかなく、 ubt(4)でbtsco(4)を使おうとすると、USBアイソクロナス転送が必要で、 NetBSDのechi(4)やxhci(4)ではアイソクロナス転送はサポートされて いないので、btsco(4)ではBluetoothのオーディオデバイスでは オーディオの録音、再生ができなかった。

しばらく前に、bta2dpd(8)と言うのがnat@によってNetBSD-currentに追加された。 これがxhci(4)で使えるのかが、ずっと気になっていた。 やっと、Jabra MOVE Wireless で試してみた。 結果としては、ubt(4)につないだJabra MOVE Wirelessで再生できた。

Bluetoothの基本的な設定

ペアリングやプロファイルの選択は、btsco(4)の場合と同じであった。 以下のようにすれば良い。

まずは、Bluetooth接続に必要なデーモン等を起動しておく。 以下のように追加する。


# vi /etc/rc.conf
bluetooth=YES
# /etc/rc.d/bluetooth start
configuring Bluetooth controllers: ubt0.
starting Bluetooth Link Key/PIN Code manager
starting Bluetooth Service Discovery server
もし、継続的に使用しないのであれば、以下のようにしても良い。

# /etc/rc.d/bluetooth onestart
configuring Bluetooth controllers: ubt0.
starting Bluetooth Link Key/PIN Code manager
starting Bluetooth Service Discovery server

ワイヤレスヘッドフォンをペアリング待ちにした上で、以下のように実行し、 ワイヤレスヘッドフォンのアドレスを取得する。


$ btconfig ubt0 inquiry
Device Discovery from device: ubt0 ... 1 response
  1: bdaddr XX:YY:ZZ:XX:YY:ZZ
   : name "Jabra MOVE v2.5.0"
   : class [0x240404] Wearable Headset  
簡便のためこのアドレスを/etc/bluetooth/hostsファイルに 登録しておく。ここでは、headset1と言う名前を付けておく。

# vi /etc/bluetooth/hosts
XX:YY:ZZ:XX:YY:ZZ headset1

次に、BluetoothのPINを設定する。


$ btpin -d ubt0 -a headset1 -p 0000
Jabra MOVE Wirelessでは、PINは0000で良いようだ。

次は、アドレスheadset1のデバイスをヘッドセット(HSET)に設定する。


# btdevctl -d ubt0 -a headset1 -s HSET -A
※ この設定は不要だった (2020-06-06)。

ここまでは、btsco(4)の場合と一緒である。 次がbta2dpd(8)の使用方法である。 まずテストしてみる。


$ file test.wav
test.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz
# bta2dpd -a headset1 test.wav
しかし、これではwavファイルしか再生できないので、例えばmplayer等で OSSで再生したものをヘッドセットで聞くには以下のようにする。

# bta2dpd -a headset1 /dev/pad
このように実行すると、以下のようにdmesgに表示された。

pad0: outputs: 44100Hz, 16-bit, stereo
audio2 at pad0: half duplex, playback, capture, mmap
pad0: Virtual format configured - Format SLINEAR, precision 16, channels 2, frequency 44100
spkr3 at audio2: PC Speaker (synthesized)
wsbell at spkr3 not configured
よって、/dev/sound2で再生すると、 /dev/pad(/dev/pad0と同じものを指している)に その内容がコピーされることになると分かる。 例えば、以下のようにmplayerで再生すれば、ヘッドセットで聞こえた。

$ mplayer -ao oss:/dev/sound2 test.mp3

おわりに

xhci(4)でBluetoothオーディオを使えるのは非常に便利だった。

MPEG 2.5

MPEG 2.5と言う表記を見掛けたのだが、どういうものか理解できなかった。 /usr/pkgsrc/audio を以下のように検索すると、 /usr/pkgsrc/audio/libmad/DESCR に、MPEG-2 extension to Lower Sam...