aboutsummaryrefslogtreecommitdiff
path: root/tests/functional/arm
diff options
context:
space:
mode:
Diffstat (limited to 'tests/functional/arm')
-rw-r--r--tests/functional/arm/meson.build64
-rwxr-xr-xtests/functional/arm/test_aspeed_ast1030.py90
-rwxr-xr-xtests/functional/arm/test_aspeed_ast2500.py56
-rwxr-xr-xtests/functional/arm/test_aspeed_ast2600_buildroot.py102
-rwxr-xr-xtests/functional/arm/test_aspeed_ast2600_sdk.py94
-rwxr-xr-xtests/functional/arm/test_aspeed_bletchley.py25
-rwxr-xr-xtests/functional/arm/test_aspeed_catalina.py25
-rwxr-xr-xtests/functional/arm/test_aspeed_gb200nvl_bmc.py26
-rwxr-xr-xtests/functional/arm/test_aspeed_palmetto.py25
-rwxr-xr-xtests/functional/arm/test_aspeed_rainier.py65
-rwxr-xr-xtests/functional/arm/test_aspeed_romulus.py25
-rwxr-xr-xtests/functional/arm/test_aspeed_witherspoon.py25
-rwxr-xr-xtests/functional/arm/test_bflt.py41
-rwxr-xr-xtests/functional/arm/test_bpim2u.py180
-rwxr-xr-xtests/functional/arm/test_canona1100.py37
-rwxr-xr-xtests/functional/arm/test_collie.py31
-rwxr-xr-xtests/functional/arm/test_cubieboard.py144
-rwxr-xr-xtests/functional/arm/test_emcraft_sf2.py52
-rwxr-xr-xtests/functional/arm/test_integratorcp.py94
-rwxr-xr-xtests/functional/arm/test_max78000fthr.py48
-rwxr-xr-xtests/functional/arm/test_microbit.py31
-rwxr-xr-xtests/functional/arm/test_migration.py26
-rwxr-xr-xtests/functional/arm/test_orangepi.py237
-rwxr-xr-xtests/functional/arm/test_quanta_gsj.py92
-rwxr-xr-xtests/functional/arm/test_raspi2.py92
-rwxr-xr-xtests/functional/arm/test_realview.py47
-rwxr-xr-xtests/functional/arm/test_replay.py69
-rwxr-xr-xtests/functional/arm/test_smdkc210.py51
-rwxr-xr-xtests/functional/arm/test_stellaris.py48
-rwxr-xr-xtests/functional/arm/test_sx1.py73
-rwxr-xr-xtests/functional/arm/test_tuxrun.py70
-rwxr-xr-xtests/functional/arm/test_vexpress.py26
-rwxr-xr-xtests/functional/arm/test_virt.py30
33 files changed, 2141 insertions, 0 deletions
diff --git a/tests/functional/arm/meson.build b/tests/functional/arm/meson.build
new file mode 100644
index 0000000..d1ed076
--- /dev/null
+++ b/tests/functional/arm/meson.build
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+test_arm_timeouts = {
+ 'aspeed_palmetto' : 120,
+ 'aspeed_romulus' : 120,
+ 'aspeed_witherspoon' : 120,
+ 'aspeed_ast2500' : 720,
+ 'aspeed_ast2600_buildroot' : 720,
+ 'aspeed_ast2600_sdk' : 1200,
+ 'aspeed_bletchley' : 480,
+ 'aspeed_catalina' : 480,
+ 'aspeed_gb200nvl_bmc' : 480,
+ 'aspeed_rainier' : 480,
+ 'bpim2u' : 500,
+ 'collie' : 180,
+ 'cubieboard' : 360,
+ 'orangepi' : 540,
+ 'quanta_gsj' : 240,
+ 'raspi2' : 120,
+ 'replay' : 240,
+ 'tuxrun' : 240,
+ 'sx1' : 360,
+}
+
+tests_arm_system_quick = [
+ 'migration',
+]
+
+tests_arm_system_thorough = [
+ 'aspeed_ast1030',
+ 'aspeed_palmetto',
+ 'aspeed_romulus',
+ 'aspeed_witherspoon',
+ 'aspeed_ast2500',
+ 'aspeed_ast2600_buildroot',
+ 'aspeed_ast2600_sdk',
+ 'aspeed_bletchley',
+ 'aspeed_catalina',
+ 'aspeed_gb200nvl_bmc',
+ 'aspeed_rainier',
+ 'bpim2u',
+ 'canona1100',
+ 'collie',
+ 'cubieboard',
+ 'emcraft_sf2',
+ 'integratorcp',
+ 'max78000fthr',
+ 'microbit',
+ 'orangepi',
+ 'quanta_gsj',
+ 'raspi2',
+ 'realview',
+ 'replay',
+ 'smdkc210',
+ 'stellaris',
+ 'sx1',
+ 'vexpress',
+ 'virt',
+ 'tuxrun',
+]
+
+tests_arm_linuxuser_thorough = [
+ 'bflt',
+]
diff --git a/tests/functional/arm/test_aspeed_ast1030.py b/tests/functional/arm/test_aspeed_ast1030.py
new file mode 100755
index 0000000..60e2b02
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_ast1030.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED SoCs with firmware
+#
+# Copyright (C) 2022 ASPEED Technology Inc
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import LinuxKernelTest, Asset
+from aspeed import AspeedTest
+from qemu_test import exec_command_and_wait_for_pattern
+
+
+class AST1030Machine(AspeedTest):
+
+ ASSET_ZEPHYR_3_03 = Asset(
+ ('https://github.com/AspeedTech-BMC'
+ '/zephyr/releases/download/v00.03.03/ast1030-evb-demo.zip'),
+ '27cd73cdee6374bceb4ee58b3ace87989fa3f0684f4e612510804b588b24d4e0')
+
+ def test_arm_ast1030_zephyros_3_03(self):
+ self.set_machine('ast1030-evb')
+
+ kernel_name = "ast1030-evb-demo/zephyr.elf"
+ kernel_file = self.archive_extract(
+ self.ASSET_ZEPHYR_3_03, member=kernel_name)
+
+ self.vm.set_console()
+ self.vm.add_args('-kernel', kernel_file, '-nographic')
+ self.vm.launch()
+ self.wait_for_console_pattern("Booting Zephyr OS")
+ exec_command_and_wait_for_pattern(self, "help",
+ "Available commands")
+
+ ASSET_ZEPHYR_1_07 = Asset(
+ ('https://github.com/AspeedTech-BMC'
+ '/zephyr/releases/download/v00.01.07/ast1030-evb-demo.zip'),
+ 'ad52e27959746988afaed8429bf4e12ab988c05c4d07c9d90e13ec6f7be4574c')
+
+ def test_arm_ast1030_zephyros_1_07(self):
+ self.set_machine('ast1030-evb')
+
+ kernel_name = "ast1030-evb-demo/zephyr.bin"
+ kernel_file = self.archive_extract(
+ self.ASSET_ZEPHYR_1_07, member=kernel_name)
+
+ self.vm.set_console()
+ self.vm.add_args('-kernel', kernel_file, '-nographic')
+ self.vm.launch()
+ self.wait_for_console_pattern("Booting Zephyr OS")
+ for shell_cmd in [
+ 'kernel stacks',
+ 'otp info conf',
+ 'otp info scu',
+ 'hwinfo devid',
+ 'crypto aes256_cbc_vault',
+ 'random get',
+ 'jtag JTAG1 sw_xfer high TMS',
+ 'adc ADC0 resolution 12',
+ 'adc ADC0 read 42',
+ 'adc ADC1 read 69',
+ 'i2c scan I2C_0',
+ 'i3c attach I3C_0',
+ 'hash test',
+ 'kernel uptime',
+ 'kernel reboot warm',
+ 'kernel uptime',
+ 'kernel reboot cold',
+ 'kernel uptime',
+ ]: exec_command_and_wait_for_pattern(self, shell_cmd, "uart:~$")
+
+ def test_arm_ast1030_otp_blockdev_device(self):
+ self.vm.set_machine("ast1030-evb")
+
+ kernel_name = "ast1030-evb-demo/zephyr.elf"
+ kernel_file = self.archive_extract(self.ASSET_ZEPHYR_3_03,
+ member=kernel_name)
+ otp_img = self.generate_otpmem_image()
+
+ self.vm.set_console()
+ self.vm.add_args(
+ "-kernel", kernel_file,
+ "-blockdev", f"driver=file,filename={otp_img},node-name=otp",
+ "-global", "aspeed-otp.drive=otp",
+ )
+ self.vm.launch()
+ self.wait_for_console_pattern("Booting Zephyr OS")
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/arm/test_aspeed_ast2500.py b/tests/functional/arm/test_aspeed_ast2500.py
new file mode 100755
index 0000000..5efd104
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_ast2500.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import Asset, exec_command_and_wait_for_pattern
+from aspeed import AspeedTest
+
+
+class AST2500Machine(AspeedTest):
+
+ ASSET_BR2_202411_AST2500_FLASH = Asset(
+ ('https://github.com/legoater/qemu-aspeed-boot/raw/master/'
+ 'images/ast2500-evb/buildroot-2024.11/flash.img'),
+ '641e6906c18c0f19a2aeb48099d66d4771929c361001d554d0d45c667413e13a')
+
+ def test_arm_ast2500_evb_buildroot(self):
+ self.set_machine('ast2500-evb')
+
+ image_path = self.ASSET_BR2_202411_AST2500_FLASH.fetch()
+
+ self.vm.add_args('-device',
+ 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test')
+ self.do_test_arm_aspeed_buildroot_start(image_path, '0x0',
+ 'ast2500-evb login:')
+
+ exec_command_and_wait_for_pattern(self,
+ 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device',
+ 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d')
+ exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon1/temp1_input', '0')
+ self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
+ property='temperature', value=18000)
+ exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon1/temp1_input', '18000')
+
+ self.do_test_arm_aspeed_buildroot_poweroff()
+
+ ASSET_SDK_V908_AST2500 = Asset(
+ 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2500-default-obmc.tar.gz',
+ 'c0a2ba169efd19be5eb77c50ec2a6afd9d826e196a0be3432f969fc72d4b7c0e')
+
+ def test_arm_ast2500_evb_sdk(self):
+ self.set_machine('ast2500-evb')
+
+ self.archive_extract(self.ASSET_SDK_V908_AST2500)
+
+ self.do_test_arm_aspeed_sdk_start(
+ self.scratch_file("ast2500-default", "image-bmc"))
+
+ self.wait_for_console_pattern('ast2500-default login:')
+
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/arm/test_aspeed_ast2600_buildroot.py b/tests/functional/arm/test_aspeed_ast2600_buildroot.py
new file mode 100755
index 0000000..51f2676
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_ast2600_buildroot.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+import time
+import tempfile
+import subprocess
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+from qemu_test import exec_command_and_wait_for_pattern, skipIfMissingCommands
+
+
+class AST2600Machine(AspeedTest):
+
+ ASSET_BR2_202411_AST2600_FLASH = Asset(
+ ('https://github.com/legoater/qemu-aspeed-boot/raw/master/'
+ 'images/ast2600-evb/buildroot-2024.11/flash.img'),
+ '4bb2f3dfdea31199b51d66b42f686dc5374c144a7346fdc650194a5578b73609')
+
+ def test_arm_ast2600_evb_buildroot(self):
+ self.set_machine('ast2600-evb')
+
+ image_path = self.ASSET_BR2_202411_AST2600_FLASH.fetch()
+
+ self.vm.add_args('-device',
+ 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test')
+ self.vm.add_args('-device',
+ 'ds1338,bus=aspeed.i2c.bus.3,address=0x32')
+ self.vm.add_args('-device',
+ 'i2c-echo,bus=aspeed.i2c.bus.3,address=0x42')
+ self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00',
+ 'ast2600-evb login:')
+
+ exec_command_and_wait_for_pattern(self,
+ 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device',
+ 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d')
+ exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon1/temp1_input', '0')
+ self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
+ property='temperature', value=18000)
+ exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon1/temp1_input', '18000')
+
+ exec_command_and_wait_for_pattern(self,
+ 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-3/device/new_device',
+ 'i2c i2c-3: new_device: Instantiated device ds1307 at 0x32')
+ year = time.strftime("%Y")
+ exec_command_and_wait_for_pattern(self, 'hwclock -f /dev/rtc1', year)
+
+ exec_command_and_wait_for_pattern(self,
+ 'echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-3/new_device',
+ 'i2c i2c-3: new_device: Instantiated device slave-24c02 at 0x64')
+ exec_command_and_wait_for_pattern(self,
+ 'i2cset -y 3 0x42 0x64 0x00 0xaa i', '#')
+ exec_command_and_wait_for_pattern(self,
+ 'hexdump /sys/bus/i2c/devices/3-1064/slave-eeprom',
+ '0000000 ffaa ffff ffff ffff ffff ffff ffff ffff')
+ self.do_test_arm_aspeed_buildroot_poweroff()
+
+ ASSET_BR2_202302_AST2600_TPM_FLASH = Asset(
+ ('https://github.com/legoater/qemu-aspeed-boot/raw/master/'
+ 'images/ast2600-evb/buildroot-2023.02-tpm/flash.img'),
+ 'a46009ae8a5403a0826d607215e731a8c68d27c14c41e55331706b8f9c7bd997')
+
+ @skipIfMissingCommands('swtpm')
+ def test_arm_ast2600_evb_buildroot_tpm(self):
+ self.set_machine('ast2600-evb')
+
+ image_path = self.ASSET_BR2_202302_AST2600_TPM_FLASH.fetch()
+
+ tpmstate_dir = tempfile.TemporaryDirectory(prefix="qemu_")
+ socket = os.path.join(tpmstate_dir.name, 'swtpm-socket')
+
+ # We must put the TPM state dir in /tmp/, not the build dir,
+ # because some distros use AppArmor to lock down swtpm and
+ # restrict the set of locations it can access files in.
+ subprocess.run(['swtpm', 'socket', '-d', '--tpm2',
+ '--tpmstate', f'dir={tpmstate_dir.name}',
+ '--ctrl', f'type=unixio,path={socket}'])
+
+ self.vm.add_args('-chardev', f'socket,id=chrtpm,path={socket}')
+ self.vm.add_args('-tpmdev', 'emulator,id=tpm0,chardev=chrtpm')
+ self.vm.add_args('-device',
+ 'tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.12,address=0x2e')
+ self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', 'Aspeed AST2600 EVB')
+
+ exec_command_and_wait_for_pattern(self,
+ 'echo tpm_tis_i2c 0x2e > /sys/bus/i2c/devices/i2c-12/new_device',
+ 'tpm_tis_i2c 12-002e: 2.0 TPM (device-id 0x1, rev-id 1)')
+ exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/tpm/tpm0/pcr-sha256/0',
+ 'B804724EA13F52A9072BA87FE8FDCC497DFC9DF9AA15B9088694639C431688E0')
+
+ self.do_test_arm_aspeed_buildroot_poweroff()
+
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/arm/test_aspeed_ast2600_sdk.py b/tests/functional/arm/test_aspeed_ast2600_sdk.py
new file mode 100755
index 0000000..e3d4ed0
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_ast2600_sdk.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+import time
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+from qemu_test import exec_command_and_wait_for_pattern
+
+
+class AST2600Machine(AspeedTest):
+
+ ASSET_SDK_V908_AST2600 = Asset(
+ 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2600-default-obmc.tar.gz',
+ 'a0414f14ad696550efe083c2156dbeda855c08cc9ae7f40fe1b41bf292295f82')
+
+ def do_ast2600_pcie_test(self):
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 80:00.0',
+ '80:00.0 Host bridge: '
+ 'ASPEED Technology, Inc. Device 2600')
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 80:08.0',
+ '80:08.0 PCI bridge: '
+ 'ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge')
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 81:00.0',
+ '81:00.0 Ethernet controller: '
+ 'Intel Corporation 82574L Gigabit Network Connection')
+ exec_command_and_wait_for_pattern(self,
+ 'ip addr show dev eth4',
+ 'inet 10.0.2.15/24')
+
+ def test_arm_ast2600_evb_sdk(self):
+ self.set_machine('ast2600-evb')
+ self.require_netdev('user')
+
+ self.archive_extract(self.ASSET_SDK_V908_AST2600)
+
+ self.vm.add_args('-device',
+ 'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test')
+ self.vm.add_args('-device',
+ 'ds1338,bus=aspeed.i2c.bus.5,address=0x32')
+ self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.0')
+ self.vm.add_args('-netdev', 'user,id=net1')
+ self.do_test_arm_aspeed_sdk_start(
+ self.scratch_file("ast2600-default", "image-bmc"))
+
+ self.wait_for_console_pattern('ast2600-default login:')
+
+ exec_command_and_wait_for_pattern(self, 'root', 'Password:')
+ exec_command_and_wait_for_pattern(self, '0penBmc',
+ 'root@ast2600-default:~#')
+
+ exec_command_and_wait_for_pattern(self,
+ 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-5/device/new_device',
+ 'i2c i2c-5: new_device: Instantiated device lm75 at 0x4d')
+ exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon19/temp1_input', '0')
+ self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
+ property='temperature', value=18000)
+ exec_command_and_wait_for_pattern(self,
+ 'cat /sys/class/hwmon/hwmon19/temp1_input', '18000')
+
+ exec_command_and_wait_for_pattern(self,
+ 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-5/device/new_device',
+ 'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32')
+ year = time.strftime("%Y")
+ exec_command_and_wait_for_pattern(self,
+ '/sbin/hwclock -f /dev/rtc1', year)
+ self.do_ast2600_pcie_test()
+
+ def test_arm_ast2600_otp_blockdev_device(self):
+ self.vm.set_machine("ast2600-evb")
+
+ image_path = self.archive_extract(self.ASSET_SDK_V908_AST2600)
+ otp_img = self.generate_otpmem_image()
+
+ self.vm.set_console()
+ self.vm.add_args(
+ "-blockdev", f"driver=file,filename={otp_img},node-name=otp",
+ "-global", "aspeed-otp.drive=otp",
+ )
+ self.do_test_arm_aspeed_sdk_start(
+ self.scratch_file("ast2600-default", "image-bmc"))
+ self.wait_for_console_pattern("ast2600-default login:")
+
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/arm/test_aspeed_bletchley.py b/tests/functional/arm/test_aspeed_bletchley.py
new file mode 100755
index 0000000..5a60b24
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_bletchley.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+
+
+class BletchleyMachine(AspeedTest):
+
+ ASSET_BLETCHLEY_FLASH = Asset(
+ 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/bletchley-bmc/openbmc-20250128071329/obmc-phosphor-image-bletchley-20250128071329.static.mtd.xz',
+ 'db21d04d47d7bb2a276f59d308614b4dfb70b9c7c81facbbca40a3977a2d8844')
+
+ def test_arm_ast2600_bletchley_openbmc(self):
+ image_path = self.uncompress(self.ASSET_BLETCHLEY_FLASH)
+
+ self.do_test_arm_aspeed_openbmc('bletchley-bmc', image=image_path,
+ uboot='2019.04', cpu_id='0xf00',
+ soc='AST2600 rev A3')
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/arm/test_aspeed_catalina.py b/tests/functional/arm/test_aspeed_catalina.py
new file mode 100755
index 0000000..dc2f24e
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_catalina.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+
+
+class CatalinaMachine(AspeedTest):
+
+ ASSET_CATALINA_FLASH = Asset(
+ 'https://github.com/legoater/qemu-aspeed-boot/raw/a866feb5ef81245b4827a214584bf6bcc72939f6/images/catalina-bmc/obmc-phosphor-image-catalina-20250619123021.static.mtd.xz',
+ '287402e1ba021991e06be1d098f509444a02a3d81a73a932f66528b159e864f9')
+
+ def test_arm_ast2600_catalina_openbmc(self):
+ image_path = self.uncompress(self.ASSET_CATALINA_FLASH)
+
+ self.do_test_arm_aspeed_openbmc('catalina-bmc', image=image_path,
+ uboot='2019.04', cpu_id='0xf00',
+ soc='AST2600 rev A3')
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/arm/test_aspeed_gb200nvl_bmc.py b/tests/functional/arm/test_aspeed_gb200nvl_bmc.py
new file mode 100755
index 0000000..8e8e3f0
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_gb200nvl_bmc.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+
+
+class GB200Machine(AspeedTest):
+
+ ASSET_GB200_FLASH = Asset(
+ 'https://github.com/legoater/qemu-aspeed-boot/raw/refs/heads/master/images/gb200nvl-obmc/obmc-phosphor-image-gb200nvl-obmc-20250702182348.static.mtd.xz',
+ 'b84819317cb3dc762895ad507705978ef000bfc77c50c33a63bdd37921db0dbc')
+
+ def test_arm_aspeed_gb200_openbmc(self):
+ image_path = self.uncompress(self.ASSET_GB200_FLASH)
+
+ self.do_test_arm_aspeed_openbmc('gb200nvl-bmc', image=image_path,
+ uboot='2019.04', cpu_id='0xf00',
+ soc='AST2600 rev A3',
+ image_hostname='gb200nvl-obmc')
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/arm/test_aspeed_palmetto.py b/tests/functional/arm/test_aspeed_palmetto.py
new file mode 100755
index 0000000..ff0b821
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_palmetto.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+
+
+class PalmettoMachine(AspeedTest):
+
+ ASSET_PALMETTO_FLASH = Asset(
+ 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/palmetto-bmc/openbmc-20250128071432/obmc-phosphor-image-palmetto-20250128071432.static.mtd',
+ 'bce7c392eec75c707a91cfc8fad7ca9a69d7e4f10df936930d65c1cb9897ac81')
+
+ def test_arm_ast2400_palmetto_openbmc(self):
+ image_path = self.ASSET_PALMETTO_FLASH.fetch()
+
+ self.do_test_arm_aspeed_openbmc('palmetto-bmc', image=image_path,
+ uboot='2019.04', cpu_id='0x0',
+ soc='AST2400 rev A1')
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/arm/test_aspeed_rainier.py b/tests/functional/arm/test_aspeed_rainier.py
new file mode 100755
index 0000000..602d619
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_rainier.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+
+class RainierMachine(AspeedTest):
+
+ ASSET_RAINIER_EMMC = Asset(
+ ('https://fileserver.linaro.org/s/B6pJTwWEkzSDi36/download/'
+ 'mmc-p10bmc-20240617.qcow2'),
+ 'd523fb478d2b84d5adc5658d08502bc64b1486955683814f89c6137518acd90b')
+
+ def test_arm_aspeed_emmc_boot(self):
+ self.set_machine('rainier-bmc')
+ self.require_netdev('user')
+
+ image_path = self.ASSET_RAINIER_EMMC.fetch()
+
+ self.vm.set_console()
+ self.vm.add_args('-drive',
+ 'file=' + image_path + ',if=sd,id=sd2,index=2',
+ '-net', 'nic', '-net', 'user', '-snapshot')
+ self.vm.launch()
+
+ self.wait_for_console_pattern('U-Boot SPL 2019.04')
+ self.wait_for_console_pattern('Trying to boot from MMC1')
+ self.wait_for_console_pattern('U-Boot 2019.04')
+ self.wait_for_console_pattern('eMMC 2nd Boot')
+ self.wait_for_console_pattern('## Loading kernel from FIT Image')
+ self.wait_for_console_pattern('Starting kernel ...')
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0xf00')
+ self.wait_for_console_pattern('mmcblk0: p1 p2 p3 p4 p5 p6 p7')
+ self.wait_for_console_pattern('IBM eBMC (OpenBMC for IBM Enterprise')
+
+ ASSET_DEBIAN_LINUX_ARMHF_DEB = Asset(
+ ('http://snapshot.debian.org/archive/debian/20220606T211338Z/pool/main/l/linux/linux-image-5.17.0-2-armmp_5.17.6-1%2Bb1_armhf.deb'),
+ '8acb2b4439faedc2f3ed4bdb2847ad4f6e0491f73debaeb7f660c8abe4dcdc0e')
+
+ def test_arm_debian_kernel_boot(self):
+ self.set_machine('rainier-bmc')
+
+ kernel_path = self.archive_extract(
+ self.ASSET_DEBIAN_LINUX_ARMHF_DEB,
+ member='boot/vmlinuz-5.17.0-2-armmp')
+ dtb_path = self.archive_extract(
+ self.ASSET_DEBIAN_LINUX_ARMHF_DEB,
+ member='usr/lib/linux-image-5.17.0-2-armmp/aspeed-bmc-ibm-rainier.dtb')
+
+ self.vm.set_console()
+ self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-net', 'nic')
+ self.vm.launch()
+
+ self.wait_for_console_pattern("Booting Linux on physical CPU 0xf00")
+ self.wait_for_console_pattern("SMP: Total of 2 processors activated")
+ self.wait_for_console_pattern("No filesystem could mount root")
+
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/arm/test_aspeed_romulus.py b/tests/functional/arm/test_aspeed_romulus.py
new file mode 100755
index 0000000..0447212
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_romulus.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+
+
+class RomulusMachine(AspeedTest):
+
+ ASSET_ROMULUS_FLASH = Asset(
+ 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/romulus-bmc/openbmc-20250128071340/obmc-phosphor-image-romulus-20250128071340.static.mtd',
+ '6d031376440c82ed9d087d25e9fa76aea75b42f80daa252ec402c0bc3cf6cf5b')
+
+ def test_arm_ast2500_romulus_openbmc(self):
+ image_path = self.ASSET_ROMULUS_FLASH.fetch()
+
+ self.do_test_arm_aspeed_openbmc('romulus-bmc', image=image_path,
+ uboot='2019.04', cpu_id='0x0',
+ soc='AST2500 rev A1')
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/arm/test_aspeed_witherspoon.py b/tests/functional/arm/test_aspeed_witherspoon.py
new file mode 100755
index 0000000..51a2d47
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_witherspoon.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+
+
+class WitherspoonMachine(AspeedTest):
+
+ ASSET_WITHERSPOON_FLASH = Asset(
+ 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/witherspoon-bmc/openbmc-20240618035022/obmc-phosphor-image-witherspoon-20240618035022.ubi.mtd',
+ '937d9ed449ea6c6cbed983519088a42d0cafe276bcfe4fce07772ca6673f9213')
+
+ def test_arm_ast2500_witherspoon_openbmc(self):
+ image_path = self.ASSET_WITHERSPOON_FLASH.fetch()
+
+ self.do_test_arm_aspeed_openbmc('witherspoon-bmc', image=image_path,
+ uboot='2016.07', cpu_id='0x0',
+ soc='AST2500 rev A1')
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/arm/test_bflt.py b/tests/functional/arm/test_bflt.py
new file mode 100755
index 0000000..f273fc8
--- /dev/null
+++ b/tests/functional/arm/test_bflt.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+#
+# Test the bFLT loader format
+#
+# Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import bz2
+
+from qemu_test import QemuUserTest, Asset
+from qemu_test import skipIfMissingCommands, skipUntrustedTest
+
+
+class LoadBFLT(QemuUserTest):
+
+ ASSET_ROOTFS = Asset(
+ ('https://elinux.org/images/5/51/Stm32_mini_rootfs.cpio.bz2'),
+ 'eefb788e4980c9e8d6c9d60ce7d15d4da6bf4fbc6a80f487673824600d5ba9cc')
+
+ @skipIfMissingCommands('cpio')
+ @skipUntrustedTest()
+ def test_stm32(self):
+ # See https://elinux.org/STM32#User_Space
+ rootfs_path_bz2 = self.ASSET_ROOTFS.fetch()
+ busybox_path = self.scratch_file("bin", "busybox")
+
+ with bz2.open(rootfs_path_bz2, 'rb') as cpio_handle:
+ self.archive_extract(cpio_handle, format="cpio")
+
+ res = self.run_cmd(busybox_path)
+ ver = 'BusyBox v1.24.0.git (2015-02-03 22:17:13 CET) multi-call binary.'
+ self.assertIn(ver, res.stdout)
+
+ res = self.run_cmd(busybox_path, ['uname', '-a'])
+ unm = 'armv7l GNU/Linux'
+ self.assertIn(unm, res.stdout)
+
+
+if __name__ == '__main__':
+ QemuUserTest.main()
diff --git a/tests/functional/arm/test_bpim2u.py b/tests/functional/arm/test_bpim2u.py
new file mode 100755
index 0000000..8bed64b
--- /dev/null
+++ b/tests/functional/arm/test_bpim2u.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel on a Banana Pi machine
+# and checks the console
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+
+from qemu_test import LinuxKernelTest, exec_command_and_wait_for_pattern
+from qemu_test import Asset, interrupt_interactive_console_until_pattern
+from qemu_test import skipBigDataTest
+from qemu_test.utils import image_pow2ceil_expand
+
+
+class BananaPiMachine(LinuxKernelTest):
+
+ ASSET_DEB = Asset(
+ ('https://apt.armbian.com/pool/main/l/linux-6.6.16/'
+ 'linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'),
+ '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22')
+
+ ASSET_INITRD = Asset(
+ ('https://github.com/groeck/linux-build-test/raw/'
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
+ 'arm/rootfs-armv7a.cpio.gz'),
+ '2c8dbdb16ea7af2dfbcbea96044dde639fb07d09fd3c4fb31f2027ef71e55ddd')
+
+ ASSET_ROOTFS = Asset(
+ ('http://storage.kernelci.org/images/rootfs/buildroot/'
+ 'buildroot-baseline/20230703.0/armel/rootfs.ext2.xz'),
+ '42b44a12965ac0afe9a88378527fb698a7dc76af50495efc2361ee1595b4e5c6')
+
+ ASSET_SD_IMAGE = Asset(
+ ('https://downloads.openwrt.org/releases/22.03.3/targets/sunxi/cortexa7/'
+ 'openwrt-22.03.3-sunxi-cortexa7-sinovoip_bananapi-m2-ultra-ext4-sdcard.img.gz'),
+ '5b41b4e11423e562c6011640f9a7cd3bdd0a3d42b83430f7caa70a432e6cd82c')
+
+ def test_arm_bpim2u(self):
+ self.set_machine('bpim2u')
+ kernel_path = self.archive_extract(
+ self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
+ dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/'
+ 'sun8i-r40-bananapi-m2-ultra.dtb')
+ dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
+
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyS0,115200n8 '
+ 'earlycon=uart,mmio32,0x1c28000')
+ self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line)
+ self.vm.launch()
+ console_pattern = 'Kernel command line: %s' % kernel_command_line
+ self.wait_for_console_pattern(console_pattern)
+ os.remove(kernel_path)
+ os.remove(dtb_path)
+
+ def test_arm_bpim2u_initrd(self):
+ self.set_machine('bpim2u')
+ kernel_path = self.archive_extract(
+ self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
+ dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/'
+ 'sun8i-r40-bananapi-m2-ultra.dtb')
+ dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
+ initrd_path = self.uncompress(self.ASSET_INITRD)
+
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyS0,115200 '
+ 'panic=-1 noreboot')
+ self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-initrd', initrd_path,
+ '-append', kernel_command_line,
+ '-no-reboot')
+ self.vm.launch()
+ self.wait_for_console_pattern('Boot successful.')
+
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+ 'Allwinner sun8i Family')
+ exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
+ 'system-control@1c00000')
+ exec_command_and_wait_for_pattern(self, 'reboot',
+ 'reboot: Restarting system')
+ # Wait for VM to shut down gracefully
+ self.vm.wait()
+ os.remove(kernel_path)
+ os.remove(dtb_path)
+ os.remove(initrd_path)
+
+ def test_arm_bpim2u_gmac(self):
+ self.set_machine('bpim2u')
+ self.require_netdev('user')
+
+ deb_path = self.ASSET_DEB.fetch()
+ kernel_path = self.archive_extract(
+ self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
+ dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/'
+ 'sun8i-r40-bananapi-m2-ultra.dtb')
+ dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
+ rootfs_path = self.uncompress(self.ASSET_ROOTFS)
+ image_pow2ceil_expand(rootfs_path)
+
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyS0,115200 '
+ 'root=b300 rootwait rw '
+ 'panic=-1 noreboot')
+ self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-drive', 'file=' + rootfs_path + ',if=sd,format=raw',
+ '-net', 'nic,model=gmac,netdev=host_gmac',
+ '-netdev', 'user,id=host_gmac',
+ '-append', kernel_command_line,
+ '-no-reboot')
+ self.vm.launch()
+ shell_ready = "/bin/sh: can't access tty; job control turned off"
+ self.wait_for_console_pattern(shell_ready)
+
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+ 'Allwinner sun8i Family')
+ exec_command_and_wait_for_pattern(self, 'cat /proc/partitions',
+ 'mmcblk')
+ exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up',
+ 'eth0: Link is Up')
+ exec_command_and_wait_for_pattern(self, 'udhcpc eth0',
+ 'udhcpc: lease of 10.0.2.15 obtained')
+ exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2',
+ '3 packets transmitted, 3 packets received, 0% packet loss')
+ exec_command_and_wait_for_pattern(self, 'reboot',
+ 'reboot: Restarting system')
+ # Wait for VM to shut down gracefully
+ self.vm.wait()
+ os.remove(kernel_path)
+ os.remove(dtb_path)
+ os.remove(rootfs_path)
+
+ @skipBigDataTest()
+ def test_arm_bpim2u_openwrt_22_03_3(self):
+ self.set_machine('bpim2u')
+ self.require_netdev('user')
+
+ # This test download a 8.9 MiB compressed image and expand it
+ # to 127 MiB.
+ image_path = self.uncompress(self.ASSET_SD_IMAGE)
+ image_pow2ceil_expand(image_path)
+
+ self.vm.set_console()
+ self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
+ '-nic', 'user',
+ '-no-reboot')
+ self.vm.launch()
+
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'usbcore.nousb '
+ 'noreboot')
+
+ self.wait_for_console_pattern('U-Boot SPL')
+
+ interrupt_interactive_console_until_pattern(
+ self, 'Hit any key to stop autoboot:', '=>')
+ exec_command_and_wait_for_pattern(self, "setenv extraargs '" +
+ kernel_command_line + "'", '=>')
+ exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...')
+
+ self.wait_for_console_pattern(
+ 'Please press Enter to activate this console.')
+
+ exec_command_and_wait_for_pattern(self, ' ', 'root@')
+
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+ 'Allwinner sun8i Family')
+ exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
+ 'system-control@1c00000')
+ os.remove(image_path)
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()
diff --git a/tests/functional/arm/test_canona1100.py b/tests/functional/arm/test_canona1100.py
new file mode 100755
index 0000000..21a1a59
--- /dev/null
+++ b/tests/functional/arm/test_canona1100.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the canon-a1100 machine with firmware
+#
+# Copyright (c) 2020 Red Hat, Inc.
+#
+# Author:
+# Thomas Huth <thuth@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later. See the COPYING file in the top-level directory.
+
+from qemu_test import QemuSystemTest, Asset
+from qemu_test import wait_for_console_pattern
+
+
+class CanonA1100Machine(QemuSystemTest):
+ """Boots the barebox firmware and checks that the console is operational"""
+
+ timeout = 90
+
+ ASSET_BIOS = Asset(('https://qemu-advcal.gitlab.io'
+ '/qac-best-of-multiarch/download/day18.tar.xz'),
+ '28e71874ce985be66b7fd1345ed88cb2523b982f899c8d2900d6353054a1be49')
+
+ def test_arm_canona1100(self):
+ self.set_machine('canon-a1100')
+
+ bios = self.archive_extract(self.ASSET_BIOS,
+ member="day18/barebox.canon-a1100.bin")
+ self.vm.set_console()
+ self.vm.add_args('-bios', bios)
+ self.vm.launch()
+ wait_for_console_pattern(self, 'running /env/bin/init')
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
diff --git a/tests/functional/arm/test_collie.py b/tests/functional/arm/test_collie.py
new file mode 100755
index 0000000..fe1be3d
--- /dev/null
+++ b/tests/functional/arm/test_collie.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel on a collie machine
+# and checks the console
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import LinuxKernelTest, Asset
+
+
+class CollieTest(LinuxKernelTest):
+
+ ASSET_ZIMAGE = Asset(
+ 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/collie/zImage',
+ '10ace8abf9e0875ef8a83b8829cc3b5b50bc6d7bc3ca29f19f49f5673a43c13b')
+
+ ASSET_ROOTFS = Asset(
+ 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/collie/rootfs-sa110.cpio',
+ '89ccaaa5c6b33331887047e1618ffe81b0f55909173944347d5d2426f3bcc1f2')
+
+ def test_arm_collie(self):
+ self.set_machine('collie')
+ zimage_path = self.ASSET_ZIMAGE.fetch()
+ rootfs_path = self.ASSET_ROOTFS.fetch()
+ self.vm.add_args('-append', 'rdinit=/sbin/init console=ttySA1')
+ self.launch_kernel(zimage_path,
+ initrd=rootfs_path,
+ wait_for='reboot: Restarting system')
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()
diff --git a/tests/functional/arm/test_cubieboard.py b/tests/functional/arm/test_cubieboard.py
new file mode 100755
index 0000000..b536c2f
--- /dev/null
+++ b/tests/functional/arm/test_cubieboard.py
@@ -0,0 +1,144 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel and checks the console
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern
+from qemu_test import interrupt_interactive_console_until_pattern
+from qemu_test import skipBigDataTest
+from qemu_test.utils import image_pow2ceil_expand
+
+
+class CubieboardMachine(LinuxKernelTest):
+
+ ASSET_DEB = Asset(
+ ('https://apt.armbian.com/pool/main/l/linux-6.6.16/'
+ 'linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'),
+ '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22')
+
+ ASSET_INITRD = Asset(
+ ('https://github.com/groeck/linux-build-test/raw/'
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
+ 'arm/rootfs-armv5.cpio.gz'),
+ '334b8d256db67a3f2b3ad070aa08b5ade39624e0e7e35b02f4359a577bc8f39b')
+
+ ASSET_SATA_ROOTFS = Asset(
+ ('https://github.com/groeck/linux-build-test/raw/'
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
+ 'arm/rootfs-armv5.ext2.gz'),
+ '17fc750da568580b39372133051ef2f0a963c0c0b369b845614442d025701745')
+
+ ASSET_OPENWRT = Asset(
+ ('https://downloads.openwrt.org/releases/22.03.2/targets/sunxi/cortexa8/'
+ 'openwrt-22.03.2-sunxi-cortexa8-cubietech_a10-cubieboard-ext4-sdcard.img.gz'),
+ '94b5ecbfbc0b3b56276e5146b899eafa2ac5dc2d08733d6705af9f144f39f554')
+
+ def test_arm_cubieboard_initrd(self):
+ self.set_machine('cubieboard')
+ kernel_path = self.archive_extract(
+ self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
+ dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' +
+ 'sun4i-a10-cubieboard.dtb')
+ dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
+ initrd_path = self.uncompress(self.ASSET_INITRD)
+
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyS0,115200 '
+ 'usbcore.nousb '
+ 'panic=-1 noreboot')
+ self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-initrd', initrd_path,
+ '-append', kernel_command_line,
+ '-no-reboot')
+ self.vm.launch()
+ self.wait_for_console_pattern('Boot successful.')
+
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+ 'Allwinner sun4i/sun5i')
+ exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
+ 'system-control@1c00000')
+ exec_command_and_wait_for_pattern(self, 'reboot',
+ 'reboot: Restarting system')
+ # Wait for VM to shut down gracefully
+ self.vm.wait()
+
+ def test_arm_cubieboard_sata(self):
+ self.set_machine('cubieboard')
+ kernel_path = self.archive_extract(
+ self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
+ dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' +
+ 'sun4i-a10-cubieboard.dtb')
+ dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
+
+ rootfs_path = self.uncompress(self.ASSET_SATA_ROOTFS)
+
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyS0,115200 '
+ 'usbcore.nousb '
+ 'root=/dev/sda ro '
+ 'panic=-1 noreboot')
+ self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-drive', 'if=none,format=raw,id=disk0,file='
+ + rootfs_path,
+ '-device', 'ide-hd,bus=ide.0,drive=disk0',
+ '-append', kernel_command_line,
+ '-no-reboot')
+ self.vm.launch()
+ self.wait_for_console_pattern('Boot successful.')
+
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+ 'Allwinner sun4i/sun5i')
+ exec_command_and_wait_for_pattern(self, 'cat /proc/partitions',
+ 'sda')
+ exec_command_and_wait_for_pattern(self, 'reboot',
+ 'reboot: Restarting system')
+ # Wait for VM to shut down gracefully
+ self.vm.wait()
+
+ @skipBigDataTest()
+ def test_arm_cubieboard_openwrt_22_03_2(self):
+ # This test download a 7.5 MiB compressed image and expand it
+ # to 126 MiB.
+ self.set_machine('cubieboard')
+ self.require_netdev('user')
+
+ image_path = self.uncompress(self.ASSET_OPENWRT)
+ image_pow2ceil_expand(image_path)
+
+ self.vm.set_console()
+ self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
+ '-nic', 'user',
+ '-no-reboot')
+ self.vm.launch()
+
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'usbcore.nousb '
+ 'noreboot')
+
+ self.wait_for_console_pattern('U-Boot SPL')
+
+ interrupt_interactive_console_until_pattern(
+ self, 'Hit any key to stop autoboot:', '=>')
+ exec_command_and_wait_for_pattern(self, "setenv extraargs '" +
+ kernel_command_line + "'", '=>')
+ exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...')
+
+ self.wait_for_console_pattern(
+ 'Please press Enter to activate this console.')
+
+ exec_command_and_wait_for_pattern(self, ' ', 'root@')
+
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+ 'Allwinner sun4i/sun5i')
+ exec_command_and_wait_for_pattern(self, 'reboot',
+ 'reboot: Restarting system')
+ # Wait for VM to shut down gracefully
+ self.vm.wait()
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()
diff --git a/tests/functional/arm/test_emcraft_sf2.py b/tests/functional/arm/test_emcraft_sf2.py
new file mode 100755
index 0000000..f9f3f06
--- /dev/null
+++ b/tests/functional/arm/test_emcraft_sf2.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel and checks the console
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+import shutil
+
+from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern
+from qemu_test.utils import file_truncate
+
+class EmcraftSf2Machine(LinuxKernelTest):
+
+ ASSET_UBOOT = Asset(
+ ('https://raw.githubusercontent.com/Subbaraya-Sundeep/qemu-test-binaries/'
+ 'fe371d32e50ca682391e1e70ab98c2942aeffb01/u-boot'),
+ '5c6a15103375db11b21f2236473679a9dbbed6d89652bfcdd501c263d68ab725')
+
+ ASSET_SPI = Asset(
+ ('https://raw.githubusercontent.com/Subbaraya-Sundeep/qemu-test-binaries/'
+ 'fe371d32e50ca682391e1e70ab98c2942aeffb01/spi.bin'),
+ 'cd9bdd2c4cb55a59c3adb6bcf74881667c4500dde0570a43aa3be2b17eecfdb6')
+
+ def test_arm_emcraft_sf2(self):
+ self.set_machine('emcraft-sf2')
+ self.require_netdev('user')
+
+ uboot_path = self.ASSET_UBOOT.fetch()
+ spi_path = self.ASSET_SPI.fetch()
+ spi_path_rw = self.scratch_file('spi.bin')
+ shutil.copy(spi_path, spi_path_rw)
+ os.chmod(spi_path_rw, 0o600)
+
+ file_truncate(spi_path_rw, 16 << 20) # Spansion S25FL128SDPBHICO is 16 MiB
+
+ self.vm.set_console()
+ kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE
+ self.vm.add_args('-kernel', uboot_path,
+ '-append', kernel_command_line,
+ '-drive', 'file=' + spi_path_rw + ',if=mtd,format=raw',
+ '-no-reboot')
+ self.vm.launch()
+ self.wait_for_console_pattern('Enter \'help\' for a list')
+
+ exec_command_and_wait_for_pattern(self, 'ifconfig eth0 10.0.2.15',
+ 'eth0: link becomes ready')
+ exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2',
+ '3 packets transmitted, 3 packets received, 0% packet loss')
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()
diff --git a/tests/functional/arm/test_integratorcp.py b/tests/functional/arm/test_integratorcp.py
new file mode 100755
index 0000000..23ae919
--- /dev/null
+++ b/tests/functional/arm/test_integratorcp.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel and checks the console
+#
+# Copyright (c) 2020 Red Hat, Inc.
+#
+# Author:
+# Thomas Huth <thuth@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later. See the COPYING file in the top-level directory.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import logging
+
+from qemu_test import QemuSystemTest, Asset
+from qemu_test import wait_for_console_pattern
+from qemu_test import skipIfMissingImports, skipUntrustedTest
+
+
+class IntegratorMachine(QemuSystemTest):
+
+ timeout = 90
+
+ ASSET_KERNEL = Asset(
+ ('https://github.com/zayac/qemu-arm/raw/master/'
+ 'arm-test/kernel/zImage.integrator'),
+ '26e7c7e8f943de785d95bd3c74d66451604a9b6a7a3d25dceb279e7548fd8e78')
+
+ ASSET_INITRD = Asset(
+ ('https://github.com/zayac/qemu-arm/raw/master/'
+ 'arm-test/kernel/arm_root.img'),
+ 'e187c27fb342ad148c7f33475fbed124933e0b3f4be8c74bc4f3426a4793373a')
+
+ ASSET_TUXLOGO = Asset(
+ ('https://github.com/torvalds/linux/raw/v2.6.12/'
+ 'drivers/video/logo/logo_linux_vga16.ppm'),
+ 'b762f0d91ec018887ad1b334543c2fdf9be9fdfc87672b409211efaa3ea0ef79')
+
+ def boot_integratorcp(self):
+ kernel_path = self.ASSET_KERNEL.fetch()
+ initrd_path = self.ASSET_INITRD.fetch()
+
+ self.set_machine('integratorcp')
+ self.vm.set_console()
+ self.vm.add_args('-kernel', kernel_path,
+ '-initrd', initrd_path,
+ '-append', 'printk.time=0 console=ttyAMA0')
+ self.vm.launch()
+
+ @skipUntrustedTest()
+ def test_integratorcp_console(self):
+ """
+ Boots the Linux kernel and checks that the console is operational
+ """
+ self.boot_integratorcp()
+ wait_for_console_pattern(self, 'Log in as root')
+
+ @skipIfMissingImports("numpy", "cv2")
+ @skipUntrustedTest()
+ def test_framebuffer_tux_logo(self):
+ """
+ Boot Linux and verify the Tux logo is displayed on the framebuffer.
+ """
+ import numpy as np
+ import cv2
+
+ screendump_path = self.scratch_file("screendump.pbm")
+ tuxlogo_path = self.ASSET_TUXLOGO.fetch()
+
+ self.boot_integratorcp()
+ framebuffer_ready = 'Console: switching to colour frame buffer device'
+ wait_for_console_pattern(self, framebuffer_ready)
+ self.vm.cmd('human-monitor-command', command_line='stop')
+ res = self.vm.cmd('human-monitor-command',
+ command_line='screendump %s' % screendump_path)
+ if 'unknown command' in res:
+ self.skipTest('screendump not available')
+
+ cpu_count = 1
+ match_threshold = 0.92
+ screendump_bgr = cv2.imread(screendump_path)
+ screendump_gray = cv2.cvtColor(screendump_bgr, cv2.COLOR_BGR2GRAY)
+ result = cv2.matchTemplate(screendump_gray, cv2.imread(tuxlogo_path, 0),
+ cv2.TM_CCOEFF_NORMED)
+ loc = np.where(result >= match_threshold)
+ tux_count = 0
+ for tux_count, pt in enumerate(zip(*loc[::-1]), start=1):
+ self.log.debug('found Tux at position [x, y] = %s', pt)
+ self.assertGreaterEqual(tux_count, cpu_count)
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
diff --git a/tests/functional/arm/test_max78000fthr.py b/tests/functional/arm/test_max78000fthr.py
new file mode 100755
index 0000000..a82980b
--- /dev/null
+++ b/tests/functional/arm/test_max78000fthr.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+#
+# Functional test that checks the max78000fthr machine.
+# Tests ICC, GCR, TRNG, AES, and UART
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern
+from qemu_test import wait_for_console_pattern
+
+
+class Max78000Machine(QemuSystemTest):
+
+ ASSET_FW = Asset(
+ 'https://github.com/JacksonDonaldson/max78000Test/raw/main/build/max78000.bin',
+ '86940b4bf60931bc6a8aa5db4b9f7f3cf8f64dbbd7ac534647980e536cf3adf7')
+
+ def test_fthr(self):
+ self.set_machine('max78000fthr')
+ fw_path = self.ASSET_FW.fetch()
+ self.vm.set_console()
+ self.vm.add_args('-kernel', fw_path)
+ self.vm.add_args('-device', "loader,file=" + fw_path + ",addr=0x10000000")
+ self.vm.launch()
+
+ wait_for_console_pattern(self, 'started')
+
+ # i -> prints instruction cache values
+ exec_command_and_wait_for_pattern(self, 'i', 'CTRL: 00010001')
+
+ # r -> gcr resets the machine
+ exec_command_and_wait_for_pattern(self, 'r', 'started')
+
+ # z -> sets some memory, then has gcr zero it
+ exec_command_and_wait_for_pattern(self, 'z', 'initial value: 12345678')
+ wait_for_console_pattern(self, "after memz: 00000000")
+
+ # t -> runs trng
+ exec_command_and_wait_for_pattern(self, 't', 'random data:')
+
+ # a -> runs aes
+ exec_command_and_wait_for_pattern(self, 'a',
+ 'encrypted to : a47ca9dd e0df4c86 a070af6e 91710dec')
+ wait_for_console_pattern(self,
+ 'encrypted to : cab7a28e bf456751 9049fcea 8960494b')
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
diff --git a/tests/functional/arm/test_microbit.py b/tests/functional/arm/test_microbit.py
new file mode 100755
index 0000000..68ea4e7
--- /dev/null
+++ b/tests/functional/arm/test_microbit.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright 2025, The QEMU Project Developers.
+#
+# A functional test that runs MicroPython on the arm microbit machine.
+
+from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern
+from qemu_test import wait_for_console_pattern
+
+
+class MicrobitMachine(QemuSystemTest):
+
+ ASSET_MICRO = Asset('https://ozlabs.org/~joel/microbit-micropython.hex',
+ '021641f93dfb11767d4978dbb3ca7f475d1b13c69e7f4aec3382f212636bffd6')
+
+ def test_arm_microbit(self):
+ self.set_machine('microbit')
+
+ micropython = self.ASSET_MICRO.fetch()
+ self.vm.set_console()
+ self.vm.add_args('-device', f'loader,file={micropython}')
+ self.vm.launch()
+ wait_for_console_pattern(self, 'Type "help()" for more information.')
+ exec_command_and_wait_for_pattern(self, 'import machine as mch', '>>>')
+ exec_command_and_wait_for_pattern(self, 'mch.reset()', 'MicroPython')
+ wait_for_console_pattern(self, '>>>')
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
diff --git a/tests/functional/arm/test_migration.py b/tests/functional/arm/test_migration.py
new file mode 100755
index 0000000..0aa89f4
--- /dev/null
+++ b/tests/functional/arm/test_migration.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# arm migration test
+
+from migration import MigrationTest
+
+
+class ArmMigrationTest(MigrationTest):
+
+ def test_migration_with_tcp_localhost(self):
+ self.set_machine('npcm750-evb')
+ self.migration_with_tcp_localhost()
+
+ def test_migration_with_unix(self):
+ self.set_machine('npcm750-evb')
+ self.migration_with_unix()
+
+ def test_migration_with_exec(self):
+ self.set_machine('npcm750-evb')
+ self.migration_with_exec()
+
+
+if __name__ == '__main__':
+ MigrationTest.main()
diff --git a/tests/functional/arm/test_orangepi.py b/tests/functional/arm/test_orangepi.py
new file mode 100755
index 0000000..f9bfa8c
--- /dev/null
+++ b/tests/functional/arm/test_orangepi.py
@@ -0,0 +1,237 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel on an Orange Pi machine
+# and checks the console
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+import shutil
+
+from qemu_test import LinuxKernelTest, exec_command_and_wait_for_pattern
+from qemu_test import Asset, interrupt_interactive_console_until_pattern
+from qemu_test import wait_for_console_pattern, skipBigDataTest
+from qemu_test.utils import image_pow2ceil_expand
+
+
+class OrangePiMachine(LinuxKernelTest):
+
+ ASSET_DEB = Asset(
+ ('https://apt.armbian.com/pool/main/l/linux-6.6.16/'
+ 'linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'),
+ '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22')
+
+ ASSET_INITRD = Asset(
+ ('https://github.com/groeck/linux-build-test/raw/'
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
+ 'arm/rootfs-armv7a.cpio.gz'),
+ '2c8dbdb16ea7af2dfbcbea96044dde639fb07d09fd3c4fb31f2027ef71e55ddd')
+
+ ASSET_ROOTFS = Asset(
+ ('http://storage.kernelci.org/images/rootfs/buildroot/'
+ 'buildroot-baseline/20230703.0/armel/rootfs.ext2.xz'),
+ '42b44a12965ac0afe9a88378527fb698a7dc76af50495efc2361ee1595b4e5c6')
+
+ ASSET_ARMBIAN = Asset(
+ ('https://k-space.ee.armbian.com/archive/orangepipc/archive/'
+ 'Armbian_23.8.1_Orangepipc_jammy_current_6.1.47.img.xz'),
+ 'b386dff6552513b5f164ea00f94814a6b0f1da9fb90b83725e949cf797e11afb')
+
+ ASSET_UBOOT = Asset(
+ ('http://snapshot.debian.org/archive/debian/20200108T145233Z/pool/'
+ 'main/u/u-boot/u-boot-sunxi_2020.01%2Bdfsg-1_armhf.deb'),
+ '9223d94dc283ab54df41ce9d6f69025a5b47fece29fb67a714e23aa0cdf3bdfa')
+
+ ASSET_NETBSD = Asset(
+ ('https://archive.netbsd.org/pub/NetBSD-archive/NetBSD-9.0/'
+ 'evbarm-earmv7hf/binary/gzimg/armv7.img.gz'),
+ '20d3e07dc057e15c12452620e90ecab2047f0f7940d9cba8182ebc795927177f')
+
+ def test_arm_orangepi(self):
+ self.set_machine('orangepi-pc')
+ kernel_path = self.archive_extract(
+ self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
+ dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' +
+ 'sun8i-h3-orangepi-pc.dtb')
+ dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
+
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyS0,115200n8 '
+ 'earlycon=uart,mmio32,0x1c28000')
+ self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line)
+ self.vm.launch()
+ console_pattern = 'Kernel command line: %s' % kernel_command_line
+ self.wait_for_console_pattern(console_pattern)
+ os.remove(kernel_path)
+ os.remove(dtb_path)
+
+ def test_arm_orangepi_initrd(self):
+ self.set_machine('orangepi-pc')
+ kernel_path = self.archive_extract(
+ self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
+ dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' +
+ 'sun8i-h3-orangepi-pc.dtb')
+ dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
+ initrd_path = self.uncompress(self.ASSET_INITRD)
+
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyS0,115200 '
+ 'panic=-1 noreboot')
+ self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-initrd', initrd_path,
+ '-append', kernel_command_line,
+ '-no-reboot')
+ self.vm.launch()
+ self.wait_for_console_pattern('Boot successful.')
+
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+ 'Allwinner sun8i Family')
+ exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
+ 'system-control@1c00000')
+ exec_command_and_wait_for_pattern(self, 'reboot',
+ 'reboot: Restarting system')
+ # Wait for VM to shut down gracefully
+ self.vm.wait()
+ os.remove(kernel_path)
+ os.remove(dtb_path)
+ os.remove(initrd_path)
+
+ def test_arm_orangepi_sd(self):
+ self.set_machine('orangepi-pc')
+ self.require_netdev('user')
+ kernel_path = self.archive_extract(
+ self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi')
+ dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' +
+ 'sun8i-h3-orangepi-pc.dtb')
+ dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
+ rootfs_path = self.uncompress(self.ASSET_ROOTFS)
+ image_pow2ceil_expand(rootfs_path)
+
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyS0,115200 '
+ 'root=/dev/mmcblk0 rootwait rw '
+ 'panic=-1 noreboot')
+ self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-drive', 'file=' + rootfs_path + ',if=sd,format=raw',
+ '-append', kernel_command_line,
+ '-no-reboot')
+ self.vm.launch()
+ shell_ready = "/bin/sh: can't access tty; job control turned off"
+ self.wait_for_console_pattern(shell_ready)
+
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+ 'Allwinner sun8i Family')
+ exec_command_and_wait_for_pattern(self, 'cat /proc/partitions',
+ 'mmcblk0')
+ exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up',
+ 'eth0: Link is Up')
+ exec_command_and_wait_for_pattern(self, 'udhcpc eth0',
+ 'udhcpc: lease of 10.0.2.15 obtained')
+ exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2',
+ '3 packets transmitted, 3 packets received, 0% packet loss')
+ exec_command_and_wait_for_pattern(self, 'reboot',
+ 'reboot: Restarting system')
+ # Wait for VM to shut down gracefully
+ self.vm.wait()
+ os.remove(kernel_path)
+ os.remove(dtb_path)
+ os.remove(rootfs_path)
+
+ @skipBigDataTest()
+ def test_arm_orangepi_armbian(self):
+ self.set_machine('orangepi-pc')
+ self.require_netdev('user')
+
+ # This test download a 275 MiB compressed image and expand it
+ # to 1036 MiB, but the underlying filesystem is 1552 MiB...
+ # As we expand it to 2 GiB we are safe.
+ image_path = self.uncompress(self.ASSET_ARMBIAN)
+ image_pow2ceil_expand(image_path)
+
+ self.vm.set_console()
+ self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
+ '-nic', 'user',
+ '-no-reboot')
+ self.vm.launch()
+
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyS0,115200 '
+ 'loglevel=7 '
+ 'nosmp '
+ 'systemd.default_timeout_start_sec=9000 '
+ 'systemd.mask=armbian-zram-config.service '
+ 'systemd.mask=armbian-ramlog.service')
+
+ self.wait_for_console_pattern('U-Boot SPL')
+ self.wait_for_console_pattern('Autoboot in ')
+ exec_command_and_wait_for_pattern(self, ' ', '=>')
+ exec_command_and_wait_for_pattern(self, "setenv extraargs '" +
+ kernel_command_line + "'", '=>')
+ exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...')
+
+ self.wait_for_console_pattern('systemd[1]: Hostname set ' +
+ 'to <orangepipc>')
+ self.wait_for_console_pattern('Starting Load Kernel Modules...')
+
+ @skipBigDataTest()
+ def test_arm_orangepi_uboot_netbsd9(self):
+ self.set_machine('orangepi-pc')
+ self.require_netdev('user')
+
+ # This test download a 304MB compressed image and expand it to 2GB
+ # We use the common OrangePi PC 'plus' build of U-Boot for our secondary
+ # program loader (SPL). We will then set the path to the more specific
+ # OrangePi "PC" device tree blob with 'setenv fdtfile' in U-Boot prompt,
+ # before to boot NetBSD.
+ uboot_path = 'usr/lib/u-boot/orangepi_plus/u-boot-sunxi-with-spl.bin'
+ uboot_path = self.archive_extract(self.ASSET_UBOOT, member=uboot_path)
+ image_path = self.uncompress(self.ASSET_NETBSD)
+ image_pow2ceil_expand(image_path)
+ image_drive_args = 'if=sd,format=raw,snapshot=on,file=' + image_path
+
+ # dd if=u-boot-sunxi-with-spl.bin of=armv7.img bs=1K seek=8 conv=notrunc
+ with open(uboot_path, 'rb') as f_in:
+ with open(image_path, 'r+b') as f_out:
+ f_out.seek(8 * 1024)
+ shutil.copyfileobj(f_in, f_out)
+
+ self.vm.set_console()
+ self.vm.add_args('-nic', 'user',
+ '-drive', image_drive_args,
+ '-global', 'allwinner-rtc.base-year=2000',
+ '-no-reboot')
+ self.vm.launch()
+ wait_for_console_pattern(self, 'U-Boot 2020.01+dfsg-1')
+ interrupt_interactive_console_until_pattern(self,
+ 'Hit any key to stop autoboot:',
+ 'switch to partitions #0, OK')
+
+ exec_command_and_wait_for_pattern(self, '', '=>')
+ cmd = 'setenv bootargs root=ld0a'
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
+ cmd = 'setenv kernel netbsd-GENERIC.ub'
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
+ cmd = 'setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb'
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
+ cmd = ("setenv bootcmd 'fatload mmc 0:1 ${kernel_addr_r} ${kernel}; "
+ "fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}; "
+ "fdt addr ${fdt_addr_r}; "
+ "bootm ${kernel_addr_r} - ${fdt_addr_r}'")
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
+
+ exec_command_and_wait_for_pattern(self, 'boot',
+ 'Booting kernel from Legacy Image')
+ wait_for_console_pattern(self, 'Starting kernel ...')
+ wait_for_console_pattern(self, 'NetBSD 9.0 (GENERIC)')
+ # Wait for user-space
+ wait_for_console_pattern(self, 'Starting root file system check')
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()
diff --git a/tests/functional/arm/test_quanta_gsj.py b/tests/functional/arm/test_quanta_gsj.py
new file mode 100755
index 0000000..cb0545f
--- /dev/null
+++ b/tests/functional/arm/test_quanta_gsj.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel and checks the console
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern
+from qemu_test import interrupt_interactive_console_until_pattern, skipSlowTest
+
+
+class EmcraftSf2Machine(LinuxKernelTest):
+
+ ASSET_IMAGE = Asset(
+ ('https://github.com/hskinnemoen/openbmc/releases/download/'
+ '20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz'),
+ 'eccd4e375cde53034c84aece5c511932cacf838d9fd3f63da368a511757da72b')
+
+ ASSET_INITRD = Asset(
+ ('https://github.com/hskinnemoen/openbmc/releases/download/'
+ '20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz'),
+ '37b05009fc54db1434beac12bd7ff99a2e751a2f032ee18d9042f991dd0cdeaa')
+
+ ASSET_KERNEL = Asset(
+ ('https://github.com/hskinnemoen/openbmc/releases/download/'
+ '20200711-gsj-qemu-0/uImage-gsj.bin'),
+ 'ce6d6b37bff46c74fc7b1e90da10a431cc37a62cdb35ec199fa73473d0790110')
+
+ ASSET_DTB = Asset(
+ ('https://github.com/hskinnemoen/openbmc/releases/download/'
+ '20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb'),
+ '3249b2da787d4b9ad4e61f315b160abfceb87b5e1895a7ce898ce7f40c8d4045')
+
+ @skipSlowTest()
+ def test_arm_quanta_gsj(self):
+ self.set_machine('quanta-gsj')
+ image_path = self.uncompress(self.ASSET_IMAGE, format='gz')
+
+ self.vm.set_console()
+ drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0'
+ self.vm.add_args('-drive', drive_args)
+ self.vm.launch()
+
+ # Disable drivers and services that stall for a long time during boot,
+ # to avoid running past the 90-second timeout. These may be removed
+ # as the corresponding device support is added.
+ kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + (
+ 'console=${console} '
+ 'mem=${mem} '
+ 'initcall_blacklist=npcm_i2c_bus_driver_init '
+ 'systemd.mask=systemd-random-seed.service '
+ 'systemd.mask=dropbearkey.service '
+ )
+
+ self.wait_for_console_pattern('> BootBlock by Nuvoton')
+ self.wait_for_console_pattern('>Device: Poleg BMC NPCM730')
+ self.wait_for_console_pattern('>Skip DDR init.')
+ self.wait_for_console_pattern('U-Boot ')
+ interrupt_interactive_console_until_pattern(
+ self, 'Hit any key to stop autoboot:', 'U-Boot>')
+ exec_command_and_wait_for_pattern(
+ self, "setenv bootargs ${bootargs} " + kernel_command_line,
+ 'U-Boot>')
+ exec_command_and_wait_for_pattern(
+ self, 'run romboot', 'Booting Kernel from flash')
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
+ self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
+ self.wait_for_console_pattern('OpenBMC Project Reference Distro')
+ self.wait_for_console_pattern('gsj login:')
+
+ def test_arm_quanta_gsj_initrd(self):
+ self.set_machine('quanta-gsj')
+ initrd_path = self.ASSET_INITRD.fetch()
+ kernel_path = self.ASSET_KERNEL.fetch()
+ dtb_path = self.ASSET_DTB.fetch()
+
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyS0,115200n8 '
+ 'earlycon=uart8250,mmio32,0xf0001000')
+ self.vm.add_args('-kernel', kernel_path,
+ '-initrd', initrd_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line)
+ self.vm.launch()
+
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
+ self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
+ self.wait_for_console_pattern(
+ 'Give root password for system maintenance')
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()
diff --git a/tests/functional/arm/test_raspi2.py b/tests/functional/arm/test_raspi2.py
new file mode 100755
index 0000000..d3c7aaa
--- /dev/null
+++ b/tests/functional/arm/test_raspi2.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel on a Raspberry Pi machine
+# and checks the console
+#
+# Copyright (c) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import LinuxKernelTest, Asset
+from qemu_test import exec_command_and_wait_for_pattern
+
+
+class ArmRaspi2Machine(LinuxKernelTest):
+
+ ASSET_KERNEL_20190215 = Asset(
+ ('http://archive.raspberrypi.org/debian/'
+ 'pool/main/r/raspberrypi-firmware/'
+ 'raspberrypi-kernel_1.20190215-1_armhf.deb'),
+ '9f1759f7228113da24f5ee2aa6312946ec09a83e076aba9406c46ff776dfb291')
+
+ ASSET_INITRD = Asset(
+ ('https://github.com/groeck/linux-build-test/raw/'
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
+ 'arm/rootfs-armv7a.cpio.gz'),
+ '2c8dbdb16ea7af2dfbcbea96044dde639fb07d09fd3c4fb31f2027ef71e55ddd')
+
+ def do_test_arm_raspi2(self, uart_id):
+ """
+ The kernel can be rebuilt using the kernel source referenced
+ and following the instructions on the on:
+ https://www.raspberrypi.org/documentation/linux/kernel/building.md
+ """
+ serial_kernel_cmdline = {
+ 0: 'earlycon=pl011,0x3f201000 console=ttyAMA0',
+ }
+ kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215,
+ member='boot/kernel7.img')
+ dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215,
+ member='boot/bcm2709-rpi-2-b.dtb')
+
+ self.set_machine('raspi2b')
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ serial_kernel_cmdline[uart_id] +
+ ' root=/dev/mmcblk0p2 rootwait ' +
+ 'dwc_otg.fiq_fsm_enable=0')
+ self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line,
+ '-device', 'usb-kbd')
+ self.vm.launch()
+
+ console_pattern = 'Kernel command line: %s' % kernel_command_line
+ self.wait_for_console_pattern(console_pattern)
+ self.wait_for_console_pattern('Product: QEMU USB Keyboard')
+
+ def test_arm_raspi2_uart0(self):
+ self.do_test_arm_raspi2(0)
+
+ def test_arm_raspi2_initrd(self):
+ kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215,
+ member='boot/kernel7.img')
+ dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215,
+ member='boot/bcm2709-rpi-2-b.dtb')
+ initrd_path = self.uncompress(self.ASSET_INITRD)
+
+ self.set_machine('raspi2b')
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'earlycon=pl011,0x3f201000 console=ttyAMA0 '
+ 'panic=-1 noreboot ' +
+ 'dwc_otg.fiq_fsm_enable=0')
+ self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-initrd', initrd_path,
+ '-append', kernel_command_line,
+ '-no-reboot')
+ self.vm.launch()
+ self.wait_for_console_pattern('Boot successful.')
+
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+ 'BCM2835')
+ exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
+ '/soc/cprman@7e101000')
+ exec_command_and_wait_for_pattern(self, 'halt', 'reboot: System halted')
+ # Wait for VM to shut down gracefully
+ self.vm.wait()
+
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()
diff --git a/tests/functional/arm/test_realview.py b/tests/functional/arm/test_realview.py
new file mode 100755
index 0000000..82cc964
--- /dev/null
+++ b/tests/functional/arm/test_realview.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel on a realview arm machine
+# and checks the console
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import LinuxKernelTest, exec_command_and_wait_for_pattern
+from qemu_test import Asset
+
+
+class RealviewMachine(LinuxKernelTest):
+
+ ASSET_REALVIEW_MPCORE = Asset(
+ ('https://archive.openwrt.org/chaos_calmer/15.05.1/realview/generic/'
+ 'openwrt-15.05.1-realview-vmlinux-initramfs.elf'),
+ 'd3a01037f33e7512d46d50975588d5c3a0e0cbf25f37afab44775c2a2be523e6')
+
+ def test_realview_ep_mpcore(self):
+ self.require_netdev('user')
+ self.set_machine('realview-eb-mpcore')
+ kernel_path = self.ASSET_REALVIEW_MPCORE.fetch()
+ self.vm.set_console()
+ kernel_param = 'console=ttyAMA0 mem=128M quiet'
+ self.vm.add_args('-kernel', kernel_path,
+ '-append', kernel_param)
+ self.vm.launch()
+ self.wait_for_console_pattern('Please press Enter to activate')
+ prompt = ':/#'
+ exec_command_and_wait_for_pattern(self, '', prompt)
+ exec_command_and_wait_for_pattern(self, 'dmesg', kernel_param)
+ self.wait_for_console_pattern(prompt)
+ exec_command_and_wait_for_pattern(self,
+ ('while ! dmesg | grep "br-lan: port 1(eth0) entered" ;'
+ ' do sleep 1 ; done'),
+ 'entered forwarding state')
+ self.wait_for_console_pattern(prompt)
+ exec_command_and_wait_for_pattern(self,
+ 'while ! ifconfig | grep "10.0.2.15" ; do sleep 1 ; done',
+ 'addr:10.0.2.15')
+ self.wait_for_console_pattern(prompt)
+ exec_command_and_wait_for_pattern(self, 'ping -c 1 10.0.2.2',
+ '1 packets received, 0% packet loss')
+
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()
diff --git a/tests/functional/arm/test_replay.py b/tests/functional/arm/test_replay.py
new file mode 100755
index 0000000..e002e6a
--- /dev/null
+++ b/tests/functional/arm/test_replay.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+#
+# Replay test that boots a Linux kernel on arm machines and checks the console
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import Asset
+from replay_kernel import ReplayKernelBase
+
+
+class ArmReplay(ReplayKernelBase):
+
+ ASSET_VIRT = Asset(
+ ('https://archives.fedoraproject.org/pub/archive/fedora/linux/'
+ 'releases/29/Everything/armhfp/os/images/pxeboot/vmlinuz'),
+ '18dd5f1a9a28bd539f9d047f7c0677211bae528e8712b40ca5a229a4ad8e2591')
+
+ def test_virt(self):
+ self.set_machine('virt')
+ kernel_path = self.ASSET_VIRT.fetch()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyAMA0')
+ console_pattern = 'VFS: Cannot open root device'
+ self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1)
+
+ ASSET_CUBIE_KERNEL = Asset(
+ ('https://apt.armbian.com/pool/main/l/linux-6.6.16/'
+ 'linux-image-current-sunxi_24.2.1_armhf_'
+ '_6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'),
+ '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22')
+
+ ASSET_CUBIE_INITRD = Asset(
+ ('https://github.com/groeck/linux-build-test/raw/'
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/arm/rootfs-armv5.cpio.gz'),
+ '334b8d256db67a3f2b3ad070aa08b5ade39624e0e7e35b02f4359a577bc8f39b')
+
+ def test_cubieboard(self):
+ self.set_machine('cubieboard')
+ kernel_path = self.archive_extract(self.ASSET_CUBIE_KERNEL,
+ member='boot/vmlinuz-6.6.16-current-sunxi')
+ dtb_path = self.archive_extract(self.ASSET_CUBIE_KERNEL,
+ member='usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb')
+ initrd_path = self.uncompress(self.ASSET_CUBIE_INITRD)
+
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyS0,115200 '
+ 'usbcore.nousb '
+ 'panic=-1 noreboot')
+ console_pattern = 'Boot successful.'
+ self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1,
+ args=('-dtb', dtb_path,
+ '-initrd', initrd_path,
+ '-no-reboot'))
+
+ ASSET_DAY16 = Asset(
+ 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day16.tar.xz',
+ '63311adb2d4c4e7a73214a86d29988add87266a909719c56acfadd026b4110a7')
+
+ def test_vexpressa9(self):
+ self.set_machine('vexpress-a9')
+ self.archive_extract(self.ASSET_DAY16)
+ kernel_path = self.scratch_file('day16', 'winter.zImage')
+ dtb_path = self.scratch_file('day16', 'vexpress-v2p-ca9.dtb')
+ self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE,
+ 'QEMU advent calendar', args=('-dtb', dtb_path))
+
+
+if __name__ == '__main__':
+ ReplayKernelBase.main()
diff --git a/tests/functional/arm/test_smdkc210.py b/tests/functional/arm/test_smdkc210.py
new file mode 100755
index 0000000..3154e7f
--- /dev/null
+++ b/tests/functional/arm/test_smdkc210.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel and checks the console
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import LinuxKernelTest, Asset
+
+
+class Smdkc210Machine(LinuxKernelTest):
+
+ ASSET_DEB = Asset(
+ ('https://snapshot.debian.org/archive/debian/20190928T224601Z/pool/'
+ 'main/l/linux/linux-image-4.19.0-6-armmp_4.19.67-2+deb10u1_armhf.deb'),
+ '421804e7579ef40d554c962850dbdf1bfc79f7fa7faec9d391397170dc806c3e')
+
+ ASSET_ROOTFS = Asset(
+ ('https://github.com/groeck/linux-build-test/raw/'
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/arm/'
+ 'rootfs-armv5.cpio.gz'),
+ '334b8d256db67a3f2b3ad070aa08b5ade39624e0e7e35b02f4359a577bc8f39b')
+
+ def test_arm_exynos4210_initrd(self):
+ self.set_machine('smdkc210')
+
+ kernel_path = self.archive_extract(self.ASSET_DEB,
+ member='boot/vmlinuz-4.19.0-6-armmp')
+ dtb_path = 'usr/lib/linux-image-4.19.0-6-armmp/exynos4210-smdkv310.dtb'
+ dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path)
+
+ initrd_path = self.uncompress(self.ASSET_ROOTFS)
+
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'earlycon=exynos4210,0x13800000 earlyprintk ' +
+ 'console=ttySAC0,115200n8 ' +
+ 'random.trust_cpu=off cryptomgr.notests ' +
+ 'cpuidle.off=1 panic=-1 noreboot')
+
+ self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-initrd', initrd_path,
+ '-append', kernel_command_line,
+ '-no-reboot')
+ self.vm.launch()
+
+ self.wait_for_console_pattern('Boot successful.')
+ # TODO user command, for now the uart is stuck
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()
diff --git a/tests/functional/arm/test_stellaris.py b/tests/functional/arm/test_stellaris.py
new file mode 100755
index 0000000..cbd21cb
--- /dev/null
+++ b/tests/functional/arm/test_stellaris.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+#
+# Functional test that checks the serial console of the stellaris machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern
+from qemu_test import wait_for_console_pattern
+
+
+class StellarisMachine(QemuSystemTest):
+
+ ASSET_DAY22 = Asset(
+ 'https://www.qemu-advent-calendar.org/2023/download/day22.tar.gz',
+ 'ae3a63ef4b7a22c21bfc7fc0d85e402fe95e223308ed23ac854405016431ff51')
+
+ def test_lm3s6965evb(self):
+ self.set_machine('lm3s6965evb')
+ kernel_path = self.archive_extract(self.ASSET_DAY22,
+ member='day22/day22.bin')
+ self.vm.set_console()
+ self.vm.add_args('-kernel', kernel_path)
+ self.vm.launch()
+
+ wait_for_console_pattern(self, 'In a one horse open')
+
+ ASSET_NOTMAIN = Asset(
+ 'https://github.com/Ahelion/QemuArmM4FDemoSw/raw/master/build/notmain.bin',
+ '6ceda031aa081a420fca2fca9e137fa681d6e3820d820ad1917736cb265e611a')
+
+ def test_lm3s811evb(self):
+ self.set_machine('lm3s811evb')
+ kernel_path = self.ASSET_NOTMAIN.fetch()
+
+ self.vm.set_console()
+ self.vm.add_args('-cpu', 'cortex-m4')
+ self.vm.add_args('-kernel', kernel_path)
+ self.vm.launch()
+
+ # The test kernel emits an initial '!' and then waits for input.
+ # For each character that we send it responds with a certain
+ # other ASCII character.
+ wait_for_console_pattern(self, '!')
+ exec_command_and_wait_for_pattern(self, '789', 'cdf')
+
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
diff --git a/tests/functional/arm/test_sx1.py b/tests/functional/arm/test_sx1.py
new file mode 100755
index 0000000..25800b3
--- /dev/null
+++ b/tests/functional/arm/test_sx1.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2024 Linaro Ltd.
+#
+# Functional test that boots a Linux kernel on an sx1 machine
+# and checks the console. We have three variants:
+# * just boot initrd
+# * boot with filesystem on SD card
+# * boot from flash
+# In all cases these images have a userspace that is configured
+# to immediately reboot the system on successful boot, so we
+# only need to wait for QEMU to exit (via -no-reboot).
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import LinuxKernelTest, Asset
+
+
+class SX1Test(LinuxKernelTest):
+
+ ASSET_ZIMAGE = Asset(
+ 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/sx1/zImage',
+ 'a0271899a8dc2165f9e0adb2d0a57fc839ae3a469722ffc56c77e108a8887615')
+
+ ASSET_INITRD = Asset(
+ 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/sx1/rootfs-armv4.cpio',
+ '35b0721249821aa544cd85b85d3cb8901db4c6d128eed86ab261e5d9e37d58f8')
+
+ ASSET_SD_FS = Asset(
+ 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/sx1/rootfs-armv4.ext2',
+ 'c1db7f43ef92469ebc8605013728c8950e7608439f01d13678994f0ce101c3a8')
+
+ ASSET_FLASH = Asset(
+ 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/sx1/flash',
+ '17e6a2758fa38efd2666be0879d4751fd37d194f25168a8deede420df519b676')
+
+ CONSOLE_ARGS = 'console=ttyS0,115200 earlycon=uart8250,mmio32,0xfffb0000,115200n8'
+
+ def test_arm_sx1_initrd(self):
+ self.set_machine('sx1')
+ zimage_path = self.ASSET_ZIMAGE.fetch()
+ initrd_path = self.ASSET_INITRD.fetch()
+ self.vm.add_args('-append', f'kunit.enable=0 rdinit=/sbin/init {self.CONSOLE_ARGS}')
+ self.vm.add_args('-no-reboot')
+ self.launch_kernel(zimage_path,
+ initrd=initrd_path,
+ wait_for='Boot successful')
+ self.vm.wait(timeout=120)
+
+ def test_arm_sx1_sd(self):
+ self.set_machine('sx1')
+ zimage_path = self.ASSET_ZIMAGE.fetch()
+ sd_fs_path = self.ASSET_SD_FS.fetch()
+ self.vm.add_args('-append', f'kunit.enable=0 root=/dev/mmcblk0 rootwait {self.CONSOLE_ARGS}')
+ self.vm.add_args('-no-reboot')
+ self.vm.add_args('-snapshot')
+ self.vm.add_args('-drive', f'format=raw,if=sd,file={sd_fs_path}')
+ self.launch_kernel(zimage_path, wait_for='Boot successful')
+ self.vm.wait(timeout=120)
+
+ def test_arm_sx1_flash(self):
+ self.set_machine('sx1')
+ zimage_path = self.ASSET_ZIMAGE.fetch()
+ flash_path = self.ASSET_FLASH.fetch()
+ self.vm.add_args('-append', f'kunit.enable=0 root=/dev/mtdblock3 rootwait {self.CONSOLE_ARGS}')
+ self.vm.add_args('-no-reboot')
+ self.vm.add_args('-snapshot')
+ self.vm.add_args('-drive', f'format=raw,if=pflash,file={flash_path}')
+ self.launch_kernel(zimage_path, wait_for='Boot successful')
+ self.vm.wait(timeout=120)
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()
diff --git a/tests/functional/arm/test_tuxrun.py b/tests/functional/arm/test_tuxrun.py
new file mode 100755
index 0000000..4ac85f4
--- /dev/null
+++ b/tests/functional/arm/test_tuxrun.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots known good tuxboot images the same way
+# that tuxrun (www.tuxrun.org) does. This tool is used by things like
+# the LKFT project to run regression tests on kernels.
+#
+# Copyright (c) 2023 Linaro Ltd.
+#
+# Author:
+# Alex Bennée <alex.bennee@linaro.org>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import Asset
+from qemu_test.tuxruntest import TuxRunBaselineTest
+
+class TuxRunArmTest(TuxRunBaselineTest):
+
+ ASSET_ARMV5_KERNEL = Asset(
+ 'https://storage.tuxboot.com/buildroot/20241119/armv5/zImage',
+ '3931a3908dbcf0ec0fe292d035ffc4dfed95f797dedd4a59ccfcf7a46e6f92d4')
+ ASSET_ARMV5_ROOTFS = Asset(
+ 'https://storage.tuxboot.com/buildroot/20241119/armv5/rootfs.ext4.zst',
+ '60ff78b68c7021df378e4fc2d66d3b016484d1acc7e07fb8920c1d8e30f4571f')
+ ASSET_ARMV5_DTB = Asset(
+ 'https://storage.tuxboot.com/buildroot/20241119/armv5/versatile-pb.dtb',
+ '50988e69ef3f3b08bfb9146e8fe414129990029e8dfbed444953b7e14809530a')
+
+ def test_armv5(self):
+ self.set_machine('versatilepb')
+ self.cpu='arm926'
+ self.console='ttyAMA0'
+ self.wait_for_shutdown=False
+ self.common_tuxrun(kernel_asset=self.ASSET_ARMV5_KERNEL,
+ rootfs_asset=self.ASSET_ARMV5_ROOTFS,
+ dtb_asset=self.ASSET_ARMV5_DTB,
+ drive="virtio-blk-pci")
+
+ ASSET_ARMV7_KERNEL = Asset(
+ 'https://storage.tuxboot.com/buildroot/20241119/armv7/zImage',
+ '1377bc3d90de5ce57ab17cd67429fe8b15c2e9964248c775c682b67e6299b991')
+ ASSET_ARMV7_ROOTFS = Asset(
+ 'https://storage.tuxboot.com/buildroot/20241119/armv7/rootfs.ext4.zst',
+ 'ed2cbc69bd6b3fbd5cafb5ee961393c7cfbe726446f14301c67d6b1f28bfdb51')
+
+ def test_armv7(self):
+ self.set_machine('virt')
+ self.cpu='cortex-a15'
+ self.console='ttyAMA0'
+ self.wait_for_shutdown=False
+ self.common_tuxrun(kernel_asset=self.ASSET_ARMV7_KERNEL,
+ rootfs_asset=self.ASSET_ARMV7_ROOTFS)
+
+ ASSET_ARMV7BE_KERNEL = Asset(
+ 'https://storage.tuxboot.com/buildroot/20241119/armv7be/zImage',
+ 'a244e6da99f1bbd254827ec7681bd4aac9eb1aa05aaebc6b15e5d289ebb683f3')
+ ASSET_ARMV7BE_ROOTFS = Asset(
+ 'https://storage.tuxboot.com/buildroot/20241119/armv7be/rootfs.ext4.zst',
+ 'd4f9c57860a512163f30ecc69b2174d1a1bdeb853a43dc49a09cfcfe84e428ea')
+
+ def test_armv7be(self):
+ self.set_machine('virt')
+ self.cpu='cortex-a15'
+ self.console='ttyAMA0'
+ self.wait_for_shutdown=False
+ self.common_tuxrun(kernel_asset=self.ASSET_ARMV7BE_KERNEL,
+ rootfs_asset=self.ASSET_ARMV7BE_ROOTFS)
+
+if __name__ == '__main__':
+ TuxRunBaselineTest.main()
diff --git a/tests/functional/arm/test_vexpress.py b/tests/functional/arm/test_vexpress.py
new file mode 100755
index 0000000..6b11552
--- /dev/null
+++ b/tests/functional/arm/test_vexpress.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel on an versatile express machine
+# and checks the console
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import LinuxKernelTest, Asset
+
+
+class VExpressTest(LinuxKernelTest):
+
+ ASSET_DAY16 = Asset(
+ 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day16.tar.xz',
+ '63311adb2d4c4e7a73214a86d29988add87266a909719c56acfadd026b4110a7')
+
+ def test_arm_vexpressa9(self):
+ self.set_machine('vexpress-a9')
+ self.archive_extract(self.ASSET_DAY16)
+ self.launch_kernel(self.scratch_file('day16', 'winter.zImage'),
+ dtb=self.scratch_file('day16',
+ 'vexpress-v2p-ca9.dtb'),
+ wait_for='QEMU advent calendar')
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()
diff --git a/tests/functional/arm/test_virt.py b/tests/functional/arm/test_virt.py
new file mode 100755
index 0000000..7b65491
--- /dev/null
+++ b/tests/functional/arm/test_virt.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots a Linux kernel and checks the console
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import LinuxKernelTest, Asset
+
+class ArmVirtMachine(LinuxKernelTest):
+
+ ASSET_KERNEL = Asset(
+ ('https://archives.fedoraproject.org/pub/archive/fedora/linux/'
+ 'releases/29/Everything/armhfp/os/images/pxeboot/vmlinuz'),
+ '18dd5f1a9a28bd539f9d047f7c0677211bae528e8712b40ca5a229a4ad8e2591')
+
+ def test_arm_virt(self):
+ self.set_machine('virt')
+ kernel_path = self.ASSET_KERNEL.fetch()
+
+ self.vm.set_console()
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+ 'console=ttyAMA0')
+ self.vm.add_args('-kernel', kernel_path,
+ '-append', kernel_command_line)
+ self.vm.launch()
+ console_pattern = 'Kernel command line: %s' % kernel_command_line
+ self.wait_for_console_pattern(console_pattern)
+
+if __name__ == '__main__':
+ LinuxKernelTest.main()