$30 off During Our Annual Pro Sale. View Details »

Blend XMODEM -UEFI de XMODEM-/KernelvmKansai8

Blend XMODEM -UEFI de XMODEM-/KernelvmKansai8

UEFIでXMODEMを実装しようと頑張った話です。

Toshifumi NISHINAGA

November 18, 2017
Tweet

More Decks by Toshifumi NISHINAGA

Other Decks in Programming

Transcript

  1. Blend
    XMODEM
    UEFI de XMODEM
    2017/11/18 KernelVM@Kansai8

    View Slide

  2. $ who
    @tnishinaga

    View Slide

  3. 今回の話
    AARCH64ボードのUEFI上でXMODEMを動かします

    View Slide

  4. 今回の話
    AARCH64ボードのUEFI上でXMODEMを動かします

    View Slide

  5. 今回の話
    AARCH64ボードから
    発表がておくれるほどに受けた
    数々のご褒美(?)についてのお話

    View Slide

  6. そもそもの動機
    1. AARCH64の勉強がしたい
    a. UEFIから起動するOSもどきを作ってみたい
    2. 手元にあるHiKey Boardでやりたい
    3. 毎回SDカード抜き差しするの大変
    4. リモートからプログラムを送りたい

    View Slide

  7. リモートからプログラムを
    送りたい!

    View Slide

  8. リモートからプログラムを送る方法たち
    ● シリアル転送(X/Y/Z MODEM, Kermit)
    ○ メリット:追加部品がいらない。パソコン側の設定もいらなくて楽。
    ○ デメリット:遅い。実装が面倒。
    ● ネットワークブート(PXE(TFTP)ブート)
    ○ メリット: 速い。安心(UEFI側の実装がちゃんとしてれば)。
    ○ デメリット:
    USB-NIC購入(1000円くらい)が必要(Hikey boardはNICを持たない)。
    パソコン側の設定がちょっと必要。
    ○ https://wiki.linaro.org/Boards/Hikey/Setup/TFTPBoot

    View Slide

  9. XMODEM
    ● X,Y,Z MODEM中で最も単純なバイナリ転送プロトコル
    ● 大抵のシリアル通信アプリケーション(minicom, TeraTerm)か
    ら使える
    ● 一部、効率や機能が不十分
    ○ でも今回のようにプログラムを送りつけるだけなら問題なし

    View Slide

  10. XMODEMの通信フロー
    ● 送信側が受信側からNAKを受
    け取ると通信開始
    ● 送信側がデータを送信、受信側
    がACKを返して1ブロックずつ転

    ● 送信側がEOTを送ると受信側
    はACKを返して転送終了
    Receiver Sender
    Block data 1
    ACK
    Block data 2
    NAK
    NAK
    EOT
    ACK

    View Slide

  11. XMODEMのエラー通信フロー
    ● 受信ブロックが壊れている場合
    はNAK(再送要求)を送る
    ● 送信側はNAKを受け取ると、前
    回のブロックを再送する
    ● 再度受け取ったブロックが正常
    ならACKを返して通信再開
    ● 送信側は一定回数以上NAKを
    受け取ると通信を諦める
    Receiver Sender
    Block data 1
    NAK
    Block data 1
    NAK
    NAK
    ACK

    View Slide

  12. ね? 簡単でしょ?

    View Slide

  13. 簡単じゃなかった

    View Slide

  14. ご褒美1
    Q. UEFIの文字コードはUTF-16。
    1byte read/writeをするにはどうすれば?
    A. “SERIAL IO PROTOCOL”を使う

    View Slide

  15. SERIAL IO PROTOCOL
    ● ボードのシリアルポートを直接Read/Writeできる
    ○ http://wiki.phoenix.com/wiki/index.php/EFI_SERIAL_IO_PROTOCOL
    ● 使い方
    ○ LocateHandleでSERIAL_IO_PROTOCOLのハンドラを取得
    ■ シリアルポートが複数ある場合、各ポートに対応した複数のハンドラが取得できる
    ○ HandleProtocolで任意のハンドラからSERIAL_IO_PROTOCOLを取得
    ○ SERIAL_IO_PROTOCOLのRead/Writeを使って読み書きすればOK
    ■ https://github.com/tnishinaga/baremetal_hikeyboard/blob/master/uefi_serial_echo_sampl
    e/main.c

    View Slide

  16. ご褒美2
    Q. どうやって一定時間ごとに
    受信待ちループを解除してNAK送信するの?
    (UEFIアプリは割り込み処理が大変)
    (受信側スタート厳しくない?)
    A. SERIAL_IO_PROTOCOLのSetAttibutesで
    タイムアウトを設定する

    View Slide

  17. SetAttributes
    ● タイムアウト設定できる
    ○ 0にするとデフォルト
    ● NAK送信→受信待ち→タイム
    アウト→NAK送信→...
    とすれば行ける!!
    http://wiki.phoenix.com/wiki/index.php/EFI_SERIAL_I
    O_PROTOCOL#SetAttributes.28.29

    View Slide

  18. うまく動かない
    デバッグしないと

    View Slide

  19. ご褒美3
    Q. シリアル1本XMODEMで使ってるよね?
    どこでPrintf debugするの?
    A. シリアルを2本生やせば良いのでは?

    View Slide

  20. シリアルを2本生やす
    ● QEMUならオプションでUSBやPCIバスにシリアルデバイスを
    生やせる......?
    ○ qemu-system-aarch64 FOOBAR \
    -chardev pty,id=pts0 -device isa-serial,chardev=pts0
    -chardev pty,id=pts1 -device isa-serial,chardev=pts1

    View Slide

  21. 生えない

    View Slide

  22. シリアルが2本生えない
    ● AARCH64はisa-busに繋げない
    ● USB, PCIにはつなげるが、UEFI側が認識しない
    ● QEMUのコードを読むとVirtマシン*には元々1本しかシリアル
    ポートがマッピングされていない(?)
    ○ https://github.com/qemu/qemu/blob/master/hw/arm/virt.c
    *: Linaroの出してるQEMUようUEFIイメージはVirtマシン専用

    View Slide

  23. ご褒美4
    Q. どうやってシリアルを2本生やすの?
    A. x86_64のQEMUに生やす

    View Slide

  24. x86 QEMUでシリアルを2本生やす
    ● x86_64のQRMUならシリアルを2本生やせる
    ○ qemu-system-x86_64 -cpu qemu64 \
    -drive if=pflash,format=raw,unit=0,file=/usr/share/ovmf/ovmf_code_x64.bin,readonly=on \
    -drive if=pflash,format=raw,unit=1,file=/usr/share/ovmf/ovmf_vars_x64.bin \
    -hda fat:rw:. \
    -chardev pty,id=pts0 -device isa-serial,chardev=pts0 \
    -chardev pty,id=pts1 -device isa-serial,chardev=pts1
    ● ちゃんとUEFI側でも認識する
    ○ 片方をデバッグ、片方をXMODEM通信用にしてデバッグ開始

    View Slide

  25. MINICOM vs TMUX

    View Slide

  26. ご褒美5
    ● ptsをめぐる争い
    a. QEMUがシリアルポートをptsにつなげる
    b. minicomでptsを開く
    c. QEMUを終了する(minicomはptsを開いたまま)
    d. tmuxで新しいウィンドウを開く
    e. tmuxとminicomの入出力が繋がり入力を奪い合う
    ● 対応
    a. デバッグ中は今開いてるターミナルだけで頑張る

    View Slide

  27. データの一部
    消えてない?

    View Slide

  28. ご褒美6
    ● 問題
    a. 送信側はNAKを受け取ってデータを送ろうとしてる
    b. 受信側はデータを受け取れずタイムアウトしてNAKを送る
    c. NAKを受け取った送信側はデータを再送する
    d. 以降繰り返し
    e. (データが闇に消えてる気がする)
    ● 対策
    a. タイムアウトを数回繰り返すまで待ってからNAKを送るようにした
    b. ちょっとぎこちないがx86のQEMU上ではデータを受け取れた

    View Slide

  29. 後は実機に持っていくだけ!

    View Slide

  30. 動かない。

    View Slide

  31. ご褒美7
    ● 問題
    a. ご褒美6と同じく、データを受け取れずNAKを送り続けている
    b. デバッグしたいがシリアル1本しか無い
    ● 対策
    a. ファイルに書き出せば良いのでは?

    View Slide

  32. UEFIでのファイル読み書き
    1. HandleProtocolとmainの引数のimage handleから
    LOADED_IMAGE_PROTOCOLを取得する
    2. 再度HandleProtocolとLOADED_IMAGE_PROTOCOLのDeviceHandleからボ
    リュームのEFI_FILE_IO_INTERFACEを取得する
    3. EFI_FILE_IO_INTERFACEのOpenVolumeでストレージのルートを開いた
    EFI_FILE_PROTOCOLを得る
    4. EFI_FILE_PROTOCOLのOpenでファイルを開く
    5. EFI_FILE_PROTOCOLのWriteでファイルに書き込む
    6. EFI_FILE_PROTOCOLのCloseでファイルを閉じる

    View Slide

  33. これでログが取れるね!

    View Slide

  34. View Slide

  35. 書き込みデータがお
    かしい

    View Slide

  36. ご褒美8
    ● 問題
    ○ 書き込んだ文字列が謎のデータに化けてる
    ○ 実機だけ発生。QEMUでは発生しない。
    ● 対策
    ○ 実機のファームウェアをアップデートしてみよう

    View Slide

  37. HiKey boardをアップデートしよう
    ● HiKey BoardのUEFIファーム導入方法は以下参照
    ○ https://github.com/96boards/documentation/wiki/HiKeyUEFI

    View Slide

  38. ご褒美9
    Q. 同じようなファイルのダウンロード先
    が複数(Debian, Android, release, snapshot...)
    あるけど何処のをつかえばいいの?
    A. UEFI Shellを使いたいなら
    uefi-openplatformpkgのlatestをつかえば良い
    (reference-platformのはちょい使いづらい)

    View Slide

  39. HiKey boardをアップデートしよう
    ● openplatformpkgなどからファイルを取得する
    ○ wget
    https://builds.96boards.org/snapshots/reference-platform/components/uefi-staging/latest/hikey/release/hisi-i
    dt.py
    ○ wget https://builds.96boards.org/snapshots/hikey/linaro/uefi-openplatformpkg/latest/l-loader.bin
    ○ wget https://builds.96boards.org/snapshots/hikey/linaro/uefi-openplatformpkg/latest/fip.bin
    ○ wget https://builds.96boards.org/snapshots/hikey/linaro/uefi-openplatformpkg/latest/ptable-linux-4g.img
    ○ wget https://builds.96boards.org/snapshots/hikey/linaro/uefi-openplatformpkg/latest/ptable-linux-8g.img
    ○ wget https://builds.96boards.org/snapshots/hikey/linaro/uefi-openplatformpkg/latest/nvme.img
    ● boot-fat.uefi.imgは空のFATパーティションを用意する
    ○ 既にBOOTパーティションにGRUB等が書き込まれている場合はShellが正しく
    起動しなくなる
    ■ dd if=/dev/zero of=boot-fat.uefi.img bs=1M count=64 && mkfs.vfat boot-fat.uefi.img

    View Slide

  40. View Slide

  41. HiKey boardをアップデートしよう
    ● openplatformpkgなどからファイルを取得する
    ○ wget
    https://builds.96boards.org/snapshots/reference-platform/components/uefi-staging/latest/hikey/release/hisi-i
    dt.py
    ○ wget https://builds.96boards.org/snapshots/hikey/linaro/uefi-openplatformpkg/latest/l-loader.bin
    ○ wget https://builds.96boards.org/snapshots/hikey/linaro/uefi-openplatformpkg/latest/fip.bin
    ○ wget https://builds.96boards.org/snapshots/hikey/linaro/uefi-openplatformpkg/latest/ptable-linux-4g.img
    ○ wget https://builds.96boards.org/snapshots/hikey/linaro/uefi-openplatformpkg/latest/ptable-linux-8g.img
    ○ wget https://builds.96boards.org/snapshots/hikey/linaro/uefi-openplatformpkg/latest/nvme.img
    ● boot-fat.uefi.imgは空のFATパーティションを用意する
    ○ 既にBOOTパーティションにGRUB等が書き込まれている場合はShellが正しく
    起動しなくなる
    ■ dd if=/dev/zero of=boot-fat.uefi.img bs=1M count=64 && mkfs.vfat boot-fat.uefi.img

    View Slide

  42. HiKey boardをアップデートしよう
    ● その後
    ○ ドキュメントを参照しながらファームを更新する
    ■ https://github.com/96boards/documentation/wiki/HiKeyUEFI
    ○ UEFI Shellを使いたいだけならboot-fat.uefi.img の書き込みまでで止めて良

    View Slide

  43. 正しく
    書き込めるようになった

    View Slide

  44. これでログが取れるね!

    View Slide

  45. 時間切れ

    View Slide

  46. まとめ
    ● XMODEMはプロトコルは簡単だがUEFIでの実装結構大変
    ● UEFIではSERIAL_IO_PROTOCOLを使うと
    バイト単位でシリアル読み書きできる
    ● SERIAL_IO_PROTOCOLでタイムアウト使ったときの
    受信データの扱いは不安
    ● ptsはtmux等との奪い合いが起こる。仲良くしてほしい。
    ● UEFIでシリアルを使うアプリのデバッグ大変
    ● 実機のUEFI実装にはバグがあるかも。
    エミュレータでの動作と比較検証大事。

    View Slide