iPad pro 2018 11inch WiFi modelを購入しました
2019年3月末に2018年モデルのiPad Pro 11inchとその周辺機器を購入しました。
それから約1ヶ月ほど使ってみて、買った周辺機器やアプリなどが色々あるので、感想を書いていこうと思います。
忙しい人向け
- お金の余裕があればiPadはCellerモデルをおすすめ
- 保護フィルムは紙質感のものをiPadと一緒に買ってつけよう
- アプリの自動更新は真っ先に止めよう
- iPad上でコーディングする際の良い方法があれば教えてください
目的
iPadでやりたかったことは以下です。
- スムーズなPDFの閲覧およびPDF内へのメモ書き込み
- 2000ページ越えPDFファイルの閲覧(ARMのアーキテクチャマニュアル等)
- キーボード付きのリモートSSH作業
- キーボード付きの簡易コーディング作業
- 簡単なお絵かき(ホワイトボードの代わりくらい)
この希望を満たせないかなと色々買ったりしてみました。
購入したハードウェア
購入したハードウェアの一覧は以下です。
- iPad Pro 2018 11inch(WiFi model)
- iPad smart keyboard folio(11inch, US)
- (+ Apple care)
- Apple Pencil(2nd Gen)
- Apple USB-C - 3.5 mmヘッドフォンジャックアダプタ
- iPad 2018 11.1インチ用フィルム/ペーパーライク/反射防止/ケント紙タイプ
- Anker PowerLine II USB-C & USB-C 2.0 ケーブル (1.8m)
iPad Pro 11inch(2018 model)
iPad Proには11inchと12.9inchモデルがあります。 今回はお値段と大きさの都合から11inchを購入しました。
大きさによる不満はほぼ無いです。あるとすれば、iPadは2つまでアプリを同時に画面に表示して使えるようになっているので、この機能を使ってドキュメントを書きながらsshで作業するなどしているときはすこしだけ大きな画面が欲しくなります。
お値段の都合から今回はWiFiモデルを購入しましたが、こちらはCellerモデルを購入した方が良かったと今は考えてます。iPhoneを持っているのでWiFIモデルでもテザリングでうまく使えると考えてましたが、取り出してiPhoneにテザリングで接続して...という一手間が増えるのは不便です。
加えて、iOSはWiFiデータ通信はアプリ別通信量等がみられないので、通信量の多いアプリを見つけて設定を変えてということがうまくできないのが大変です。 iPadは接続先がテザリングのiPhoneであることは知っているはずですが、データ通信量の手加減をしてくれないようで、わたしは4/1の初日に、ほとんど使ってないiPadに1.5GBものデータ通信量をもぐもぐされました。 前述の通りWiFi通信ではアプリごとのデータ通信量がわからないので正確な原因特定はできていませんが、アプリの自動更新を止めたところ今のところは通信量が落ち着いてます。 iPadを買ったら最初にこの設定を行ないましょう。
smart keyboard folio 11inch(US)
iPadのカバー兼物理キーボードです。 カバーだけのものに比べ重さと値段が結構増えますが、わたしは購入して良かったと考えてます。
というのも、iPadの標準のスクリーンキーボードは慣れてないせいもあると思いますが結構打ちづらく、ミスタイプが辛いのです。加えて公式のスクリーンキーボードは日本語と英語の切り替えボタンの反応が良くないのと矢印キーが無いのも大変です。スクリーンだと選択とコピペがやりづらいのもあります。
そもそもアプリによっては文章の一部選択ができなかったり、うまくコピーが働かなかったりしてキーボードがあってもうまくいかない場面が出てきたり色々あるのですが、そういう不満を挙げ続けていくと「あれ?わたしの欲しかったのはiPadではなくMacBookだったのでは?」と考えてしまうので「iPadでやるのはiPadでできる軽量なことまで。それ以上はパソコンでやる」というふうに割り切って使う必要があると思います。
話を戻しましょう。このキーボードカバーもファンクションキーがないなど気になるところはありますが、本体とセットで持ち歩けていつでもサッとキーボードが使えるのは、よく文章を書く人にとっては便利だと思います。
キーのサイズはエンターキー付近の幅がすこし狭くなっていますが、概ね問題ありません。 なお、12.9inchモデルのキーボードはその辺りの幅も通常サイズのようです。
Apple Pencil(2nd gen)
実は2世代目のpencilが使いたいというのが、最近出たiPad miniではなくproを購入した理由になります。
2世代目はマグネットでipadにつながり、勝手に充電されるのが便利で良いです。 ただし、そんな強くくっついているわけではないので、いつ落とすか心配です。 iPadをカバンに入れて持ち運ぶ際はペンだけカバンのポケットに入れたりしています。
ペンを収納する機能のついたケースもあるようです。
Apple care
延長保証です。
今回購入した2018年モデルはネット上の「曲がりやすい」という噂や、実際にバッグに入れて使ってるだけで曲がった人の報告ツイート(URL失念)などを見かけていたので、絶対に入った方が良いと考えました。
「Apple製品はapple care等の補償もりもりにして買うものだよ」と友人のろまのふさんが言っていたのも理由の一つだったりします。
最近のデバイスは修理も大変ですし、壊してから数万の修理代をかけるよりは最初に1万円払ったほうがお得かなと考えてます。
Apple USB-C - 3.5 mmヘッドフォンジャックアダプタ
iPadでリズムゲームするなら必須です。千円くらいで買えます。
iPad 2018 11.1インチ用フィルム/ペーパーライク/反射防止/ケント紙タイプ
iPadの表面を紙っぽくする保護フィルムです。ペンシルでの書き心地が良くなります。 iPadと一緒に購入して開封後すぐにつけるといいと思います。
完全に予想外だったのですが、これをつけると滑りがよくなってiPadでのリズムゲームが捗ります(リズムゲームやるために買ったわけじゃないんですが...iPadでリズムゲームやるの楽しい...)。
Anker PowerLine II USB-C & USB-C 2.0 ケーブル (1.8m)
標準のケーブルは短いので買いました。充電だけでしか使ってませんが問題なく使えてます。
インストールしたソフトウェア
インストールして良かったアプリを抜粋してご紹介。
Blink Shell: Mosh & SSH Client
有料買い切りのSSHクライアントです。2400円だったはず。
SSH Jumpが使えるとのことで買いましたが、以下に書かれているようにProxyCommandにncを使った設定を入れないとうまく動きませんでした。設定を入れれば動くのでそのまま使っています。
ssh -o "RemoteCommand=nc %h %p 2>/dev/null" -q JUMP_SERVER
Port forwardingもできます。ただしiOSの仕様でバックグラウンドにいったアプリは10分で消されてしまうからか、しばらくすると接続が切れてしまいます。ちょっと残念。
LastPass
クラウドで管理するタイプのパスワードマネージャーです。
今までKeePass + Dropboxで運用していたのですが、Dropboxのbtrfs非対応化とiOS用KeePassクライアントで使いやすいものがなかったので乗り換えました。
iPad上でもパスワード生成してアカウント作成などが手軽にできて便利です。
今は無料版を使っていますが、Yubikeyを買ったら有料版にしてYubikeyと連携して使っていこうと思います。
GoodNotes 5
PDFを読んだり注釈を入れたり、手書きノートを作ったりできる買い切り有料アプリです。 他人からのおすすめで購入しました。 今のところ2000ページ越えのマニュアルも読めるし検索できて便利に使えてます。
Paper by WeTransfer
slankさんのおススメを受けてかった、ホワイトボード的に使えるお絵かきアプリです。月額課金の有料アプリです。 有料にすると一部を選択してcutして移動などができるようになり大変便利になります。
PWEditor
テキストエディタです。Google DriveやDropboxなどのファイルが読めます。 Markdownをとりあえず読みたいときに使ってます。 120円で広告を外せます。やすい。
足りないもの
コードエディタ
大規模なコードを見たり書いたりするにはPWEditorは力不足を感じるので、良いエディタを探しています。
リモートサーバーにSSHで入ってファイルを編集するといったことができるととても嬉しいのです。 現在はVPSにSSHで入ってemacsで開発をしていますが、パソコンではvscodeで開発を行なっているので、できればGUIなエディタが欲しいです。
coder.comのサービスにはとても期待しており課金して利用する予定でしたが、現在は課金プランもなくなり、無料版では重くて使えないという状況です。 クラウドサービス上に認証ありでサクッと建てる方法があれば自分で建てて使いたいのですが、知識不足でできていません。ご存知の方がいれば教えてください。
Rockstor をインストール時に暗号化してリモートから鍵入力できるようにする話
NAS用LinuxディストリビューションのRockstorを使ってお家のNASを作り直したので、そのときにやったことを備忘録として書き残しておきます。
再構築の目的
私は以前からRockstorを入れたNASサーバーを運用していたのですが、以下の点が気になっていたのでOSごとインストールし直しを行いました。
- UEFIでなくBIOSブートでインストールされている
- Data diskが暗号化されていない
- data diskの鍵を入れるOS diskも暗号化されていない
- RAIDを組むためにData diskを2枚指したのにRAIDを組めていない
再構築の主目的は以下の2点になります。
- RockstorのOSの入っているdisk(以降OS disk)含めて暗号化する
- Dataを入れるdisk(以降data disk)をRAID1にする
なお、RockstorをUEFIブートするようインストールする件に関しては、途中で発生した問題をすべて解決できなかったので諦めました。詳細は最後におまけで記します。
暗号化の話
インストール
最近のインストーラーはとても親切なので、指示に従っているだけでDisk暗号化をしつつOSのインストールができました。 わからないことがあっても、RockstorはRHEL系ディストリビューションをベースとしているので、FedoraやCentOSのドキュメントを参考にすれば良いでしょう。
ディスク暗号化のリモート解除
さて、ここが私がこの備忘録を書いたきっかけになります。
インストール後、実際に起動してみて困ったのが起動時のディスク暗号化解除方法です。 Rockstorでディスク暗号化を行いつつインストールを行うと、起動時にディスク暗号化を解除するためのパスコード入力を求められます。 しかし、うちのサーバーマシンは基本的にディスプレイとキーボードを外して運用していることに加え、頻繁に電源をON//OFFするので、毎回起動時にパスワード入力を求められると不便です。
これを解決するために、はUSBメモリに鍵を入れ、起動時に自動で復号する方法やSSH経由でリモートから鍵入力をする方法がありますが、今回は後者を試してみました。この方法を使うメリットとしては、復号鍵が対象から分離されることと、USBメモリなど追加で必要なものがないので気軽に試せる点があるでしょう。
基本的な作業手順は以下のサイトのStep6以降を進めるだけです。
こちらも参考になります。
https://github.com/dracut-crypt-ssh/dracut-crypt-ssh
Rockstorのマシンにrootでログインした後、dracut-crypt-sshパッケージを入れます。
sudo yum install wget -y sudo wget -O /etc/yum.repos.d/rbu-dracut-crypt-ssh-epel-7.repo https://copr.fedorainfracloud.org/coprs/rbu/dracut-crypt-ssh/repo/epel-7/rbu-dracut-crypt-ssh-epel-7.repo sudo yum install dracut-crypt-ssh -y
次に/etc/default/grubを開いてgrubのエントリを修正し、起動時にIPアドレスを得るように設定します。
アドレス取得をDHCPで行う場合は、GRUB_CMDLINE_LINUX="crashkernel=auto
と rd.luks.uuid=
の間に rd.neednet=1 ip=dhcp
を入れれば設定完了です。
static IPを割り当てたい方は以下を参照してください。
設定後のGRUB_CMDLINE_LINUX
の行はこんな感じになります。
GRUB_CMDLINE_LINUX="crashkernel=auto rd.neednet=1 ip=dchp rd.luks.uuid=luks-xxxx rhgb quiet"
設定が完了したら以下のコマンドでgrubのconfigを生成します。
sudo grub2-mkconfig -o /etc/grub2.cfg
次にinitramfs内に入れるSSHの設定を記入していきます。
/etc/dracut.conf.d/crypt-ssh.conf
を開いて以下を追記します。
dropbear_acl="/etc/dropbear/keys/authorized_keys" dropbear_ecdsa_key="/etc/dropbear/keys/ssh_ecdsa_key" dropbear_rsa_key="/etc/dropbear/keys/ssh_rsa_key"
ファイルを保存したら、ここで設定した場所に新しいSSH鍵を生成します。 この鍵は起動時にディスク復号パスワードを受け取るためのSSH通信に利用されます。
sudo mkdir -p /etc/dropbear/keys/; sudo chmod /etc/dropbear/keys/ sudo ssh-keygen -t ecdsa -f /etc/dropbear/keys/ssh_ecdsa_key sudo ssh-keygen -t rsa -f /etc/dropbear/keys/ssh_rsa_key sudo chmod 400 /etc/dropbear/keys/*_key; sudo chmod 444 /etc/dropbear/keys/*.pub
次に /etc/dropbear/keys/authorized_keys
を開き、ディスク復号鍵を送るための、接続元マシンの公開鍵を記述します。ここで記述する鍵はrsaの公開鍵である必要があります。dropbearを使う場合はed25519鍵でアクセスできないようです。ここ、ドハマりポイントでした。
最後にdracutコマンドでinitramfsを生成して再起動すれば設定完了です。
sudo dracut -f && sudo reboot
再起動後、サーバーにユーザーroot、ポート222で接続し、console_authコマンド実行後にディスク復号のパスワードを入れればOSが立ち上がります。
なお、このアンロックの手順も自動化できるようなのですが、とりあえず今日はここまでで。詳しい話は以下を参照。
https://github.com/dracut-crypt-ssh/dracut-crypt-ssh#34-unlocking-using-the-unlock-command
data disk暗号化
data diskの暗号化は公式のドキュメントがあるのでこちらを参照して作成してください。
http://rockstor.com/docs/luks/luks.html
RAIDを組む場合は先にディスク暗号化を済ませてからpool割当のところで設定すれば作れます。詳しくは以下参照です。
http://rockstor.com/docs/pools-btrfs.html#redundancy-profiles
おまけ: RockstorがUEFIブートでインストールできない話
結論から話せば、少なくとも2019年2月ごろのRockstorはUEFIブートからインストールができませんでした。以下理由を記しますが、メモをとっていなかったため誤りが含まれるかもしれません。
まず、インストーラーのISOをそのままUSBメモリに書き込むとUEFIブートしません。
これはfatでフォーマットしたUSBメモリにISOの中身を書き込むと回避できますが、今度は立ち上がったKernelがrootfsをマウントできず失敗します。
これはどうやらrootfsのラベル指定がUSBメモリのラベルを指していないことが原因のようで、grub.cfgを書き換えてUSBメモリのラベルで参照できるようにすると解決します。
この修正でインストーラーが立ち上がるところまで進みますが、インストール途中にエラーが起きて先に進めない問題が発生したため、解決を諦めました。
おしまい
おしまい。
Chisel + PYNQでLチカ(お正月FPGAあそび)
お正月なので普段やらないことをやろうと思い、買ってから2年ほど放置してしまっていたPYNQ-Z1を使ってFPGAを触ってみました。
「RISC-Vで遊びたい」という気持ちと「FPGAをさわってみたい」という気持ちがあったので、「PYNQでRISC-Vを動かしてみる」ことを最終目標にしました。 しかし、これではお正月休みだけでは終わらないので、このお休みの間は「PYNQでChiselを使ってLチカする」のをゴールとしてやってみました。
今回はそこで何やったかのメモ的な記事です。
なお、私はFPGAもScalaもChiselもほぼ初挑戦です。
Vivado setup
PYNQにはXilinx社のZynqというFPGAが乗っているので、Xilinx社のVivadoという開発環境で開発を行います。 以下のサイトからアカウントを作ってインストールします。WebPackライセンスを選択すればいろいろ制限はありますが無料で使えます。
インストールが終わったら以下からPYNQ向けのボードファイルをもらってきてインストールします。
https://github.com/cathalmccabe/pynq-z1_board_files/raw/master/pynq-z1.zip
$ wget https://github.com/cathalmccabe/pynq-z1_board_files/raw/master/pynq-z1.zip $ unzip pynq-z1.zip $ sudo cp -r pynq-z1 /tools/Xilinx/Vivado/2018.3/data/boards/board_files
PS + PL でLチカ
環境設定が終わったので、組み込み版HelloWorldであるLチカをやってみます。
PYNQボード向けの入門ドキュメントは少ないので、だいたい同じ構成のZyboというボード向けの初心者用ドキュメントを参考に、一部読み替えつつLチカをしてみます。
Getting Started with Zynq [Reference.Digilentinc]
PYNQボードに乗っているZynqというFPGAチップには、ARMのCPUコア(PS: Processing System)とFPGA(PL: Programmable Logic)が1つのチップに乗っています。 今回参考にするドキュメントの例では、PL部に用意したGPIOをPS部のプログラムから制御して、スライドスイッチの状態に応じてLEDを点灯させるというものになります。
Zybo向けに書かれたこのドキュメントをPYNQで用いるための変更点としては、PYNQにはスライドスイッチが2つしか無いので、手順4.3で設定するスイッチをswts_2bitsに設定する必要があります。
PL部のみでLチカ
次にPYNQをPS部を用いず普通のFPGAボードとして利用する方法が知りたいので、以下のサイトを参考にPL部のみでLチカをしてみたいと思います。
こちらのドキュメントもZYNQ向けなので、「ピンアサインをする」のところでクロックなどが接続されているピンがPYNQと異なります。そのため、以下のマニュアルを参考に変更を加えます。
https://reference.digilentinc.com/_media/reference/programmable-logic/pynq-z1/pynq-rm.pdf
「11 Clock Sources」と「12 Basic I/O」を読むと、クロックソースとLEDのピン配置が以下の表のようになっていることがわかるので、設定します。
Parts | FPGA Pin |
---|---|
125MHz Clock | H16 |
LED LD0 | R14 |
LED LD1 | P14 |
LED LD2 | N16 |
LED LD3 | M14 |
回路がうまく動けば、1秒ごとにLEDが4つとも点滅します。
Chiselを使ったLチカ
RISC-VのコアはChiselという、ScalaのDSLとして実装された言語を用いて書かれています。 このChiselの書き方を学ぶため、まずはこのChiselを使って先程のPL部だけで行うLチカの回路を作ってみたいと思います。
まずChiselから実際のボード上で動く回路を作るまでの流れが知りたかったので調べてみます。 Chiselのコードをビルドすると、中間表現を経由してVerilogのコードが得られます。実際のボード上で動かすためにはこの生成したVerilogをvivadoに取り込んでピンアサインなどを設定してビルドする必要が有るようです。
詳細についてはmskysphinzさんのブログ記事が参考になりました(ありがとうございます)。
次にプロジェクトの開始の際には、chisel-templateというリポジトリをベースに行うのが良いようです。
chisel-remplateにはGCDを求める回路が最初から書かれています。 最初は簡単のためメソッド名等はそのままに中身だけ書き換えてLチカのコードを書いていきます。
src/main/scala/gcd/GCD.scala
Verilogで書いていたLチカのコードをChiselで書き直します。 Clockは暗黙の引数として有るようなので、書かなくて良いようです。 onoff変数の値をLED4つに反映させる方法がわからなかったので、LED0にだけonoffの値を入れるようにしています。
// src/main/scala/gcd/GCD.scala package gcd import chisel3._ /** * Compute GCD using subtraction method. * Subtracts the smaller from the larger until register y is zero. * value in register x is then the GCD */ class GCD extends Module { val io = IO(new Bundle { val outputLED = Output(UInt(4.W)) }) // parameter CNT_1SEC = 27'd124999999; // 125MHz clk for 1sec val CNT_1SEC = RegInit(124999999.U(27.W)) // reg [26:0] cnt = 27'd0; val cnt = RegInit(0.U(27.W)) // reg onoff = 1'd0; val onoff = RegInit(false.B) // if (cnt == CNT_1SEC) begin when(cnt === CNT_1SEC) { // cnt <= 27'd0; // onoff <= ~onoff; cnt := 0.U onoff := ~onoff } .otherwise { // cnt <= cnt + 27'd1; cnt := cnt + 1.U } // assign LED = {onoff, onoff, onoff, onoff}; io.outputLED := onoff }
src/test/scala/gcd/GCDUnitTest.scala
回路のテストコードを書きます。
サンプルではpokeを使って回路に入力を設定しているものがよく見られますが、この回路は入力がクロックしか無いので、pokeで入力設定を行わなくても良いようです。
stepを進めるとクロックが入力されてカウンタが上がっていきます。 今回125MHzでLEDの出力を反転させるので、stepで125,000,000進めた後にexpectを使って出力が変わっているかをチェックします。
class GCDUnitTester(c: GCD) extends PeekPokeTester(c) { private val gcd = c // return 0 when clk counter == 0 expect(gcd.io.outputLED, 0) // return 0 when clk counter == 1 step(1) expect(gcd.io.outputLED, 0) // return 1 when clk counter == 124999999 step(125000000 - 1) expect(gcd.io.outputLED, 1) // return 1 when clk counter == 0 step(1) expect(gcd.io.outputLED, 1) // return 0 when clk counter == 124999999 step(125000000 - 1) expect(gcd.io.outputLED, 0) }
src/test/scala/gcd/GCDMain.scala
そのままもテストはできますがVerilogファイルの出力ができなかったので、chisel-wikiを参考にMainメソッドに1行追加してVerilogのコードをビルドできるようにします。 以下のドキュメントを参考に、出力のための処理を追記します。
Frequently Asked Questions · freechipsproject/chisel3 Wiki · GitHub
object GCDMain extends App { iotesters.Driver.execute(args, () => new GCD) { c => new GCDUnitTester(c) } // 追記 chisel3.Driver.execute(args, () => new GCD) }
テスト
tutorialのREADME.mdに書いてあるとおりに以下のコマンドを実行するとテストが走ります。
$ sbt 'testOnly gcd.GCDTester -- -z Basic'
うまくいけばこんな感じのログが出てきます。
$ sbt 'testOnly gcd.GCDTester -- -z Basic' [info] Loading settings from plugins.sbt ... [info] Loading project definition from /home/tnishinaga/projects/chisel/chisel_ledblink/project [info] Loading settings from build.sbt ... [info] Set current project to chisel-ledblink (in build file:/home/tnishinaga/projects/chisel/chisel_ledblink/) [info] Compiling 1 Scala source to /home/tnishinaga/projects/chisel/chisel_ledblink/target/scala-2.11/classes ... [warn] there was one feature warning; re-run with -feature for details [warn] one warning found [info] Done compiling. [info] [0.005] Elaborating design... [info] [2.191] Done elaborating. Total FIRRTL Compile Time: 512.2 ms Total FIRRTL Compile Time: 201.5 ms file loaded in 0.388108123 seconds, 13 symbols, 9 statements [info] [0.002] SEED 1546794998929 test GCD Success: 5 tests passed in 250000005 cycles in 118.643097 seconds 2107160.15 Hz [info] [118.613] RAN 250000000 CYCLES PASSED [info] GCDTester: [info] GCD [info] Basic test using Driver.execute [info] - should be used as an alternative way to run specification [info] using --backend-name verilator [info] running with --is-verbose [info] running with --generate-vcd-output on [info] running with --generate-vcd-output off [info] ScalaTest [info] Run completed in 2 minutes, 3 seconds. [info] Total number of tests run: 1 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. [info] Passed: Total 1, Failed 0, Errors 0, Passed 1 [success] Total time: 135 s, completed Jan 7, 2019 00:01:42 AM
Verilogコードの生成
Verilogのコード生成は以下のコマンドで行えました。 このコマンドがスマートな方法かはわかりませんが、動いたので良しとしています。どなたか良い方法をご存知の方は教えてください。
$ sbt 'test:runMain gcd.GCDMain --target-dir buildstuff --top-name GCDMain'
うまくビルドが終わればbuildstuffディレクトリ以下にGCDMain.vというファイルができているはずです。 機械が生成したコードなので、先程の人間の作ったコードに比べるとちと読みづらいです。
module GCD( // @[:@3.2] input clock, // @[:@4.4] input reset, // @[:@5.4] output [3:0] io_outputLED // @[:@6.4] ); reg [26:0] cnt; // @[GCD.scala 19:21:@9.4] reg [31:0] _RAND_0; reg onoff; // @[GCD.scala 21:23:@10.4] reg [31:0] _RAND_1; wire _T_13; // @[GCD.scala 25:12:@11.4] wire _T_15; // @[GCD.scala 27:14:@14.6] wire [27:0] _T_17; // @[GCD.scala 29:16:@18.6] wire [26:0] _T_18; // @[GCD.scala 29:16:@19.6] wire [26:0] _GEN_0; // @[GCD.scala 25:26:@12.4] wire _GEN_1; // @[GCD.scala 25:26:@12.4] assign _T_13 = cnt == 27'h773593f; // @[GCD.scala 25:12:@11.4] assign _T_15 = ~ onoff; // @[GCD.scala 27:14:@14.6] assign _T_17 = cnt + 27'h1; // @[GCD.scala 29:16:@18.6] assign _T_18 = cnt + 27'h1; // @[GCD.scala 29:16:@19.6] assign _GEN_0 = _T_13 ? 27'h0 : _T_18; // @[GCD.scala 25:26:@12.4] assign _GEN_1 = _T_13 ? _T_15 : onoff; // @[GCD.scala 25:26:@12.4] assign io_outputLED = {{3'd0}, onoff}; // @[GCD.scala 33:16:@22.4] `ifdef RANDOMIZE_GARBAGE_ASSIGN `define RANDOMIZE `endif `ifdef RANDOMIZE_INVALID_ASSIGN `define RANDOMIZE `endif `ifdef RANDOMIZE_REG_INIT `define RANDOMIZE `endif `ifdef RANDOMIZE_MEM_INIT `define RANDOMIZE `endif `ifndef RANDOM `define RANDOM $random `endif `ifdef RANDOMIZE integer initvar; initial begin `ifdef INIT_RANDOM `INIT_RANDOM `endif `ifndef VERILATOR #0.002 begin end `endif `ifdef RANDOMIZE_REG_INIT _RAND_0 = {1{`RANDOM}}; cnt = _RAND_0[26:0]; `endif // RANDOMIZE_REG_INIT `ifdef RANDOMIZE_REG_INIT _RAND_1 = {1{`RANDOM}}; onoff = _RAND_1[0:0]; `endif // RANDOMIZE_REG_INIT end `endif // RANDOMIZE always @(posedge clock) begin if (reset) begin cnt <= 27'h0; end else begin if (_T_13) begin cnt <= 27'h0; end else begin cnt <= _T_18; end end if (reset) begin onoff <= 1'h0; end else begin if (_T_13) begin onoff <= _T_15; end end end endmodule
FPGAでの動作確認
PL部でのLチカを参考に、VerilogのコードをコピペしてVivadoでビルドを行います。 Chiselはreset用のpinも欲しがるので、私はとりあえずスライドスイッチのついているM20を設定しました。
PYNQにうまく書き込めれば、LEDのLD0だけがチカチカするはずです。
おもったこと
最後に、やってる途中に思ったことをつらつらと。
UEFIの呼び出し規則について
UEFIの呼び出し規則について調べたので忘れないようにメモしておきます。
呼び出し規則とバイナリフォーマット
UEFIのアプリケーションは以下の点が一般的なLinuxのアプリケーションと異なるため、Linux環境上でUEFIアプリをビルドするには解決の必要があります。
- 関数呼び出し規則(calling convention)が異なる(x86, x86_64の場合)
- 実行バイナリのファイル形式がPEフォーマット(UEFI Specification Version 2.5 Errata A pp.18 2.1.1 UEFI Images参照)
私のようにx86以外をターゲットとしてビルドする際は後者の解決が重要ですが、今回は前者について調べたことを記します。
呼び出し規則への対応
前者の呼び出し規則とは、関数を呼び出す際のレジスタの使い方などを決めているものです。 規則にはどのレジスタに引数を入れて渡すか、どのレジスタに戻り地を入れて返すかなどが決められているため、この規則が異なる関数をそのまま呼び出すことはできません。 この規則の違いがx86系のプロセッサ上で動作するUEFIアプリを作る際に問題となります。
x86 Linux向けにアプリをビルドすると、呼び出し規則はSystem V ABIに定められたものが使われます。 一方、UEFIではMS-ABIやMicrosoft x64 calling conventionと呼ばれるWindowsで使われる呼び出し規則を利用しているため、Linux等からUEFIアプリをビルドするためにはこの呼び出し規約の差異を解決する必要があります。 (UEFI Specification Version 2.5 Errata A pp.32 2.3.4.2 Detailed Calling Conventionsを参照。直接MS-ABIとは書いてはない)
私の知っている限りでは、この差異を解決する方法が2つあります。
- MS-ABIでビルドする
- ラッパー関数で呼び出し規則を修正する
MS-ABIでビルドする
前者はコンパイラにms-abiを用いるオプションを指定したり、attribute で指定することで解決を行います。
gnu-efiではコンパイラがms-abiに対応している場合、defineを使ってEFIAPIをつけた関数に __attribute__((ms_abi))
を適応してms-abiで呼び出すようにしています。
- efibind.h 188行目付近参照
ラッパー関数で呼び出し規則を修正する
後者はコンパイラがms-abiを利用できない場合に利用される方法です。 gnu-efi ではuefi_call_wrapperというラッパー関数(中身はマクロ)を利用して、引数の数に合わせて引数の順序を入れ替える関数を選んで使用しています。
- efibind.h 294行目以降参照
Linuxでも同じようなことをやっているようです(efi_call関数を参照)。
linux/efi_stub_64.S at 6f0d349d922ba44e4348a17a78ea51b7135965b1 · torvalds/linux · GitHub
なお、ARMやその他アーキテクチャでは基本的にLinuxと同様のABIを用いているので、ABIの変換作業は必要ありません。 実際にgnu-efiのラッパー関数も変換を行っていないようです。
gnu-efi / Code / [fc5af9] /inc/aarch64/efibind.h
以上です。 PEフォーマットの件は次回書きます。
Bus Blaster v3を買いました
かっちった
BusBlaster3届いた pic.twitter.com/xhP1mYTfYl
— tn (@tnishinaga) June 2, 2018
購入まで
先週Japan Technical Jamboree(Twitterでのハッシュタグは #celfjp
)という、組み込みLinuxに関係する企業の方や趣味の方が集まる勉強会で、個人としてSynQuacerを個人マネーで購入して遊んでいることを報告してきました。
Japan Technical Jamboree 65 - eLinux.org
スライドはこちら
SynQuacerにはJTAGデバッグ用の端子が搭載されているのですが、信号電圧が1.8Vなので私の愛用していたOlimexのARM-USB-TINY-H というJTAGアダプタが使えないという問題がありました。
この件についてJamboree内でBus Blaster v3を使うことをおすすめ*1されたので、さくっとSeeed Studioで購入しました。
商品のページはこちら。
一緒にアクリルパネルをおすすめされたので、こちらも一緒に購入しました。
お値段
気になるお値段は以下(2018/05/25時点)。
もの | お値段(USD) |
---|---|
Bus Blaster v3 | 34.95 |
アクリルケース | 3.00 |
送料(fedex) | 20.72 |
合計 | 58.67 |
PayPal でアカウント登録して、PayPal経由で支払いしました。
支払った額は日本円で6,708円でした。
届くまで
- 5月25日金曜日夕方に注文
- 5月30日住所情報不足で配達不可のため修正
- 5月31日到着
大体1週間で届きました。 私が住所を間違えなければも少し早く届いたと思います。
これから
このJTAGアダプタがRasPiに使えるかやSynQuacerにつなげる際のやり方などはこれから試します。 本日はこれにて。
Windows10とArch Linuxをファイルシステムを暗号化しながら入れた話 その1
あらすじ
新マシンとしてThinkPad X230の中古品と480GBのSSDを買ったので、セットアップを行いました。その時行ったことを備忘録として書いておこうと思います。
ハードの性能はこんな感じです。
name | spec |
---|---|
Hardware | ThinkPad x230 |
CPU | Intel(R) Core(TM) i5-3320M CPU @ 2.60GHz |
Memory | 8GB |
Storage | SSD 480GB |
OSのインストールは以下の希望を満たせるよう、進めることにします。
- Windows & Linux dual boot
- UEFIブート(not CSMモード)
- Win,Linux どちらでも読み書きできる領域(ファイル交換用)を16GBがほしい
- winもLinuxもファイルシステムを暗号化したい(紛失後の情報流出の心配を減らしたい)
- 暗号化されたswap領域も欲しい
- サスペンドのみでハイバネートは使わない
- Btrfs + snapper + snap-syncで差分バックアップ取れるようにしたい
一言でまとめるとすると「(UEFI + Windows 10 + Bitlocker(without TPM)) and (UEFI + Arch Linux + dm-crypt + Btrfs)」とかけばいいのでしょうか......? 結構大変です。
手順が長くなるので、以下の3つくらいに記事を分けたいと思います。
- USBディスクからArchをインストールするまで
- Archのデスクトップ環境を作るまで
- Snapperで定期snapshot取得およびバックアップを設定するまで
Windowsのインストール
先にWindows 10を120GBのパーティションを作ってインストールします。
細かいインストール方法等は省略します。
UEFIの設定でTPMをDisableにすればBitlockerを用いて暗号化も可能です。 TPMを有効にしたまま行うのは難しそうです。
Linuxをインストール
パーティション作成
既にWindowsのパーティションが4つでできているので、新たにrootfs(sda5)に298GiB、swap(sda6)に16GiB、ファイル交換用(sda7)に16GiBのパーティションを作ります。
fdisk /dev/sda
完成後はこんな感じになります。
partition | size | type |
---|---|---|
/dev/sda1 | 499M | Windows recovery environment |
/dev/sda2 | 100M | EFI System |
/dev/sda3 | 16M | Microsoft reserved |
/dev/sda4 | 116G | Microsoft basic data(Windows10 OS) |
/dev/sda5 | 298G | Linux filesystem(rootfs) |
/dev/sda6 | 16G | Linux swap |
/dev/sda7 | 16G | Microsoft basic data(ファイル交換用) |
最後のsda7だけ暗号化しないのでexfatでフォーマットしておきます。
mkfs.exfat /dev/sda7
ファイルシステム作成とマウント
rootfsの暗号化
以下を参考に、dm-crypt/LUKSを使ってrootfsを暗号化します。
sudo cryptsetup -s 512 luksFormat /dev/sda5
Are you sure? (Type uppercase yes):
と聞かれるので、大文字でYESと答えます。
次にパスワードを聞かれるので、入力してください。。
これで暗号化完了です。
暗号化を解除するには、以下のコマンドを実行します。
cryptsetup open --type luks /dev/sda5 cryptroot
これで /dev/mapper/cryptroot
に復号されたデバイスがマップされます。
rootfsパーティション作成
復号されたデバイス上にbtrfsのファイルシステムを作ります。
mkfs.btrfs /dev/mapper/cryptroot
マウント
compress=zstd
をつけて圧縮を有効にしながら、rootfsを/mnt
にマウントします。
mount -o compress=zstd /dev/mapper/cryptroot /mnt
subvolume の作成
Snapperで使える推奨ファイルシステムレイアウトを作ります。 推奨レイアウトについては以下を参照してください。
cd /mnt sudo btrfs subvolume create @ sudo btrfs subvolume create @home sudo btrfs subvolume create @log
一緒にsnapper向けのsubvolumeも作ります。
sudo btrfs subvolume create @snapshots sudo btrfs subvolume create @snapshots/snapshots_root sudo btrfs subvolume create @snapshots/snapshots_home
一旦マウントし直します。
cd umount /mnt mount -o compress=zstd,subvol=@ /dev/mapper/cryptroot /mnt mkdir /mnt/home mount -o compress=zstd,subvol=@home /dev/mapper/cryptroot /mnt/home mkdir -p /mnt/var/log mount -o compress=zstd,subvol=@log /dev/mapper/cryptroot /mnt/var/log
cd /mnt mkdir -p var/cache/pacman/ btrfs subvolume create var/cache/pacman/pkg btrfs subvolume create var/abs btrfs subvolume create var/tmp btrfs subvolume create srv
bootのマウント
bootをマウントします。
mkdir /mnt/boot mount /dev/sda2 /mnt/boot
Archのセットアップとインストール
システムクロック更新
timedatectl set-ntp true
ミラー選択
/etc/pacman.d/mirrorlist を編集します。
sed -i -e "s/Server/#Server/" /etc/pacman.d/mirrorlist nano /etc/pacman.d/mirrorlist
JAPANのミラーだけコメントアウトから外してください。
base systemのインストール
cd /mnt pacstrap /mnt base base-devel
fstabの反映
マウント情報をfstabに反映します。
genfstab -U /mnt >> /mnt/etc/fstab
暗号化されたswap領域の作成とマウント設定
swapはRAMのデータが一時的に退避される場所です。 なので、ここが暗号化されていないとRAMにあるデータが一部読み取れてしまうかもしれないので、暗号化します。
ハイバネートをすることを考えなければ、swapの暗号化は非常に簡単です。
以下のドキュメントを参考に /mnt/etc/crypttab
と /mnt/etc/fstab
を修正すれば、swapの暗号化は完了します。
まずswapパーティション(sda6)の先頭1Mをext2でフォーマットし、UUIDを得ます。
mkfs.ext2 -L cryptswap /dev/sda6 1M blkid /dev/sda6
すると、UUIDとLABELが得られるので、どちらか好きな方を使って /mnt/etc/crypttab
に暗号化の設定を追記します。
swap LABEL=cryptswap /dev/urandom swap,offset=2048,cipher=aes-xts-plain64,size=256
これで起動時に暗号化されたswapが /dev/mapper/swap
にマウントされるので、このswapを使うようにfstabに追記します。
/dev/mapper/swap none swap defaults 0 0
なぜこのようにoffsetを使うかの理由は、以下を参照してください。
It is more reliable to identify the correct partition by giving it a genuine UUID or LABEL. By default that does not work because dm-crypt and mkswap would simply overwrite any content on that partition which would remove the UUID and LABEL too
swapの書き込み制限
sudo sh -c "echo 10 > /proc/sys/vm/swappiness" sudo sh -c 'echo "vm.swappiness = 10" >> /mnt/etc/sysctl.conf'
swapの書き込み回数を減らしてSSDの寿命を伸ばします。
chroot
chrootでArchのrootfsを設定していきます。
arch-chroot /mnt
タイムゾーン設定
ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
locale設定
/etc/locale.gen
を編集して以下のコメントを外します。
そして以下のコマンドを実行します。
locale-gen
最後にlocaleを設定します。
sudo sh -c 'echo LANG=en_US.UTF-8 > /etc/locale.conf'
一応vconsoleも設定します。
sudo sh -c 'echo KEYMAP=jp106 > /etc/vconsole.conf'
Hostname
ホスト名を適当に設定します。 /etc/hosts
も忘れずに。
echo HOGEHOE > /etc/hostname
127.0.0.1 localhost.localdomain localhost ::1 localhost.localdomain localhost 127.0.1.1 HOGEHOGE.localdomain HOGEHOGE
systemctl-boot
systemd-bootをブートローダーとしてインストールします。
bootctl --path=/boot install
rootfsを暗号化してるので、以下の /boot/loader/entries/arch.conf
を作ります。
title Arch Linux Encrypted linux /vmlinuz-linux initrd /initramfs-linux.img options cryptdevice=UUID=<UUID>:<mapped-name> root=UUID=<luks-UUID> rootflags=subvol=@ quiet rw
UUIDは以下のコマンドで調べられます。
ls -l /dev/disk/by-uuid/
/dev/sda5
が
例えば
# ls -l /dev/disk/by-uuid/ lrwxrwxrwx 1 root root 10 Feb 8 2018 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX -> ../../dm-0 lrwxrwxrwx 1 root root 10 Feb 8 2018 (hidden) -> ../../sdb2 lrwxrwxrwx 1 root root 10 Feb 8 2018 (hidden) -> ../../sdb1 lrwxrwxrwx 1 root root 10 Feb 8 2018 YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY -> ../../sda5 lrwxrwxrwx 1 root root 10 Feb 8 2018 (hidden) -> ../../sda2 lrwxrwxrwx 1 root root 10 Feb 8 2018 (hidden) -> ../../sda1 lrwxrwxrwx 1 root root 10 Feb 8 2018 (hidden) -> ../../sda7 lrwxrwxrwx 1 root root 10 Feb 8 02:01 (hidden) -> ../../sda6
となる場合は/boot/loader/entries/arch.conf
は以下のようになります。
title Arch Linux Encrypted linux /vmlinuz-linux initrd /initramfs-linux.img options cryptdevice=UUID=YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY:cryptroot root=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX rw rootflags=subvol=@ quiet
一緒に、Windowsをブートするためのエントリも作成してください。
title Windows 10 loader EFI/MICROSOFT/BOOT/BOOTMGFW.EFI
btrfs-progs
btrfs をつかうので、入れておきます。
sudo pacman -S btrfs-progs
これを入れておかないと、次のmkcpioでbtrfsのモジュールが入りません。
mkcpio
ブート時にrootfsの暗号化を解除できるよう /etc/mkinitcpio.conf
に encrypt フックを追加します。
HOOKSの行を以下のように書き換えてください。
HOOKS=(base udev autodetect keyboard keymap consolefont modconf block encrypt btrfs filesystems)
initramfsを作り直します。
mkinitcpio -p linux
ansible動かせるように色々インストール
初期セットアップを別マシンからansibleで行えるようにしたいので、必要なファイルを入れておきます。
sudo pacman -S python openssh sudo systemctl enable sshd.service
user追加
管理に使うユーザーを追加します。
useradd -m -G wheel USERNAME passwd USERNAME
visudo
wheelのひとはNOPASSWDでsudo使えるようにしておくと、ansibleでの初期セットアップができて便利なので、設定しておきます。
リブート
最後にリブートして完了です。
exit cd umount -R /mnt reboot
おしまい
今回はここでおしまいです。
QEMUのARM Virtマシンのペリフェラルメモリマップについてのメモ
QEMUのARM Virtマシンのペリフェラルメモリマップは何処を見ればいいんだっけ......とよく忘れるので、パスと見るべきところをメモします。
マシンを定義しているファイルはこれ。
qemu/virt.c at master · qemu/qemu · GitHub
メモリマップは125行目辺り MemMapEntry a15memmap[]
にかかれています。
以下、該当コードを引用します。
static const MemMapEntry a15memmap[] = { /* Space up to 0x8000000 is reserved for a boot ROM */ [VIRT_FLASH] = { 0, 0x08000000 }, [VIRT_CPUPERIPHS] = { 0x08000000, 0x00020000 }, /* GIC distributor and CPU interfaces sit inside the CPU peripheral space */ [VIRT_GIC_DIST] = { 0x08000000, 0x00010000 }, [VIRT_GIC_CPU] = { 0x08010000, 0x00010000 }, [VIRT_GIC_V2M] = { 0x08020000, 0x00001000 }, /* The space in between here is reserved for GICv3 CPU/vCPU/HYP */ [VIRT_GIC_ITS] = { 0x08080000, 0x00020000 }, /* This redistributor space allows up to 2*64kB*123 CPUs */ [VIRT_GIC_REDIST] = { 0x080A0000, 0x00F60000 }, [VIRT_UART] = { 0x09000000, 0x00001000 }, [VIRT_RTC] = { 0x09010000, 0x00001000 }, [VIRT_FW_CFG] = { 0x09020000, 0x00000018 }, [VIRT_GPIO] = { 0x09030000, 0x00001000 }, [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, [VIRT_SECURE_MEM] = { 0x0e000000, 0x01000000 }, [VIRT_PCIE_MMIO] = { 0x10000000, 0x2eff0000 }, [VIRT_PCIE_PIO] = { 0x3eff0000, 0x00010000 }, [VIRT_PCIE_ECAM] = { 0x3f000000, 0x01000000 }, [VIRT_MEM] = { 0x40000000, RAMLIMIT_BYTES }, /* Second PCIe window, 512GB wide at the 512GB boundary */ [VIRT_PCIE_MMIO_HIGH] = { 0x8000000000ULL, 0x8000000000ULL }, };
どのペリフェラルが使われているかはここからはわからないので、memmapの1列目の文字列から探していく必要があります。
例えばUARTなら、VIRT_UARTで検索をすると1422行目あたりに create_uart
関数を呼び出しているところが見つかります。
create_uart(vms, pic, VIRT_UART, sysmem, serial_hds[0]);
この create_uart
関数の定義は644行目あたりにあり、このコードを見ていくと頭の方にペリフェラルの名前が書いてあるので、PL011が使われていることがわかります。
static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, MemoryRegion *mem, Chardev *chr) { char *nodename; hwaddr base = vms->memmap[uart].base; hwaddr size = vms->memmap[uart].size; int irq = vms->irqmap[uart]; const char compat[] = "arm,pl011\0arm,primecell";
後はペリフェラルの資料を探して読んでドライバを実装すればOKです。
おしまい。