1# SPDX-License-Identifier: GPL-2.0 2# (C) Copyright 2023, Advanced Micro Devices, Inc. 3 4""" 5Note: This test relies on boardenv_* containing configuration values to define 6which the network environment available for testing. Without this, this test 7will be automatically skipped. 8 9For example: 10 11.. code-block:: python 12 13 # Details regarding a boot image file that may be read from a TFTP server. This 14 # variable may be omitted or set to None if TFTP boot testing is not possible 15 # or desired. 16 env__net_tftp_bootable_file = { 17 'fn': 'image.ub', 18 'addr': 0x10000000, 19 'size': 5058624, 20 'crc32': 'c2244b26', 21 'pattern': 'Linux', 22 'config': 'config@2', 23 'timeout': 50000, 24 'check_type': 'boot_error', 25 'check_pattern': 'ERROR', 26 } 27 28 # False or omitted if a TFTP boot test should be tested. 29 # If TFTP boot testing is not possible or desired, set this variable to True. 30 # For example: If FIT image is not proper to boot 31 env__tftp_boot_test_skip = False 32 33 34Here is the example of FIT image configurations: 35 36.. code-block:: devicetree 37 38 configurations { 39 default = "config@1"; 40 config@1 { 41 description = "Boot Linux kernel with config@1"; 42 kernel = "kernel@0"; 43 fdt = "fdt@0"; 44 ramdisk = "ramdisk@0"; 45 hash@1 { 46 algo = "sha1"; 47 }; 48 }; 49 config@2 { 50 description = "Boot Linux kernel with config@2"; 51 kernel = "kernel@1"; 52 fdt = "fdt@1"; 53 ramdisk = "ramdisk@1"; 54 hash@1 { 55 algo = "sha1"; 56 }; 57 }; 58 }; 59 60.. code-block:: python 61 62 # Details regarding a file that may be read from a TFTP server. This variable 63 # may be omitted or set to None if PXE testing is not possible or desired. 64 env__net_pxe_bootable_file = { 65 'fn': 'default', 66 'addr': 0x10000000, 67 'size': 74, 68 'timeout': 50000, 69 'pattern': 'Linux', 70 'valid_label': '1', 71 'invalid_label': '2', 72 'exp_str_invalid': 'Skipping install for failure retrieving', 73 'local_label': '3', 74 'exp_str_local': 'missing environment variable: localcmd', 75 'empty_label': '4', 76 'exp_str_empty': 'No kernel given, skipping boot', 77 'check_type': 'boot_error', 78 'check_pattern': 'ERROR', 79 } 80 81 # False if a PXE boot test should be tested. 82 # If PXE boot testing is not possible or desired, set this variable to True. 83 # For example: If pxe configuration file is not proper to boot 84 env__pxe_boot_test_skip = False 85 86Here is the example of pxe configuration file ordered based on the execution 87flow: 88 891) /tftpboot/pxelinux.cfg/default-arm-zynqmp 90 91.. code-block:: 92 93 menu include pxelinux.cfg/default-arm 94 timeout 50 95 96 default Linux 97 982) /tftpboot/pxelinux.cfg/default-arm 99 100.. code-block:: 101 102 menu title Linux boot selections 103 menu include pxelinux.cfg/default 104 105 label install 106 menu label Invalid boot 107 kernel kernels/install.bin 108 append console=ttyAMA0,38400 debug earlyprintk 109 initrd initrds/uzInitrdDebInstall 110 111 label local 112 menu label Local boot 113 append root=/dev/sdb1 114 localboot 1 115 116 label boot 117 menu label Empty boot 118 1193) /tftpboot/pxelinux.cfg/default 120 121.. code-block:: 122 123 label Linux 124 menu label Boot kernel 125 kernel Image 126 fdt system.dtb 127 initrd rootfs.cpio.gz.u-boot 128""" 129 130import pytest 131import utils 132import test_net 133import re 134 135def setup_networking(ubman): 136 """Setup networking 137 138 Making use of the test_net test, first try and configure networking via 139 DHCP. If this fails, fall back to static configuration. 140 """ 141 test_net.test_net_dhcp(ubman) 142 if not test_net.net_set_up: 143 test_net.test_net_setup_static(ubman) 144 145def setup_tftpboot_boot(ubman): 146 """Setup for the tftpboot 'boot' test 147 148 We check that a file to use has been configured. If it has, we download it 149 and ensure it has the expected crc32 value. 150 """ 151 f = ubman.config.env.get('env__net_tftp_bootable_file', None) 152 if not f: 153 pytest.skip('No TFTP bootable file to read') 154 155 setup_networking(ubman) 156 addr = f.get('addr', None) 157 if not addr: 158 addr = utils.find_ram_base(ubman) 159 160 fn = f['fn'] 161 timeout = f.get('timeout', 50000) 162 163 with ubman.temporary_timeout(timeout): 164 output = ubman.run_command('tftpboot %x %s' % (addr, fn)) 165 166 expected_text = 'Bytes transferred = ' 167 sz = f.get('size', None) 168 if sz: 169 expected_text += '%d' % sz 170 assert expected_text in output 171 172 expected_crc = f.get('crc32', None) 173 output = ubman.run_command('crc32 %x $filesize' % addr) 174 if expected_crc: 175 assert expected_crc in output 176 177 pattern = f.get('pattern') 178 chk_type = f.get('check_type', 'boot_error') 179 chk_pattern = re.compile(f.get('check_pattern', 'ERROR')) 180 config = f.get('config', None) 181 182 return addr, timeout, pattern, chk_type, chk_pattern, config 183 184@pytest.mark.buildconfigspec('cmd_tftpboot') 185def test_net_tftpboot_boot(ubman): 186 """Boot the loaded image 187 188 A boot file (fit image) is downloaded from the TFTP server and booted using 189 bootm command with the default fit configuration, its boot log pattern are 190 validated. 191 192 The details of the file to download are provided by the boardenv_* file; 193 see the comment at the beginning of this file. 194 """ 195 if ubman.config.env.get('env__tftp_boot_test_skip', True): 196 pytest.skip('TFTP boot test is not enabled!') 197 198 addr, timeout, pattern, chk_type, chk_pattern, imcfg = setup_tftpboot_boot( 199 ubman 200 ) 201 202 if imcfg: 203 bootcmd = 'bootm %x#%s' % (addr, imcfg) 204 else: 205 bootcmd = 'bootm %x' % addr 206 207 with ubman.enable_check( 208 chk_type, chk_pattern 209 ), ubman.temporary_timeout(timeout): 210 try: 211 # wait_for_prompt=False makes the core code not wait for the U-Boot 212 # prompt code to be seen, since it won't be on a successful kernel 213 # boot 214 ubman.run_command(bootcmd, wait_for_prompt=False) 215 216 # Wait for boot log pattern 217 ubman.wait_for(pattern) 218 finally: 219 # This forces the console object to be shutdown, so any subsequent 220 # test will reset the board back into U-Boot. We want to force this 221 # no matter whether the kernel boot passed or failed. 222 ubman.drain_console() 223 ubman.cleanup_spawn() 224 225def setup_pxe_boot(ubman): 226 """Setup for the PXE 'boot' test 227 228 Make sure that the file to load via PXE boot has been configured. 229 """ 230 f = ubman.config.env.get('env__net_pxe_bootable_file', None) 231 if not f: 232 pytest.skip('No PXE bootable file to read') 233 234 setup_networking(ubman) 235 bootfile = ubman.run_command('echo $bootfile') 236 if not bootfile: 237 bootfile = '<NULL>' 238 239 return f, bootfile 240 241@pytest.mark.buildconfigspec('cmd_pxe') 242def test_net_pxe_boot(ubman): 243 """Test the pxe boot command. 244 245 A pxe configuration file is downloaded from the TFTP server and interpreted 246 to boot the images mentioned in pxe configuration file. 247 248 The details of the file to download are provided by the boardenv_* file; 249 see the comment at the beginning of this file. 250 """ 251 if ubman.config.env.get('env__pxe_boot_test_skip', True): 252 pytest.skip('PXE boot test is not enabled!') 253 254 f, bootfile = setup_pxe_boot(ubman) 255 addr = f.get('addr', None) 256 timeout = f.get('timeout', ubman.p.timeout) 257 fn = f['fn'] 258 259 if addr: 260 ubman.run_command('setenv pxefile_addr_r %x' % addr) 261 262 with ubman.temporary_timeout(timeout): 263 output = ubman.run_command('pxe get') 264 265 expected_text = 'Bytes transferred = ' 266 sz = f.get('size', None) 267 if sz: 268 expected_text += '%d' % sz 269 assert 'TIMEOUT' not in output 270 assert expected_text in output 271 assert f"Config file '{bootfile}' found" in output 272 273 pattern = f.get('pattern') 274 chk_type = f.get('check_type', 'boot_error') 275 chk_pattern = re.compile(f.get('check_pattern', 'ERROR')) 276 277 if not addr: 278 pxe_boot_cmd = 'pxe boot' 279 else: 280 pxe_boot_cmd = 'pxe boot %x' % addr 281 282 with ubman.enable_check( 283 chk_type, chk_pattern 284 ), ubman.temporary_timeout(timeout): 285 try: 286 ubman.run_command(pxe_boot_cmd, wait_for_prompt=False) 287 ubman.wait_for(pattern) 288 finally: 289 ubman.drain_console() 290 ubman.cleanup_spawn() 291 292@pytest.mark.buildconfigspec('cmd_pxe') 293def test_net_pxe_boot_config(ubman): 294 """Test the pxe boot command by selecting different combination of labels 295 296 A pxe configuration file is downloaded from the TFTP server and interpreted 297 to boot the images mentioned in pxe configuration file. 298 299 The details of the file to download are provided by the boardenv_* file; 300 see the comment at the beginning of this file. 301 """ 302 if ubman.config.env.get('env__pxe_boot_test_skip', True): 303 pytest.skip('PXE boot test is not enabled!') 304 305 f, bootfile = setup_pxe_boot(ubman) 306 addr = f.get('addr', None) 307 timeout = f.get('timeout', ubman.p.timeout) 308 fn = f['fn'] 309 local_label = f['local_label'] 310 empty_label = f['empty_label'] 311 exp_str_local = f['exp_str_local'] 312 exp_str_empty = f['exp_str_empty'] 313 314 if addr: 315 ubman.run_command('setenv pxefile_addr_r %x' % addr) 316 317 with ubman.temporary_timeout(timeout): 318 output = ubman.run_command('pxe get') 319 320 expected_text = 'Bytes transferred = ' 321 sz = f.get('size', None) 322 if sz: 323 expected_text += '%d' % sz 324 assert 'TIMEOUT' not in output 325 assert expected_text in output 326 assert f"Config file '{bootfile}' found" in output 327 328 pattern = f.get('pattern') 329 chk_type = f.get('check_type', 'boot_error') 330 chk_pattern = re.compile(f.get('check_pattern', 'ERROR')) 331 332 if not addr: 333 pxe_boot_cmd = 'pxe boot' 334 else: 335 pxe_boot_cmd = 'pxe boot %x' % addr 336 337 with ubman.enable_check( 338 chk_type, chk_pattern 339 ), ubman.temporary_timeout(timeout): 340 try: 341 ubman.run_command(pxe_boot_cmd, wait_for_prompt=False) 342 343 # pxe config is loaded where multiple labels are there and need to 344 # select particular label to boot and check for expected string 345 # In this case, local label is selected and it should look for 346 # localcmd env variable and if that variable is not defined it 347 # should not boot it and come out to u-boot prompt 348 ubman.wait_for('Enter choice:') 349 ubman.run_command(local_label, wait_for_prompt=False) 350 expected_str = ubman.p.expect([exp_str_local]) 351 assert ( 352 expected_str == 0 353 ), f'Expected string: {exp_str_local} did not match!' 354 355 # In this case, empty label is selected and it should look for 356 # kernel image path and if it is not set it should fail it and load 357 # default label to boot 358 ubman.run_command(pxe_boot_cmd, wait_for_prompt=False) 359 ubman.wait_for('Enter choice:') 360 ubman.run_command(empty_label, wait_for_prompt=False) 361 expected_str = ubman.p.expect([exp_str_empty]) 362 assert ( 363 expected_str == 0 364 ), f'Expected string: {exp_str_empty} did not match!' 365 366 ubman.wait_for(pattern) 367 finally: 368 ubman.drain_console() 369 ubman.cleanup_spawn() 370 371@pytest.mark.buildconfigspec('cmd_pxe') 372def test_net_pxe_boot_config_invalid(ubman): 373 """Test the pxe boot command by selecting invalid label 374 375 A pxe configuration file is downloaded from the TFTP server and interpreted 376 to boot the images mentioned in pxe configuration file. 377 378 The details of the file to download are provided by the boardenv_* file; 379 see the comment at the beginning of this file. 380 """ 381 if ubman.config.env.get('env__pxe_boot_test_skip', True): 382 pytest.skip('PXE boot test is not enabled!') 383 384 f, bootfile = setup_pxe_boot(ubman) 385 addr = f.get('addr', None) 386 timeout = f.get('timeout', ubman.p.timeout) 387 fn = f['fn'] 388 invalid_label = f['invalid_label'] 389 exp_str_invalid = f['exp_str_invalid'] 390 391 if addr: 392 ubman.run_command('setenv pxefile_addr_r %x' % addr) 393 394 with ubman.temporary_timeout(timeout): 395 output = ubman.run_command('pxe get') 396 397 expected_text = 'Bytes transferred = ' 398 sz = f.get('size', None) 399 if sz: 400 expected_text += '%d' % sz 401 assert 'TIMEOUT' not in output 402 assert expected_text in output 403 assert f"Config file '{bootfile}' found" in output 404 405 pattern = f.get('pattern') 406 if not addr: 407 pxe_boot_cmd = 'pxe boot' 408 else: 409 pxe_boot_cmd = 'pxe boot %x' % addr 410 411 with ubman.temporary_timeout(timeout): 412 try: 413 ubman.run_command(pxe_boot_cmd, wait_for_prompt=False) 414 415 # pxe config is loaded where multiple labels are there and need to 416 # select particular label to boot and check for expected string 417 # In this case invalid label is selected, it should load invalid 418 # label and if it fails it should load the default label to boot 419 ubman.wait_for('Enter choice:') 420 ubman.run_command(invalid_label, wait_for_prompt=False) 421 expected_str = ubman.p.expect([exp_str_invalid]) 422 assert ( 423 expected_str == 0 424 ), f'Expected string: {exp_str_invalid} did not match!' 425 426 ubman.wait_for(pattern) 427 finally: 428 ubman.drain_console() 429 ubman.cleanup_spawn() 430