Merge branch '2024-01-29-pytest-enhancements'

- Update pygit2 version and add a number of additional hardware pytests
This commit is contained in:
Tom Rini 2024-01-29 10:56:56 -05:00
commit ce54325c42
8 changed files with 1983 additions and 2 deletions

View file

@ -11,10 +11,10 @@ more-itertools==7.2.0
packaging==23.2
pbr==5.4.3
pluggy==0.13.0
py==1.10.0
py==1.11.0
pycryptodomex==3.19.1
pyelftools==0.27
pygit2==1.9.2
pygit2==1.13.3
pyparsing==3.0.7
pytest==6.2.5
pytest-xdist==2.5.0

View file

@ -85,6 +85,13 @@ env__gpio_dev_config = {
'gpio_ip_pin_clear':'66',
'gpio_clear_value': 'value is 0',
'gpio_set_value': 'value is 1',
# GPIO pin list to test gpio functionality for each pins, pin should be
# pin names (str)
'gpio_pin_list': ['gpio@1000031', 'gpio@1000032', 'gpio@20000033'],
# GPIO input output list for shorted gpio pins to test gpio
# functionality for each of pairs, where the first element is
# configured as input and second as output
'gpio_ip_op_list': [['gpio0', 'gpio1'], ['gpio2', 'gpio3']],
}
"""
@ -223,3 +230,86 @@ def test_gpio_input_generic(u_boot_console):
response = u_boot_console.run_command(cmd)
good_response = gpio_set_value
assert good_response in response
@pytest.mark.buildconfigspec('cmd_gpio')
def test_gpio_pins_generic(u_boot_console):
"""Test various gpio related functionality, such as the input, set, clear,
and toggle for the set of gpio pin list.
Specific set of gpio pins (by mentioning gpio pin name) configured as
input (mentioned as 'gpio_pin_list') to be tested for multiple gpio
commands.
"""
f = u_boot_console.config.env.get('env__gpio_dev_config', False)
if not f:
pytest.skip('gpio not configured')
gpio_pins = f.get('gpio_pin_list', None)
if not gpio_pins:
pytest.skip('gpio pin list are not configured')
for gpin in gpio_pins:
# gpio input
u_boot_console.run_command(f'gpio input {gpin}')
expected_response = f'{gpin}: input:'
response = u_boot_console.run_command(f'gpio status -a {gpin}')
assert expected_response in response
# gpio set
u_boot_console.run_command(f'gpio set {gpin}')
expected_response = f'{gpin}: output: 1'
response = u_boot_console.run_command(f'gpio status -a {gpin}')
assert expected_response in response
# gpio clear
u_boot_console.run_command(f'gpio clear {gpin}')
expected_response = f'{gpin}: output: 0'
response = u_boot_console.run_command(f'gpio status -a {gpin}')
assert expected_response in response
# gpio toggle
u_boot_console.run_command(f'gpio toggle {gpin}')
expected_response = f'{gpin}: output: 1'
response = u_boot_console.run_command(f'gpio status -a {gpin}')
assert expected_response in response
@pytest.mark.buildconfigspec('cmd_gpio')
def test_gpio_pins_input_output_generic(u_boot_console):
"""Test gpio related functionality such as input and output for the list of
shorted gpio pins provided as a pair of input and output pins. This test
will fail, if the gpio pins are not shorted properly.
Specific set of shorted gpio pins (by mentioning gpio pin name)
configured as input and output (mentioned as 'gpio_ip_op_list') as a
pair to be tested for gpio input output case.
"""
f = u_boot_console.config.env.get('env__gpio_dev_config', False)
if not f:
pytest.skip('gpio not configured')
gpio_pins = f.get('gpio_ip_op_list', None)
if not gpio_pins:
pytest.skip('gpio pin list for input and output are not configured')
for gpins in gpio_pins:
u_boot_console.run_command(f'gpio input {gpins[0]}')
expected_response = f'{gpins[0]}: input:'
response = u_boot_console.run_command(f'gpio status -a {gpins[0]}')
assert expected_response in response
u_boot_console.run_command(f'gpio set {gpins[1]}')
expected_response = f'{gpins[1]}: output:'
response = u_boot_console.run_command(f'gpio status -a {gpins[1]}')
assert expected_response in response
u_boot_console.run_command(f'gpio clear {gpins[1]}')
expected_response = f'{gpins[0]}: input: 0'
response = u_boot_console.run_command(f'gpio status -a {gpins[0]}')
assert expected_response in response
u_boot_console.run_command(f'gpio set {gpins[1]}')
expected_response = f'{gpins[0]}: input: 1'
response = u_boot_console.run_command(f'gpio status -a {gpins[0]}')
assert expected_response in response

671
test/py/tests/test_mmc.py Normal file
View file

@ -0,0 +1,671 @@
# SPDX-License-Identifier: GPL-2.0
# (C) Copyright 2023, Advanced Micro Devices, Inc.
import pytest
import random
import re
import u_boot_utils
"""
Note: This test doesn't rely on boardenv_* configuration values but it can
change the test behavior. To test MMC file system cases (fat32, ext2, ext4),
MMC device should be formatted and valid partitions should be created for
different file system, otherwise it may leads to failure. This test will be
skipped if the MMC device is not detected.
For example:
# Setup env__mmc_device_test_skip to not skipping the test. By default, its
# value is set to True. Set it to False to run all tests for MMC device.
env__mmc_device_test_skip = False
"""
mmc_set_up = False
controllers = 0
devices = {}
def setup_mmc(u_boot_console):
if u_boot_console.config.env.get('env__mmc_device_test_skip', True):
pytest.skip('MMC device test is not enabled')
@pytest.mark.buildconfigspec('cmd_mmc')
def test_mmc_list(u_boot_console):
setup_mmc(u_boot_console)
output = u_boot_console.run_command('mmc list')
if 'No MMC device available' in output:
pytest.skip('No SD/MMC/eMMC controller available')
if 'Card did not respond to voltage select' in output:
pytest.skip('No SD/MMC card present')
array = output.split()
global devices
global controllers
controllers = int(len(array) / 2)
for x in range(0, controllers):
y = x * 2
devices[x] = {}
devices[x]['name'] = array[y]
global mmc_set_up
mmc_set_up = True
@pytest.mark.buildconfigspec('cmd_mmc')
def test_mmc_dev(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
fail = 0
for x in range(0, controllers):
devices[x]['detected'] = 'yes'
output = u_boot_console.run_command('mmc dev %d' % x)
# Some sort of switch here
if 'Card did not respond to voltage select' in output:
fail = 1
devices[x]['detected'] = 'no'
if 'no mmc device at slot' in output:
devices[x]['detected'] = 'no'
if 'MMC: no card present' in output:
devices[x]['detected'] = 'no'
if fail:
pytest.fail('Card not present')
@pytest.mark.buildconfigspec('cmd_mmc')
def test_mmcinfo(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
output = u_boot_console.run_command('mmcinfo')
if 'busy timeout' in output:
pytest.skip('No SD/MMC/eMMC device present')
obj = re.search(r'Capacity: (\d+|\d+[\.]?\d)', output)
try:
capacity = float(obj.groups()[0])
print(capacity)
devices[x]['capacity'] = capacity
print('Capacity of dev %d is: %g GiB' % (x, capacity))
except ValueError:
pytest.fail('MMC capacity not recognized')
@pytest.mark.buildconfigspec('cmd_mmc')
def test_mmc_info(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
output = u_boot_console.run_command('mmc info')
obj = re.search(r'Capacity: (\d+|\d+[\.]?\d)', output)
try:
capacity = float(obj.groups()[0])
print(capacity)
if devices[x]['capacity'] != capacity:
pytest.fail("MMC capacity doesn't match mmcinfo")
except ValueError:
pytest.fail('MMC capacity not recognized')
@pytest.mark.buildconfigspec('cmd_mmc')
def test_mmc_rescan(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
if not devices:
pytest.skip('No devices detected')
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
output = u_boot_console.run_command('mmc rescan')
if output:
pytest.fail('mmc rescan has something to check')
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_mmc')
def test_mmc_part(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
if not devices:
pytest.skip('No devices detected')
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
output = u_boot_console.run_command('mmc part')
lines = output.split('\n')
part_fat = []
part_ext = []
for line in lines:
obj = re.search(
r'(\d)\s+\d+\s+\d+\s+\w+\d+\w+-\d+\s+(\d+\w+)', line)
if obj:
part_id = int(obj.groups()[0])
part_type = obj.groups()[1]
print('part_id:%d, part_type:%s' % (part_id, part_type))
if part_type in ['0c', '0b', '0e']:
print('Fat detected')
part_fat.append(part_id)
elif part_type == '83':
print('ext detected')
part_ext.append(part_id)
else:
pytest.fail('Unsupported Filesystem on device %d' % x)
devices[x]['ext4'] = part_ext
devices[x]['ext2'] = part_ext
devices[x]['fat'] = part_fat
if not part_ext and not part_fat:
pytest.fail('No partition detected on device %d' % x)
@pytest.mark.buildconfigspec('cmd_mmc')
@pytest.mark.buildconfigspec('cmd_fat')
def test_mmc_fatls_fatinfo(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'fat'
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
output = u_boot_console.run_command(
'fatls mmc %d:%s' % (x, part))
if 'Unrecognized filesystem type' in output:
partitions.remove(part)
pytest.fail('Unrecognized filesystem')
if not re.search(r'\d file\(s\), \d dir\(s\)', output):
pytest.fail('%s read failed on device %d' % (fs.upper, x))
output = u_boot_console.run_command(
'fatinfo mmc %d:%s' % (x, part))
string = 'Filesystem: %s' % fs.upper
if re.search(string, output):
pytest.fail('%s FS failed on device %d' % (fs.upper(), x))
part_detect = 1
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())
@pytest.mark.buildconfigspec('cmd_mmc')
@pytest.mark.buildconfigspec('cmd_fat')
@pytest.mark.buildconfigspec('cmd_memory')
def test_mmc_fatload_fatwrite(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'fat'
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
addr = u_boot_utils.find_ram_base(u_boot_console)
devices[x]['addr_%d' % part] = addr
size = random.randint(4, 1 * 1024 * 1024)
devices[x]['size_%d' % part] = size
# count CRC32
output = u_boot_console.run_command('crc32 %x %x' % (addr, size))
m = re.search('==> (.+?)', output)
if not m:
pytest.fail('CRC32 failed')
expected_crc32 = m.group(1)
devices[x]['expected_crc32_%d' % part] = expected_crc32
# do write
file = '%s_%d' % ('uboot_test', size)
devices[x]['file_%d' % part] = file
output = u_boot_console.run_command(
'%swrite mmc %d:%s %x %s %x' % (fs, x, part, addr, file, size)
)
assert 'Unable to write' not in output
assert 'Error' not in output
assert 'overflow' not in output
expected_text = '%d bytes written' % size
assert expected_text in output
alignment = int(
u_boot_console.config.buildconfig.get(
'config_sys_cacheline_size', 128
)
)
offset = random.randrange(alignment, 1024, alignment)
output = u_boot_console.run_command(
'%sload mmc %d:%s %x %s' % (fs, x, part, addr + offset, file)
)
assert 'Invalid FAT entry' not in output
assert 'Unable to read file' not in output
assert 'Misaligned buffer address' not in output
expected_text = '%d bytes read' % size
assert expected_text in output
output = u_boot_console.run_command(
'crc32 %x $filesize' % (addr + offset)
)
assert expected_crc32 in output
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())
@pytest.mark.buildconfigspec('cmd_mmc')
@pytest.mark.buildconfigspec('cmd_ext4')
def test_mmc_ext4ls(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'ext4'
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
u_boot_console.run_command('mmc dev %d' % x)
for part in partitions:
output = u_boot_console.run_command('%sls mmc %d:%s' % (fs, x, part))
if 'Unrecognized filesystem type' in output:
partitions.remove(part)
pytest.fail('Unrecognized filesystem')
part_detect = 1
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())
@pytest.mark.buildconfigspec('cmd_mmc')
@pytest.mark.buildconfigspec('cmd_ext4')
@pytest.mark.buildconfigspec('ext4_write')
@pytest.mark.buildconfigspec('cmd_memory')
def test_mmc_ext4load_ext4write(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'ext4'
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
addr = u_boot_utils.find_ram_base(u_boot_console)
devices[x]['addr_%d' % part] = addr
size = random.randint(4, 1 * 1024 * 1024)
devices[x]['size_%d' % part] = size
# count CRC32
output = u_boot_console.run_command('crc32 %x %x' % (addr, size))
m = re.search('==> (.+?)', output)
if not m:
pytest.fail('CRC32 failed')
expected_crc32 = m.group(1)
devices[x]['expected_crc32_%d' % part] = expected_crc32
# do write
file = '%s_%d' % ('uboot_test', size)
devices[x]['file_%d' % part] = file
output = u_boot_console.run_command(
'%swrite mmc %d:%s %x /%s %x' % (fs, x, part, addr, file, size)
)
assert 'Unable to write' not in output
assert 'Error' not in output
assert 'overflow' not in output
expected_text = '%d bytes written' % size
assert expected_text in output
offset = random.randrange(128, 1024, 128)
output = u_boot_console.run_command(
'%sload mmc %d:%s %x /%s' % (fs, x, part, addr + offset, file)
)
expected_text = '%d bytes read' % size
assert expected_text in output
output = u_boot_console.run_command(
'crc32 %x $filesize' % (addr + offset)
)
assert expected_crc32 in output
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())
@pytest.mark.buildconfigspec('cmd_mmc')
@pytest.mark.buildconfigspec('cmd_ext2')
def test_mmc_ext2ls(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'ext2'
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
output = u_boot_console.run_command('%sls mmc %d:%s' % (fs, x, part))
if 'Unrecognized filesystem type' in output:
partitions.remove(part)
pytest.fail('Unrecognized filesystem')
part_detect = 1
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())
@pytest.mark.buildconfigspec('cmd_mmc')
@pytest.mark.buildconfigspec('cmd_ext2')
@pytest.mark.buildconfigspec('cmd_ext4')
@pytest.mark.buildconfigspec('ext4_write')
@pytest.mark.buildconfigspec('cmd_memory')
def test_mmc_ext2load(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'ext2'
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
addr = devices[x]['addr_%d' % part]
size = devices[x]['size_%d' % part]
expected_crc32 = devices[x]['expected_crc32_%d' % part]
file = devices[x]['file_%d' % part]
offset = random.randrange(128, 1024, 128)
output = u_boot_console.run_command(
'%sload mmc %d:%s %x /%s' % (fs, x, part, addr + offset, file)
)
expected_text = '%d bytes read' % size
assert expected_text in output
output = u_boot_console.run_command(
'crc32 %x $filesize' % (addr + offset)
)
assert expected_crc32 in output
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())
@pytest.mark.buildconfigspec('cmd_mmc')
@pytest.mark.buildconfigspec('cmd_fs_generic')
def test_mmc_ls(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
if not devices:
pytest.skip('No devices detected')
part_detect = 0
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
for fs in ['fat', 'ext4']:
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
output = u_boot_console.run_command('ls mmc %d:%s' % (x, part))
if re.search(r'No \w+ table on this device', output):
pytest.fail(
'%s: Partition table not found %d' % (fs.upper(), x)
)
if not part_detect:
pytest.skip('No partition detected')
@pytest.mark.buildconfigspec('cmd_mmc')
@pytest.mark.buildconfigspec('cmd_fs_generic')
def test_mmc_load(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
if not devices:
pytest.skip('No devices detected')
part_detect = 0
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
for fs in ['fat', 'ext4']:
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
addr = devices[x]['addr_%d' % part]
size = devices[x]['size_%d' % part]
expected_crc32 = devices[x]['expected_crc32_%d' % part]
file = devices[x]['file_%d' % part]
offset = random.randrange(128, 1024, 128)
output = u_boot_console.run_command(
'load mmc %d:%s %x /%s' % (x, part, addr + offset, file)
)
expected_text = '%d bytes read' % size
assert expected_text in output
output = u_boot_console.run_command(
'crc32 %x $filesize' % (addr + offset)
)
assert expected_crc32 in output
if not part_detect:
pytest.skip('No partition detected')
@pytest.mark.buildconfigspec('cmd_mmc')
@pytest.mark.buildconfigspec('cmd_fs_generic')
def test_mmc_save(u_boot_console):
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
if not devices:
pytest.skip('No devices detected')
part_detect = 0
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
for fs in ['fat', 'ext4']:
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
addr = devices[x]['addr_%d' % part]
size = 0
file = devices[x]['file_%d' % part]
offset = random.randrange(128, 1024, 128)
output = u_boot_console.run_command(
'save mmc %d:%s %x /%s %d'
% (x, part, addr + offset, file, size)
)
expected_text = '%d bytes written' % size
assert expected_text in output
if not part_detect:
pytest.skip('No partition detected')
@pytest.mark.buildconfigspec('cmd_mmc')
@pytest.mark.buildconfigspec('cmd_fat')
@pytest.mark.buildconfigspec('cmd_memory')
def test_mmc_fat_read_write_files(u_boot_console):
test_mmc_list(u_boot_console)
test_mmc_dev(u_boot_console)
test_mmcinfo(u_boot_console)
test_mmc_part(u_boot_console)
if not mmc_set_up:
pytest.skip('No SD/MMC/eMMC controller available')
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'fat'
# Number of files to be written/read in MMC card
num_files = 100
for x in range(0, controllers):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('mmc dev %d' % x)
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
addr = u_boot_utils.find_ram_base(u_boot_console)
count_f = 0
addr_l = []
size_l = []
file_l = []
crc32_l = []
offset_l = []
addr_l.append(addr)
while count_f < num_files:
size_l.append(random.randint(4, 1 * 1024 * 1024))
# CRC32 count
output = u_boot_console.run_command(
'crc32 %x %x' % (addr_l[count_f], size_l[count_f])
)
m = re.search('==> (.+?)', output)
if not m:
pytest.fail('CRC32 failed')
crc32_l.append(m.group(1))
# Write operation
file_l.append('%s_%d_%d' % ('uboot_test', count_f, size_l[count_f]))
output = u_boot_console.run_command(
'%swrite mmc %d:%s %x %s %x'
% (
fs,
x,
part,
addr_l[count_f],
file_l[count_f],
size_l[count_f],
)
)
assert 'Unable to write' not in output
assert 'Error' not in output
assert 'overflow' not in output
expected_text = '%d bytes written' % size_l[count_f]
assert expected_text in output
addr_l.append(addr_l[count_f] + size_l[count_f] + 1048576)
count_f += 1
count_f = 0
while count_f < num_files:
alignment = int(
u_boot_console.config.buildconfig.get(
'config_sys_cacheline_size', 128
)
)
offset_l.append(random.randrange(alignment, 1024, alignment))
# Read operation
output = u_boot_console.run_command(
'%sload mmc %d:%s %x %s'
% (
fs,
x,
part,
addr_l[count_f] + offset_l[count_f],
file_l[count_f],
)
)
assert 'Invalid FAT entry' not in output
assert 'Unable to read file' not in output
assert 'Misaligned buffer address' not in output
expected_text = '%d bytes read' % size_l[count_f]
assert expected_text in output
output = u_boot_console.run_command(
'crc32 %x $filesize' % (addr_l[count_f] + offset_l[count_f])
)
assert crc32_l[count_f] in output
count_f += 1
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())

View file

@ -0,0 +1,92 @@
# SPDX-License-Identifier: GPL-2.0
# (C) Copyright 2023, Advanced Micro Devices, Inc.
import pytest
"""
Note: This test relies on boardenv_* containing configuration values to define
the SCSI device number, type and capacity. This test will be automatically
skipped without this.
For example:
# Setup env__scsi_device_test to set the SCSI device number/slot, the type of
device, and the device capacity in MB.
env__scsi_device_test = {
'dev_num': 0,
'device_type': 'Hard Disk',
'device_capacity': '476940.0 MB',
}
"""
def scsi_setup(u_boot_console):
f = u_boot_console.config.env.get('env__scsi_device_test', None)
if not f:
pytest.skip('No SCSI device to test')
dev_num = f.get('dev_num', None)
if not isinstance(dev_num, int):
pytest.skip('No device number specified in env file to read')
dev_type = f.get('device_type')
if not dev_type:
pytest.skip('No device type specified in env file to read')
dev_size = f.get('device_capacity')
if not dev_size:
pytest.skip('No device capacity specified in env file to read')
return dev_num, dev_type, dev_size
@pytest.mark.buildconfigspec('cmd_scsi')
def test_scsi_reset(u_boot_console):
dev_num, dev_type, dev_size = scsi_setup(u_boot_console)
output = u_boot_console.run_command('scsi reset')
assert f'Device {dev_num}:' in output
assert f'Type: {dev_type}' in output
assert f'Capacity: {dev_size}' in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_scsi')
def test_scsi_info(u_boot_console):
dev_num, dev_type, dev_size = scsi_setup(u_boot_console)
output = u_boot_console.run_command('scsi info')
assert f'Device {dev_num}:' in output
assert f'Type: {dev_type}' in output
assert f'Capacity: {dev_size}' in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_scsi')
def test_scsi_scan(u_boot_console):
dev_num, dev_type, dev_size = scsi_setup(u_boot_console)
output = u_boot_console.run_command('scsi scan')
assert f'Device {dev_num}:' in output
assert f'Type: {dev_type}' in output
assert f'Capacity: {dev_size}' in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_scsi')
def test_scsi_dev(u_boot_console):
dev_num, dev_type, dev_size = scsi_setup(u_boot_console)
output = u_boot_console.run_command('scsi device')
assert 'no scsi devices available' not in output
assert f'device {dev_num}:' in output
assert f'Type: {dev_type}' in output
assert f'Capacity: {dev_size}' in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
output = u_boot_console.run_command('scsi device %d' % dev_num)
assert 'is now current device' in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_scsi')
def test_scsi_part(u_boot_console):
test_scsi_dev(u_boot_console)
output = u_boot_console.run_command('scsi part')
assert 'Partition Map for SCSI device' in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')

626
test/py/tests/test_usb.py Normal file
View file

@ -0,0 +1,626 @@
# SPDX-License-Identifier: GPL-2.0
# (C) Copyright 2023, Advanced Micro Devices, Inc.
import pytest
import random
import re
import u_boot_utils
"""
Note: This test doesn't rely on boardenv_* configuration values but it can
change the test behavior. To test USB file system cases (fat32, ext2, ext4),
USB device should be formatted and valid partitions should be created for
different file system, otherwise it may leads to failure. This test will be
skipped if the USB device is not detected.
For example:
# Setup env__usb_device_test_skip to not skipping the test. By default, its
# value is set to True. Set it to False to run all tests for USB device.
env__usb_device_test_skip = False
"""
def setup_usb(u_boot_console):
if u_boot_console.config.env.get('env__usb_device_test_skip', True):
pytest.skip('USB device test is not enabled')
@pytest.mark.buildconfigspec('cmd_usb')
def test_usb_start(u_boot_console):
setup_usb(u_boot_console)
output = u_boot_console.run_command('usb start')
# if output is empty, usb start may already run as part of preboot command
# re-start the usb, in that case
if not output:
u_boot_console.run_command('usb stop')
output = u_boot_console.run_command('usb start')
if 'No USB device found' in output:
pytest.skip('No USB controller available')
if 'Card did not respond to voltage select' in output:
pytest.skip('No USB device present')
controllers = 0
storage_device = 0
obj = re.search(r'\d USB Device\(s\) found', output)
controllers = int(obj.group()[0])
if not controllers:
pytest.skip('No USB device present')
obj = re.search(r'\d Storage Device\(s\) found', output)
storage_device = int(obj.group()[0])
if not storage_device:
pytest.skip('No USB storage device present')
assert 'USB init failed' not in output
assert 'starting USB...' in output
if 'Starting the controller' in output:
assert 'USB XHCI' in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
return controllers, storage_device
@pytest.mark.buildconfigspec('cmd_usb')
def test_usb_stop(u_boot_console):
setup_usb(u_boot_console)
output = u_boot_console.run_command('usb stop')
assert 'stopping USB..' in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
output = u_boot_console.run_command('usb dev')
assert "USB is stopped. Please issue 'usb start' first." in output
@pytest.mark.buildconfigspec('cmd_usb')
def test_usb_reset(u_boot_console):
setup_usb(u_boot_console)
output = u_boot_console.run_command('usb reset')
if 'No USB device found' in output:
pytest.skip('No USB controller available')
if 'Card did not respond to voltage select' in output:
pytest.skip('No USB device present')
obj = re.search(r'\d USB Device\(s\) found', output)
usb_dev_num = int(obj.group()[0])
if not usb_dev_num:
pytest.skip('No USB device present')
obj = re.search(r'\d Storage Device\(s\) found', output)
usb_stor_num = int(obj.group()[0])
if not usb_stor_num:
pytest.skip('No USB storage device present')
assert 'BUG' not in output
assert 'USB init failed' not in output
assert 'resetting USB...' in output
if 'Starting the controller' in output:
assert 'USB XHCI' in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_usb')
def test_usb_info(u_boot_console):
controllers, storage_device = test_usb_start(u_boot_console)
output = u_boot_console.run_command('usb info')
num_controller = len(re.findall(': Hub,', output))
num_mass_storage = len(re.findall(': Mass Storage,', output))
assert num_controller == controllers - 1
assert num_mass_storage == storage_device
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
for i in range(0, storage_device + controllers - 1):
output = u_boot_console.run_command('usb info %d' % i)
num_controller = len(re.findall(': Hub,', output))
num_mass_storage = len(re.findall(': Mass Storage,', output))
assert num_controller + num_mass_storage == 1
assert 'No device available' not in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_usb')
def test_usb_tree(u_boot_console):
controllers, storage_device = test_usb_start(u_boot_console)
output = u_boot_console.run_command('usb tree')
num_controller = len(re.findall('Hub', output))
num_mass_storage = len(re.findall('Mass Storage', output))
assert num_controller == controllers - 1
assert num_mass_storage == storage_device
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_usb')
@pytest.mark.buildconfigspec('usb_storage')
def test_usb_storage(u_boot_console):
controllers, storage_device = test_usb_start(u_boot_console)
output = u_boot_console.run_command('usb storage')
obj = re.findall(r'Capacity: (\d+|\d+[\.]?\d)', output)
devices = {}
for key in range(int(storage_device)):
devices[key] = {}
for x in range(int(storage_device)):
try:
capacity = float(obj[x].split()[0])
devices[x]['capacity'] = capacity
print('USB storage device %d capacity is: %g MB' % (x, capacity))
except ValueError:
pytest.fail('USB storage device capacity not recognized')
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_usb')
def test_usb_dev(u_boot_console):
controllers, storage_device = test_usb_start(u_boot_console)
output = u_boot_console.run_command('usb dev')
assert 'no usb devices available' not in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
devices = {}
for key in range(int(storage_device)):
devices[key] = {}
fail = 0
for x in range(0, storage_device):
devices[x]['detected'] = 'yes'
output = u_boot_console.run_command('usb dev %d' % x)
if 'Card did not respond to voltage select' in output:
fail = 1
devices[x]['detected'] = 'no'
if 'No USB device found' in output:
devices[x]['detected'] = 'no'
if 'unknown device' in output:
devices[x]['detected'] = 'no'
assert 'is now current device' in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
if fail:
pytest.fail('USB device not present')
return devices, controllers, storage_device
@pytest.mark.buildconfigspec('cmd_usb')
def test_usb_part(u_boot_console):
devices, controllers, storage_device = test_usb_dev(u_boot_console)
if not devices:
pytest.skip('No devices detected')
u_boot_console.run_command('usb part')
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
for i in range(0, storage_device):
if devices[i]['detected'] == 'yes':
u_boot_console.run_command('usb dev %d' % i)
output = u_boot_console.run_command('usb part')
lines = output.split('\n')
part_fat = []
part_ext = []
for line in lines:
obj = re.search(r'(\d)\s+\d+\s+\d+\s+\w+\d+\w+-\d+\s+(\d+\w+)', line)
if obj:
part_id = int(obj.groups()[0])
part_type = obj.groups()[1]
print('part_id:%d, part_type:%s' % (part_id, part_type))
if part_type == '0c' or part_type == '0b' or part_type == '0e':
print('Fat detected')
part_fat.append(part_id)
elif part_type == '83':
print('ext detected')
part_ext.append(part_id)
else:
pytest.fail('Unsupported Filesystem on device %d' % i)
devices[i]['ext4'] = part_ext
devices[i]['ext2'] = part_ext
devices[i]['fat'] = part_fat
if not part_ext and not part_fat:
pytest.fail('No partition detected on device %d' % i)
return devices, controllers, storage_device
@pytest.mark.buildconfigspec('cmd_usb')
@pytest.mark.buildconfigspec('cmd_fat')
def test_usb_fatls_fatinfo(u_boot_console):
devices, controllers, storage_device = test_usb_part(u_boot_console)
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'fat'
for x in range(0, int(storage_device)):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('usb dev %d' % x)
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
output = u_boot_console.run_command('fatls usb %d:%s' % (x, part))
if 'Unrecognized filesystem type' in output:
partitions.remove(part)
pytest.fail('Unrecognized filesystem')
if not re.search(r'\d file\(s\), \d dir\(s\)', output):
pytest.fail('%s read failed on device %d' % (fs.upper, x))
output = u_boot_console.run_command('fatinfo usb %d:%s' % (x, part))
string = 'Filesystem: %s' % fs.upper
if re.search(string, output):
pytest.fail('%s FS failed on device %d' % (fs.upper(), x))
part_detect = 1
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())
@pytest.mark.buildconfigspec('cmd_usb')
@pytest.mark.buildconfigspec('cmd_fat')
@pytest.mark.buildconfigspec('cmd_memory')
def test_usb_fatload_fatwrite(u_boot_console):
devices, controllers, storage_device = test_usb_part(u_boot_console)
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'fat'
for x in range(0, int(storage_device)):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('usb dev %d' % x)
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
addr = u_boot_utils.find_ram_base(u_boot_console)
size = random.randint(4, 1 * 1024 * 1024)
output = u_boot_console.run_command('crc32 %x %x' % (addr, size))
m = re.search('==> (.+?)', output)
if not m:
pytest.fail('CRC32 failed')
expected_crc32 = m.group(1)
file = '%s_%d' % ('uboot_test', size)
output = u_boot_console.run_command(
'%swrite usb %d:%s %x %s %x' % (fs, x, part, addr, file, size)
)
assert 'Unable to write' not in output
assert 'Error' not in output
assert 'overflow' not in output
expected_text = '%d bytes written' % size
assert expected_text in output
alignment = int(
u_boot_console.config.buildconfig.get(
'config_sys_cacheline_size', 128
)
)
offset = random.randrange(alignment, 1024, alignment)
output = u_boot_console.run_command(
'%sload usb %d:%s %x %s' % (fs, x, part, addr + offset, file)
)
assert 'Invalid FAT entry' not in output
assert 'Unable to read file' not in output
assert 'Misaligned buffer address' not in output
expected_text = '%d bytes read' % size
assert expected_text in output
output = u_boot_console.run_command(
'crc32 %x $filesize' % (addr + offset)
)
assert expected_crc32 in output
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())
return file, size
@pytest.mark.buildconfigspec('cmd_usb')
@pytest.mark.buildconfigspec('cmd_ext4')
def test_usb_ext4ls(u_boot_console):
devices, controllers, storage_device = test_usb_part(u_boot_console)
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'ext4'
for x in range(0, int(storage_device)):
if devices[x]['detected'] == 'yes':
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
u_boot_console.run_command('usb dev %d' % x)
for part in partitions:
output = u_boot_console.run_command('%sls usb %d:%s' % (fs, x, part))
if 'Unrecognized filesystem type' in output:
partitions.remove(part)
pytest.fail('Unrecognized filesystem')
part_detect = 1
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())
@pytest.mark.buildconfigspec('cmd_usb')
@pytest.mark.buildconfigspec('cmd_ext4')
@pytest.mark.buildconfigspec('ext4_write')
@pytest.mark.buildconfigspec('cmd_memory')
def test_usb_ext4load_ext4write(u_boot_console):
devices, controllers, storage_device = test_usb_part(u_boot_console)
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'ext4'
for x in range(0, int(storage_device)):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('usb dev %d' % x)
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
addr = u_boot_utils.find_ram_base(u_boot_console)
size = random.randint(4, 1 * 1024 * 1024)
output = u_boot_console.run_command('crc32 %x %x' % (addr, size))
m = re.search('==> (.+?)', output)
if not m:
pytest.fail('CRC32 failed')
expected_crc32 = m.group(1)
file = '%s_%d' % ('uboot_test', size)
output = u_boot_console.run_command(
'%swrite usb %d:%s %x /%s %x' % (fs, x, part, addr, file, size)
)
assert 'Unable to write' not in output
assert 'Error' not in output
assert 'overflow' not in output
expected_text = '%d bytes written' % size
assert expected_text in output
offset = random.randrange(128, 1024, 128)
output = u_boot_console.run_command(
'%sload usb %d:%s %x /%s' % (fs, x, part, addr + offset, file)
)
expected_text = '%d bytes read' % size
assert expected_text in output
output = u_boot_console.run_command(
'crc32 %x $filesize' % (addr + offset)
)
assert expected_crc32 in output
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())
return file, size
@pytest.mark.buildconfigspec('cmd_usb')
@pytest.mark.buildconfigspec('cmd_ext2')
def test_usb_ext2ls(u_boot_console):
devices, controllers, storage_device = test_usb_part(u_boot_console)
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'ext2'
for x in range(0, int(storage_device)):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('usb dev %d' % x)
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
output = u_boot_console.run_command('%sls usb %d:%s' % (fs, x, part))
if 'Unrecognized filesystem type' in output:
partitions.remove(part)
pytest.fail('Unrecognized filesystem')
part_detect = 1
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())
@pytest.mark.buildconfigspec('cmd_usb')
@pytest.mark.buildconfigspec('cmd_ext2')
@pytest.mark.buildconfigspec('cmd_ext4')
@pytest.mark.buildconfigspec('ext4_write')
@pytest.mark.buildconfigspec('cmd_memory')
def test_usb_ext2load(u_boot_console):
devices, controllers, storage_device = test_usb_part(u_boot_console)
file, size = test_usb_ext4load_ext4write(u_boot_console)
if not devices:
pytest.skip('No devices detected')
part_detect = 0
fs = 'ext2'
for x in range(0, int(storage_device)):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('usb dev %d' % x)
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
addr = u_boot_utils.find_ram_base(u_boot_console)
output = u_boot_console.run_command('crc32 %x %x' % (addr, size))
m = re.search('==> (.+?)', output)
if not m:
pytest.fail('CRC32 failed')
expected_crc32 = m.group(1)
offset = random.randrange(128, 1024, 128)
output = u_boot_console.run_command(
'%sload usb %d:%s %x /%s' % (fs, x, part, addr + offset, file)
)
expected_text = '%d bytes read' % size
assert expected_text in output
output = u_boot_console.run_command(
'crc32 %x $filesize' % (addr + offset)
)
assert expected_crc32 in output
if not part_detect:
pytest.skip('No %s partition detected' % fs.upper())
@pytest.mark.buildconfigspec('cmd_usb')
@pytest.mark.buildconfigspec('cmd_fs_generic')
def test_usb_ls(u_boot_console):
devices, controllers, storage_device = test_usb_part(u_boot_console)
if not devices:
pytest.skip('No devices detected')
part_detect = 0
for x in range(0, int(storage_device)):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('usb dev %d' % x)
for fs in ['fat', 'ext4']:
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
output = u_boot_console.run_command('ls usb %d:%s' % (x, part))
if re.search(r'No \w+ table on this device', output):
pytest.fail(
'%s: Partition table not found %d' % (fs.upper(), x)
)
if not part_detect:
pytest.skip('No partition detected')
@pytest.mark.buildconfigspec('cmd_usb')
@pytest.mark.buildconfigspec('cmd_fs_generic')
def test_usb_load(u_boot_console):
devices, controllers, storage_device = test_usb_part(u_boot_console)
if not devices:
pytest.skip('No devices detected')
part_detect = 0
for x in range(0, int(storage_device)):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('usb dev %d' % x)
for fs in ['fat', 'ext4']:
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
addr = u_boot_utils.find_ram_base(u_boot_console)
if fs == 'fat':
file, size = test_usb_fatload_fatwrite(u_boot_console)
elif fs == 'ext4':
file, size = test_usb_ext4load_ext4write(u_boot_console)
output = u_boot_console.run_command('crc32 %x %x' % (addr, size))
m = re.search('==> (.+?)', output)
if not m:
pytest.fail('CRC32 failed')
expected_crc32 = m.group(1)
offset = random.randrange(128, 1024, 128)
output = u_boot_console.run_command(
'load usb %d:%s %x /%s' % (x, part, addr + offset, file)
)
expected_text = '%d bytes read' % size
assert expected_text in output
output = u_boot_console.run_command(
'crc32 %x $filesize' % (addr + offset)
)
assert expected_crc32 in output
if not part_detect:
pytest.skip('No partition detected')
@pytest.mark.buildconfigspec('cmd_usb')
@pytest.mark.buildconfigspec('cmd_fs_generic')
def test_usb_save(u_boot_console):
devices, controllers, storage_device = test_usb_part(u_boot_console)
if not devices:
pytest.skip('No devices detected')
part_detect = 0
for x in range(0, int(storage_device)):
if devices[x]['detected'] == 'yes':
u_boot_console.run_command('usb dev %d' % x)
for fs in ['fat', 'ext4']:
try:
partitions = devices[x][fs]
except:
print('No %s table on this device' % fs.upper())
continue
for part in partitions:
part_detect = 1
addr = u_boot_utils.find_ram_base(u_boot_console)
size = random.randint(4, 1 * 1024 * 1024)
file = '%s_%d' % ('uboot_test', size)
offset = random.randrange(128, 1024, 128)
output = u_boot_console.run_command(
'save usb %d:%s %x /%s %x'
% (x, part, addr + offset, file, size)
)
expected_text = '%d bytes written' % size
assert expected_text in output
if not part_detect:
pytest.skip('No partition detected')

View file

@ -0,0 +1,190 @@
# SPDX-License-Identifier: GPL-2.0
# (C) Copyright 2023, Advanced Micro Devices, Inc.
import pytest
import re
import u_boot_utils
import test_net
"""
This test verifies different type of secure boot images to authentication and
decryption using AES and RSA features for AMD's Zynq SoC.
Note: This test relies on boardenv_* containing configuration values to define
the network available and files to be used for testing. Without this, this test
will be automatically skipped. It also relies on dhcp or setup_static net test
to support tftp to load files from a TFTP server.
For example:
# Details regarding the files that may be read from a TFTP server and addresses
# and size for aes and rsa cases respectively. This variable may be omitted or
# set to None if zynqmp secure testing is not possible or desired.
env__zynq_aes_readable_file = {
'fn': 'zynq_aes_image.bin',
'fnbit': 'zynq_aes_bit.bin',
'fnpbit': 'zynq_aes_par_bit.bin',
'srcaddr': 0x1000000,
'dstaddr': 0x2000000,
'dstlen': 0x1000000,
}
env__zynq_rsa_readable_file = {
'fn': 'zynq_rsa_image.bin',
'fninvalid': 'zynq_rsa_image_invalid.bin',
'srcaddr': 0x1000000,
}
"""
def zynq_secure_pre_commands(u_boot_console):
output = u_boot_console.run_command('print modeboot')
if not 'modeboot=' in output:
pytest.skip('bootmode cannnot be determined')
m = re.search('modeboot=(.+?)boot', output)
if not m:
pytest.skip('bootmode cannnot be determined')
bootmode = m.group(1)
if bootmode == 'jtag':
pytest.skip('skipping due to jtag bootmode')
@pytest.mark.buildconfigspec('cmd_zynq_aes')
def test_zynq_aes_image(u_boot_console):
f = u_boot_console.config.env.get('env__zynq_aes_readable_file', None)
if not f:
pytest.skip('No TFTP readable file for zynq secure aes case to read')
dstaddr = f.get('dstaddr', None)
if not dstaddr:
pytest.skip('No dstaddr specified in env file to read')
dstsize = f.get('dstlen', None)
if not dstsize:
pytest.skip('No dstlen specified in env file to read')
zynq_secure_pre_commands(u_boot_console)
test_net.test_net_dhcp(u_boot_console)
if not test_net.net_set_up:
test_net.test_net_setup_static(u_boot_console)
srcaddr = f.get('srcaddr', None)
if not srcaddr:
addr = u_boot_utils.find_ram_base(u_boot_console)
expected_tftp = 'Bytes transferred = '
fn = f['fn']
output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fn))
assert expected_tftp in output
expected_op = 'zynq aes [operation type] <srcaddr>'
output = u_boot_console.run_command(
'zynq aes %x $filesize %x %x' % (srcaddr, dstaddr, dstsize)
)
assert expected_op not in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_zynq_aes')
def test_zynq_aes_bitstream(u_boot_console):
f = u_boot_console.config.env.get('env__zynq_aes_readable_file', None)
if not f:
pytest.skip('No TFTP readable file for zynq secure aes case to read')
zynq_secure_pre_commands(u_boot_console)
test_net.test_net_dhcp(u_boot_console)
if not test_net.net_set_up:
test_net.test_net_setup_static(u_boot_console)
srcaddr = f.get('srcaddr', None)
if not srcaddr:
addr = u_boot_utils.find_ram_base(u_boot_console)
expected_tftp = 'Bytes transferred = '
fn = f['fnbit']
output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fn))
assert expected_tftp in output
expected_op = 'zynq aes [operation type] <srcaddr>'
output = u_boot_console.run_command(
'zynq aes load %x $filesize' % (srcaddr)
)
assert expected_op not in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_zynq_aes')
def test_zynq_aes_partial_bitstream(u_boot_console):
f = u_boot_console.config.env.get('env__zynq_aes_readable_file', None)
if not f:
pytest.skip('No TFTP readable file for zynq secure aes case to read')
zynq_secure_pre_commands(u_boot_console)
test_net.test_net_dhcp(u_boot_console)
if not test_net.net_set_up:
test_net.test_net_setup_static(u_boot_console)
srcaddr = f.get('srcaddr', None)
if not srcaddr:
addr = u_boot_utils.find_ram_base(u_boot_console)
expected_tftp = 'Bytes transferred = '
fn = f['fnpbit']
output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fn))
assert expected_tftp in output
expected_op = 'zynq aes [operation type] <srcaddr>'
output = u_boot_console.run_command('zynq aes loadp %x $filesize' % (srcaddr))
assert expected_op not in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_zynq_rsa')
def test_zynq_rsa_image(u_boot_console):
f = u_boot_console.config.env.get('env__zynq_rsa_readable_file', None)
if not f:
pytest.skip('No TFTP readable file for zynq secure rsa case to read')
zynq_secure_pre_commands(u_boot_console)
test_net.test_net_dhcp(u_boot_console)
if not test_net.net_set_up:
test_net.test_net_setup_static(u_boot_console)
srcaddr = f.get('srcaddr', None)
if not srcaddr:
addr = u_boot_utils.find_ram_base(u_boot_console)
expected_tftp = 'Bytes transferred = '
fn = f['fn']
output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fn))
assert expected_tftp in output
expected_op = 'zynq rsa <baseaddr>'
output = u_boot_console.run_command('zynq rsa %x ' % (srcaddr))
assert expected_op not in output
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@pytest.mark.buildconfigspec('cmd_zynq_rsa')
def test_zynq_rsa_image_invalid(u_boot_console):
f = u_boot_console.config.env.get('env__zynq_rsa_readable_file', None)
if not f:
pytest.skip('No TFTP readable file for zynq secure rsa case to read')
zynq_secure_pre_commands(u_boot_console)
test_net.test_net_dhcp(u_boot_console)
if not test_net.net_set_up:
test_net.test_net_setup_static(u_boot_console)
srcaddr = f.get('srcaddr', None)
if not srcaddr:
addr = u_boot_utils.find_ram_base(u_boot_console)
expected_tftp = 'Bytes transferred = '
fninvalid = f['fninvalid']
output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fninvalid))
assert expected_tftp in output
expected_op = 'zynq rsa <baseaddr>'
output = u_boot_console.run_command('zynq rsa %x ' % (srcaddr))
assert expected_op in output
output = u_boot_console.run_command('echo $?')
assert not output.endswith('0')

View file

@ -0,0 +1,208 @@
# SPDX-License-Identifier: GPL-2.0
# (C) Copyright 2023, Advanced Micro Devices, Inc.
import pytest
import random
import string
import test_net
"""
Note: This test relies on boardenv_* containing configuration values to define
RPU applications information for AMD's ZynqMP SoC which contains, application
names, processors, address where it is built, expected output and the tftp load
addresses. This test will be automatically skipped without this.
It also relies on dhcp or setup_static net test to support tftp to load
application on DDR. All the environment parameters are stored sequentially.
The length of all parameters values should be same. For example, if 2 app_names
are defined in a list as a value of parameter 'app_name' then the other
parameters value also should have a list with 2 items.
It will run RPU cases for all the applications defined in boardenv_*
configuration file.
Example:
env__zynqmp_rpu_apps = {
'app_name': ['hello_world_r5_0_ddr.elf', 'hello_world_r5_1_ddr.elf'],
'proc': ['rpu0', 'rpu1'],
'cpu_num': [4, 5],
'addr': [0xA00000, 0xB00000],
'output': ['Successfully ran Hello World application on DDR from RPU0',
'Successfully ran Hello World application on DDR from RPU1'],
'tftp_addr': [0x100000, 0x200000],
}
"""
# Get rpu apps params from env
def get_rpu_apps_env(u_boot_console):
rpu_apps = u_boot_console.config.env.get('env__zynqmp_rpu_apps', False)
if not rpu_apps:
pytest.skip('ZynqMP RPU application info not defined!')
apps = rpu_apps.get('app_name', None)
if not apps:
pytest.skip('No RPU application found!')
procs = rpu_apps.get('proc', None)
if not procs:
pytest.skip('No RPU application processor provided!')
cpu_nums = rpu_apps.get('cpu_num', None)
if not cpu_nums:
pytest.skip('No CPU number for respective processor provided!')
addrs = rpu_apps.get('addr', None)
if not addrs:
pytest.skip('No RPU application build address found!')
outputs = rpu_apps.get('output', None)
if not outputs:
pytest.skip('Expected output not found!')
tftp_addrs = rpu_apps.get('tftp_addr', None)
if not tftp_addrs:
pytest.skip('TFTP address to load application not found!')
return apps, procs, cpu_nums, addrs, outputs, tftp_addrs
# Check return code
def ret_code(u_boot_console):
return u_boot_console.run_command('echo $?')
# Initialize tcm
def tcminit(u_boot_console, rpu_mode):
output = u_boot_console.run_command('zynqmp tcminit %s' % rpu_mode)
assert 'Initializing TCM overwrites TCM content' in output
return ret_code(u_boot_console)
# Load application in DDR
def load_app_ddr(u_boot_console, tftp_addr, app):
output = u_boot_console.run_command('tftpboot %x %s' % (tftp_addr, app))
assert 'TIMEOUT' not in output
assert 'Bytes transferred = ' in output
# Load elf
u_boot_console.run_command('bootelf -p %x' % tftp_addr)
assert ret_code(u_boot_console).endswith('0')
# Disable cpus
def disable_cpus(u_boot_console, cpu_nums):
for num in cpu_nums:
u_boot_console.run_command(f'cpu {num} disable')
# Load apps on RPU cores
def rpu_apps_load(u_boot_console, rpu_mode):
apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
u_boot_console)
test_net.test_net_dhcp(u_boot_console)
if not test_net.net_set_up:
test_net.test_net_setup_static(u_boot_console)
try:
assert tcminit(u_boot_console, rpu_mode).endswith('0')
for i in range(len(apps)):
if rpu_mode == 'lockstep' and procs[i] != 'rpu0':
continue
load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
rel_addr = int(addrs[i] + 0x3C)
# Release cpu at app load address
cpu_num = cpu_nums[i]
cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rpu_mode)
output = u_boot_console.run_command(cmd)
exp_op = f'Using TCM jump trampoline for address {hex(rel_addr)}'
assert exp_op in output
assert f'R5 {rpu_mode} mode' in output
u_boot_console.wait_for(outputs[i])
assert ret_code(u_boot_console).endswith('0')
finally:
disable_cpus(u_boot_console, cpu_nums)
@pytest.mark.buildconfigspec('cmd_zynqmp')
def test_zynqmp_rpu_app_load_split(u_boot_console):
rpu_apps_load(u_boot_console, 'split')
@pytest.mark.buildconfigspec('cmd_zynqmp')
def test_zynqmp_rpu_app_load_lockstep(u_boot_console):
rpu_apps_load(u_boot_console, 'lockstep')
@pytest.mark.buildconfigspec('cmd_zynqmp')
def test_zynqmp_rpu_app_load_negative(u_boot_console):
apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
u_boot_console)
# Invalid commands
u_boot_console.run_command('zynqmp tcminit mode')
assert ret_code(u_boot_console).endswith('1')
rand_str = ''.join(random.choices(string.ascii_lowercase, k=4))
u_boot_console.run_command('zynqmp tcminit %s' % rand_str)
assert ret_code(u_boot_console).endswith('1')
rand_num = random.randint(2, 100)
u_boot_console.run_command('zynqmp tcminit %d' % rand_num)
assert ret_code(u_boot_console).endswith('1')
test_net.test_net_dhcp(u_boot_console)
if not test_net.net_set_up:
test_net.test_net_setup_static(u_boot_console)
try:
rpu_mode = 'split'
assert tcminit(u_boot_console, rpu_mode).endswith('0')
for i in range(len(apps)):
load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
# Run in split mode at different load address
rel_addr = int(addrs[i]) + random.randint(200, 1000)
cpu_num = cpu_nums[i]
cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rpu_mode)
output = u_boot_console.run_command(cmd)
exp_op = f'Using TCM jump trampoline for address {hex(rel_addr)}'
assert exp_op in output
assert f'R5 {rpu_mode} mode' in output
assert not outputs[i] in output
# Invalid rpu mode
rand_str = ''.join(random.choices(string.ascii_lowercase, k=4))
cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rand_str)
output = u_boot_console.run_command(cmd)
assert exp_op in output
assert f'Unsupported mode' in output
assert not ret_code(u_boot_console).endswith('0')
# Switch to lockstep mode, without disabling CPUs
rpu_mode = 'lockstep'
u_boot_console.run_command('zynqmp tcminit %s' % rpu_mode)
assert not ret_code(u_boot_console).endswith('0')
# Disable cpus
disable_cpus(u_boot_console, cpu_nums)
# Switch to lockstep mode, after disabling CPUs
output = u_boot_console.run_command('zynqmp tcminit %s' % rpu_mode)
assert 'Initializing TCM overwrites TCM content' in output
assert ret_code(u_boot_console).endswith('0')
# Run lockstep mode for RPU1
for i in range(len(apps)):
if procs[i] == 'rpu0':
continue
load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
rel_addr = int(addrs[i] + 0x3C)
cpu_num = cpu_nums[i]
cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rpu_mode)
output = u_boot_console.run_command(cmd)
exp_op = f'Using TCM jump trampoline for address {hex(rel_addr)}'
assert exp_op in output
assert f'R5 {rpu_mode} mode' in output
assert u_boot_console.p.expect([outputs[i]])
finally:
disable_cpus(u_boot_console, cpu_nums)
# This forces the console object to be shutdown, so any subsequent test
# will reset the board back into U-Boot.
u_boot_console.drain_console()
u_boot_console.cleanup_spawn()

View file

@ -0,0 +1,104 @@
# SPDX-License-Identifier: GPL-2.0
# (C) Copyright 2023, Advanced Micro Devices, Inc.
import pytest
import re
import u_boot_utils
import test_net
"""
This test verifies different type of secure boot images loaded at the DDR for
AMD's ZynqMP SoC.
Note: This test relies on boardenv_* containing configuration values to define
the files to be used for testing. Without this, this test will be automatically
skipped. It also relies on dhcp or setup_static net test to support tftp to
load files from a TFTP server.
For example:
# Details regarding the files that may be read from a TFTP server. This
# variable may be omitted or set to None if zynqmp secure testing is not
# possible or desired.
env__zynqmp_secure_readable_file = {
'fn': 'auth_bhdr_ppk1.bin',
'enckupfn': 'auth_bhdr_enc_kup_load.bin',
'addr': 0x1000000,
'keyaddr': 0x100000,
'keyfn': 'aes.txt',
}
"""
@pytest.mark.buildconfigspec('cmd_zynqmp')
def test_zynqmp_secure_boot_image(u_boot_console):
"""This test verifies secure boot image at the DDR address for
authentication only case.
"""
f = u_boot_console.config.env.get('env__zynqmp_secure_readable_file', None)
if not f:
pytest.skip('No TFTP readable file for zynqmp secure cases to read')
test_net.test_net_dhcp(u_boot_console)
if not test_net.net_set_up:
test_net.test_net_setup_static(u_boot_console)
addr = f.get('addr', None)
if not addr:
addr = u_boot_utils.find_ram_base(u_boot_console)
expected_tftp = 'Bytes transferred = '
fn = f['fn']
output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
assert expected_tftp in output
output = u_boot_console.run_command('zynqmp secure %x $filesize' % (addr))
assert 'Verified image at' in output
ver_addr = re.search(r'Verified image at 0x(.+)', output).group(1)
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
output = u_boot_console.run_command('print zynqmp_verified_img_addr')
assert f'zynqmp_verified_img_addr={ver_addr}' in output
assert 'Error' not in output
@pytest.mark.buildconfigspec('cmd_zynqmp')
def test_zynqmp_secure_boot_img_kup(u_boot_console):
"""This test verifies secure boot image at the DDR address for encryption
with kup key case.
"""
f = u_boot_console.config.env.get('env__zynqmp_secure_readable_file', None)
if not f:
pytest.skip('No TFTP readable file for zynqmp secure cases to read')
test_net.test_net_dhcp(u_boot_console)
if not test_net.net_set_up:
test_net.test_net_setup_static(u_boot_console)
keyaddr = f.get('keyaddr', None)
if not keyaddr:
addr = u_boot_utils.find_ram_base(u_boot_console)
expected_tftp = 'Bytes transferred = '
keyfn = f['keyfn']
output = u_boot_console.run_command('tftpboot %x %s' % (keyaddr, keyfn))
assert expected_tftp in output
addr = f.get('addr', None)
if not addr:
addr = u_boot_utils.find_ram_base(u_boot_console)
expected_tftp = 'Bytes transferred = '
fn = f['enckupfn']
output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
assert expected_tftp in output
output = u_boot_console.run_command(
'zynqmp secure %x $filesize %x' % (addr, keyaddr)
)
assert 'Verified image at' in output
ver_addr = re.search(r'Verified image at 0x(.+)', output).group(1)
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
output = u_boot_console.run_command('print zynqmp_verified_img_addr')
assert f'zynqmp_verified_img_addr={ver_addr}' in output
assert 'Error' not in output