summaryrefslogtreecommitdiffstats
path: root/docs/plat/qemu.rst
blob: 698632697d59ea75106eafdf6f0c3c1159dd9740 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
QEMU virt Armv8-A
=================

Trusted Firmware-A (TF-A) implements the EL3 firmware layer for QEMU virt
Armv8-A. BL1 is used as the BootROM, supplied with the -bios argument.
When QEMU starts all CPUs are released simultaneously, BL1 selects a
primary CPU to handle the boot and the secondaries are placed in a polling
loop to be released by normal world via PSCI.

BL2 edits the Flattened Device Tree, FDT, generated by QEMU at run-time to
add a node describing PSCI and also enable methods for the CPUs.

If ``ARM_LINUX_KERNEL_AS_BL33`` is set to 1 then this FDT will be passed to BL33
via register x0, as expected by a Linux kernel. This allows a Linux kernel image
to be booted directly as BL33 rather than using a bootloader.

An ARM64 defconfig v5.5 Linux kernel is known to boot, FDT doesn't need to be
provided as it's generated by QEMU.

Current limitations:

-  Only cold boot is supported

Getting non-TF images
---------------------

``QEMU_EFI.fd`` can be downloaded from
http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-KERNEL-AARCH64/RELEASE_GCC5/QEMU_EFI.fd

or, can be built as follows:

.. code:: shell

    git clone https://github.com/tianocore/edk2.git
    cd edk2
    git submodule update --init
    make -C BaseTools
    source edksetup.sh
    export GCC5_AARCH64_PREFIX=aarch64-linux-gnu-
    build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemuKernel.dsc

````

Then, you will get ``Build/ArmVirtQemuKernel-AARCH64/DEBUG_GCC5/FV/QEMU_EFI.fd``

Please note you do not need to use GCC 5 in spite of the environment variable
``GCC5_AARCH64_PREFIX``

The rootfs can be built by using Buildroot as follows:

.. code:: shell

    git clone git://git.buildroot.net/buildroot.git
    cd buildroot
    make qemu_aarch64_virt_defconfig
    utils/config -e BR2_TARGET_ROOTFS_CPIO
    utils/config -e BR2_TARGET_ROOTFS_CPIO_GZIP
    make olddefconfig
    make

Then, you will get ``output/images/rootfs.cpio.gz``.

Booting via semi-hosting option
-------------------------------

Boot binaries, except BL1, are primarily loaded via semi-hosting so all
binaries has to reside in the same directory as QEMU is started from. This
is conveniently achieved with symlinks the local names as:

-  ``bl2.bin`` -> BL2
-  ``bl31.bin`` -> BL31
-  ``bl33.bin`` -> BL33 (``QEMU_EFI.fd``)
-  ``Image`` -> linux/arch/arm64/boot/Image

To build:

.. code:: shell

    make CROSS_COMPILE=aarch64-none-elf- PLAT=qemu

To start (QEMU v5.0.0):

.. code:: shell

    qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57  \
        -kernel Image                           \
        -append "console=ttyAMA0,38400 keep_bootcon"   \
        -initrd rootfs.cpio.gz -smp 2 -m 1024 -bios bl1.bin   \
        -d unimp -semihosting-config enable,target=native

Booting via flash based firmwares
---------------------------------

Boot firmwares are loaded via secure FLASH0 device so ``bl1.bin`` and
``fip.bin`` should be concatenated to create a ``flash.bin`` that is flashed
onto secure FLASH0.

-  ``bl32.bin`` -> BL32 (``tee-header_v2.bin``)
-  ``bl32_extra1.bin`` -> BL32 Extra1 (``tee-pager_v2.bin``)
-  ``bl32_extra2.bin`` -> BL32 Extra2 (``tee-pageable_v2.bin``)
-  ``bl33.bin`` -> BL33 (``QEMU_EFI.fd``)
-  ``Image`` -> linux/arch/arm64/boot/Image

To build:

.. code:: shell

    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu BL32=bl32.bin \
        BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin \
        BL33=bl33.bin BL32_RAM_LOCATION=tdram SPD=opteed all fip

To build with TBBR enabled, BL31 and BL32 encrypted with test key:

.. code:: shell

    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu BL32=bl32.bin \
        BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin \
        BL33=bl33.bin BL32_RAM_LOCATION=tdram SPD=opteed all fip \
        MBEDTLS_DIR=<path-to-mbedtls-repo> TRUSTED_BOARD_BOOT=1 \
        GENERATE_COT=1 DECRYPTION_SUPPORT=aes_gcm FW_ENC_STATUS=0 \
        ENCRYPT_BL31=1 ENCRYPT_BL32=1

To build flash.bin:

.. code:: shell

    dd if=build/qemu/release/bl1.bin of=flash.bin bs=4096 conv=notrunc
    dd if=build/qemu/release/fip.bin of=flash.bin seek=64 bs=4096 conv=notrunc

To start (QEMU v5.0.0):

.. code:: shell

    qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57  \
        -kernel Image -no-acpi                     \
        -append 'console=ttyAMA0,38400 keep_bootcon'  \
        -initrd rootfs.cpio.gz -smp 2 -m 1024 -bios flash.bin   \
        -d unimp

Running QEMU in OpenCI
-----------------------

Linaro's continuous integration platform OpenCI supports running emulated tests
on QEMU. The tests are kicked off on Jenkins and deployed through the Linaro
Automation and Validation Architecture `LAVA`_.

There are a set of Linux boot tests provided in OpenCI. They rely on prebuilt
`binaries`_ for UEFI, the kernel, root file system, as well as, any other TF-A
dependencies, and are run as part of the OpenCI TF-A `daily job`_. To run them
manually, a `builder`_ job may be triggered with the test configuration
``qemu-boot-tests``.


You may see the following warning repeated several times in the boot logs:

.. code:: shell

    pflash_write: Write to buffer emulation is flawed

Please ignore this as it is an unresolved `issue in QEMU`_, it is an internal
QEMU warning that logs flawed use of "write to buffer".

.. note::
    For more information on how to trigger jobs in OpenCI, please refer to
    Linaro's CI documentation, which explains how to trigger a `manual job`_.

.. _binaries: https://downloads.trustedfirmware.org/tf-a/linux_boot/
.. _daily job: https://ci.trustedfirmware.org/view/TF-A/job/tf-a-main/
.. _builder: https://ci.trustedfirmware.org/view/TF-A/job/tf-a-builder/
.. _LAVA: https://tf.validation.linaro.org/
.. _manual job: https://tf-ci-users-guide.readthedocs.io/en/latest/#manual-job-trigger
.. _issue in QEMU: https://git.qemu.org/?p=qemu.git;a=blob;f=hw/block/pflash_cfi01.c;h=0cbc2fb4cbf62c9a033b8dd89012374ff74ed610;hb=refs/heads/master#l500