1*547738beSPhilippe Mathieu-Daudé#!/usr/bin/env python3
2*547738beSPhilippe Mathieu-Daudé#
3*547738beSPhilippe Mathieu-Daudé# Functional test that boots a Linux kernel on a Raspberry Pi machine
4*547738beSPhilippe Mathieu-Daudé# and checks the console
5*547738beSPhilippe Mathieu-Daudé#
6*547738beSPhilippe Mathieu-Daudé# SPDX-License-Identifier: GPL-2.0-or-later
7*547738beSPhilippe Mathieu-Daudé
8*547738beSPhilippe Mathieu-Daudéimport os
9*547738beSPhilippe Mathieu-Daudé
10*547738beSPhilippe Mathieu-Daudéfrom qemu_test import LinuxKernelTest, Asset
11*547738beSPhilippe Mathieu-Daudéfrom qemu_test import exec_command_and_wait_for_pattern
12*547738beSPhilippe Mathieu-Daudéfrom qemu_test.utils import gzip_uncompress
13*547738beSPhilippe Mathieu-Daudé
14*547738beSPhilippe Mathieu-Daudé
15*547738beSPhilippe Mathieu-Daudéclass Aarch64Raspi4Machine(LinuxKernelTest):
16*547738beSPhilippe Mathieu-Daudé
17*547738beSPhilippe Mathieu-Daudé    """
18*547738beSPhilippe Mathieu-Daudé    The kernel can be rebuilt using the kernel source referenced
19*547738beSPhilippe Mathieu-Daudé    and following the instructions on the on:
20*547738beSPhilippe Mathieu-Daudé    https://www.raspberrypi.org/documentation/linux/kernel/building.md
21*547738beSPhilippe Mathieu-Daudé    """
22*547738beSPhilippe Mathieu-Daudé    ASSET_KERNEL_20190215 = Asset(
23*547738beSPhilippe Mathieu-Daudé        ('http://archive.raspberrypi.org/debian/'
24*547738beSPhilippe Mathieu-Daudé         'pool/main/r/raspberrypi-firmware/'
25*547738beSPhilippe Mathieu-Daudé         'raspberrypi-kernel_1.20230106-1_arm64.deb'),
26*547738beSPhilippe Mathieu-Daudé        '56d5713c8f6eee8a0d3f0e73600ec11391144fef318b08943e9abd94c0a9baf7')
27*547738beSPhilippe Mathieu-Daudé
28*547738beSPhilippe Mathieu-Daudé    ASSET_INITRD = Asset(
29*547738beSPhilippe Mathieu-Daudé        ('https://github.com/groeck/linux-build-test/raw/'
30*547738beSPhilippe Mathieu-Daudé         '86b2be1384d41c8c388e63078a847f1e1c4cb1de/rootfs/'
31*547738beSPhilippe Mathieu-Daudé         'arm64/rootfs.cpio.gz'),
32*547738beSPhilippe Mathieu-Daudé        '7c0b16d1853772f6f4c3ca63e789b3b9ff4936efac9c8a01fb0c98c05c7a7648')
33*547738beSPhilippe Mathieu-Daudé
34*547738beSPhilippe Mathieu-Daudé    def test_arm_raspi4(self):
35*547738beSPhilippe Mathieu-Daudé        deb_path = self.ASSET_KERNEL_20190215.fetch()
36*547738beSPhilippe Mathieu-Daudé        kernel_path = self.extract_from_deb(deb_path, '/boot/kernel8.img')
37*547738beSPhilippe Mathieu-Daudé        dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2711-rpi-4-b.dtb')
38*547738beSPhilippe Mathieu-Daudé
39*547738beSPhilippe Mathieu-Daudé        self.set_machine('raspi4b')
40*547738beSPhilippe Mathieu-Daudé        self.vm.set_console()
41*547738beSPhilippe Mathieu-Daudé        kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
42*547738beSPhilippe Mathieu-Daudé                               'earlycon=pl011,mmio32,0xfe201000 ' +
43*547738beSPhilippe Mathieu-Daudé                               'console=ttyAMA0,115200 ' +
44*547738beSPhilippe Mathieu-Daudé                               'root=/dev/mmcblk1p2 rootwait ' +
45*547738beSPhilippe Mathieu-Daudé                               'dwc_otg.fiq_fsm_enable=0')
46*547738beSPhilippe Mathieu-Daudé        self.vm.add_args('-kernel', kernel_path,
47*547738beSPhilippe Mathieu-Daudé                         '-dtb', dtb_path,
48*547738beSPhilippe Mathieu-Daudé                         '-append', kernel_command_line)
49*547738beSPhilippe Mathieu-Daudé        # When PCI is supported we can add a USB controller:
50*547738beSPhilippe Mathieu-Daudé        #                '-device', 'qemu-xhci,bus=pcie.1,id=xhci',
51*547738beSPhilippe Mathieu-Daudé        #                '-device', 'usb-kbd,bus=xhci.0',
52*547738beSPhilippe Mathieu-Daudé        self.vm.launch()
53*547738beSPhilippe Mathieu-Daudé        console_pattern = 'Kernel command line: %s' % kernel_command_line
54*547738beSPhilippe Mathieu-Daudé        self.wait_for_console_pattern(console_pattern)
55*547738beSPhilippe Mathieu-Daudé        # When USB is enabled we can look for this
56*547738beSPhilippe Mathieu-Daudé        # console_pattern = 'Product: QEMU USB Keyboard'
57*547738beSPhilippe Mathieu-Daudé        # self.wait_for_console_pattern(console_pattern)
58*547738beSPhilippe Mathieu-Daudé        console_pattern = 'Waiting for root device'
59*547738beSPhilippe Mathieu-Daudé        self.wait_for_console_pattern(console_pattern)
60*547738beSPhilippe Mathieu-Daudé
61*547738beSPhilippe Mathieu-Daudé
62*547738beSPhilippe Mathieu-Daudé    def test_arm_raspi4_initrd(self):
63*547738beSPhilippe Mathieu-Daudé        deb_path = self.ASSET_KERNEL_20190215.fetch()
64*547738beSPhilippe Mathieu-Daudé        kernel_path = self.extract_from_deb(deb_path, '/boot/kernel8.img')
65*547738beSPhilippe Mathieu-Daudé        dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2711-rpi-4-b.dtb')
66*547738beSPhilippe Mathieu-Daudé        initrd_path_gz = self.ASSET_INITRD.fetch()
67*547738beSPhilippe Mathieu-Daudé        initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
68*547738beSPhilippe Mathieu-Daudé        gzip_uncompress(initrd_path_gz, initrd_path)
69*547738beSPhilippe Mathieu-Daudé
70*547738beSPhilippe Mathieu-Daudé        self.set_machine('raspi4b')
71*547738beSPhilippe Mathieu-Daudé        self.vm.set_console()
72*547738beSPhilippe Mathieu-Daudé        kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
73*547738beSPhilippe Mathieu-Daudé                               'earlycon=pl011,mmio32,0xfe201000 ' +
74*547738beSPhilippe Mathieu-Daudé                               'console=ttyAMA0,115200 ' +
75*547738beSPhilippe Mathieu-Daudé                               'panic=-1 noreboot ' +
76*547738beSPhilippe Mathieu-Daudé                               'dwc_otg.fiq_fsm_enable=0')
77*547738beSPhilippe Mathieu-Daudé        self.vm.add_args('-kernel', kernel_path,
78*547738beSPhilippe Mathieu-Daudé                         '-dtb', dtb_path,
79*547738beSPhilippe Mathieu-Daudé                         '-initrd', initrd_path,
80*547738beSPhilippe Mathieu-Daudé                         '-append', kernel_command_line,
81*547738beSPhilippe Mathieu-Daudé                         '-no-reboot')
82*547738beSPhilippe Mathieu-Daudé        # When PCI is supported we can add a USB controller:
83*547738beSPhilippe Mathieu-Daudé        #                '-device', 'qemu-xhci,bus=pcie.1,id=xhci',
84*547738beSPhilippe Mathieu-Daudé        #                '-device', 'usb-kbd,bus=xhci.0',
85*547738beSPhilippe Mathieu-Daudé        self.vm.launch()
86*547738beSPhilippe Mathieu-Daudé        self.wait_for_console_pattern('Boot successful.')
87*547738beSPhilippe Mathieu-Daudé
88*547738beSPhilippe Mathieu-Daudé        exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
89*547738beSPhilippe Mathieu-Daudé                                                'BCM2835')
90*547738beSPhilippe Mathieu-Daudé        exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
91*547738beSPhilippe Mathieu-Daudé                                                'cprman@7e101000')
92*547738beSPhilippe Mathieu-Daudé        exec_command_and_wait_for_pattern(self, 'halt', 'reboot: System halted')
93*547738beSPhilippe Mathieu-Daudé        # TODO: Raspberry Pi4 doesn't shut down properly with recent kernels
94*547738beSPhilippe Mathieu-Daudé        # Wait for VM to shut down gracefully
95*547738beSPhilippe Mathieu-Daudé        #self.vm.wait()
96*547738beSPhilippe Mathieu-Daudé
97*547738beSPhilippe Mathieu-Daudé
98*547738beSPhilippe Mathieu-Daudéif __name__ == '__main__':
99*547738beSPhilippe Mathieu-Daudé    LinuxKernelTest.main()
100