1# SPDX-License-Identifier: GPL-2.0 2# (C) Copyright 2023, Advanced Micro Devices, Inc. 3 4import pytest 5import random 6import re 7import u_boot_utils 8 9""" 10Note: This test doesn't rely on boardenv_* configuration values but it can 11change the test behavior. To test MMC file system cases (fat32, ext2, ext4), 12MMC device should be formatted and valid partitions should be created for 13different file system, otherwise it may leads to failure. This test will be 14skipped if the MMC device is not detected. 15 16For example: 17 18# Setup env__mmc_device_test_skip to not skipping the test. By default, its 19# value is set to True. Set it to False to run all tests for MMC device. 20env__mmc_device_test_skip = False 21""" 22 23mmc_set_up = False 24controllers = 0 25devices = {} 26 27def setup_mmc(u_boot_console): 28 if u_boot_console.config.env.get('env__mmc_device_test_skip', True): 29 pytest.skip('MMC device test is not enabled') 30 31@pytest.mark.buildconfigspec('cmd_mmc') 32def test_mmc_list(u_boot_console): 33 setup_mmc(u_boot_console) 34 output = u_boot_console.run_command('mmc list') 35 if 'No MMC device available' in output: 36 pytest.skip('No SD/MMC/eMMC controller available') 37 38 if 'Card did not respond to voltage select' in output: 39 pytest.skip('No SD/MMC card present') 40 41 array = output.split() 42 global devices 43 global controllers 44 controllers = int(len(array) / 2) 45 for x in range(0, controllers): 46 y = x * 2 47 devices[x] = {} 48 devices[x]['name'] = array[y] 49 50 global mmc_set_up 51 mmc_set_up = True 52 53@pytest.mark.buildconfigspec('cmd_mmc') 54def test_mmc_dev(u_boot_console): 55 if not mmc_set_up: 56 pytest.skip('No SD/MMC/eMMC controller available') 57 58 fail = 0 59 for x in range(0, controllers): 60 devices[x]['detected'] = 'yes' 61 output = u_boot_console.run_command('mmc dev %d' % x) 62 63 # Some sort of switch here 64 if 'Card did not respond to voltage select' in output: 65 fail = 1 66 devices[x]['detected'] = 'no' 67 68 if 'no mmc device at slot' in output: 69 devices[x]['detected'] = 'no' 70 71 if 'MMC: no card present' in output: 72 devices[x]['detected'] = 'no' 73 74 if fail: 75 pytest.fail('Card not present') 76 77@pytest.mark.buildconfigspec('cmd_mmc') 78def test_mmcinfo(u_boot_console): 79 if not mmc_set_up: 80 pytest.skip('No SD/MMC/eMMC controller available') 81 82 for x in range(0, controllers): 83 if devices[x]['detected'] == 'yes': 84 u_boot_console.run_command('mmc dev %d' % x) 85 output = u_boot_console.run_command('mmcinfo') 86 if 'busy timeout' in output: 87 pytest.skip('No SD/MMC/eMMC device present') 88 89 obj = re.search(r'Capacity: (\d+|\d+[\.]?\d)', output) 90 try: 91 capacity = float(obj.groups()[0]) 92 print(capacity) 93 devices[x]['capacity'] = capacity 94 print('Capacity of dev %d is: %g GiB' % (x, capacity)) 95 except ValueError: 96 pytest.fail('MMC capacity not recognized') 97 98@pytest.mark.buildconfigspec('cmd_mmc') 99def test_mmc_info(u_boot_console): 100 if not mmc_set_up: 101 pytest.skip('No SD/MMC/eMMC controller available') 102 103 for x in range(0, controllers): 104 if devices[x]['detected'] == 'yes': 105 u_boot_console.run_command('mmc dev %d' % x) 106 107 output = u_boot_console.run_command('mmc info') 108 109 obj = re.search(r'Capacity: (\d+|\d+[\.]?\d)', output) 110 try: 111 capacity = float(obj.groups()[0]) 112 print(capacity) 113 if devices[x]['capacity'] != capacity: 114 pytest.fail("MMC capacity doesn't match mmcinfo") 115 116 except ValueError: 117 pytest.fail('MMC capacity not recognized') 118 119@pytest.mark.buildconfigspec('cmd_mmc') 120def test_mmc_rescan(u_boot_console): 121 if not mmc_set_up: 122 pytest.skip('No SD/MMC/eMMC controller available') 123 124 if not devices: 125 pytest.skip('No devices detected') 126 127 for x in range(0, controllers): 128 if devices[x]['detected'] == 'yes': 129 u_boot_console.run_command('mmc dev %d' % x) 130 output = u_boot_console.run_command('mmc rescan') 131 if output: 132 pytest.fail('mmc rescan has something to check') 133 output = u_boot_console.run_command('echo $?') 134 assert output.endswith('0') 135 136@pytest.mark.buildconfigspec('cmd_mmc') 137def test_mmc_part(u_boot_console): 138 if not mmc_set_up: 139 pytest.skip('No SD/MMC/eMMC controller available') 140 141 if not devices: 142 pytest.skip('No devices detected') 143 144 for x in range(0, controllers): 145 if devices[x]['detected'] == 'yes': 146 u_boot_console.run_command('mmc dev %d' % x) 147 output = u_boot_console.run_command('mmc part') 148 149 lines = output.split('\n') 150 part_fat = [] 151 part_ext = [] 152 for line in lines: 153 obj = re.search( 154 r'(\d)\s+\d+\s+\d+\s+\w+\d+\w+-\d+\s+(\d+\w+)', line) 155 if obj: 156 part_id = int(obj.groups()[0]) 157 part_type = obj.groups()[1] 158 print('part_id:%d, part_type:%s' % (part_id, part_type)) 159 160 if part_type in ['0c', '0b', '0e']: 161 print('Fat detected') 162 part_fat.append(part_id) 163 elif part_type == '83': 164 print('ext detected') 165 part_ext.append(part_id) 166 else: 167 pytest.fail('Unsupported Filesystem on device %d' % x) 168 devices[x]['ext4'] = part_ext 169 devices[x]['ext2'] = part_ext 170 devices[x]['fat'] = part_fat 171 172 if not part_ext and not part_fat: 173 pytest.fail('No partition detected on device %d' % x) 174 175@pytest.mark.buildconfigspec('cmd_mmc') 176@pytest.mark.buildconfigspec('cmd_fat') 177def test_mmc_fatls_fatinfo(u_boot_console): 178 if not mmc_set_up: 179 pytest.skip('No SD/MMC/eMMC controller available') 180 181 if not devices: 182 pytest.skip('No devices detected') 183 184 part_detect = 0 185 fs = 'fat' 186 for x in range(0, controllers): 187 if devices[x]['detected'] == 'yes': 188 u_boot_console.run_command('mmc dev %d' % x) 189 try: 190 partitions = devices[x][fs] 191 except: 192 print('No %s table on this device' % fs.upper()) 193 continue 194 195 for part in partitions: 196 output = u_boot_console.run_command( 197 'fatls mmc %d:%s' % (x, part)) 198 if 'Unrecognized filesystem type' in output: 199 partitions.remove(part) 200 pytest.fail('Unrecognized filesystem') 201 202 if not re.search(r'\d file\(s\), \d dir\(s\)', output): 203 pytest.fail('%s read failed on device %d' % (fs.upper, x)) 204 output = u_boot_console.run_command( 205 'fatinfo mmc %d:%s' % (x, part)) 206 string = 'Filesystem: %s' % fs.upper 207 if re.search(string, output): 208 pytest.fail('%s FS failed on device %d' % (fs.upper(), x)) 209 part_detect = 1 210 211 if not part_detect: 212 pytest.skip('No %s partition detected' % fs.upper()) 213 214 215@pytest.mark.buildconfigspec('cmd_mmc') 216@pytest.mark.buildconfigspec('cmd_fat') 217@pytest.mark.buildconfigspec('cmd_memory') 218def test_mmc_fatload_fatwrite(u_boot_console): 219 if not mmc_set_up: 220 pytest.skip('No SD/MMC/eMMC controller available') 221 222 if not devices: 223 pytest.skip('No devices detected') 224 225 part_detect = 0 226 fs = 'fat' 227 for x in range(0, controllers): 228 if devices[x]['detected'] == 'yes': 229 u_boot_console.run_command('mmc dev %d' % x) 230 try: 231 partitions = devices[x][fs] 232 except: 233 print('No %s table on this device' % fs.upper()) 234 continue 235 236 for part in partitions: 237 part_detect = 1 238 addr = u_boot_utils.find_ram_base(u_boot_console) 239 devices[x]['addr_%d' % part] = addr 240 size = random.randint(4, 1 * 1024 * 1024) 241 devices[x]['size_%d' % part] = size 242 # count CRC32 243 output = u_boot_console.run_command('crc32 %x %x' % (addr, size)) 244 m = re.search('==> (.+?)', output) 245 if not m: 246 pytest.fail('CRC32 failed') 247 expected_crc32 = m.group(1) 248 devices[x]['expected_crc32_%d' % part] = expected_crc32 249 # do write 250 file = '%s_%d' % ('uboot_test', size) 251 devices[x]['file_%d' % part] = file 252 output = u_boot_console.run_command( 253 '%swrite mmc %d:%s %x %s %x' % (fs, x, part, addr, file, size) 254 ) 255 assert 'Unable to write' not in output 256 assert 'Error' not in output 257 assert 'overflow' not in output 258 expected_text = '%d bytes written' % size 259 assert expected_text in output 260 261 alignment = int( 262 u_boot_console.config.buildconfig.get( 263 'config_sys_cacheline_size', 128 264 ) 265 ) 266 offset = random.randrange(alignment, 1024, alignment) 267 output = u_boot_console.run_command( 268 '%sload mmc %d:%s %x %s' % (fs, x, part, addr + offset, file) 269 ) 270 assert 'Invalid FAT entry' not in output 271 assert 'Unable to read file' not in output 272 assert 'Misaligned buffer address' not in output 273 expected_text = '%d bytes read' % size 274 assert expected_text in output 275 276 output = u_boot_console.run_command( 277 'crc32 %x $filesize' % (addr + offset) 278 ) 279 assert expected_crc32 in output 280 281 if not part_detect: 282 pytest.skip('No %s partition detected' % fs.upper()) 283 284@pytest.mark.buildconfigspec('cmd_mmc') 285@pytest.mark.buildconfigspec('cmd_ext4') 286def test_mmc_ext4ls(u_boot_console): 287 if not mmc_set_up: 288 pytest.skip('No SD/MMC/eMMC controller available') 289 290 if not devices: 291 pytest.skip('No devices detected') 292 293 part_detect = 0 294 fs = 'ext4' 295 for x in range(0, controllers): 296 if devices[x]['detected'] == 'yes': 297 try: 298 partitions = devices[x][fs] 299 except: 300 print('No %s table on this device' % fs.upper()) 301 continue 302 303 u_boot_console.run_command('mmc dev %d' % x) 304 for part in partitions: 305 output = u_boot_console.run_command('%sls mmc %d:%s' % (fs, x, part)) 306 if 'Unrecognized filesystem type' in output: 307 partitions.remove(part) 308 pytest.fail('Unrecognized filesystem') 309 part_detect = 1 310 311 if not part_detect: 312 pytest.skip('No %s partition detected' % fs.upper()) 313 314@pytest.mark.buildconfigspec('cmd_mmc') 315@pytest.mark.buildconfigspec('cmd_ext4') 316@pytest.mark.buildconfigspec('ext4_write') 317@pytest.mark.buildconfigspec('cmd_memory') 318def test_mmc_ext4load_ext4write(u_boot_console): 319 if not mmc_set_up: 320 pytest.skip('No SD/MMC/eMMC controller available') 321 322 if not devices: 323 pytest.skip('No devices detected') 324 325 part_detect = 0 326 fs = 'ext4' 327 for x in range(0, controllers): 328 if devices[x]['detected'] == 'yes': 329 u_boot_console.run_command('mmc dev %d' % x) 330 try: 331 partitions = devices[x][fs] 332 except: 333 print('No %s table on this device' % fs.upper()) 334 continue 335 336 for part in partitions: 337 part_detect = 1 338 addr = u_boot_utils.find_ram_base(u_boot_console) 339 devices[x]['addr_%d' % part] = addr 340 size = random.randint(4, 1 * 1024 * 1024) 341 devices[x]['size_%d' % part] = size 342 # count CRC32 343 output = u_boot_console.run_command('crc32 %x %x' % (addr, size)) 344 m = re.search('==> (.+?)', output) 345 if not m: 346 pytest.fail('CRC32 failed') 347 expected_crc32 = m.group(1) 348 devices[x]['expected_crc32_%d' % part] = expected_crc32 349 # do write 350 351 file = '%s_%d' % ('uboot_test', size) 352 devices[x]['file_%d' % part] = file 353 output = u_boot_console.run_command( 354 '%swrite mmc %d:%s %x /%s %x' % (fs, x, part, addr, file, size) 355 ) 356 assert 'Unable to write' not in output 357 assert 'Error' not in output 358 assert 'overflow' not in output 359 expected_text = '%d bytes written' % size 360 assert expected_text in output 361 362 offset = random.randrange(128, 1024, 128) 363 output = u_boot_console.run_command( 364 '%sload mmc %d:%s %x /%s' % (fs, x, part, addr + offset, file) 365 ) 366 expected_text = '%d bytes read' % size 367 assert expected_text in output 368 369 output = u_boot_console.run_command( 370 'crc32 %x $filesize' % (addr + offset) 371 ) 372 assert expected_crc32 in output 373 374 if not part_detect: 375 pytest.skip('No %s partition detected' % fs.upper()) 376 377@pytest.mark.buildconfigspec('cmd_mmc') 378@pytest.mark.buildconfigspec('cmd_ext2') 379def test_mmc_ext2ls(u_boot_console): 380 if not mmc_set_up: 381 pytest.skip('No SD/MMC/eMMC controller available') 382 383 if not devices: 384 pytest.skip('No devices detected') 385 386 part_detect = 0 387 fs = 'ext2' 388 for x in range(0, controllers): 389 if devices[x]['detected'] == 'yes': 390 u_boot_console.run_command('mmc dev %d' % x) 391 try: 392 partitions = devices[x][fs] 393 except: 394 print('No %s table on this device' % fs.upper()) 395 continue 396 397 for part in partitions: 398 part_detect = 1 399 output = u_boot_console.run_command('%sls mmc %d:%s' % (fs, x, part)) 400 if 'Unrecognized filesystem type' in output: 401 partitions.remove(part) 402 pytest.fail('Unrecognized filesystem') 403 part_detect = 1 404 405 if not part_detect: 406 pytest.skip('No %s partition detected' % fs.upper()) 407 408@pytest.mark.buildconfigspec('cmd_mmc') 409@pytest.mark.buildconfigspec('cmd_ext2') 410@pytest.mark.buildconfigspec('cmd_ext4') 411@pytest.mark.buildconfigspec('ext4_write') 412@pytest.mark.buildconfigspec('cmd_memory') 413def test_mmc_ext2load(u_boot_console): 414 if not mmc_set_up: 415 pytest.skip('No SD/MMC/eMMC controller available') 416 417 if not devices: 418 pytest.skip('No devices detected') 419 420 part_detect = 0 421 fs = 'ext2' 422 for x in range(0, controllers): 423 if devices[x]['detected'] == 'yes': 424 u_boot_console.run_command('mmc dev %d' % x) 425 try: 426 partitions = devices[x][fs] 427 except: 428 print('No %s table on this device' % fs.upper()) 429 continue 430 431 for part in partitions: 432 part_detect = 1 433 addr = devices[x]['addr_%d' % part] 434 size = devices[x]['size_%d' % part] 435 expected_crc32 = devices[x]['expected_crc32_%d' % part] 436 file = devices[x]['file_%d' % part] 437 438 offset = random.randrange(128, 1024, 128) 439 output = u_boot_console.run_command( 440 '%sload mmc %d:%s %x /%s' % (fs, x, part, addr + offset, file) 441 ) 442 expected_text = '%d bytes read' % size 443 assert expected_text in output 444 445 output = u_boot_console.run_command( 446 'crc32 %x $filesize' % (addr + offset) 447 ) 448 assert expected_crc32 in output 449 450 if not part_detect: 451 pytest.skip('No %s partition detected' % fs.upper()) 452 453@pytest.mark.buildconfigspec('cmd_mmc') 454@pytest.mark.buildconfigspec('cmd_fs_generic') 455def test_mmc_ls(u_boot_console): 456 if not mmc_set_up: 457 pytest.skip('No SD/MMC/eMMC controller available') 458 459 if not devices: 460 pytest.skip('No devices detected') 461 462 part_detect = 0 463 for x in range(0, controllers): 464 if devices[x]['detected'] == 'yes': 465 u_boot_console.run_command('mmc dev %d' % x) 466 for fs in ['fat', 'ext4']: 467 try: 468 partitions = devices[x][fs] 469 except: 470 print('No %s table on this device' % fs.upper()) 471 continue 472 473 for part in partitions: 474 part_detect = 1 475 output = u_boot_console.run_command('ls mmc %d:%s' % (x, part)) 476 if re.search(r'No \w+ table on this device', output): 477 pytest.fail( 478 '%s: Partition table not found %d' % (fs.upper(), x) 479 ) 480 481 if not part_detect: 482 pytest.skip('No partition detected') 483 484@pytest.mark.buildconfigspec('cmd_mmc') 485@pytest.mark.buildconfigspec('cmd_fs_generic') 486def test_mmc_load(u_boot_console): 487 if not mmc_set_up: 488 pytest.skip('No SD/MMC/eMMC controller available') 489 490 if not devices: 491 pytest.skip('No devices detected') 492 493 part_detect = 0 494 for x in range(0, controllers): 495 if devices[x]['detected'] == 'yes': 496 u_boot_console.run_command('mmc dev %d' % x) 497 for fs in ['fat', 'ext4']: 498 try: 499 partitions = devices[x][fs] 500 except: 501 print('No %s table on this device' % fs.upper()) 502 continue 503 504 for part in partitions: 505 part_detect = 1 506 addr = devices[x]['addr_%d' % part] 507 size = devices[x]['size_%d' % part] 508 expected_crc32 = devices[x]['expected_crc32_%d' % part] 509 file = devices[x]['file_%d' % part] 510 511 offset = random.randrange(128, 1024, 128) 512 output = u_boot_console.run_command( 513 'load mmc %d:%s %x /%s' % (x, part, addr + offset, file) 514 ) 515 expected_text = '%d bytes read' % size 516 assert expected_text in output 517 518 output = u_boot_console.run_command( 519 'crc32 %x $filesize' % (addr + offset) 520 ) 521 assert expected_crc32 in output 522 523 if not part_detect: 524 pytest.skip('No partition detected') 525 526@pytest.mark.buildconfigspec('cmd_mmc') 527@pytest.mark.buildconfigspec('cmd_fs_generic') 528def test_mmc_save(u_boot_console): 529 if not mmc_set_up: 530 pytest.skip('No SD/MMC/eMMC controller available') 531 532 if not devices: 533 pytest.skip('No devices detected') 534 535 part_detect = 0 536 for x in range(0, controllers): 537 if devices[x]['detected'] == 'yes': 538 u_boot_console.run_command('mmc dev %d' % x) 539 for fs in ['fat', 'ext4']: 540 try: 541 partitions = devices[x][fs] 542 except: 543 print('No %s table on this device' % fs.upper()) 544 continue 545 546 for part in partitions: 547 part_detect = 1 548 addr = devices[x]['addr_%d' % part] 549 size = 0 550 file = devices[x]['file_%d' % part] 551 552 offset = random.randrange(128, 1024, 128) 553 output = u_boot_console.run_command( 554 'save mmc %d:%s %x /%s %d' 555 % (x, part, addr + offset, file, size) 556 ) 557 expected_text = '%d bytes written' % size 558 assert expected_text in output 559 560 if not part_detect: 561 pytest.skip('No partition detected') 562 563@pytest.mark.buildconfigspec('cmd_mmc') 564@pytest.mark.buildconfigspec('cmd_fat') 565@pytest.mark.buildconfigspec('cmd_memory') 566def test_mmc_fat_read_write_files(u_boot_console): 567 test_mmc_list(u_boot_console) 568 test_mmc_dev(u_boot_console) 569 test_mmcinfo(u_boot_console) 570 test_mmc_part(u_boot_console) 571 if not mmc_set_up: 572 pytest.skip('No SD/MMC/eMMC controller available') 573 574 if not devices: 575 pytest.skip('No devices detected') 576 577 part_detect = 0 578 fs = 'fat' 579 580 # Number of files to be written/read in MMC card 581 num_files = 100 582 583 for x in range(0, controllers): 584 if devices[x]['detected'] == 'yes': 585 u_boot_console.run_command('mmc dev %d' % x) 586 try: 587 partitions = devices[x][fs] 588 except: 589 print('No %s table on this device' % fs.upper()) 590 continue 591 592 for part in partitions: 593 part_detect = 1 594 addr = u_boot_utils.find_ram_base(u_boot_console) 595 count_f = 0 596 addr_l = [] 597 size_l = [] 598 file_l = [] 599 crc32_l = [] 600 offset_l = [] 601 addr_l.append(addr) 602 603 while count_f < num_files: 604 size_l.append(random.randint(4, 1 * 1024 * 1024)) 605 606 # CRC32 count 607 output = u_boot_console.run_command( 608 'crc32 %x %x' % (addr_l[count_f], size_l[count_f]) 609 ) 610 m = re.search('==> (.+?)', output) 611 if not m: 612 pytest.fail('CRC32 failed') 613 crc32_l.append(m.group(1)) 614 615 # Write operation 616 file_l.append('%s_%d_%d' % ('uboot_test', count_f, size_l[count_f])) 617 output = u_boot_console.run_command( 618 '%swrite mmc %d:%s %x %s %x' 619 % ( 620 fs, 621 x, 622 part, 623 addr_l[count_f], 624 file_l[count_f], 625 size_l[count_f], 626 ) 627 ) 628 assert 'Unable to write' not in output 629 assert 'Error' not in output 630 assert 'overflow' not in output 631 expected_text = '%d bytes written' % size_l[count_f] 632 assert expected_text in output 633 634 addr_l.append(addr_l[count_f] + size_l[count_f] + 1048576) 635 count_f += 1 636 637 count_f = 0 638 while count_f < num_files: 639 alignment = int( 640 u_boot_console.config.buildconfig.get( 641 'config_sys_cacheline_size', 128 642 ) 643 ) 644 offset_l.append(random.randrange(alignment, 1024, alignment)) 645 646 # Read operation 647 output = u_boot_console.run_command( 648 '%sload mmc %d:%s %x %s' 649 % ( 650 fs, 651 x, 652 part, 653 addr_l[count_f] + offset_l[count_f], 654 file_l[count_f], 655 ) 656 ) 657 assert 'Invalid FAT entry' not in output 658 assert 'Unable to read file' not in output 659 assert 'Misaligned buffer address' not in output 660 expected_text = '%d bytes read' % size_l[count_f] 661 assert expected_text in output 662 663 output = u_boot_console.run_command( 664 'crc32 %x $filesize' % (addr_l[count_f] + offset_l[count_f]) 665 ) 666 assert crc32_l[count_f] in output 667 668 count_f += 1 669 670 if not part_detect: 671 pytest.skip('No %s partition detected' % fs.upper()) 672