1#!/usr/bin/env python3 2# 3# Functional test that boots a kernel and checks the console 4# 5# SPDX-FileCopyrightText: 2023-2024 Linaro Ltd. 6# SPDX-FileContributor: Philippe Mathieu-Daudé <philmd@linaro.org> 7# SPDX-FileContributor: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org> 8# 9# SPDX-License-Identifier: GPL-2.0-or-later 10 11import os 12 13from qemu_test import QemuSystemTest, Asset 14from qemu_test import wait_for_console_pattern 15from qemu_test import interrupt_interactive_console_until_pattern 16from qemu_test.utils import lzma_uncompress 17from unittest import skipUnless 18 19 20class Aarch64SbsarefMachine(QemuSystemTest): 21 """ 22 As firmware runs at a higher privilege level than the hypervisor we 23 can only run these tests under TCG emulation. 24 """ 25 26 timeout = 180 27 28 ASSET_FLASH0 = Asset( 29 ('https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/' 30 '20240619-148232/edk2/SBSA_FLASH0.fd.xz'), 31 '0c954842a590988f526984de22e21ae0ab9cb351a0c99a8a58e928f0c7359cf7') 32 33 ASSET_FLASH1 = Asset( 34 ('https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/' 35 '20240619-148232/edk2/SBSA_FLASH1.fd.xz'), 36 'c6ec39374c4d79bb9e9cdeeb6db44732d90bb4a334cec92002b3f4b9cac4b5ee') 37 38 def fetch_firmware(self): 39 """ 40 Flash volumes generated using: 41 42 Toolchain from Debian: 43 aarch64-linux-gnu-gcc (Debian 12.2.0-14) 12.2.0 44 45 Used components: 46 47 - Trusted Firmware v2.11.0 48 - Tianocore EDK2 4d4f569924 49 - Tianocore EDK2-platforms 3f08401 50 51 """ 52 53 # Secure BootRom (TF-A code) 54 fs0_xz_path = self.ASSET_FLASH0.fetch() 55 fs0_path = os.path.join(self.workdir, "SBSA_FLASH0.fd") 56 lzma_uncompress(fs0_xz_path, fs0_path) 57 58 # Non-secure rom (UEFI and EFI variables) 59 fs1_xz_path = self.ASSET_FLASH1.fetch() 60 fs1_path = os.path.join(self.workdir, "SBSA_FLASH1.fd") 61 lzma_uncompress(fs1_xz_path, fs1_path) 62 63 for path in [fs0_path, fs1_path]: 64 with open(path, "ab+") as fd: 65 fd.truncate(256 << 20) # Expand volumes to 256MiB 66 67 self.set_machine('sbsa-ref') 68 self.vm.set_console() 69 self.vm.add_args( 70 "-drive", f"if=pflash,file={fs0_path},format=raw", 71 "-drive", f"if=pflash,file={fs1_path},format=raw", 72 ) 73 74 def test_sbsaref_edk2_firmware(self): 75 76 self.fetch_firmware() 77 78 self.vm.add_args('-cpu', 'cortex-a57') 79 self.vm.launch() 80 81 # TF-A boot sequence: 82 # 83 # https://github.com/ARM-software/arm-trusted-firmware/blob/v2.8.0/\ 84 # docs/design/trusted-board-boot.rst#trusted-board-boot-sequence 85 # https://trustedfirmware-a.readthedocs.io/en/v2.8/\ 86 # design/firmware-design.html#cold-boot 87 88 # AP Trusted ROM 89 wait_for_console_pattern(self, "Booting Trusted Firmware") 90 wait_for_console_pattern(self, "BL1: v2.11.0(release):") 91 wait_for_console_pattern(self, "BL1: Booting BL2") 92 93 # Trusted Boot Firmware 94 wait_for_console_pattern(self, "BL2: v2.11.0(release)") 95 wait_for_console_pattern(self, "Booting BL31") 96 97 # EL3 Runtime Software 98 wait_for_console_pattern(self, "BL31: v2.11.0(release)") 99 100 # Non-trusted Firmware 101 wait_for_console_pattern(self, "UEFI firmware (version 1.0") 102 interrupt_interactive_console_until_pattern(self, "QEMU SBSA-REF Machine") 103 104 105 ASSET_ALPINE_ISO = Asset( 106 ('https://dl-cdn.alpinelinux.org/' 107 'alpine/v3.17/releases/aarch64/alpine-standard-3.17.2-aarch64.iso'), 108 '5a36304ecf039292082d92b48152a9ec21009d3a62f459de623e19c4bd9dc027') 109 110 # This tests the whole boot chain from EFI to Userspace 111 # We only boot a whole OS for the current top level CPU and GIC 112 # Other test profiles should use more minimal boots 113 def boot_alpine_linux(self, cpu=None): 114 self.fetch_firmware() 115 116 iso_path = self.ASSET_ALPINE_ISO.fetch() 117 118 self.vm.set_console() 119 self.vm.add_args( 120 "-drive", f"file={iso_path},media=cdrom,format=raw", 121 ) 122 if cpu: 123 self.vm.add_args("-cpu", cpu) 124 125 self.vm.launch() 126 wait_for_console_pattern(self, "Welcome to Alpine Linux 3.17") 127 128 def test_sbsaref_alpine_linux_cortex_a57(self): 129 self.boot_alpine_linux("cortex-a57") 130 131 def test_sbsaref_alpine_linux_default_cpu(self): 132 self.boot_alpine_linux() 133 134 def test_sbsaref_alpine_linux_max_pauth_off(self): 135 self.boot_alpine_linux("max,pauth=off") 136 137 def test_sbsaref_alpine_linux_max_pauth_impdef(self): 138 self.boot_alpine_linux("max,pauth-impdef=on") 139 140 @skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'), 'Test might timeout') 141 def test_sbsaref_alpine_linux_max(self): 142 self.boot_alpine_linux("max") 143 144 145 ASSET_OPENBSD_ISO = Asset( 146 ('https://cdn.openbsd.org/pub/OpenBSD/7.3/arm64/miniroot73.img'), 147 '7fc2c75401d6f01fbfa25f4953f72ad7d7c18650056d30755c44b9c129b707e5') 148 149 # This tests the whole boot chain from EFI to Userspace 150 # We only boot a whole OS for the current top level CPU and GIC 151 # Other test profiles should use more minimal boots 152 def boot_openbsd73(self, cpu=None): 153 self.fetch_firmware() 154 155 img_path = self.ASSET_OPENBSD_ISO.fetch() 156 157 self.vm.set_console() 158 self.vm.add_args( 159 "-drive", f"file={img_path},format=raw,snapshot=on", 160 ) 161 if cpu: 162 self.vm.add_args("-cpu", cpu) 163 164 self.vm.launch() 165 wait_for_console_pattern(self, 166 "Welcome to the OpenBSD/arm64" 167 " 7.3 installation program.") 168 169 def test_sbsaref_openbsd73_cortex_a57(self): 170 self.boot_openbsd73("cortex-a57") 171 172 def test_sbsaref_openbsd73_default_cpu(self): 173 self.boot_openbsd73() 174 175 def test_sbsaref_openbsd73_max_pauth_off(self): 176 self.boot_openbsd73("max,pauth=off") 177 178 @skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'), 'Test might timeout') 179 def test_sbsaref_openbsd73_max_pauth_impdef(self): 180 self.boot_openbsd73("max,pauth-impdef=on") 181 182 @skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'), 'Test might timeout') 183 def test_sbsaref_openbsd73_max(self): 184 self.boot_openbsd73("max") 185 186 187 ASSET_FREEBSD_ISO = Asset( 188 ('https://download.freebsd.org/releases/arm64/aarch64/ISO-IMAGES/' 189 '14.1/FreeBSD-14.1-RELEASE-arm64-aarch64-bootonly.iso'), 190 '44cdbae275ef1bb6dab1d5fbb59473d4f741e1c8ea8a80fd9e906b531d6ad461') 191 192 # This tests the whole boot chain from EFI to Userspace 193 # We only boot a whole OS for the current top level CPU and GIC 194 # Other test profiles should use more minimal boots 195 def boot_freebsd14(self, cpu=None): 196 self.fetch_firmware() 197 198 img_path = self.ASSET_FREEBSD_ISO.fetch() 199 200 self.vm.set_console() 201 self.vm.add_args( 202 "-drive", f"file={img_path},format=raw,snapshot=on", 203 ) 204 if cpu: 205 self.vm.add_args("-cpu", cpu) 206 207 self.vm.launch() 208 wait_for_console_pattern(self, 'Welcome to FreeBSD!') 209 210 def test_sbsaref_freebsd14_cortex_a57(self): 211 self.boot_freebsd14("cortex-a57") 212 213 def test_sbsaref_freebsd14_default_cpu(self): 214 self.boot_freebsd14() 215 216 def test_sbsaref_freebsd14_max_pauth_off(self): 217 self.boot_freebsd14("max,pauth=off") 218 219 @skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'), 'Test might timeout') 220 def test_sbsaref_freebsd14_max_pauth_impdef(self): 221 self.boot_freebsd14("max,pauth-impdef=on") 222 223 @skipUnless(os.getenv('QEMU_TEST_TIMEOUT_EXPECTED'), 'Test might timeout') 224 def test_sbsaref_freebsd14_max(self): 225 self.boot_freebsd14("max") 226 227 228if __name__ == '__main__': 229 QemuSystemTest.main() 230