デバイスツリー Overlay について調べてみた

#1.はじめに
ARM CPUを内蔵するFPGAをLinuxで動作させているうちに、デバイスツリーだけでなく、デバイツリー オーバーレイという仕組みを使うと良いことがあること分かりました（FPGAをコンフィグレーションできるとか）。
デバイツリー **オーバーレイ**の使い方について調べてみた内容を書かせていただきます。（主にFPGAのLinuxを開発している人向け, 実機での動作確認はIntel系のFPGAでのみやっております：[DeviceTree Overlay でのFPGAコンフィグ(DE10nano)](https://qiita.com/eofz/items/884b37e401c07a264d38) ）。

なお、ここでは「デバイスツリー」についての内容は含みません。そちらについては別の資料ををご覧ください（ [デバイスツリーについて調べてみた](https://qiita.com/eofz/items/20cfa99601756fc98905) もあります）。



# Devicetree Overlay でできること
Kernelは、起動時にbootloaderから指定されたデバイスツリーを読み込みます(base tree)。通常は、デバイスツリー情報は再起動しない限り変更はできないのですが、デバイツリー**オーバーレイ**を使えば、base treeの内容に対し、
- node(=デバイス）の追加
- propertyの追加
- propertyのvalue変更
といったことが再起動なしできるようになります。
オーバーレイする内容は、オーバーレイファイルで記述し、そのファイルを読み込むことで実施されます。オーバーレイファイルは、複数読み込むことも可能です。
また、オーバーレイした内容は、オーバーレイファイル単位で削除することが可能となり、そのオーバーレイファイルを読み込む前の状態に戻すこともできるようになってます。

オーバーレイファイルを読み込んだり、削除したりすることでデバイスツリーの内容が変化しますが、その点でのデバイスツリーの内容は、live treeと呼ばれます。デバイツリーオーバーレイが実行されてなければ、live tree = base tree です。



# Devicetree Overlay ファイルの書き方
デバイスツリーオーバーレイファイルも、テキストソースとバイナリがあり、デバイスツリーと同じくdtcでコンパイルします。デバイスツリーファイルと区別するため、ここではオーバーレイソースの拡張子を.dtso, オーバーレイバイナリの拡張子を.dtboとしてます。

必要最小限度のオーバーレイファイルは以下です。

```text:minimum.dtso

/dts-v1/;
/plugin/;
/ {
    fragment@0 { /* node名は何でも良い */
        target = <phandle>; /* overlayするnodeの phandle */
　　　　/*　もしくは */
　　　　 target-path="/path"; /* overlayするnodeの path */

        __overlay__ {
            /* オーバーレイする property 定義 たち*/
            /* オーバーレイする node 定義 たち*/
        };
    };
};
```

必要な内容はシンプルで、

- 冒頭の /dts-v1/; の後に `/plugin/;`
- ルートnode
- ルートnodeの子node。 nodeの名前は何でも良い
- 子node に `target`（もしくは `target-path`）propertyと `__overlay__` nodeを持たせる
    - `target` or `target-path` propertyで、オーバレイ対象となるnodeを指定
        - `target` ではphandleで指定(もしくはラベル)
        - `target-path` ではpath stringで指定
    - `__overlay__` node 内に具体的にオーバーレイする内容を記述
        - 追加したいpropertyやnodeたちを定義する

となります。冒頭の `/plugin/;`は、オーバーレイファイルの記述中に、過去に読み込んだデバイスツリー(live tree)で定義したlabelを参照できるようにするためのものです。例えば、`target`のvalueとしてbase treeで定義されているラベル名を使えるようになります（オーバーレイファイル中にこのファイル内で定義されていないラベルがあってもdtcでエラーとならない）。
ただし、base tree が、dtcでのコンパイル時に.dtbにシンボル情報も含めるよう -@ オプションが付けられている必要があります（FPGA用のGitリポジトリにあるKernel Sourceでmakeした .dtb なら -@ 付でコンパイルされていると思います)。

# Devicetree Overlayの実行方法
FPGAベンダがメンテナンスしているのGitリポジトリのKernel SourceにはConfigFsというドライバ入っており、デフォルトで使えるようになっています(参考資料1,2より）のでこの仕組みを使っていきます。

*残念ながら、ユーザーランド（ユーザーコマンドやアプリケーション）からOverlayを行う方法は、現時点ではMainline Kernelに取り込まれていません(5.7.0-rc6)。Overlayを行うKernel driverを自分で書く必要があります。configfsの仕組みだとどんなDvicetree nodeでも任意のタイミング書き換えられてしまうので、そのようなことを想定していないドライバで問題が起こる...といった問題が挙げられている様で。Mainlineに入るのはもう少し時間がかかりそうです。*

以下、デバイスツリーオーバーレイ用のconfigfsのpathを $OVL_PATH とします。

X系: OVL_PATH=/configfs/device-tree/overlays 
I系: OVL_PATH=/sys/kernel/config/device-tree/overlays
（X系では、`mkdir /configfs; mount -t configfs configfs /configfs` を事前にしておく必要ありそうな)

## オーバレイ実施
次のの2つのステップで実行されます。

- $OVL_PATH ディレクトリ下に任意の名前でディレクトリを作る。
- 作成したディレクトリ下に自動的に dtbo ファイルが生成されるので、その dtbo ファイルに自分のオーバレイファイル(.dtbo)を書き込む。

my_overlay1_dir ディレクトリを作り、my_overlay1.dtbo というオーバーレイファイル読み込ませる例は以下となります。(root ユーザでの実行を想定してます）

```
# mkdir $OVL_PATH/my_overlay1_dir
# cat my_overlay1.dtbo > $OVL_PATH/my_overlay1_dir/dtbo 
```

## オーバーレイ削除
削除は1ステップで実行されます。

- オーバーレイ用に生成した $OVL_PATH ディレクトリ下のディレクトリを削除する

上の例でオーバーレイした内容を削除する場合は、

```
# rmdir $OVL_PATH/my_overlay1_dir
```

## その他の機能
オーバーレイ用に作成したディレクトリ下には、`dtbo` 以外に `path`, `status` というファイルが自動で生成されます。
`path` は、`dtbo` と同様にオバーレイ実施を行えるインターフェースですが、/lib/firmware/ 下に置いたオーバーレイファイルを読み込むもので、以下のコマンドにより /lib/firmware/の下にある abc.dtbo でオバーレイを行います。

```
# echo "abc.dtbo" > $OVL_PATH/my_overlay1_dir/path
```


`status` は、オーバーレイ用ディレクトリの状態を知ることができるインターフェースで、cat することでこのディレクトリの dtboもしくはpath を使ってオーバーレイが実施されているかを知ることが可能です。


```
# cat $OVL_PATH/my_overlay1_dir/status
 /*applied か unapplied がprint される*/
```


# 参考資料
[参考資料1: Solution Zynq PL Programming With FPGA Manager](https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841645/Solution+Zynq+PL+Programming+With+FPGA+Manager#Test+Procedure-Using+Device+Tree+Overlay:)
[参考資料2: Rockeboards.org HowToCreate a DeviceTree](https://rocketboards.org/foswiki/Documentation/HOWTOCreateADeviceTree)
[FPGA+SoC+LinuxでDevice Tree Overlayを試してみた](https://qiita.com/ikwzm/items/ec514e955c16076327ce) ：@ikwzm さんの記事、いつも参考にさせていただいておりますm(--)m