NERVES_SERIAL_NUMBER環境変数はいつ設定するの?
【名古屋】Nervesで令和のLチカ?!と大須でパーツお買い物(piyopiyo.ex勉強会)に参加して、5年ぶり(!)にElixir/Nervesをお触りしていたときのこと。
Nerves PJをSDカードに焼くには環境変数を設定してからmix firmware && mix burnしてね的なスライドがありました。
次のように環境変数を設定しておくと、Nervesに反映されるらしい。
- NERVES_SERIAL_NUMBER ... ボードID、ホスト名に反映される
- NERVES_WIFI_SSID ... WiFiのSSIDが設定される
- NERVES_WIFI_PASSPHRASE ... WiFiのパスワードが設定される
NERVES_WIFI_SSIDとNERVES_WIFI_PASSPHRASEは、スライドの指示で書き換えたconfig/target.exs内でSystem.get_env()を使って環境変数を取得してWiFi設定していました。
config/target.exsはコンパイル時(mix firmware)に評価するらしいです。なので、mix firmwareの前に環境変数を設定ですね。
一方、NERVES_SERIAL_NUMBERは、、、むぅ、なんかよくわからない。
イベントに参加していた @mnishiguchi さんに聞いてみると「Nerves Livebookで見たことあるような。」とアドバイスいただきました。
sudo NERVES_WIFI_SSID='access_point' NERVES_WIFI_PASSPHRASE='passphrase' fwup nerves_livebook_rpi0.fw
んんん?
piyopiyo.ex勉強会のときと、環境変数を設定するタイミングが違う...
- (ここで環境変数(NERVES_SERIAL_NUMBERなど)を設定せよ by piyopiyo.ex勉強会スライド)
-
mix firmware(-->xxx.fw) - (ここで環境変数(NERVES_SERIAL_NUMBERなど)を設定せよ by Nerves Livebook)
-
mix burnorfwup(--> microSD)
なんかよく分からない。
環境変数を元に.fwファイルの中身を書き換えちゃうの??
なんかこわい。
キーワードは「U-Boot環境変数」「ファームウェア変数」
fwupで設定できちゃう謎挙動を理解にはU-Boot環境変数とファームウェア変数というキーワードが重要です!
Nerves LivebookのNERVES_WIFI_SSIDの動きを見てみましょう。(←本来なら、NERVES_SERIAL_NUMBERの動きを見るところですが、、、実装がシンプルなNERVES_WIFI_SSIDで。)
-
fwupを実行したときに、環境変数NERVES_WIFI_SSIDをU-Boot環境変数wifi_ssidに書きますhttps://github.com/nerves-livebook/nerves_livebook/blob/b88b815d4d86eaf7a9ff136aa38b0766c80ed4e8/config/provisioning.conf#L12

-
Nervesの実行時に、
Nerves.Runtime.KVでファームウェア変数wifi_ssidをVintageNetWiFiに設定しますhttps://github.com/nerves-livebook/nerves_livebook/blob/b88b815d4d86eaf7a9ff136aa38b0766c80ed4e8/lib/nerves_livebook/application.ex#L46-L58

fwupで書き込むU-Boot環境変数とNerves.Runtime.KVで読み込むファームウェア変数がどう繋がっているかというと、、、実体はどちらもmicroSDのProvisioning informationに書かれた値で、同一のものを指しています。あぁ、ややこしい。
Provisioning informationは、どこかって?
ここ。microSDのMBRとBoot Aの間の、ここです。(赤枠の箇所)
https://www.slideshare.net/slideshow/elixiriotcoolnerves-236780506/236780506#12

ルートファイルシステムのどこかではなく、Provisioning informationという専用のパーティション(で、フォーマットはU-Boot環境変数)のため、fwupが設定できるという仕掛けでした。
Provisioning informationの値を見てみよう
NERVES_SERIAL_NUMBER環境変数を1234にして、fwupします。
mix nerves.new hello_nerves
cd hello_nerves
export MIX_TARGET=rpi3
mix deps.get
mix firmware
NERVES_SERIAL_NUMBER=1234 fwup _build/rpi3_dev/nerves/images/hello_nerves.fw
IExでNerves.Runtime.KV.get_all()を実行してProvisioning informationを表示します。
iex(1)> Nerves.Runtime.KV.get_all()
%{
"a.nerves_fw_application_part0_devpath" => "/dev/mmcblk0p3",
"a.nerves_fw_application_part0_fstype" => "ext4",
"a.nerves_fw_application_part0_target" => "/root",
"a.nerves_fw_architecture" => "arm",
"a.nerves_fw_author" => "The Nerves Team",
"a.nerves_fw_description" => "",
"a.nerves_fw_misc" => "",
"a.nerves_fw_platform" => "rpi3",
"a.nerves_fw_product" => "hello_nerves",
"a.nerves_fw_uuid" => "036c1904-b564-5cd5-788f-e0e37e05c25e",
"a.nerves_fw_vcs_identifier" => "",
"a.nerves_fw_version" => "0.1.0",
"nerves_fw_active" => "a",
"nerves_fw_devpath" => "/dev/mmcblk0",
"nerves_serial_number" => "1234"
}
Provisioning informationの値を見てみよう(マニア向け)
Provisioning informationはmicroSDの0x2000に位置しています。
fwupで.imgファイルに出力してダンプすれば、値を確認することができます。
mix nerves.new hello_nerves
cd hello_nerves
export MIX_TARGET=rpi3
mix deps.get
mix firmware
NERVES_SERIAL_NUMBER=1234 fwup -d hello_nerves_1234.img _build/rpi3_dev/nerves/images/hello_nerves.fw
NERVES_SERIAL_NUMBER=5678 fwup -d hello_nerves_5678.img _build/rpi3_dev/nerves/images/hello_nerves.fw
まとめ
- コンパイル後に、Nervesへ変数を渡す手段がある。(
fwupでProvisioning informationへ) - 複数マシンに対して設定を変えたいときに使う。
- まさにNerves Livebookが好例。
- 固定IPアドレスやNTP、サーバーへの接続情報など良さそう。
- 変数の追加は
config/provisioning.confへ。 - Provisioning informationは保護(暗号化など)されていない。
おまけ
NERVES_SERIAL_NUMBERが実行時にどういう流れでホスト名に反映されるかは、ちょっとややこしいです。
興味があれば調べてみてくださいませ。
