【入門】U-Boot config読解(ターゲットボード固有部)

# 1. はじめに
この記事では、U-Bootソースに対する理解を深めるためのヒントになる情報をまとめていきます。U-Bootは、動作するボード毎に合わせて異なる起動プロセスを実施しています。本記事では、U-Bootが動作しているボードのことをターゲットボード、ボード毎に異なる処理のことをターゲットボード固有部と呼びます。今回は、U-Bootがどのようにターゲットボード固有の処理を切り替えているのか紹介します。

# 2. U-Bootとは
多種のプラットフォームに対応しているブートローダーの一種です。主に、組込み機器で使われることが多いです。また、GPL-2.0+で公開されたソースであり、以下からダウンロードすることが可能です。
 - https://git.denx.de/u-boot.git

# 3. ソースコード読解
早速ソースコードの読み方について説明していきます。2020年1月時点で、U-BootのソースはかなりLinuxカーネルに近い構造になっており、Linuxカーネルを読みなれた人には馴染みのある記述が増えています。一方で、ターゲットボード毎に処理が分かれている部分もまだまだあります。このターゲットボード毎の設定を、どこでどうやって規定しているか理解することで、U-Bootを読み解くのがかなり容易になります。この記事では、そのターゲットボード固有の部分、特にconfigについて紹介していきます。

ここでは、以下の順で説明していきます。
 - 3.1. ソース環境
 - 3.2. defconfig
 - 3.3. Kconfig
 - 3.4. SYS_CONFIG

###3.1. ソース環境
ここからは、イメージしやすいように具体例を挙げながら紹介していきます。今回は以下の環境で説明を進めていきます。

ソースコード
- リポジトリ：https://git.denx.de/u-boot.git
- branch：v2020.01
ターゲットボード
- Renesas：H3ULCB (R-Car Starter Kit Premier) board

U-Bootをビルドするだけなら、非常に簡単にできます。defconfigを指定してmakeコマンドを実行するだけです。ここの仕組みは、Linuxカーネルと同じです。
※クロスコンパイラ等の設定は別途必要です

```rb
make r8a7795_ulcb_defconfig
make all
```

###3.2. defconfig
defconfigは、実行することで各ターゲットボード向けのconfigを一括で設定することができるファイルです。ここで設定されるconfigは、様々な階層にあるKconfigで定義されたオプションのON/OFFを設定するためのものです。オプションは、U-Bootの最上位ディレクトリにあるKconfigから順に呼び出されるKcongigによって、ツリー構造として構成されています。defconfigに記述されているconfigは、これらのKconfigで定義されたオプションを設定しています。

では、このdefconfigからターゲットボード固有の設定に繋がる記述をピックアップして説明していきます。

- configs/r8a7795_ulcb_defconfig

|項番  |config名  |設定値  |
|:-:|---|:-:|
|①  |CONFIG_ARM|y|
|②  |CONFIG_ARCH_RMOBILE|y|
|③  |CONFIG_RCAR_GEN3|y|
|④  |CONFIG_TARGET_ULCB|y|
|⑤  |CONFIG_DEFAULT_DEVICE_TREE|"r8a7795-h3ulcb-u-boot"|

上記のdefconfigの記述を確認していきましょう。
**- ①～③**
これらの記述で、どのSoC向けのconfigを有効にするか決定しています。
例えば、①～③のconfigを有効にした場合、以下のRcar-gen3向けのKconfigに記載された内容が有効になります。
 - arch/arm/mach-rmobile/Kconfig.64

**- ④**
ターゲットボードを指定しています。

**- ⑤**
このターゲットボードで使用するDevice tree blob(dtb)名を指定しています。


###3.3. Kconfig
早速、arch/arm/mach-rmobile/Kconfig.64を見て行きましょう。
 ※ ソース片目に説明を読んでみてください。

まず、記述全体が"if RCAR_GEN3"で囲まれており、
このファイルがRcar-Gen3専用のものであることが確認できます。

次に、defconfig節の④で説明した"CONFIG_TARGET_ULCB=y"を思い出してください。
この記述のため、"config TARGET_ULCB"が有効になります。

また、ここで大事なことは、このKconfigファイルから更にKconfigファイルをロードしていることです。
いくつかロードしている中で、H3ULCBボードに関係しそうなKconfigファイルを見てみましょう。

 - board/renesas/ulcb/Kconfig

記述内容は少ないですが、大事な情報が多いので全文を記載します。

```rb
if TARGET_ULCB
config SYS_SOC
        default "rmobile"
config SYS_BOARD
        default "ulcb"
config SYS_VENDOR
        default "renesas"
config SYS_CONFIG_NAME
        default "ulcb"
endif
```

まず、記述全体が"if TARGET_ULCB"で囲まれており、H3ULCB専用の設定であることが確認できます。

- SYS_SOC
ターゲットボードのSoCを指定しています。

- SYS_BOARD
後述する"SYS_VENDOR"と合わせて、ビルドを実行するターゲットボード固有処理部を規定するための設定です。
make実行時に、"board/\<SYS_VENDOR>/\<SYS_BOARD>/Makefile"を実行するします。また、"SYS_VENDOR"が未定義の場合、"board/\<SYS_BOARD>/Makefile"となります。

- SYS_VENDOR
"SYS_BOARD"と合わせて、ビルドを実行するボード固有処理部を規定するための設定です。

- SYS_CONFIG_NAME
インクルードするボード固有ヘッダーの指定。
ビルド時に、"include/configs/\<SYS_CONFIG_NAME>.h"をインクルードします。

###3.4. SYS_CONFIG
Kconfigで指定されたSYS_CONFIGファイルについて簡単に説明します。
 - include/configs/ulcb.h

このファイル(とそこからincludeされているヘッダーファイル)に記載されている記述はかなり多く、ボードの動作に大きな影響を与えます。例えば、クロック設定やeMMCなどの外部デバイス設定など、多くのボード固有設定が記載されています。
更には、defconfigや"make menuconfig"でON/OFFを切り替えられる機能さえ、SYS_CONFIGで指定されたファイル内(今回でいうulcb.h)で定義することによって有効化できます。

# 4. まとめ
この記事では、ターゲットボード固有の部分に注目してU-Bootのconfigについて紹介しました。どうやってターゲットボード固有の設定を実施しているのか理解しておけば、ソース解析だけでなく、用途に合わせてU-Boot自体を変更することも容易になります。