コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2024年7月23日 >>> 2024年7月23日
link もっと後

2024年7月23日

OpenSBIを調べる - QEMUのデバイスツリー

目次: Linux

OpenSBIのブート部分を調べます。OpenSBIはいくつか動作モードがあるのですが、payloadを持ったタイプを調べます。対象のファイル名はbuild/platform/generic/firmware/fw_payload.binもしくは.elfです。

今回はOpenSBIを見る前にQEMUの動作、デバイスツリーの扱いについて調べます。実行環境はQEMU RV64 virt machine(qemu-system-riscv64 -machine virt)です。なぜ突然QEMUの話をするかというと、OpenSBIはQEMUからデバイスツリーを受け取るからです。OpenSBIを調べる前にQEMUがわかっていた方が理解しやすいです。

QEMUは-dtbオプションにてデバイスツリーファイルを明示的に指定できます。もし-dtbオプションを省略するとHW構成に従ってデバイスツリーを自動生成します。便利ですね。明示的に指定した場合、自動生成した場合いずれであってもQEMUのメモリの何処かにデバイスツリーのデータを展開します。

OpenSBIにデバイスツリーのアドレスを渡す方法

OpenSBIを起動するときはレジスタa0にhartid、レジスタa1にデバイスツリーのアドレスを渡す決まりがあります。

OpenSBIのドキュメント(適当訳)
####opensbi/docs/firmware/fw.md####

OpenSBI Platform Firmwares
==========================

OpenSBI provides firmware builds for specific platforms. Different types of
firmwares are supported to deal with the differences between different platforms
early boot stage. All firmwares will execute the same initialization procedure
of the platform hardware according to the platform specific code as well as
OpenSBI generic library code. The supported firmwares type will differ in how
the arguments passed by the platform early boot stage are handled, as well as
how the boot stage following the firmware will be handled and executed.

The previous booting stage will pass information via the following registers
of RISC-V CPU:

* hartid via *a0* register
* device tree blob address in memory via *a1* register. The address must
  be aligned to 8 bytes.

(適当訳)
OpenSBIは特定のプラットフォーム用のファームウェアビルドを提供します。初期ブートローダーでの
異なるプラットフォーム間の違いに対処するため、いろいろな種類のファームウェアがサポートされています。
全てのファームウェアはプラットフォーム固有のコードとOpenSBIの汎用ライブラリのコードに従って、
プラットフォームHWの同じ初期化処理を実行します(訳注: 何を言いたいかよくわからん……)。
サポートされているファームウェアの種類は、プラットフォームの初期ブートローダーから渡された引数が
どのように処理されるかと、ファームウェアに続く起動段階がどのように処理され実行されるかによって異なります。

直前のブートローダーは、次のRISC-V CPUレジスタ経由で情報を渡します:

* レジスタa0経由でhartid
* レジスタa1経由でメモリ上のデバイスツリーブロブ(訳注: *.dtbのこと)のアドレス、アドレスは8バイトアラインが必要

QEMUの場合はブートROMコード(qemu-system-riscv64 -machine virtの場合はアドレス0x1000付近)がレジスタa1にアドレスを設定します。コードの逆アセンブルはこんな感じです。

QEMUのブートROMの逆アセンブルとダンプ
   0x1000:      auipc   t0,0x0      //t0 <- 0x1000
   0x1004:      addi    a2,t0,40    //a2 <- 0x1028
   0x1008:      csrr    a0,mhartid  //a0 <- hartid
   0x100c:      ld      a1,32(t0)   //a1 <- 0x87e00000(アドレス0x1020の値)
   0x1010:      ld      t0,24(t0)   //t0 <- 0x80000000(アドレス0x1018の値)
   0x1014:      jr      t0          //0x80000000にジャンプ(OpenSBIの先頭)

0x1000: 0x00000297      0x02828613      0xf1402573      0x0202b583
0x1010: 0x0182b283      0x00028067      0x80000000      0x00000000
0x1020: 0x87e00000      0x00000000      0x4942534f      0x00000000
0x1030: 0x00000002      0x00000000      0x80000000      0x00000000

QEMUはリセットすると必ずブートROMコードから実行開始しますから、常にレジスタa1に0x87e00000(-m 128MBの場合、メモリ量に依存してアドレスが変わる)を設定してからOpenSBIにジャンプすることがわかります。アドレス0x87e00000付近の内容をダンプすると、

QEMUのデバイスツリー配置領域のダンプ
0x87e00000:     0xedfe0dd0      0x201c0000      0x38000000      0x341a0000
0x87e00010:     0x28000000      0x11000000      0x10000000      0x00000000
0x87e00020:     0xec010000      0xfc190000      0x00000000      0x00000000
0x87e00030:     0x00000000      0x00000000      0x01000000      0x00000000
0x87e00040:     0x03000000      0x04000000      0x1d000000      0x02000000
0x87e00050:     0x03000000      0x04000000      0x11000000      0x02000000
0x87e00060:     0x03000000      0x0d000000      0x06000000      0x63736972
0x87e00070:     0x69762d76      0x6f697472      0x6d657100      0x03000000

なるほど、このデータはデバイスツリーですね……と思える人は相当デバイスツリー通です。私はわかりませんので、データが何者か調べるため先頭にある謎の値0xedfe0dd0に注目します。

デバイスツリーのドキュメント(5. Flattened Devicetree (DTB) Format)を見るとヘッダは下記のようになっています。先頭のmagicメンバーはマジックナンバーであり、ビッグエンディアンの0xd00dfeedでなければならないと記述されています。

Flattened Devicetreeのヘッダ構造体の定義

struct fdt_header {
    uint32_t magic;
    uint32_t totalsize;
    uint32_t off_dt_struct;
    uint32_t off_dt_strings;
    uint32_t off_mem_rsvmap;
    uint32_t version;
    uint32_t last_comp_version;
    uint32_t boot_cpuid_phys;
    uint32_t size_dt_strings;
    uint32_t size_dt_struct;
};

メモリ上にあった謎の値0xedfe0dd0をビッグエンディアンで解釈すると0xd00dfeedとなり、struct fdt_headerのマジックナンバーと一致しました。このデータはきっとデバイスツリーでしょう。

まとめるとQEMU(qemu-system-riscv64 -machine virt)のブートROMコードは、

  • 起動オプションに応じてデバイスツリーを自動生成して0x87e00000に配置(アドレスはメモリ量依存で変わる)
  • もしくは-dtbオプションに指定した*.dtbファイルを0x87e00000に配置
  • ROMブートコードでデバイスツリー先頭のアドレスをレジスタa1に格納

このような動作をします。

QEMUが自動生成するデバイスツリーをダンプ

QEMUが自動生成したデバイスツリーをファイルにダンプする方法をメモしておきます。簡単に言えばQEMU Monitorでdumpdtb (file名)コマンドを実行すればダンプできます。

QEMU Monitorを使うにはいくつか手があります。グラフィック環境が使えるなら-nographicと-monオプションを外し、ウインドウから入力するのが一番早いでしょう。

QEMU Monitorの使用方法(GUI)
# グラフィック環境が使えるとき

./qemu-system-riscv64 \
  -machine virt \
  -bios none \
  -chardev stdio,id=con,mux=on \
  -serial chardev:con \
  -smp 4

こんなウインドウが表示されるはずです。


QEMU Monitor(GUI)

グラフィック環境がない場合はシリアル出力を一時的に無効化して、-monを標準入出力に振り向けると使えるようです。

QEMU Monitorの使用方法(CUI)
# グラフィック環境が使えないとき

./qemu-system-riscv64 \
  -machine virt \
  -bios none \
  -nographic \
  -chardev stdio,id=con,mux=on \
  -chardev null,id=none,mux=on \
  -serial chardev:none \
  -mon chardev=con,mode=readline \
  -smp 4

QEMU 9.0.2 monitor - type 'help' for more information
(qemu) dumpdtb virt.dtb
info: dtb dumped to virt.dtb
(qemu) 

もっとスマートなやり方がありそうですけど……使えればよしとしましょう。

QEMUは起動時にデバイスツリーを自動生成もしくはファイルからロードしてくれることがわかりました。次回はOpenSBIでデバイスツリーをどう扱っているか調べたいと思います。

編集者:すずき(2024/07/26 00:10)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2024年7月23日 >>> 2024年7月23日
link もっと後

管理用メニュー

link 記事を新規作成

<2024>
<<<07>>>
-123456
78910111213
14151617181920
21222324252627
28293031---

最近のコメント5件

  • link 14年6月13日
    2048player...さん (09/26 01:04)
    「最後に、この式を出すのに紙4枚(A4)も...」
  • link 14年6月13日
    2048playerさん (09/26 01:00)
    「今のところ最も簡略化した式です。\n--...」
  • link 14年6月13日
    2048playerさん (09/16 01:00)
    「返信ありがとうございます。\nコメントが...」
  • link 14年6月13日
    すずきさん (09/12 21:19)
    「コメントありがとうございます。同じ結果に...」
  • link 14年6月13日
    2048playerさん (09/08 17:30)
    「私も2048の最高スコアを求めたのですが...」

最近の記事3件

  • link 24年9月14日
    すずき (09/22 11:23)
    「[OpenSBIを調べる - scratch領域の詳細] 目次: Linux今回はOpenSBIのコード内に頻出するscrat...」
  • link 21年8月11日
    すずき (09/22 00:15)
    「[Kindle - まとめリンク] 目次: Kindle初代Kindle Fire HDの話。Kindle Fire HDのカ...」
  • link 24年8月11日
    すずき (09/22 00:14)
    「[Amazonマイリストへの問い合わせの返事がきた] 目次: Kindle先日(2024年8月4日の日記参照)Amazonへ問...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www2.katsuster.net
RDFファイル RSS 1.0

最終更新: 09/26 01:04