1*f7d6b772SThomas Huth#!/usr/bin/env python3 2*f7d6b772SThomas Huth# 3*f7d6b772SThomas Huth# Functional test that boots a Linux kernel on a Banana Pi machine 4*f7d6b772SThomas Huth# and checks the console 5*f7d6b772SThomas Huth# 6*f7d6b772SThomas Huth# SPDX-License-Identifier: GPL-2.0-or-later 7*f7d6b772SThomas Huth 8*f7d6b772SThomas Huthimport os 9*f7d6b772SThomas Huth 10*f7d6b772SThomas Huthfrom qemu_test import LinuxKernelTest, exec_command_and_wait_for_pattern 11*f7d6b772SThomas Huthfrom qemu_test import Asset, interrupt_interactive_console_until_pattern 12*f7d6b772SThomas Huthfrom qemu_test.utils import archive_extract, gzip_uncompress, lzma_uncompress 13*f7d6b772SThomas Huthfrom qemu_test.utils import image_pow2ceil_expand 14*f7d6b772SThomas Huthfrom unittest import skipUnless 15*f7d6b772SThomas Huth 16*f7d6b772SThomas Huthclass BananaPiMachine(LinuxKernelTest): 17*f7d6b772SThomas Huth 18*f7d6b772SThomas Huth ASSET_DEB = Asset( 19*f7d6b772SThomas Huth ('https://apt.armbian.com/pool/main/l/linux-6.6.16/' 20*f7d6b772SThomas Huth 'linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'), 21*f7d6b772SThomas Huth '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22') 22*f7d6b772SThomas Huth 23*f7d6b772SThomas Huth ASSET_INITRD = Asset( 24*f7d6b772SThomas Huth ('https://github.com/groeck/linux-build-test/raw/' 25*f7d6b772SThomas Huth '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' 26*f7d6b772SThomas Huth 'arm/rootfs-armv7a.cpio.gz'), 27*f7d6b772SThomas Huth '2c8dbdb16ea7af2dfbcbea96044dde639fb07d09fd3c4fb31f2027ef71e55ddd') 28*f7d6b772SThomas Huth 29*f7d6b772SThomas Huth ASSET_ROOTFS = Asset( 30*f7d6b772SThomas Huth ('http://storage.kernelci.org/images/rootfs/buildroot/' 31*f7d6b772SThomas Huth 'buildroot-baseline/20230703.0/armel/rootfs.ext2.xz'), 32*f7d6b772SThomas Huth '42b44a12965ac0afe9a88378527fb698a7dc76af50495efc2361ee1595b4e5c6') 33*f7d6b772SThomas Huth 34*f7d6b772SThomas Huth ASSET_SD_IMAGE = Asset( 35*f7d6b772SThomas Huth ('https://downloads.openwrt.org/releases/22.03.3/targets/sunxi/cortexa7/' 36*f7d6b772SThomas Huth 'openwrt-22.03.3-sunxi-cortexa7-sinovoip_bananapi-m2-ultra-ext4-sdcard.img.gz'), 37*f7d6b772SThomas Huth '5b41b4e11423e562c6011640f9a7cd3bdd0a3d42b83430f7caa70a432e6cd82c') 38*f7d6b772SThomas Huth 39*f7d6b772SThomas Huth def test_arm_bpim2u(self): 40*f7d6b772SThomas Huth self.set_machine('bpim2u') 41*f7d6b772SThomas Huth deb_path = self.ASSET_DEB.fetch() 42*f7d6b772SThomas Huth kernel_path = self.extract_from_deb(deb_path, 43*f7d6b772SThomas Huth '/boot/vmlinuz-6.6.16-current-sunxi') 44*f7d6b772SThomas Huth dtb_path = ('/usr/lib/linux-image-6.6.16-current-sunxi/' 45*f7d6b772SThomas Huth 'sun8i-r40-bananapi-m2-ultra.dtb') 46*f7d6b772SThomas Huth dtb_path = self.extract_from_deb(deb_path, dtb_path) 47*f7d6b772SThomas Huth 48*f7d6b772SThomas Huth self.vm.set_console() 49*f7d6b772SThomas Huth kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 50*f7d6b772SThomas Huth 'console=ttyS0,115200n8 ' 51*f7d6b772SThomas Huth 'earlycon=uart,mmio32,0x1c28000') 52*f7d6b772SThomas Huth self.vm.add_args('-kernel', kernel_path, 53*f7d6b772SThomas Huth '-dtb', dtb_path, 54*f7d6b772SThomas Huth '-append', kernel_command_line) 55*f7d6b772SThomas Huth self.vm.launch() 56*f7d6b772SThomas Huth console_pattern = 'Kernel command line: %s' % kernel_command_line 57*f7d6b772SThomas Huth self.wait_for_console_pattern(console_pattern) 58*f7d6b772SThomas Huth os.remove(kernel_path) 59*f7d6b772SThomas Huth os.remove(dtb_path) 60*f7d6b772SThomas Huth 61*f7d6b772SThomas Huth def test_arm_bpim2u_initrd(self): 62*f7d6b772SThomas Huth self.set_machine('bpim2u') 63*f7d6b772SThomas Huth deb_path = self.ASSET_DEB.fetch() 64*f7d6b772SThomas Huth kernel_path = self.extract_from_deb(deb_path, 65*f7d6b772SThomas Huth '/boot/vmlinuz-6.6.16-current-sunxi') 66*f7d6b772SThomas Huth dtb_path = ('/usr/lib/linux-image-6.6.16-current-sunxi/' 67*f7d6b772SThomas Huth 'sun8i-r40-bananapi-m2-ultra.dtb') 68*f7d6b772SThomas Huth dtb_path = self.extract_from_deb(deb_path, dtb_path) 69*f7d6b772SThomas Huth initrd_path_gz = self.ASSET_INITRD.fetch() 70*f7d6b772SThomas Huth initrd_path = os.path.join(self.workdir, 'rootfs.cpio') 71*f7d6b772SThomas Huth gzip_uncompress(initrd_path_gz, initrd_path) 72*f7d6b772SThomas Huth 73*f7d6b772SThomas Huth self.vm.set_console() 74*f7d6b772SThomas Huth kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 75*f7d6b772SThomas Huth 'console=ttyS0,115200 ' 76*f7d6b772SThomas Huth 'panic=-1 noreboot') 77*f7d6b772SThomas Huth self.vm.add_args('-kernel', kernel_path, 78*f7d6b772SThomas Huth '-dtb', dtb_path, 79*f7d6b772SThomas Huth '-initrd', initrd_path, 80*f7d6b772SThomas Huth '-append', kernel_command_line, 81*f7d6b772SThomas Huth '-no-reboot') 82*f7d6b772SThomas Huth self.vm.launch() 83*f7d6b772SThomas Huth self.wait_for_console_pattern('Boot successful.') 84*f7d6b772SThomas Huth 85*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', 86*f7d6b772SThomas Huth 'Allwinner sun8i Family') 87*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', 88*f7d6b772SThomas Huth 'system-control@1c00000') 89*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, 'reboot', 90*f7d6b772SThomas Huth 'reboot: Restarting system') 91*f7d6b772SThomas Huth # Wait for VM to shut down gracefully 92*f7d6b772SThomas Huth self.vm.wait() 93*f7d6b772SThomas Huth os.remove(kernel_path) 94*f7d6b772SThomas Huth os.remove(dtb_path) 95*f7d6b772SThomas Huth os.remove(initrd_path) 96*f7d6b772SThomas Huth 97*f7d6b772SThomas Huth def test_arm_bpim2u_gmac(self): 98*f7d6b772SThomas Huth self.set_machine('bpim2u') 99*f7d6b772SThomas Huth self.require_netdev('user') 100*f7d6b772SThomas Huth 101*f7d6b772SThomas Huth deb_path = self.ASSET_DEB.fetch() 102*f7d6b772SThomas Huth kernel_path = self.extract_from_deb(deb_path, 103*f7d6b772SThomas Huth '/boot/vmlinuz-6.6.16-current-sunxi') 104*f7d6b772SThomas Huth dtb_path = ('/usr/lib/linux-image-6.6.16-current-sunxi/' 105*f7d6b772SThomas Huth 'sun8i-r40-bananapi-m2-ultra.dtb') 106*f7d6b772SThomas Huth dtb_path = self.extract_from_deb(deb_path, dtb_path) 107*f7d6b772SThomas Huth rootfs_path_xz = self.ASSET_ROOTFS.fetch() 108*f7d6b772SThomas Huth rootfs_path = os.path.join(self.workdir, 'rootfs.cpio') 109*f7d6b772SThomas Huth lzma_uncompress(rootfs_path_xz, rootfs_path) 110*f7d6b772SThomas Huth image_pow2ceil_expand(rootfs_path) 111*f7d6b772SThomas Huth 112*f7d6b772SThomas Huth self.vm.set_console() 113*f7d6b772SThomas Huth kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 114*f7d6b772SThomas Huth 'console=ttyS0,115200 ' 115*f7d6b772SThomas Huth 'root=b300 rootwait rw ' 116*f7d6b772SThomas Huth 'panic=-1 noreboot') 117*f7d6b772SThomas Huth self.vm.add_args('-kernel', kernel_path, 118*f7d6b772SThomas Huth '-dtb', dtb_path, 119*f7d6b772SThomas Huth '-drive', 'file=' + rootfs_path + ',if=sd,format=raw', 120*f7d6b772SThomas Huth '-net', 'nic,model=gmac,netdev=host_gmac', 121*f7d6b772SThomas Huth '-netdev', 'user,id=host_gmac', 122*f7d6b772SThomas Huth '-append', kernel_command_line, 123*f7d6b772SThomas Huth '-no-reboot') 124*f7d6b772SThomas Huth self.vm.launch() 125*f7d6b772SThomas Huth shell_ready = "/bin/sh: can't access tty; job control turned off" 126*f7d6b772SThomas Huth self.wait_for_console_pattern(shell_ready) 127*f7d6b772SThomas Huth 128*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', 129*f7d6b772SThomas Huth 'Allwinner sun8i Family') 130*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', 131*f7d6b772SThomas Huth 'mmcblk') 132*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up', 133*f7d6b772SThomas Huth 'eth0: Link is Up') 134*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, 'udhcpc eth0', 135*f7d6b772SThomas Huth 'udhcpc: lease of 10.0.2.15 obtained') 136*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2', 137*f7d6b772SThomas Huth '3 packets transmitted, 3 packets received, 0% packet loss') 138*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, 'reboot', 139*f7d6b772SThomas Huth 'reboot: Restarting system') 140*f7d6b772SThomas Huth # Wait for VM to shut down gracefully 141*f7d6b772SThomas Huth self.vm.wait() 142*f7d6b772SThomas Huth os.remove(kernel_path) 143*f7d6b772SThomas Huth os.remove(dtb_path) 144*f7d6b772SThomas Huth os.remove(rootfs_path) 145*f7d6b772SThomas Huth 146*f7d6b772SThomas Huth @skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'), 'storage limited') 147*f7d6b772SThomas Huth def test_arm_bpim2u_openwrt_22_03_3(self): 148*f7d6b772SThomas Huth self.set_machine('bpim2u') 149*f7d6b772SThomas Huth # This test download a 8.9 MiB compressed image and expand it 150*f7d6b772SThomas Huth # to 127 MiB. 151*f7d6b772SThomas Huth image_path_gz = self.ASSET_SD_IMAGE.fetch() 152*f7d6b772SThomas Huth image_path = os.path.join(self.workdir, 'sdcard.img') 153*f7d6b772SThomas Huth gzip_uncompress(image_path_gz, image_path) 154*f7d6b772SThomas Huth image_pow2ceil_expand(image_path) 155*f7d6b772SThomas Huth 156*f7d6b772SThomas Huth self.vm.set_console() 157*f7d6b772SThomas Huth self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw', 158*f7d6b772SThomas Huth '-nic', 'user', 159*f7d6b772SThomas Huth '-no-reboot') 160*f7d6b772SThomas Huth self.vm.launch() 161*f7d6b772SThomas Huth 162*f7d6b772SThomas Huth kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 163*f7d6b772SThomas Huth 'usbcore.nousb ' 164*f7d6b772SThomas Huth 'noreboot') 165*f7d6b772SThomas Huth 166*f7d6b772SThomas Huth self.wait_for_console_pattern('U-Boot SPL') 167*f7d6b772SThomas Huth 168*f7d6b772SThomas Huth interrupt_interactive_console_until_pattern( 169*f7d6b772SThomas Huth self, 'Hit any key to stop autoboot:', '=>') 170*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, "setenv extraargs '" + 171*f7d6b772SThomas Huth kernel_command_line + "'", '=>') 172*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...'); 173*f7d6b772SThomas Huth 174*f7d6b772SThomas Huth self.wait_for_console_pattern( 175*f7d6b772SThomas Huth 'Please press Enter to activate this console.') 176*f7d6b772SThomas Huth 177*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, ' ', 'root@') 178*f7d6b772SThomas Huth 179*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', 180*f7d6b772SThomas Huth 'Allwinner sun8i Family') 181*f7d6b772SThomas Huth exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', 182*f7d6b772SThomas Huth 'system-control@1c00000') 183*f7d6b772SThomas Huth os.remove(image_path) 184*f7d6b772SThomas Huth 185*f7d6b772SThomas Huthif __name__ == '__main__': 186*f7d6b772SThomas Huth LinuxKernelTest.main() 187