1146773Ssam# SPDX-License-Identifier: GPL-2.0 2146773Ssam# (C) Copyright 2023, Advanced Micro Devices, Inc. 3146773Ssam 4146773Ssamimport pytest 5146773Ssamimport random 6146773Ssamimport re 7146773Ssamimport u_boot_utils 8146773Ssam 9146773Ssam""" 10146773SsamNote: This test doesn't rely on boardenv_* configuration values but it can 11146773Ssamchange the test behavior. To test USB file system cases (fat32, ext2, ext4), 12146773SsamUSB device should be formatted and valid partitions should be created for 13146773Ssamdifferent file system, otherwise it may leads to failure. This test will be 14146773Ssamskipped if the USB device is not detected. 15146773Ssam 16146773SsamFor example: 17146773Ssam 18190207Srpaulo# Setup env__usb_device_test_skip to not skipping the test. By default, its 19146773Ssam# value is set to True. Set it to False to run all tests for USB device. 20146773Ssamenv__usb_device_test_skip = False 21146773Ssam""" 22146773Ssam 23146773Ssamdef setup_usb(u_boot_console): 24146773Ssam if u_boot_console.config.env.get('env__usb_device_test_skip', True): 25146773Ssam pytest.skip('USB device test is not enabled') 26146773Ssam 27146773Ssam@pytest.mark.buildconfigspec('cmd_usb') 28146773Ssamdef test_usb_start(u_boot_console): 29214478Srpaulo setup_usb(u_boot_console) 30146773Ssam output = u_boot_console.run_command('usb start') 31146773Ssam 32146773Ssam # if output is empty, usb start may already run as part of preboot command 33146773Ssam # re-start the usb, in that case 34146773Ssam if not output: 35146773Ssam u_boot_console.run_command('usb stop') 36146773Ssam output = u_boot_console.run_command('usb start') 37146773Ssam 38146773Ssam if 'No USB device found' in output: 39146773Ssam pytest.skip('No USB controller available') 40146773Ssam 41146773Ssam if 'Card did not respond to voltage select' in output: 42146773Ssam pytest.skip('No USB device present') 43146773Ssam 44146773Ssam controllers = 0 45146773Ssam storage_device = 0 46 obj = re.search(r'\d USB Device\(s\) found', output) 47 controllers = int(obj.group()[0]) 48 49 if not controllers: 50 pytest.skip('No USB device present') 51 52 obj = re.search(r'\d Storage Device\(s\) found', output) 53 storage_device = int(obj.group()[0]) 54 55 if not storage_device: 56 pytest.skip('No USB storage device present') 57 58 assert 'USB init failed' not in output 59 assert 'starting USB...' in output 60 61 if 'Starting the controller' in output: 62 assert 'USB XHCI' in output 63 64 output = u_boot_console.run_command('echo $?') 65 assert output.endswith('0') 66 return controllers, storage_device 67 68@pytest.mark.buildconfigspec('cmd_usb') 69def test_usb_stop(u_boot_console): 70 setup_usb(u_boot_console) 71 output = u_boot_console.run_command('usb stop') 72 assert 'stopping USB..' in output 73 74 output = u_boot_console.run_command('echo $?') 75 assert output.endswith('0') 76 77 output = u_boot_console.run_command('usb dev') 78 assert "USB is stopped. Please issue 'usb start' first." in output 79 80@pytest.mark.buildconfigspec('cmd_usb') 81def test_usb_reset(u_boot_console): 82 setup_usb(u_boot_console) 83 output = u_boot_console.run_command('usb reset') 84 85 if 'No USB device found' in output: 86 pytest.skip('No USB controller available') 87 88 if 'Card did not respond to voltage select' in output: 89 pytest.skip('No USB device present') 90 91 obj = re.search(r'\d USB Device\(s\) found', output) 92 usb_dev_num = int(obj.group()[0]) 93 94 if not usb_dev_num: 95 pytest.skip('No USB device present') 96 97 obj = re.search(r'\d Storage Device\(s\) found', output) 98 usb_stor_num = int(obj.group()[0]) 99 100 if not usb_stor_num: 101 pytest.skip('No USB storage device present') 102 103 assert 'BUG' not in output 104 assert 'USB init failed' not in output 105 assert 'resetting USB...' in output 106 107 if 'Starting the controller' in output: 108 assert 'USB XHCI' in output 109 110 output = u_boot_console.run_command('echo $?') 111 assert output.endswith('0') 112 113@pytest.mark.buildconfigspec('cmd_usb') 114def test_usb_info(u_boot_console): 115 controllers, storage_device = test_usb_start(u_boot_console) 116 output = u_boot_console.run_command('usb info') 117 118 num_controller = len(re.findall(': Hub,', output)) 119 num_mass_storage = len(re.findall(': Mass Storage,', output)) 120 121 assert num_controller == controllers - 1 122 assert num_mass_storage == storage_device 123 124 output = u_boot_console.run_command('echo $?') 125 assert output.endswith('0') 126 127 for i in range(0, storage_device + controllers - 1): 128 output = u_boot_console.run_command('usb info %d' % i) 129 num_controller = len(re.findall(': Hub,', output)) 130 num_mass_storage = len(re.findall(': Mass Storage,', output)) 131 assert num_controller + num_mass_storage == 1 132 assert 'No device available' not in output 133 output = u_boot_console.run_command('echo $?') 134 assert output.endswith('0') 135 136@pytest.mark.buildconfigspec('cmd_usb') 137def test_usb_tree(u_boot_console): 138 controllers, storage_device = test_usb_start(u_boot_console) 139 output = u_boot_console.run_command('usb tree') 140 141 num_controller = len(re.findall('Hub', output)) 142 num_mass_storage = len(re.findall('Mass Storage', output)) 143 144 assert num_controller == controllers - 1 145 assert num_mass_storage == storage_device 146 147 output = u_boot_console.run_command('echo $?') 148 assert output.endswith('0') 149 150@pytest.mark.buildconfigspec('cmd_usb') 151@pytest.mark.buildconfigspec('usb_storage') 152def test_usb_storage(u_boot_console): 153 controllers, storage_device = test_usb_start(u_boot_console) 154 output = u_boot_console.run_command('usb storage') 155 156 obj = re.findall(r'Capacity: (\d+|\d+[\.]?\d)', output) 157 devices = {} 158 159 for key in range(int(storage_device)): 160 devices[key] = {} 161 162 for x in range(int(storage_device)): 163 try: 164 capacity = float(obj[x].split()[0]) 165 devices[x]['capacity'] = capacity 166 print('USB storage device %d capacity is: %g MB' % (x, capacity)) 167 except ValueError: 168 pytest.fail('USB storage device capacity not recognized') 169 170 output = u_boot_console.run_command('echo $?') 171 assert output.endswith('0') 172 173@pytest.mark.buildconfigspec('cmd_usb') 174def test_usb_dev(u_boot_console): 175 controllers, storage_device = test_usb_start(u_boot_console) 176 output = u_boot_console.run_command('usb dev') 177 178 assert 'no usb devices available' not in output 179 180 output = u_boot_console.run_command('echo $?') 181 assert output.endswith('0') 182 183 devices = {} 184 185 for key in range(int(storage_device)): 186 devices[key] = {} 187 188 fail = 0 189 for x in range(0, storage_device): 190 devices[x]['detected'] = 'yes' 191 output = u_boot_console.run_command('usb dev %d' % x) 192 193 if 'Card did not respond to voltage select' in output: 194 fail = 1 195 devices[x]['detected'] = 'no' 196 197 if 'No USB device found' in output: 198 devices[x]['detected'] = 'no' 199 200 if 'unknown device' in output: 201 devices[x]['detected'] = 'no' 202 203 assert 'is now current device' in output 204 output = u_boot_console.run_command('echo $?') 205 assert output.endswith('0') 206 207 if fail: 208 pytest.fail('USB device not present') 209 210 return devices, controllers, storage_device 211 212@pytest.mark.buildconfigspec('cmd_usb') 213def test_usb_part(u_boot_console): 214 devices, controllers, storage_device = test_usb_dev(u_boot_console) 215 if not devices: 216 pytest.skip('No devices detected') 217 218 u_boot_console.run_command('usb part') 219 220 output = u_boot_console.run_command('echo $?') 221 assert output.endswith('0') 222 223 for i in range(0, storage_device): 224 if devices[i]['detected'] == 'yes': 225 u_boot_console.run_command('usb dev %d' % i) 226 output = u_boot_console.run_command('usb part') 227 228 lines = output.split('\n') 229 part_fat = [] 230 part_ext = [] 231 for line in lines: 232 obj = re.search(r'(\d)\s+\d+\s+\d+\s+\w+\d+\w+-\d+\s+(\d+\w+)', line) 233 if obj: 234 part_id = int(obj.groups()[0]) 235 part_type = obj.groups()[1] 236 print('part_id:%d, part_type:%s' % (part_id, part_type)) 237 238 if part_type == '0c' or part_type == '0b' or part_type == '0e': 239 print('Fat detected') 240 part_fat.append(part_id) 241 elif part_type == '83': 242 print('ext detected') 243 part_ext.append(part_id) 244 else: 245 pytest.fail('Unsupported Filesystem on device %d' % i) 246 devices[i]['ext4'] = part_ext 247 devices[i]['ext2'] = part_ext 248 devices[i]['fat'] = part_fat 249 250 if not part_ext and not part_fat: 251 pytest.fail('No partition detected on device %d' % i) 252 253 return devices, controllers, storage_device 254 255@pytest.mark.buildconfigspec('cmd_usb') 256@pytest.mark.buildconfigspec('cmd_fat') 257def test_usb_fatls_fatinfo(u_boot_console): 258 devices, controllers, storage_device = test_usb_part(u_boot_console) 259 if not devices: 260 pytest.skip('No devices detected') 261 262 part_detect = 0 263 fs = 'fat' 264 for x in range(0, int(storage_device)): 265 if devices[x]['detected'] == 'yes': 266 u_boot_console.run_command('usb dev %d' % x) 267 try: 268 partitions = devices[x][fs] 269 except: 270 print('No %s table on this device' % fs.upper()) 271 continue 272 273 for part in partitions: 274 output = u_boot_console.run_command('fatls usb %d:%s' % (x, part)) 275 if 'Unrecognized filesystem type' in output: 276 partitions.remove(part) 277 pytest.fail('Unrecognized filesystem') 278 279 if not re.search(r'\d file\(s\), \d dir\(s\)', output): 280 pytest.fail('%s read failed on device %d' % (fs.upper, x)) 281 282 output = u_boot_console.run_command('fatinfo usb %d:%s' % (x, part)) 283 string = 'Filesystem: %s' % fs.upper 284 if re.search(string, output): 285 pytest.fail('%s FS failed on device %d' % (fs.upper(), x)) 286 part_detect = 1 287 288 if not part_detect: 289 pytest.skip('No %s partition detected' % fs.upper()) 290 291@pytest.mark.buildconfigspec('cmd_usb') 292@pytest.mark.buildconfigspec('cmd_fat') 293@pytest.mark.buildconfigspec('cmd_memory') 294def test_usb_fatload_fatwrite(u_boot_console): 295 devices, controllers, storage_device = test_usb_part(u_boot_console) 296 if not devices: 297 pytest.skip('No devices detected') 298 299 part_detect = 0 300 fs = 'fat' 301 for x in range(0, int(storage_device)): 302 if devices[x]['detected'] == 'yes': 303 u_boot_console.run_command('usb dev %d' % x) 304 try: 305 partitions = devices[x][fs] 306 except: 307 print('No %s table on this device' % fs.upper()) 308 continue 309 310 for part in partitions: 311 part_detect = 1 312 addr = u_boot_utils.find_ram_base(u_boot_console) 313 size = random.randint(4, 1 * 1024 * 1024) 314 output = u_boot_console.run_command('crc32 %x %x' % (addr, size)) 315 m = re.search('==> (.+?)', output) 316 if not m: 317 pytest.fail('CRC32 failed') 318 expected_crc32 = m.group(1) 319 320 file = '%s_%d' % ('uboot_test', size) 321 output = u_boot_console.run_command( 322 '%swrite usb %d:%s %x %s %x' % (fs, x, part, addr, file, size) 323 ) 324 assert 'Unable to write' not in output 325 assert 'Error' not in output 326 assert 'overflow' not in output 327 expected_text = '%d bytes written' % size 328 assert expected_text in output 329 330 alignment = int( 331 u_boot_console.config.buildconfig.get( 332 'config_sys_cacheline_size', 128 333 ) 334 ) 335 offset = random.randrange(alignment, 1024, alignment) 336 output = u_boot_console.run_command( 337 '%sload usb %d:%s %x %s' % (fs, x, part, addr + offset, file) 338 ) 339 assert 'Invalid FAT entry' not in output 340 assert 'Unable to read file' not in output 341 assert 'Misaligned buffer address' not in output 342 expected_text = '%d bytes read' % size 343 assert expected_text in output 344 345 output = u_boot_console.run_command( 346 'crc32 %x $filesize' % (addr + offset) 347 ) 348 assert expected_crc32 in output 349 350 if not part_detect: 351 pytest.skip('No %s partition detected' % fs.upper()) 352 353 return file, size 354 355@pytest.mark.buildconfigspec('cmd_usb') 356@pytest.mark.buildconfigspec('cmd_ext4') 357def test_usb_ext4ls(u_boot_console): 358 devices, controllers, storage_device = test_usb_part(u_boot_console) 359 if not devices: 360 pytest.skip('No devices detected') 361 362 part_detect = 0 363 fs = 'ext4' 364 for x in range(0, int(storage_device)): 365 if devices[x]['detected'] == 'yes': 366 try: 367 partitions = devices[x][fs] 368 except: 369 print('No %s table on this device' % fs.upper()) 370 continue 371 372 u_boot_console.run_command('usb dev %d' % x) 373 for part in partitions: 374 output = u_boot_console.run_command('%sls usb %d:%s' % (fs, x, part)) 375 if 'Unrecognized filesystem type' in output: 376 partitions.remove(part) 377 pytest.fail('Unrecognized filesystem') 378 part_detect = 1 379 380 if not part_detect: 381 pytest.skip('No %s partition detected' % fs.upper()) 382 383@pytest.mark.buildconfigspec('cmd_usb') 384@pytest.mark.buildconfigspec('cmd_ext4') 385@pytest.mark.buildconfigspec('ext4_write') 386@pytest.mark.buildconfigspec('cmd_memory') 387def test_usb_ext4load_ext4write(u_boot_console): 388 devices, controllers, storage_device = test_usb_part(u_boot_console) 389 if not devices: 390 pytest.skip('No devices detected') 391 392 part_detect = 0 393 fs = 'ext4' 394 for x in range(0, int(storage_device)): 395 if devices[x]['detected'] == 'yes': 396 u_boot_console.run_command('usb dev %d' % x) 397 try: 398 partitions = devices[x][fs] 399 except: 400 print('No %s table on this device' % fs.upper()) 401 continue 402 403 for part in partitions: 404 part_detect = 1 405 addr = u_boot_utils.find_ram_base(u_boot_console) 406 size = random.randint(4, 1 * 1024 * 1024) 407 output = u_boot_console.run_command('crc32 %x %x' % (addr, size)) 408 m = re.search('==> (.+?)', output) 409 if not m: 410 pytest.fail('CRC32 failed') 411 expected_crc32 = m.group(1) 412 file = '%s_%d' % ('uboot_test', size) 413 414 output = u_boot_console.run_command( 415 '%swrite usb %d:%s %x /%s %x' % (fs, x, part, addr, file, size) 416 ) 417 assert 'Unable to write' not in output 418 assert 'Error' not in output 419 assert 'overflow' not in output 420 expected_text = '%d bytes written' % size 421 assert expected_text in output 422 423 offset = random.randrange(128, 1024, 128) 424 output = u_boot_console.run_command( 425 '%sload usb %d:%s %x /%s' % (fs, x, part, addr + offset, file) 426 ) 427 expected_text = '%d bytes read' % size 428 assert expected_text in output 429 430 output = u_boot_console.run_command( 431 'crc32 %x $filesize' % (addr + offset) 432 ) 433 assert expected_crc32 in output 434 435 if not part_detect: 436 pytest.skip('No %s partition detected' % fs.upper()) 437 438 return file, size 439 440@pytest.mark.buildconfigspec('cmd_usb') 441@pytest.mark.buildconfigspec('cmd_ext2') 442def test_usb_ext2ls(u_boot_console): 443 devices, controllers, storage_device = test_usb_part(u_boot_console) 444 if not devices: 445 pytest.skip('No devices detected') 446 447 part_detect = 0 448 fs = 'ext2' 449 for x in range(0, int(storage_device)): 450 if devices[x]['detected'] == 'yes': 451 u_boot_console.run_command('usb dev %d' % x) 452 try: 453 partitions = devices[x][fs] 454 except: 455 print('No %s table on this device' % fs.upper()) 456 continue 457 458 for part in partitions: 459 part_detect = 1 460 output = u_boot_console.run_command('%sls usb %d:%s' % (fs, x, part)) 461 if 'Unrecognized filesystem type' in output: 462 partitions.remove(part) 463 pytest.fail('Unrecognized filesystem') 464 part_detect = 1 465 466 if not part_detect: 467 pytest.skip('No %s partition detected' % fs.upper()) 468 469@pytest.mark.buildconfigspec('cmd_usb') 470@pytest.mark.buildconfigspec('cmd_ext2') 471@pytest.mark.buildconfigspec('cmd_ext4') 472@pytest.mark.buildconfigspec('ext4_write') 473@pytest.mark.buildconfigspec('cmd_memory') 474def test_usb_ext2load(u_boot_console): 475 devices, controllers, storage_device = test_usb_part(u_boot_console) 476 file, size = test_usb_ext4load_ext4write(u_boot_console) 477 478 if not devices: 479 pytest.skip('No devices detected') 480 481 part_detect = 0 482 fs = 'ext2' 483 for x in range(0, int(storage_device)): 484 if devices[x]['detected'] == 'yes': 485 u_boot_console.run_command('usb dev %d' % x) 486 try: 487 partitions = devices[x][fs] 488 except: 489 print('No %s table on this device' % fs.upper()) 490 continue 491 492 for part in partitions: 493 part_detect = 1 494 addr = u_boot_utils.find_ram_base(u_boot_console) 495 output = u_boot_console.run_command('crc32 %x %x' % (addr, size)) 496 m = re.search('==> (.+?)', output) 497 if not m: 498 pytest.fail('CRC32 failed') 499 expected_crc32 = m.group(1) 500 501 offset = random.randrange(128, 1024, 128) 502 output = u_boot_console.run_command( 503 '%sload usb %d:%s %x /%s' % (fs, x, part, addr + offset, file) 504 ) 505 expected_text = '%d bytes read' % size 506 assert expected_text in output 507 508 output = u_boot_console.run_command( 509 'crc32 %x $filesize' % (addr + offset) 510 ) 511 assert expected_crc32 in output 512 513 if not part_detect: 514 pytest.skip('No %s partition detected' % fs.upper()) 515 516@pytest.mark.buildconfigspec('cmd_usb') 517@pytest.mark.buildconfigspec('cmd_fs_generic') 518def test_usb_ls(u_boot_console): 519 devices, controllers, storage_device = test_usb_part(u_boot_console) 520 if not devices: 521 pytest.skip('No devices detected') 522 523 part_detect = 0 524 for x in range(0, int(storage_device)): 525 if devices[x]['detected'] == 'yes': 526 u_boot_console.run_command('usb dev %d' % x) 527 for fs in ['fat', 'ext4']: 528 try: 529 partitions = devices[x][fs] 530 except: 531 print('No %s table on this device' % fs.upper()) 532 continue 533 534 for part in partitions: 535 part_detect = 1 536 output = u_boot_console.run_command('ls usb %d:%s' % (x, part)) 537 if re.search(r'No \w+ table on this device', output): 538 pytest.fail( 539 '%s: Partition table not found %d' % (fs.upper(), x) 540 ) 541 542 if not part_detect: 543 pytest.skip('No partition detected') 544 545@pytest.mark.buildconfigspec('cmd_usb') 546@pytest.mark.buildconfigspec('cmd_fs_generic') 547def test_usb_load(u_boot_console): 548 devices, controllers, storage_device = test_usb_part(u_boot_console) 549 if not devices: 550 pytest.skip('No devices detected') 551 552 part_detect = 0 553 for x in range(0, int(storage_device)): 554 if devices[x]['detected'] == 'yes': 555 u_boot_console.run_command('usb dev %d' % x) 556 for fs in ['fat', 'ext4']: 557 try: 558 partitions = devices[x][fs] 559 except: 560 print('No %s table on this device' % fs.upper()) 561 continue 562 563 for part in partitions: 564 part_detect = 1 565 addr = u_boot_utils.find_ram_base(u_boot_console) 566 567 if fs == 'fat': 568 file, size = test_usb_fatload_fatwrite(u_boot_console) 569 elif fs == 'ext4': 570 file, size = test_usb_ext4load_ext4write(u_boot_console) 571 572 output = u_boot_console.run_command('crc32 %x %x' % (addr, size)) 573 m = re.search('==> (.+?)', output) 574 if not m: 575 pytest.fail('CRC32 failed') 576 expected_crc32 = m.group(1) 577 578 offset = random.randrange(128, 1024, 128) 579 output = u_boot_console.run_command( 580 'load usb %d:%s %x /%s' % (x, part, addr + offset, file) 581 ) 582 expected_text = '%d bytes read' % size 583 assert expected_text in output 584 585 output = u_boot_console.run_command( 586 'crc32 %x $filesize' % (addr + offset) 587 ) 588 assert expected_crc32 in output 589 590 if not part_detect: 591 pytest.skip('No partition detected') 592 593@pytest.mark.buildconfigspec('cmd_usb') 594@pytest.mark.buildconfigspec('cmd_fs_generic') 595def test_usb_save(u_boot_console): 596 devices, controllers, storage_device = test_usb_part(u_boot_console) 597 if not devices: 598 pytest.skip('No devices detected') 599 600 part_detect = 0 601 for x in range(0, int(storage_device)): 602 if devices[x]['detected'] == 'yes': 603 u_boot_console.run_command('usb dev %d' % x) 604 for fs in ['fat', 'ext4']: 605 try: 606 partitions = devices[x][fs] 607 except: 608 print('No %s table on this device' % fs.upper()) 609 continue 610 611 for part in partitions: 612 part_detect = 1 613 addr = u_boot_utils.find_ram_base(u_boot_console) 614 size = random.randint(4, 1 * 1024 * 1024) 615 file = '%s_%d' % ('uboot_test', size) 616 617 offset = random.randrange(128, 1024, 128) 618 output = u_boot_console.run_command( 619 'save usb %d:%s %x /%s %x' 620 % (x, part, addr + offset, file, size) 621 ) 622 expected_text = '%d bytes written' % size 623 assert expected_text in output 624 625 if not part_detect: 626 pytest.skip('No partition detected') 627