Raspberry Piを使ったUEFIのお勉強：導入編

お仕事でARMのLinux組み込み装置の開発をしていますが、ここ数年はブートローダに携わることが多い。
最初に担当したのはU-Bootのみでしたが、それがTrustrd Firmware＋U-Bootになり、最近はUEFIも出てきました。

U-Bootまでは(ドライバの詳細な処理などはともかく)どの処理がどういった順番で動いて初期化処理を行い、Linuxをロード・起動するのかを、大まかには理解できていたのですが、UEFIになってからは、あんまり理解出来ていないです。

そこで、UEFIについて学習することにしました。UEFIプログラミングについて検索すると、アプリケーションを作って動作させる記事はあるのですが、UEFIの動作について書かれている(日本語の)記事はないみたいです。だったらちょっと書いてみようかと考えました。

本当はお仕事で触っているSoCやソースコードについて学習して、記事を書きたいのですが、ブートローダはプロプライエタリな部分が多くて出来ません。そこでEDK IIで公開されているPlatformの中から、家にあったRaspberry Pi 3B+を使用することにしました。

この記事が、私と同じ様にARM組み込みシステムのUEFI開発をしている人にどれくらい役に立つかは、今の段階ではわかりません。
とりあえず手を動かさない事には、何も始まりませんので、この導入編ではRaspberry Pi 3でUEFIを動作させてみることにします。

## 環境
ターゲットボードは、先にも書きましたが**Raspberry Pi 3 Model B+ (2017)** を使用します。
ホストPCとしては**Ubuntu 20.04.4 LTS** を使っています。
## ビルド
ますはホストPCにソースコードを持ってきます。
UEFIのソースコードは、TianoCoreというコミュニティで管理されています。
https://www.tianocore.org/
TianoCoreはEDK II(以下edk2)というファームウェア開発環境を公開しています。
edk2には複数のプロジェクトがあり、プラットフォーム向けの実装はedk2-platformで公開されています。
https://github.com/tianocore/edk2-platforms
上記ページにサポートしているプラットフォームの一覧([Supported Platforms](https://github.com/tianocore/edk2-platforms#supported-platforms))があり、各プラットフォームの詳細ページにリンクが張られています。
Raspberry Pi 3向けのページは[Raspberry Pi 3 Platform](https://github.com/tianocore/edk2-platforms/tree/master/Platform/RaspberryPi/RPi3)であり、サポートハードやプロジェクトのステータス、ビルド方法や起動方法などが記載されています。
ビルド方法([Building](https://github.com/tianocore/edk2-platforms/tree/master/Platform/RaspberryPi/RPi3#building))をみると、「edk2-platfomsのReadme.mdを見てね」とかかれているので、そちら([How to build (Linux Environment)](https://github.com/tianocore/edk2-platforms#how-to-build-linux-environment))を参照します。
### クロスコンパイル環境の構築
[Prerequisites](https://github.com/tianocore/edk2-platforms#prerequisites)にはクロスコンパイラやビルドに必要なパッケージについて記載がありますが、わりとあっさり書かれているため、私は以下のページを参考にしました。
https://jensd.be/1126/linux/cross-compiling-for-arm-or-aarch64-on-debian-or-ubuntu
また、実際にビルドしてみて足りないパッケージも追加しています。結果としては以下のコマンドを実行しました。
```
~$ sudo apt install gcc make gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu
~$ sudo apt install g++
~$ sudo apt install uuid-dev
~$ sudo apt install iasl
~$ sudo apt install libssl-dev
~$ sudo ln -s /usr/bin/python3 /usr/bin/python
```
### ソースコードの入手
[Obtaining source code](https://github.com/tianocore/edk2-platforms#obtaining-source-code)にしたがって、ソースコードを入手します。
まずワークスペースを作って、
```
~$ export  WORKSPACE=~/tianocore
~$ mkdir -p $WORKSPACE
~$ cd $WORKSPACE
```
edk2をgit cloneして、
```
~/tianocore$ git clone https://github.com/tianocore/edk2.git
Cloning into 'edk2'...
remote: Enumerating objects: 372449, done.
remote: Counting objects: 100% (37/37), done.
remote: Compressing objects: 100% (28/28), done.
remote: Total 372449 (delta 13), reused 27 (delta 8), pack-reused 372412
Receiving objects: 100% (372449/372449), 303.62 MiB | 8.81 MiB/s, done.
Resolving deltas: 100% (269928/269928), done.
~/tianocore$ cd edk2/
~/tianocore/edk2$ git submodule update --init
Submodule 'SoftFloat' (https://github.com/ucb-bar/berkeley-softfloat-3.git) registered for path 'ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3'
Submodule 'BaseTools/Source/C/BrotliCompress/brotli' (https://github.com/google/brotli) registered for path 'BaseTools/Source/C/BrotliCompress/brotli'
Submodule 'CryptoPkg/Library/OpensslLib/openssl' (https://github.com/openssl/openssl) registered for path 'CryptoPkg/Library/OpensslLib/openssl'
Submodule 'MdeModulePkg/Library/BrotliCustomDecompressLib/brotli' (https://github.com/google/brotli) registered for path 'MdeModulePkg/Library/BrotliCustomDecompressLib/brotli'
Submodule 'MdeModulePkg/Universal/RegularExpressionDxe/oniguruma' (https://github.com/kkos/oniguruma) registered for path 'MdeModulePkg/Universal/RegularExpressionDxe/oniguruma'
Submodule 'RedfishPkg/Library/JsonLib/jansson' (https://github.com/akheron/jansson) registered for path 'RedfishPkg/Library/JsonLib/jansson'
Submodule 'UnitTestFrameworkPkg/Library/CmockaLib/cmocka' (https://github.com/tianocore/edk2-cmocka.git) registered for path 'UnitTestFrameworkPkg/Library/CmockaLib/cmocka'
Cloning into '/home/kameyama/tianocore/edk2/ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3'...
Cloning into '/home/kameyama/tianocore/edk2/BaseTools/Source/C/BrotliCompress/brotli'...
Cloning into '/home/kameyama/tianocore/edk2/CryptoPkg/Library/OpensslLib/openssl'...
Cloning into '/home/kameyama/tianocore/edk2/MdeModulePkg/Library/BrotliCustomDecompressLib/brotli'...
Cloning into '/home/kameyama/tianocore/edk2/MdeModulePkg/Universal/RegularExpressionDxe/oniguruma'...
Cloning into '/home/kameyama/tianocore/edk2/RedfishPkg/Library/JsonLib/jansson'...
Cloning into '/home/kameyama/tianocore/edk2/UnitTestFrameworkPkg/Library/CmockaLib/cmocka'...
Submodule path 'ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3': checked out 'b64af41c3276f97f0e181920400ee056b9c88037'
Submodule path 'BaseTools/Source/C/BrotliCompress/brotli': checked out 'f4153a09f87cbb9c826d8fc12c74642bb2d879ea'
Submodule path 'CryptoPkg/Library/OpensslLib/openssl': checked out 'd82e959e621a3d597f1e0d50ff8c2d8b96915fd7'
Submodule path 'MdeModulePkg/Library/BrotliCustomDecompressLib/brotli': checked out 'f4153a09f87cbb9c826d8fc12c74642bb2d879ea'
Submodule path 'MdeModulePkg/Universal/RegularExpressionDxe/oniguruma': checked out 'abfc8ff81df4067f309032467785e06975678f0d'
Submodule path 'RedfishPkg/Library/JsonLib/jansson': checked out 'e9ebfa7e77a6bee77df44e096b100e7131044059'
Submodule path 'UnitTestFrameworkPkg/Library/CmockaLib/cmocka': checked out '1cc9cde3448cdd2e000886a26acf1caac2db7cf1'
~/tianocore/edk2$kameyama@night-walk:~/tianocore/edk2$ cd ..
kameyama@night-walk:~/tianocore$
```
次にedk2-platformsをもってきて、
```
~/tianocore$ git clone https://github.com/tianocore/edk2-platforms.git
Cloning into 'edk2-platforms'...
remote: Enumerating objects: 298385, done.
remote: Counting objects: 100% (579/579), done.
remote: Compressing objects: 100% (313/313), done.
remote: Total 298385 (delta 292), reused 474 (delta 256), pack-reused 297806
Receiving objects: 100% (298385/298385), 270.84 MiB | 23.45 MiB/s, done.
Resolving deltas: 100% (217704/217704), done.
~/tianocore$ cd edk2-platforms/
~/tianocore/edk2-platforms$ git submodule update --init
Submodule 'Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi' (https://github.com/riscv/opensbi) registered for path 'Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi'
Cloning into '/home/kameyama/tianocore/edk2-platforms/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi'...
Submodule path 'Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi': checked out 'a731c7e36988c3308e1978ecde491f2f6182d490'
~/tianocore/edk2-platforms$ cd ..
~/tianocore$
```
要るかわからないですが、edk2-non-osiをもってきます。
```
~/tianocore$ git clone https://github.com/tianocore/edk2-non-osi.git
Cloning into 'edk2-non-osi'...
remote: Enumerating objects: 2212, done.
remote: Counting objects: 100% (80/80), done.
remote: Compressing objects: 100% (32/32), done.
remote: Total 2212 (delta 50), reused 58 (delta 47), pack-reused 2132
Receiving objects: 100% (2212/2212), 20.09 MiB | 18.74 MiB/s, done.
Resolving deltas: 100% (1138/1138), done.
~/tianocore$
```
最後に環境変数PACKAGES_PATHを設定します。
```
~/tianocore$ export PACKAGES_PATH=$PWD/edk2:$PWD/edk2-platforms:$PWD/edk2-non-osi
```
### ビルド
つぎにビルドします。[Using uefi-tools helper scripts](https://github.com/tianocore/edk2-platforms#using-uefi-tools-helper-scripts)に、Linaroが公開しているビルドスクリプトを使用する方法が記載されていますが、デバッグビルドに対応していなかったので、[Manual building](https://github.com/tianocore/edk2-platforms#manual-building)に従います。

まずは環境変数設定用シェルを実行します。
```
~/tianocore$ . edk2/edksetup.sh
Using EDK2 in-source Basetools
WORKSPACE: /home/kameyama/tianocore
EDK_TOOLS_PATH: /home/kameyama/tianocore/edk2/BaseTools
CONF_PATH: /home/kameyama/tianocore/edk2/Conf
Copying $EDK_TOOLS_PATH/Conf/build_rule.template
     to /home/kameyama/tianocore/edk2/Conf/build_rule.txt
Copying $EDK_TOOLS_PATH/Conf/tools_def.template
     to /home/kameyama/tianocore/edk2/Conf/tools_def.txt
Copying $EDK_TOOLS_PATH/Conf/target.template
     to /home/kameyama/tianocore/edk2/Conf/target.txt
~/tianocore$
```
次にBaseToolsをビルドします。
```
~/tianocore$ make -C edk2/BaseTools
make: ディレクトリ '/home/kameyama/tianocore/edk2/BaseTools'　に入ります
make -C Source/C
・・・・中略・・・・
testSurrogatePairUnicodeCharInUtf8FileWithBom (CheckUnicodeSourceFiles.Tests) ... ok
testUtf16InUniFile (CheckUnicodeSourceFiles.Tests) ... ok
testValidUtf8File (CheckUnicodeSourceFiles.Tests) ... ok
testValidUtf8FileWithBom (CheckUnicodeSourceFiles.Tests) ... ok

----------------------------------------------------------------------
Ran 301 tests in 1.014s

OK
make[1]: ディレクトリ '/home/kameyama/tianocore/edk2/BaseTools/Tests' から出ます
make: ディレクトリ '/home/kameyama/tianocore/edk2/BaseTools' から出ます
~/tianocore$
```
最後にUEFIをビルドします。まずクロスコンパイラ用の環境変数を設定して、
```
~/tianocore$ export GCC5_AARCH64_PREFIX=aarch64-linux-gnu-
```
コンパイルを実行します。引数にはdscファイルを指定する必要があるので、RPi3用のdscファイルを検索します。
```
~/tianocore$ find edk2-platforms/ -name \*.dsc | grep  -i RP
edk2-platforms/Platform/StandaloneMm/PlatformStandaloneMmPkg/PlatformStandaloneMmRpmb.dsc
edk2-platforms/Platform/Intel/WhitleyOpenBoardPkg/Uba/UbaRpBoards.dsc
edk2-platforms/Platform/RaspberryPi/RPi4/RPi4.dsc
edk2-platforms/Platform/RaspberryPi/RPi3/RPi3.dsc
edk2-platforms/Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dsc
~/tianocore$
```
**Platform/RaspberryPi/RPi3/RPi3.dsc** がそれっぽいです。
```
~/tianocore$ build -a AARCH64 -t GCC5 -p Platform/RaspberryPi/RPi3/RPi3.dsc
Build environment: Linux-5.13.0-44-generic-x86_64-with-glibc2.29
Build start time: 13:42:35, Sep.18 2022

WORKSPACE        = /home/kameyama/tianocore
PACKAGES_PATH    = /home/kameyama/tianocore/edk2:/home/kameyama/tianocore/edk2-platforms:/home/kameyama/tianocore/edk2-non-osi
EDK_TOOLS_PATH   = /home/kameyama/tianocore/edk2/BaseTools
CONF_PATH        = /home/kameyama/tianocore/edk2/Conf
PYTHON_COMMAND   = /usr/bin/python3.8


Processing meta-data .
Architecture(s)  = AARCH64
Build target     = DEBUG
Toolchain        = GCC5

Active Platform          = /home/kameyama/tianocore/edk2-platforms/Platform/RaspberryPi/RPi3/RPi3.dsc
..... done!
Building ... /home/kameyama/tianocore/edk2/ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf [AARCH64]
Building ... /home/kameyama/tianocore/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf [AARCH64]

・・・・中略・・・・

Fd File Name:RPI_EFI (/home/kameyama/tianocore/Build/RPi3/DEBUG_GCC5/FV/RPI_EFI.fd)

Generate Region at Offset 0x0
   Region Size = 0x10000
   Region File Name = /home/kameyama/tianocore/edk2-non-osi/Platform/RaspberryPi/RPi3/TrustedFirmware/bl1.bin
Padding region starting from offset 0x10000, with size 0x10000

Generate Region at Offset 0x10000
   Region Size = 0x10000
   Region Name = None

Generate Region at Offset 0x20000
   Region Size = 0x10000
   Region File Name = /home/kameyama/tianocore/edk2-non-osi/Platform/RaspberryPi/RPi3/TrustedFirmware/fip.bin

Generate Region at Offset 0x30000
   Region Size = 0x1A0000
   Region Name = FV

Generating FVMAIN_COMPACT FV

Generating FVMAIN FV
#######
Generate Region at Offset 0x1D0000
   Region Size = 0xE000
   Region Name = DATA

Generate Region at Offset 0x1DE000
   Region Size = 0x1000
   Region Name = None

Generate Region at Offset 0x1DF000
   Region Size = 0x1000
   Region Name = DATA

Generate Region at Offset 0x1E0000
   Region Size = 0x10000
   Region Name = None

GUID cross reference file can be found at /home/kameyama/tianocore/Build/RPi3/DEBUG_GCC5/FV/Guid.xref

FV Space Information
FVMAIN [99%Full] 7326336 (0x6fca80) total, 7326312 (0x6fca68) used, 24 (0x18) free
FVMAIN_COMPACT [76%Full] 1703936 (0x1a0000) total, 1305808 (0x13ecd0) used, 398128 (0x61330) free

- Done -
Build end time: 13:46:45, Sep.18 2022
Build total time: 00:04:11

~/tianocore$ 
```
ビルド生成物は \<WORKSPACE>/Build/RPi3/DEBUG_GCC5/FV/配下に出来ています。
```
~/tianocore$ ls -l Build/RPi3/DEBUG_GCC5/FV/
合計 10884
-rw-rw-r--  1 kameyama kameyama 7326336  9月 18 13:46 FVMAIN.Fv
-rw-rw-r--  1 kameyama kameyama      84  9月 18 13:46 FVMAIN.Fv.map
-rw-rw-r--  1 kameyama kameyama    3802  9月 18 13:46 FVMAIN.Fv.txt
-rw-rw-r--  1 kameyama kameyama      20  9月 18 13:46 FVMAIN.ext
-rw-rw-r--  1 kameyama kameyama   12985  9月 18 13:46 FVMAIN.inf
-rw-rw-r--  1 kameyama kameyama 1703936  9月 18 13:46 FVMAIN_COMPACT.Fv
-rw-rw-r--  1 kameyama kameyama     300  9月 18 13:46 FVMAIN_COMPACT.Fv.map
-rw-rw-r--  1 kameyama kameyama     154  9月 18 13:46 FVMAIN_COMPACT.Fv.txt
-rw-rw-r--  1 kameyama kameyama     883  9月 18 13:46 FVMAIN_COMPACT.inf
drwxrwxr-x 82 kameyama kameyama   12288  9月 18 13:46 Ffs
-rw-rw-r--  1 kameyama kameyama   21247  9月 18 13:46 Guid.xref
-rw-rw-r--  1 kameyama kameyama     464  9月 18 13:46 GuidedSectionTools.txt
-rw-rw-r--  1 kameyama kameyama 2031616  9月 18 13:46 RPI_EFI.fd
~/tianocore$
```
## 起動
ビルドが通ったので、起動させます。

### 起動メディアの作成
[Booting the firmware](https://github.com/tianocore/edk2-platforms/tree/master/Platform/RaspberryPi/RPi3#booting-the-firmware)に従い、起動用のメディアを作成します。

microSDカードを用意してFAT32でフォーマットします。本記事ではUEFIの起動を目的としていますので、OSの起動までは行いません。よって、microSDは小さい容量のもので構いません。

:::note info
余談ですが、私は起動メディアの作成を、Windows10 PCで行っています。Windows10以降、FAT32のフォーマットをサポートしなくなっているらしく、仕方がないので私は[これ](https://www.iodata.jp/lib/product/i/2107.htm)を使ってフォーマットしています。
LinuxではFAT32でフォーマットできるので、そちらを使うのがいいでしょう。
:::

次に https://github.com/raspberrypi/firmware/tree/master/boot から必要なファイルをダウンロードします。
bootcode.bin、fixup.dat、start.elfは共通なので、ダウンロードします。
私の環境ではRaspberry Pi 3 Modele B+なのでdtbは、**bcm2710-rpi-3-b-plus.dtb** になります。
また、Bluetoothには対応していないので、**overlays/disable-bt.dtbo** を使用することにします。
最後にconfig.txtを作ります。
```
arm_control=0x200
enable_uart=1
armstub=RPI_EFI.fd
disable_commandline_tags=2
device_tree_address=0x1f0000
device_tree_end=0x200000
dtoverlay=disable-bt.dtbo
```
ダウンロードしたファイルと、ビルド生成物**RPI_EFI.fd** 、config.txtをmicroSDにコピーします。
microSDの構成としては以下の様になります。
```
/
+- RPI_EFI.fd
+- bcm2710-rpi-3-b-plus.dtb
+- bootcode.bin
+- config.txt
+- fixup.dat
+- start.elf
+- overlays
     +-  disable-bt.dtbo
```

:::note warn
先にも書きましたが、当面OSは起動するつもりがないので、dtb/dtboは使われないと思っています。
実際、overlays/disable-bt.dtboはファイルを削除し、config.txtからdtoverlay指定を削除しても問題ないのですが、bcm2710-rpi-3-b-plus.dtbを削除すると、シリアルコンソールが文字化けします。
termを再接続すると文字化けしなくなるのですが、Raspberry Piの再起動、あるいはUEFIからRESETを実行すると、再び文字化けします。
どこかでdtbを参照してるのでしょうか？
:::

### Raspberry Piの準備
起動するRaspberry Piを準備します。私の場合、以下を準備しました。
* Raspberry Pi3対応電源アダプター(5V 3.0A)
Raspberry Pi3以降、消費電力がかなり上がっているそうです。UEFIでそこまで電力を消費することがあるかは不明ですが、うまく動かなかった場合に電源を疑うのが嫌なので3Aのものを用意しています
* USBシリアル変換モジュール
* Windows PC + Tera Term
Raspberry Piの操作はTera Termで接続したシリアルコンソールで行います。Raspberry PiにUSBキーボードを接続すれば、そちらでも操作はできるのですが、デバッグログはシリアルコンソールにしか出ないので、シリアルコンソールは必須となります。
USBシリアル変換モジュールとRaspberry Piとの接続については、ここでは説明を割愛させていただきます。
* HDMI接続モニター
モニターはなくても当面困りませんが、起動画面のカスタマイズもそのうちやりたいと思っているので用意しています。

### 起動
microSDをRaspberry Piにさして、電源を入れます。
モニターを接続していれば以下の画面が表示されます。
![2022091913313411.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564717/10f1ef05-52cf-2c0a-479a-0dce77a41629.png)
いつもの画面がでたあと、
![2022091913314855.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564717/f5e6c72d-3815-92ee-cc70-547ef934625d.png)
ロゴ画面がでます。プログレスバーが右端まで伸びますが、Boot設定をしていないので、
![2022091913320065.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564717/7f3e6fe0-2147-94d9-f84b-3f0b17fe4eb2.png)
ここでとまります。この時、Tera Termには以下の画面が表示されています。
![term01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564717/d894a73c-9943-fd78-36c0-13c708f96962.png)
ここで、Tera Termから何かのキーを入力するとBoot Manager Menuが表示されます。
![2022091913443854.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564717/30b85fcd-a8b7-04c8-cb11-8705affa6aa9.png)
こちらがモニター
![term02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564717/69c08c7a-928b-52dc-3d6c-9871d0dbd780.png)
Tera Termにも同じメニューが表示されます。
これでやっと準備が整いました。

## 起動ログ
ここまでだと公開されている手順をなぞっただけになってしまいますので、起動時にコンソールに表示されるログメッセージについて少し書いて、導入編を終わりたいと思います。

[ARM Trusted Firmware (TF-A)](https://github.com/tianocore/edk2-platforms/tree/master/Platform/RaspberryPi/RPi3#arm-trusted-firmware-tf-a)にも書かれていますが、Raspberry Pi向けのUEFIはTrusted Firmwareから起動されています。そのため、電源投入を行うとTrusted Firmwareのメッセージが最初に出ます。
```
NOTICE:  Booting Trusted Firmware
NOTICE:  BL1: v2.6(release):
NOTICE:  BL1: Built : 16:56:39, Jan  7 2022
NOTICE:  rpi3: Detected: Raspberry Pi 3 Model B+ (1GB, Sony, UK) [0x00a020d3]
NOTICE:  BL1: Booting BL2
NOTICE:  BL2: v2.6(release):
NOTICE:  BL2: Built : 16:56:33, Jan  7 2022
NOTICE:  BL1: Booting BL31
NOTICE:  BL31: v2.6(release):
NOTICE:  BL31: Built : 16:56:36, Jan  7 2022
UEFI firmware (version EDK2-DEV built at 13:43:14 on Sep 18 2022)
・・・・・
```
:::note info
Trusted Firmwareについての詳細は[ARM Trusted Firmware for Raspberry Pi 3](https://github.com/tianocore/edk2-non-osi/blob/master/Platform/RaspberryPi/RPi3/TrustedFirmware/Readme.md#arm-trusted-firmware-for-raspberry-pi-3)を参照してください。Trusted Firmwareも自分でビルドして動作させることが可能です。
:::
「UEFI firmware ...」以降がUEFIが表示しているメッセージになります。
```
UEFI firmware (version EDK2-DEV built at 13:43:14 on Sep 18 2022)
Board Rev: 0xA020D3
RAM < 1GB: 0x00000000 (Size 0x3B400000)
VideoCore: 0x3B400000 (Size 0x04C00000)
Total RAM: 0x40000000
VideoCore range overlapped SoC MMIO, now 0x3B400000 (Size 0x03C00000)
FD:
	PhysicalBase: 0x0
	VirtualBase: 0x0
	Length: 0x1D0000
FD Variables:
	PhysicalBase: 0x1D0000
	VirtualBase: 0x1D0000
	Length: 0x20000
Flattened Device Tree:
	PhysicalBase: 0x1F0000
	VirtualBase: 0x1F0000
	Length: 0x10000
TF-A RAM:
	PhysicalBase: 0x1F0000
	VirtualBase: 0x1F0000
	Length: 0x210000
System RAM < 1GB:
	PhysicalBase: 0x400000
	VirtualBase: 0x400000
	Length: 0x3B000000
GPU Reserved:
	PhysicalBase: 0x3B400000
	VirtualBase: 0x3B400000
	Length: 0x3C00000
SoC Reserved (283x):
	PhysicalBase: 0x3F000000
	VirtualBase: 0x3F000000
	Length: 0x2000000
add-symbol-file /home/kameyama/tianocore/Build/RPi3/DEBUG_GCC5/AARCH64/MdeModulePkg/Core/Dxe/DxeMain/DEBUG/DxeCore.dll 0x3A5A0000
Loading DxeCore at 0x003A59F000 EntryPoint=0x003A5BD798
CoreInitializeMemoryServices:
  BaseAddress - 0x400000 Length - 0x37000000 MinimalMemorySizeNeeded - 0x34AE000
InstallProtocolInterface: 5B1B31A1-9562-11D2-8E3F-00A0C969723B 3A5CA2D8
ProtectUefiImageCommon - 0x3A5CA2D8
  - 0x000000003A59F000 - 0x0000000000048000
InstallProtocolInterface: C85D06BE-5F75-48CE-A80F-1236BA3B87B1 3A5CA5D0
DxeMain: MemoryBaseAddress=0x400000 MemoryLength=0x37000000
add-symbol-file /home/kameyama/tianocore/Build/RPi3/DEBUG_GCC5/AARCH64/MdeModulePkg/Core/Dxe/DxeMain/DEBUG/DxeCore.dll 0x3A5A0000
HOBLIST address in DXE = 0x36E36018
Memory Allocation 0x00000004 0x3B3F8000 - 0x3B3F8FFF
Memory Allocation 0x00000000 0x0 - 0x1CFFFF
Memory Allocation 0x00000006 0x1D0000 - 0x1EFFFF
Memory Allocation 0x00000000 0x1F0000 - 0x1FFFFF
Memory Allocation 0x00000000 0x1F0000 - 0x3FFFFF
Memory Allocation 0x00000004 0x3B3F7000 - 0x3B3F7FFF
Memory Allocation 0x00000004 0x3B3F6000 - 0x3B3F6FFF
Memory Allocation 0x00000004 0x3B3F5000 - 0x3B3F5FFF
Memory Allocation 0x00000004 0x3B3F4000 - 0x3B3F4FFF
Memory Allocation 0x00000004 0x3B3F3000 - 0x3B3F3FFF
Memory Allocation 0x00000004 0x3B3F9000 - 0x3B3FFFFF
Memory Allocation 0x00000004 0x3B3E3000 - 0x3B3F2FFF
Memory Allocation 0x00000004 0x3ACE5000 - 0x3B3E2FFF
Memory Allocation 0x00000004 0x3A5E7000 - 0x3ACE4FFF
Memory Allocation 0x00000003 0x3A59F000 - 0x3A5E6FFF
Memory Allocation 0x00000003 0x3A59F000 - 0x3A5E6FFF
FV Hob            0x30000 - 0x1CFFFF
FV Hob            0x3A5E7000 - 0x3ACE3A7F
FV2 Hob           0x3A5E7000 - 0x3ACE3A7F
                  9A15AA37-D555-4A4E-B541-86391FF68164 - 9E21FD93-9C72-4C15-8C4B-E77F1DB2D792
```
「UEFI firmware ...」メッセージはedk2/ArmPlatformPkg/PrePi/PrePi.cのPrePiMain()で表示しています。
```
VOID
PrePiMain (
  IN  UINTN   UefiMemoryBase,
  IN  UINTN   StacksBase,
  IN  UINT64  StartTimeStamp
  )
{
  EFI_HOB_HANDOFF_INFO_TABLE  *HobList;
  ARM_MP_CORE_INFO_PPI        *ArmMpCoreInfoPpi;
  UINTN                       ArmCoreCount;
  ARM_CORE_INFO               *ArmCoreInfoTable;
  EFI_STATUS                  Status;
  CHAR8                       Buffer[100];
  UINTN                       CharCount;
  UINTN                       StacksSize;
  FIRMWARE_SEC_PERFORMANCE    Performance;

  // If ensure the FD is either part of the System Memory or totally outside of the System Memory (XIP)
  ASSERT (
    IS_XIP () ||
    ((FixedPcdGet64 (PcdFdBaseAddress) >= FixedPcdGet64 (PcdSystemMemoryBase)) &&
     ((UINT64)(FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= (UINT64)mSystemMemoryEnd))
    );

  // Initialize the architecture specific bits
  ArchInitialize ();

  // Initialize the Serial Port
  SerialPortInitialize ();
  CharCount = AsciiSPrint (
                Buffer,
                sizeof (Buffer),
                "UEFI firmware (version %s built at %a on %a)\n\r",
                (CHAR16 *)PcdGetPtr (PcdFirmwareVersionString),
                __TIME__,
                __DATE__
                );
  SerialPortWrite ((UINT8 *)Buffer, CharCount);
```
次回以降ではここら辺を足掛かりに、UEFIの初期化処理を調べていこうかと思います。

※各種製品名は、各社の製品名称、商標または登録商標です。本記事に記載されているシステム名、製品名には、必ずしも商標表示（(R)、TM）を付記していません。