GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2015 Stephen Warren
|
||||
# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
# pytest runs tests the order of their module path, which is related to the
|
||||
# filename containing the test. This file is named such that it is sorted
|
||||
# first, simply as a very basic sanity check of the functionality of the U-Boot
|
||||
# command prompt.
|
||||
|
||||
def test_version(u_boot_console):
|
||||
"""Test that the "version" command prints the U-Boot version."""
|
||||
|
||||
# "version" prints the U-Boot sign-on message. This is usually considered
|
||||
# an error, so that any unexpected reboot causes an error. Here, this
|
||||
# error detection is disabled since the sign-on message is expected.
|
||||
with u_boot_console.disable_check('main_signon'):
|
||||
response = u_boot_console.run_command('version')
|
||||
# Ensure "version" printed what we expected.
|
||||
u_boot_console.validate_version_string_in_text(response)
|
||||
@@ -0,0 +1,75 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# (C) Copyright 2018 Texas Instruments, <www.ti.com>
|
||||
|
||||
# Test A/B update commands.
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import u_boot_utils
|
||||
|
||||
class ABTestDiskImage(object):
|
||||
"""Disk Image used by the A/B tests."""
|
||||
|
||||
def __init__(self, u_boot_console):
|
||||
"""Initialize a new ABTestDiskImage object.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
filename = 'test_ab_disk_image.bin'
|
||||
|
||||
persistent = u_boot_console.config.persistent_data_dir + '/' + filename
|
||||
self.path = u_boot_console.config.result_dir + '/' + filename
|
||||
|
||||
with u_boot_utils.persistent_file_helper(u_boot_console.log, persistent):
|
||||
if os.path.exists(persistent):
|
||||
u_boot_console.log.action('Disk image file ' + persistent +
|
||||
' already exists')
|
||||
else:
|
||||
u_boot_console.log.action('Generating ' + persistent)
|
||||
fd = os.open(persistent, os.O_RDWR | os.O_CREAT)
|
||||
os.ftruncate(fd, 524288)
|
||||
os.close(fd)
|
||||
cmd = ('sgdisk', persistent)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
|
||||
cmd = ('sgdisk', '--new=1:64:512', '--change-name=1:misc',
|
||||
persistent)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
cmd = ('sgdisk', '--load-backup=' + persistent)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
|
||||
cmd = ('cp', persistent, self.path)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
|
||||
di = None
|
||||
@pytest.fixture(scope='function')
|
||||
def ab_disk_image(u_boot_console):
|
||||
global di
|
||||
if not di:
|
||||
di = ABTestDiskImage(u_boot_console)
|
||||
return di
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.buildconfigspec('android_ab')
|
||||
@pytest.mark.buildconfigspec('cmd_ab_select')
|
||||
@pytest.mark.requiredtool('sgdisk')
|
||||
def test_ab(ab_disk_image, u_boot_console):
|
||||
"""Test the 'ab_select' command."""
|
||||
|
||||
u_boot_console.run_command('host bind 0 ' + ab_disk_image.path)
|
||||
|
||||
output = u_boot_console.run_command('ab_select slot_name host 0#misc')
|
||||
assert 're-initializing A/B metadata' in output
|
||||
assert 'Attempting slot a, tries remaining 7' in output
|
||||
output = u_boot_console.run_command('printenv slot_name')
|
||||
assert 'slot_name=a' in output
|
||||
|
||||
output = u_boot_console.run_command('ab_select slot_name host 0:1')
|
||||
assert 'Attempting slot b, tries remaining 7' in output
|
||||
output = u_boot_console.run_command('printenv slot_name')
|
||||
assert 'slot_name=b' in output
|
||||
@@ -0,0 +1,137 @@
|
||||
# Copyright (c) 2018, Linaro Limited
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Android Verified Boot 2.0 Test
|
||||
|
||||
"""
|
||||
This tests Android Verified Boot 2.0 support in U-boot:
|
||||
|
||||
For additional details about how to build proper vbmeta partition
|
||||
check doc/android/avb2.txt
|
||||
|
||||
For configuration verification:
|
||||
- Corrupt boot partition and check for failure
|
||||
- Corrupt vbmeta partition and check for failure
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import u_boot_utils as util
|
||||
|
||||
# defauld mmc id
|
||||
mmc_dev = 1
|
||||
temp_addr = 0x90000000
|
||||
temp_addr2 = 0x90002000
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_avb')
|
||||
@pytest.mark.buildconfigspec('cmd_mmc')
|
||||
def test_avb_verify(u_boot_console):
|
||||
"""Run AVB 2.0 boot verification chain with avb subset of commands
|
||||
"""
|
||||
|
||||
success_str = "Verification passed successfully"
|
||||
|
||||
response = u_boot_console.run_command('avb init %s' %str(mmc_dev))
|
||||
assert response == ''
|
||||
response = u_boot_console.run_command('avb verify')
|
||||
assert response.find(success_str)
|
||||
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_avb')
|
||||
@pytest.mark.buildconfigspec('cmd_mmc')
|
||||
def test_avb_mmc_uuid(u_boot_console):
|
||||
"""Check if 'avb get_uuid' works, compare results with
|
||||
'part list mmc 1' output
|
||||
"""
|
||||
|
||||
response = u_boot_console.run_command('avb init %s' % str(mmc_dev))
|
||||
assert response == ''
|
||||
|
||||
response = u_boot_console.run_command('mmc rescan; mmc dev %s' %
|
||||
str(mmc_dev))
|
||||
assert response.find('is current device')
|
||||
|
||||
part_lines = u_boot_console.run_command('mmc part').splitlines()
|
||||
part_list = {}
|
||||
cur_partname = ''
|
||||
|
||||
for line in part_lines:
|
||||
if '"' in line:
|
||||
start_pt = line.find('"')
|
||||
end_pt = line.find('"', start_pt + 1)
|
||||
cur_partname = line[start_pt + 1: end_pt]
|
||||
|
||||
if 'guid:' in line:
|
||||
guid_to_check = line.split('guid:\t')
|
||||
part_list[cur_partname] = guid_to_check[1]
|
||||
|
||||
# lets check all guids with avb get_guid
|
||||
for part, guid in part_list.iteritems():
|
||||
avb_guid_resp = u_boot_console.run_command('avb get_uuid %s' % part)
|
||||
assert guid == avb_guid_resp.split('UUID: ')[1]
|
||||
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_avb')
|
||||
def test_avb_read_rb(u_boot_console):
|
||||
"""Test reading rollback indexes
|
||||
"""
|
||||
|
||||
response = u_boot_console.run_command('avb init %s' % str(mmc_dev))
|
||||
assert response == ''
|
||||
|
||||
response = u_boot_console.run_command('avb read_rb 1')
|
||||
assert response == 'Rollback index: 0'
|
||||
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_avb')
|
||||
def test_avb_is_unlocked(u_boot_console):
|
||||
"""Test if device is in the unlocked state
|
||||
"""
|
||||
|
||||
response = u_boot_console.run_command('avb init %s' % str(mmc_dev))
|
||||
assert response == ''
|
||||
|
||||
response = u_boot_console.run_command('avb is_unlocked')
|
||||
assert response == 'Unlocked = 1'
|
||||
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_avb')
|
||||
@pytest.mark.buildconfigspec('cmd_mmc')
|
||||
def test_avb_mmc_read(u_boot_console):
|
||||
"""Test mmc read operation
|
||||
"""
|
||||
|
||||
response = u_boot_console.run_command('mmc rescan; mmc dev %s 0' %
|
||||
str(mmc_dev))
|
||||
assert response.find('is current device')
|
||||
|
||||
response = u_boot_console.run_command('mmc read 0x%x 0x100 0x1' % temp_addr)
|
||||
assert response.find('read: OK')
|
||||
|
||||
response = u_boot_console.run_command('avb init %s' % str(mmc_dev))
|
||||
assert response == ''
|
||||
|
||||
response = u_boot_console.run_command('avb read_part xloader 0 100 0x%x' %
|
||||
temp_addr2)
|
||||
assert response.find('Read 512 bytes')
|
||||
|
||||
# Now lets compare two buffers
|
||||
response = u_boot_console.run_command('cmp 0x%x 0x%x 40' %
|
||||
(temp_addr, temp_addr2))
|
||||
assert response.find('64 word')
|
||||
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_avb')
|
||||
@pytest.mark.buildconfigspec('optee_ta_avb')
|
||||
def test_avb_persistent_values(u_boot_console):
|
||||
"""Test reading/writing persistent storage to avb
|
||||
"""
|
||||
|
||||
response = u_boot_console.run_command('avb init %s' % str(mmc_dev))
|
||||
assert response == ''
|
||||
|
||||
response = u_boot_console.run_command('avb write_pvalue test value_value')
|
||||
assert response == 'Wrote 12 bytes'
|
||||
|
||||
response = u_boot_console.run_command('avb read_pvalue test 12')
|
||||
assert response == 'Read 12 bytes, value = value_value'
|
||||
@@ -0,0 +1,179 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
import os.path
|
||||
import pytest
|
||||
import re
|
||||
|
||||
def in_tree(response, name, uclass, drv, depth, last_child):
|
||||
lines = [x.strip() for x in response.splitlines()]
|
||||
leaf = ' ' * 4 * depth;
|
||||
if not last_child:
|
||||
leaf = leaf + r'\|'
|
||||
else:
|
||||
leaf = leaf + '`'
|
||||
leaf = leaf + '-- ' + name
|
||||
line = (r' *{:10.10} [0-9]* \[ [ +] \] {:20.20} {}$'
|
||||
.format(uclass, drv, leaf))
|
||||
prog = re.compile(line)
|
||||
for l in lines:
|
||||
if prog.match(l):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_bind')
|
||||
def test_bind_unbind_with_node(u_boot_console):
|
||||
|
||||
#bind /bind-test. Device should come up as well as its children
|
||||
response = u_boot_console.run_command('bind /bind-test generic_simple_bus')
|
||||
assert response == ''
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True)
|
||||
assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, False)
|
||||
assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True)
|
||||
|
||||
#Unbind child #1. No error expected and all devices should be there except for bind-test-child1
|
||||
response = u_boot_console.run_command('unbind /bind-test/bind-test-child1')
|
||||
assert response == ''
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True)
|
||||
assert 'bind-test-child1' not in tree
|
||||
assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True)
|
||||
|
||||
#bind child #1. No error expected and all devices should be there
|
||||
response = u_boot_console.run_command('bind /bind-test/bind-test-child1 phy_sandbox')
|
||||
assert response == ''
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True)
|
||||
assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, True)
|
||||
assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, False)
|
||||
|
||||
#Unbind child #2. No error expected and all devices should be there except for bind-test-child2
|
||||
response = u_boot_console.run_command('unbind /bind-test/bind-test-child2')
|
||||
assert response == ''
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True)
|
||||
assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, True)
|
||||
assert 'bind-test-child2' not in tree
|
||||
|
||||
|
||||
#Bind child #2. No error expected and all devices should be there
|
||||
response = u_boot_console.run_command('bind /bind-test/bind-test-child2 generic_simple_bus')
|
||||
assert response == ''
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True)
|
||||
assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, False)
|
||||
assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True)
|
||||
|
||||
#Unbind parent. No error expected. All devices should be removed and unbound
|
||||
response = u_boot_console.run_command('unbind /bind-test')
|
||||
assert response == ''
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
assert 'bind-test' not in tree
|
||||
assert 'bind-test-child1' not in tree
|
||||
assert 'bind-test-child2' not in tree
|
||||
|
||||
#try binding invalid node with valid driver
|
||||
response = u_boot_console.run_command('bind /not-a-valid-node generic_simple_bus')
|
||||
assert response != ''
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
assert 'not-a-valid-node' not in tree
|
||||
|
||||
#try binding valid node with invalid driver
|
||||
response = u_boot_console.run_command('bind /bind-test not_a_driver')
|
||||
assert response != ''
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
assert 'bind-test' not in tree
|
||||
|
||||
#bind /bind-test. Device should come up as well as its children
|
||||
response = u_boot_console.run_command('bind /bind-test generic_simple_bus')
|
||||
assert response == ''
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True)
|
||||
assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, False)
|
||||
assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True)
|
||||
|
||||
response = u_boot_console.run_command('unbind /bind-test')
|
||||
assert response == ''
|
||||
|
||||
def get_next_line(tree, name):
|
||||
treelines = [x.strip() for x in tree.splitlines() if x.strip()]
|
||||
child_line = ''
|
||||
for idx, line in enumerate(treelines):
|
||||
if ('-- ' + name) in line:
|
||||
try:
|
||||
child_line = treelines[idx+1]
|
||||
except:
|
||||
pass
|
||||
break
|
||||
return child_line
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_bind')
|
||||
def test_bind_unbind_with_uclass(u_boot_console):
|
||||
#bind /bind-test
|
||||
response = u_boot_console.run_command('bind /bind-test generic_simple_bus')
|
||||
assert response == ''
|
||||
|
||||
#make sure bind-test-child2 is there and get its uclass/index pair
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
child2_line = [x.strip() for x in tree.splitlines() if '-- bind-test-child2' in x]
|
||||
assert len(child2_line) == 1
|
||||
|
||||
child2_uclass = child2_line[0].split()[0]
|
||||
child2_index = int(child2_line[0].split()[1])
|
||||
|
||||
#bind generic_simple_bus as a child of bind-test-child2
|
||||
response = u_boot_console.run_command('bind {} {} generic_simple_bus'.format(child2_uclass, child2_index, 'generic_simple_bus'))
|
||||
|
||||
#check that the child is there and its uclass/index pair is right
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
|
||||
child_of_child2_line = get_next_line(tree, 'bind-test-child2')
|
||||
assert child_of_child2_line
|
||||
child_of_child2_index = int(child_of_child2_line.split()[1])
|
||||
assert in_tree(tree, 'generic_simple_bus', 'simple_bus', 'generic_simple_bus', 2, True)
|
||||
assert child_of_child2_index == child2_index + 1
|
||||
|
||||
#unbind the child and check it has been removed
|
||||
response = u_boot_console.run_command('unbind simple_bus {}'.format(child_of_child2_index))
|
||||
assert response == ''
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True)
|
||||
assert not in_tree(tree, 'generic_simple_bus', 'simple_bus', 'generic_simple_bus', 2, True)
|
||||
child_of_child2_line = get_next_line(tree, 'bind-test-child2')
|
||||
assert child_of_child2_line == ''
|
||||
|
||||
#bind generic_simple_bus as a child of bind-test-child2
|
||||
response = u_boot_console.run_command('bind {} {} generic_simple_bus'.format(child2_uclass, child2_index, 'generic_simple_bus'))
|
||||
|
||||
#check that the child is there and its uclass/index pair is right
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
treelines = [x.strip() for x in tree.splitlines() if x.strip()]
|
||||
|
||||
child_of_child2_line = get_next_line(tree, 'bind-test-child2')
|
||||
assert child_of_child2_line
|
||||
child_of_child2_index = int(child_of_child2_line.split()[1])
|
||||
assert in_tree(tree, 'generic_simple_bus', 'simple_bus', 'generic_simple_bus', 2, True)
|
||||
assert child_of_child2_index == child2_index + 1
|
||||
|
||||
#unbind the child and check it has been removed
|
||||
response = u_boot_console.run_command('unbind {} {} generic_simple_bus'.format(child2_uclass, child2_index, 'generic_simple_bus'))
|
||||
assert response == ''
|
||||
|
||||
tree = u_boot_console.run_command('dm tree')
|
||||
assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True)
|
||||
|
||||
child_of_child2_line = get_next_line(tree, 'bind-test-child2')
|
||||
assert child_of_child2_line == ''
|
||||
|
||||
#unbind the child again and check it doesn't change the tree
|
||||
tree_old = u_boot_console.run_command('dm tree')
|
||||
response = u_boot_console.run_command('unbind {} {} generic_simple_bus'.format(child2_uclass, child2_index, 'generic_simple_bus'))
|
||||
tree_new = u_boot_console.run_command('dm tree')
|
||||
|
||||
assert response == ''
|
||||
assert tree_old == tree_new
|
||||
|
||||
response = u_boot_console.run_command('unbind /bind-test')
|
||||
assert response == ''
|
||||
@@ -0,0 +1,320 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
# Test U-Boot's "dfu" command. The test starts DFU in U-Boot, waits for USB
|
||||
# device enumeration on the host, executes dfu-util multiple times to test
|
||||
# various transfer sizes, many of which trigger USB driver edge cases, and
|
||||
# finally aborts the "dfu" command in U-Boot.
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import pytest
|
||||
import u_boot_utils
|
||||
|
||||
"""
|
||||
Note: This test relies on:
|
||||
|
||||
a) boardenv_* to contain configuration values to define which USB ports are
|
||||
available for testing. Without this, this test will be automatically skipped.
|
||||
For example:
|
||||
|
||||
env__usb_dev_ports = (
|
||||
{
|
||||
'fixture_id': 'micro_b',
|
||||
'tgt_usb_ctlr': '0',
|
||||
'host_usb_dev_node': '/dev/usbdev-p2371-2180',
|
||||
# This parameter is optional /if/ you only have a single board
|
||||
# attached to your host at a time.
|
||||
'host_usb_port_path': '3-13',
|
||||
},
|
||||
)
|
||||
|
||||
# Optional entries (required only when 'alt_id_test_file' and
|
||||
# 'alt_id_dummy_file' are specified).
|
||||
test_file_name = '/dfu_test.bin'
|
||||
dummy_file_name = '/dfu_dummy.bin'
|
||||
# Above files are used to generate proper 'alt_info' entry
|
||||
'alt_info': '/%s ext4 0 2;/%s ext4 0 2' % (test_file_name, dummy_file_name),
|
||||
|
||||
env__dfu_configs = (
|
||||
# eMMC, partition 1
|
||||
{
|
||||
'fixture_id': 'emmc',
|
||||
'alt_info': '/dfu_test.bin ext4 0 1;/dfu_dummy.bin ext4 0 1',
|
||||
'cmd_params': 'mmc 0',
|
||||
# This value is optional.
|
||||
# If present, it specified the set of transfer sizes tested.
|
||||
# If missing, a default list of sizes will be used, which covers
|
||||
# various useful corner cases.
|
||||
# Manually specifying test sizes is useful if you wish to test 4 DFU
|
||||
# configurations, but don't want to test every single transfer size
|
||||
# on each, to avoid bloating the overall time taken by testing.
|
||||
'test_sizes': (63, 64, 65),
|
||||
# This value is optional.
|
||||
# The name of the environment variable that the the dfu command reads
|
||||
# alt info from. If unspecified, this defaults to dfu_alt_info, which is
|
||||
# valid for most systems. Some systems use a different variable name.
|
||||
# One example is the Odroid XU3, which automatically generates
|
||||
# $dfu_alt_info, each time the dfu command is run, by concatenating
|
||||
# $dfu_alt_boot and $dfu_alt_system.
|
||||
'alt_info_env_name': 'dfu_alt_system',
|
||||
# This value is optional.
|
||||
# For boards which require the 'test file' alt setting number other than
|
||||
# default (0) it is possible to specify exact file name to be used as
|
||||
# this parameter.
|
||||
'alt_id_test_file': test_file_name,
|
||||
# This value is optional.
|
||||
# For boards which require the 'dummy file' alt setting number other
|
||||
# than default (1) it is possible to specify exact file name to be used
|
||||
# as this parameter.
|
||||
'alt_id_dummy_file': dummy_file_name,
|
||||
},
|
||||
)
|
||||
|
||||
b) udev rules to set permissions on devices nodes, so that sudo is not
|
||||
required. For example:
|
||||
|
||||
ACTION=="add", SUBSYSTEM=="block", SUBSYSTEMS=="usb", KERNELS=="3-13", MODE:="666"
|
||||
|
||||
(You may wish to change the group ID instead of setting the permissions wide
|
||||
open. All that matters is that the user ID running the test can access the
|
||||
device.)
|
||||
|
||||
c) An optional udev rule to give you a persistent value to use in
|
||||
host_usb_dev_node. For example:
|
||||
|
||||
IMPORT{builtin}="path_id"
|
||||
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="", SYMLINK+="bus/usb/by-path/$env{ID_PATH}"
|
||||
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", SYMLINK+="bus/usb/by-path/$env{ID_PATH}-port$env{.ID_PORT}"
|
||||
"""
|
||||
|
||||
# The set of file sizes to test. These values trigger various edge-cases such
|
||||
# as one less than, equal to, and one greater than typical USB max packet
|
||||
# sizes, and similar boundary conditions.
|
||||
test_sizes_default = (
|
||||
64 - 1,
|
||||
64,
|
||||
64 + 1,
|
||||
128 - 1,
|
||||
128,
|
||||
128 + 1,
|
||||
960 - 1,
|
||||
960,
|
||||
960 + 1,
|
||||
4096 - 1,
|
||||
4096,
|
||||
4096 + 1,
|
||||
1024 * 1024 - 1,
|
||||
1024 * 1024,
|
||||
8 * 1024 * 1024,
|
||||
)
|
||||
|
||||
first_usb_dev_port = None
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_dfu')
|
||||
@pytest.mark.requiredtool('dfu-util')
|
||||
def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
|
||||
"""Test the "dfu" command; the host system must be able to enumerate a USB
|
||||
device when "dfu" is running, various DFU transfers are tested, and the
|
||||
USB device must disappear when "dfu" is aborted.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console connection.
|
||||
env__usb_dev_port: The single USB device-mode port specification on
|
||||
which to run the test. See the file-level comment above for
|
||||
details of the format.
|
||||
env__dfu_config: The single DFU (memory region) configuration on which
|
||||
to run the test. See the file-level comment above for details
|
||||
of the format.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
def start_dfu():
|
||||
"""Start U-Boot's dfu shell command.
|
||||
|
||||
This also waits for the host-side USB enumeration process to complete.
|
||||
|
||||
Args:
|
||||
None.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
u_boot_utils.wait_until_file_open_fails(
|
||||
env__usb_dev_port['host_usb_dev_node'], True)
|
||||
fh = u_boot_utils.attempt_to_open_file(
|
||||
env__usb_dev_port['host_usb_dev_node'])
|
||||
if fh:
|
||||
fh.close()
|
||||
raise Exception('USB device present before dfu command invoked')
|
||||
|
||||
u_boot_console.log.action(
|
||||
'Starting long-running U-Boot dfu shell command')
|
||||
|
||||
dfu_alt_info_env = env__dfu_config.get('alt_info_env_name', \
|
||||
'dfu_alt_info')
|
||||
|
||||
cmd = 'setenv "%s" "%s"' % (dfu_alt_info_env,
|
||||
env__dfu_config['alt_info'])
|
||||
u_boot_console.run_command(cmd)
|
||||
|
||||
cmd = 'dfu 0 ' + env__dfu_config['cmd_params']
|
||||
u_boot_console.run_command(cmd, wait_for_prompt=False)
|
||||
u_boot_console.log.action('Waiting for DFU USB device to appear')
|
||||
fh = u_boot_utils.wait_until_open_succeeds(
|
||||
env__usb_dev_port['host_usb_dev_node'])
|
||||
fh.close()
|
||||
|
||||
def stop_dfu(ignore_errors):
|
||||
"""Stop U-Boot's dfu shell command from executing.
|
||||
|
||||
This also waits for the host-side USB de-enumeration process to
|
||||
complete.
|
||||
|
||||
Args:
|
||||
ignore_errors: Ignore any errors. This is useful if an error has
|
||||
already been detected, and the code is performing best-effort
|
||||
cleanup. In this case, we do not want to mask the original
|
||||
error by "honoring" any new errors.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
try:
|
||||
u_boot_console.log.action(
|
||||
'Stopping long-running U-Boot dfu shell command')
|
||||
u_boot_console.ctrlc()
|
||||
u_boot_console.log.action(
|
||||
'Waiting for DFU USB device to disappear')
|
||||
u_boot_utils.wait_until_file_open_fails(
|
||||
env__usb_dev_port['host_usb_dev_node'], ignore_errors)
|
||||
except:
|
||||
if not ignore_errors:
|
||||
raise
|
||||
|
||||
def run_dfu_util(alt_setting, fn, up_dn_load_arg):
|
||||
"""Invoke dfu-util on the host.
|
||||
|
||||
Args:
|
||||
alt_setting: The DFU "alternate setting" identifier to interact
|
||||
with.
|
||||
fn: The host-side file name to transfer.
|
||||
up_dn_load_arg: '-U' or '-D' depending on whether a DFU upload or
|
||||
download operation should be performed.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
cmd = ['dfu-util', '-a', alt_setting, up_dn_load_arg, fn]
|
||||
if 'host_usb_port_path' in env__usb_dev_port:
|
||||
cmd += ['-p', env__usb_dev_port['host_usb_port_path']]
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
u_boot_console.wait_for('Ctrl+C to exit ...')
|
||||
|
||||
def dfu_write(alt_setting, fn):
|
||||
"""Write a file to the target board using DFU.
|
||||
|
||||
Args:
|
||||
alt_setting: The DFU "alternate setting" identifier to interact
|
||||
with.
|
||||
fn: The host-side file name to transfer.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
run_dfu_util(alt_setting, fn, '-D')
|
||||
|
||||
def dfu_read(alt_setting, fn):
|
||||
"""Read a file from the target board using DFU.
|
||||
|
||||
Args:
|
||||
alt_setting: The DFU "alternate setting" identifier to interact
|
||||
with.
|
||||
fn: The host-side file name to transfer.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
# dfu-util fails reads/uploads if the host file already exists
|
||||
if os.path.exists(fn):
|
||||
os.remove(fn)
|
||||
run_dfu_util(alt_setting, fn, '-U')
|
||||
|
||||
def dfu_write_read_check(size):
|
||||
"""Test DFU transfers of a specific size of data
|
||||
|
||||
This function first writes data to the board then reads it back and
|
||||
compares the written and read back data. Measures are taken to avoid
|
||||
certain types of false positives.
|
||||
|
||||
Args:
|
||||
size: The data size to test.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
test_f = u_boot_utils.PersistentRandomFile(u_boot_console,
|
||||
'dfu_%d.bin' % size, size)
|
||||
readback_fn = u_boot_console.config.result_dir + '/dfu_readback.bin'
|
||||
|
||||
u_boot_console.log.action('Writing test data to DFU primary ' +
|
||||
'altsetting')
|
||||
dfu_write(alt_setting_test_file, test_f.abs_fn)
|
||||
|
||||
u_boot_console.log.action('Writing dummy data to DFU secondary ' +
|
||||
'altsetting to clear DFU buffers')
|
||||
dfu_write(alt_setting_dummy_file, dummy_f.abs_fn)
|
||||
|
||||
u_boot_console.log.action('Reading DFU primary altsetting for ' +
|
||||
'comparison')
|
||||
dfu_read(alt_setting_test_file, readback_fn)
|
||||
|
||||
u_boot_console.log.action('Comparing written and read data')
|
||||
written_hash = test_f.content_hash
|
||||
read_back_hash = u_boot_utils.md5sum_file(readback_fn, size)
|
||||
assert(written_hash == read_back_hash)
|
||||
|
||||
# This test may be executed against multiple USB ports. The test takes a
|
||||
# long time, so we don't want to do the whole thing each time. Instead,
|
||||
# execute the full test on the first USB port, and perform a very limited
|
||||
# test on other ports. In the limited case, we solely validate that the
|
||||
# host PC can enumerate the U-Boot USB device.
|
||||
global first_usb_dev_port
|
||||
if not first_usb_dev_port:
|
||||
first_usb_dev_port = env__usb_dev_port
|
||||
if env__usb_dev_port == first_usb_dev_port:
|
||||
sizes = env__dfu_config.get('test_sizes', test_sizes_default)
|
||||
else:
|
||||
sizes = []
|
||||
|
||||
dummy_f = u_boot_utils.PersistentRandomFile(u_boot_console,
|
||||
'dfu_dummy.bin', 1024)
|
||||
|
||||
alt_setting_test_file = env__dfu_config.get('alt_id_test_file', '0')
|
||||
alt_setting_dummy_file = env__dfu_config.get('alt_id_dummy_file', '1')
|
||||
|
||||
ignore_cleanup_errors = True
|
||||
try:
|
||||
start_dfu()
|
||||
|
||||
u_boot_console.log.action(
|
||||
'Overwriting DFU primary altsetting with dummy data')
|
||||
dfu_write(alt_setting_test_file, dummy_f.abs_fn)
|
||||
|
||||
for size in sizes:
|
||||
with u_boot_console.log.section('Data size %d' % size):
|
||||
dfu_write_read_check(size)
|
||||
# Make the status of each sub-test obvious. If the test didn't
|
||||
# pass, an exception was thrown so this code isn't executed.
|
||||
u_boot_console.log.status_pass('OK')
|
||||
ignore_cleanup_errors = False
|
||||
finally:
|
||||
stop_dfu(ignore_cleanup_errors)
|
||||
@@ -0,0 +1,196 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright (c) 2016, Alexander Graf <agraf@suse.de>
|
||||
#
|
||||
# based on test_net.py.
|
||||
|
||||
# Test efi loader implementation
|
||||
|
||||
import pytest
|
||||
import u_boot_utils
|
||||
|
||||
"""
|
||||
Note: This test relies on boardenv_* containing configuration values to define
|
||||
which network environment is available for testing. Without this, the parts
|
||||
that rely on network will be automatically skipped.
|
||||
|
||||
For example:
|
||||
|
||||
# Boolean indicating whether the Ethernet device is attached to USB, and hence
|
||||
# USB enumeration needs to be performed prior to network tests.
|
||||
# This variable may be omitted if its value is False.
|
||||
env__net_uses_usb = False
|
||||
|
||||
# Boolean indicating whether the Ethernet device is attached to PCI, and hence
|
||||
# PCI enumeration needs to be performed prior to network tests.
|
||||
# This variable may be omitted if its value is False.
|
||||
env__net_uses_pci = True
|
||||
|
||||
# True if a DHCP server is attached to the network, and should be tested.
|
||||
# If DHCP testing is not possible or desired, this variable may be omitted or
|
||||
# set to False.
|
||||
env__net_dhcp_server = True
|
||||
|
||||
# A list of environment variables that should be set in order to configure a
|
||||
# static IP. If solely relying on DHCP, this variable may be omitted or set to
|
||||
# an empty list.
|
||||
env__net_static_env_vars = [
|
||||
('ipaddr', '10.0.0.100'),
|
||||
('netmask', '255.255.255.0'),
|
||||
('serverip', '10.0.0.1'),
|
||||
]
|
||||
|
||||
# Details regarding a file that may be read from a TFTP server. This variable
|
||||
# may be omitted or set to None if TFTP testing is not possible or desired.
|
||||
env__efi_loader_helloworld_file = {
|
||||
'fn': 'lib/efi_loader/helloworld.efi',
|
||||
'size': 5058624,
|
||||
'crc32': 'c2244b26',
|
||||
}
|
||||
"""
|
||||
|
||||
net_set_up = False
|
||||
|
||||
def test_efi_pre_commands(u_boot_console):
|
||||
"""Execute any commands required to enable network hardware.
|
||||
|
||||
These commands are provided by the boardenv_* file; see the comment at the
|
||||
beginning of this file.
|
||||
"""
|
||||
|
||||
init_usb = u_boot_console.config.env.get('env__net_uses_usb', False)
|
||||
if init_usb:
|
||||
u_boot_console.run_command('usb start')
|
||||
|
||||
init_pci = u_boot_console.config.env.get('env__net_uses_pci', False)
|
||||
if init_pci:
|
||||
u_boot_console.run_command('pci enum')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_dhcp')
|
||||
def test_efi_dhcp(u_boot_console):
|
||||
"""Test the dhcp command.
|
||||
|
||||
The boardenv_* file may be used to enable/disable this test; see the
|
||||
comment at the beginning of this file.
|
||||
"""
|
||||
|
||||
test_dhcp = u_boot_console.config.env.get('env__net_dhcp_server', False)
|
||||
if not test_dhcp:
|
||||
pytest.skip('No DHCP server available')
|
||||
|
||||
u_boot_console.run_command('setenv autoload no')
|
||||
output = u_boot_console.run_command('dhcp')
|
||||
assert 'DHCP client bound to address ' in output
|
||||
|
||||
global net_set_up
|
||||
net_set_up = True
|
||||
|
||||
@pytest.mark.buildconfigspec('net')
|
||||
def test_efi_setup_static(u_boot_console):
|
||||
"""Set up a static IP configuration.
|
||||
|
||||
The configuration is provided by the boardenv_* file; see the comment at
|
||||
the beginning of this file.
|
||||
"""
|
||||
|
||||
env_vars = u_boot_console.config.env.get('env__net_static_env_vars', None)
|
||||
if not env_vars:
|
||||
pytest.skip('No static network configuration is defined')
|
||||
|
||||
for (var, val) in env_vars:
|
||||
u_boot_console.run_command('setenv %s %s' % (var, val))
|
||||
|
||||
global net_set_up
|
||||
net_set_up = True
|
||||
|
||||
def fetch_tftp_file(u_boot_console, env_conf):
|
||||
"""Grab an env described file via TFTP and return its address
|
||||
|
||||
A file as described by an env config <env_conf> is downloaded from the TFTP
|
||||
server. The address to that file is returned.
|
||||
"""
|
||||
if not net_set_up:
|
||||
pytest.skip('Network not initialized')
|
||||
|
||||
f = u_boot_console.config.env.get(env_conf, None)
|
||||
if not f:
|
||||
pytest.skip('No %s binary specified in environment' % env_conf)
|
||||
|
||||
addr = f.get('addr', None)
|
||||
if not addr:
|
||||
addr = u_boot_utils.find_ram_base(u_boot_console)
|
||||
|
||||
fn = f['fn']
|
||||
output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
|
||||
expected_text = 'Bytes transferred = '
|
||||
sz = f.get('size', None)
|
||||
if sz:
|
||||
expected_text += '%d' % sz
|
||||
assert expected_text in output
|
||||
|
||||
expected_crc = f.get('crc32', None)
|
||||
if not expected_crc:
|
||||
return addr
|
||||
|
||||
if u_boot_console.config.buildconfig.get('config_cmd_crc32', 'n') != 'y':
|
||||
return addr
|
||||
|
||||
output = u_boot_console.run_command('crc32 %x $filesize' % addr)
|
||||
assert expected_crc in output
|
||||
|
||||
return addr
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_bootefi_hello_compile')
|
||||
def test_efi_helloworld_net(u_boot_console):
|
||||
"""Run the helloworld.efi binary via TFTP.
|
||||
|
||||
The helloworld.efi file is downloaded from the TFTP server and gets
|
||||
executed.
|
||||
"""
|
||||
|
||||
addr = fetch_tftp_file(u_boot_console, 'env__efi_loader_helloworld_file')
|
||||
|
||||
output = u_boot_console.run_command('bootefi %x' % addr)
|
||||
expected_text = 'Hello, world'
|
||||
assert expected_text in output
|
||||
expected_text = '## Application terminated, r = 0'
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_bootefi_hello')
|
||||
def test_efi_helloworld_builtin(u_boot_console):
|
||||
"""Run the builtin helloworld.efi binary.
|
||||
|
||||
The helloworld.efi file is included in U-Boot, execute it using the
|
||||
special "bootefi hello" command.
|
||||
"""
|
||||
|
||||
output = u_boot_console.run_command('bootefi hello')
|
||||
expected_text = 'Hello, world'
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_bootefi')
|
||||
def test_efi_grub_net(u_boot_console):
|
||||
"""Run the grub.efi binary via TFTP.
|
||||
|
||||
The grub.efi file is downloaded from the TFTP server and gets
|
||||
executed.
|
||||
"""
|
||||
|
||||
addr = fetch_tftp_file(u_boot_console, 'env__efi_loader_grub_file')
|
||||
|
||||
u_boot_console.run_command('bootefi %x' % addr, wait_for_prompt=False)
|
||||
|
||||
# Verify that we have an SMBIOS table
|
||||
check_smbios = u_boot_console.config.env.get('env__efi_loader_check_smbios', False)
|
||||
if check_smbios:
|
||||
u_boot_console.wait_for('grub>')
|
||||
output = u_boot_console.run_command('lsefisystab', wait_for_prompt=False, wait_for_echo=False)
|
||||
u_boot_console.wait_for('SMBIOS')
|
||||
|
||||
# Then exit cleanly
|
||||
u_boot_console.wait_for('grub>')
|
||||
output = u_boot_console.run_command('exit', wait_for_prompt=False, wait_for_echo=False)
|
||||
u_boot_console.wait_for('r = 0')
|
||||
|
||||
# And give us our U-Boot prompt back
|
||||
u_boot_console.run_command('')
|
||||
@@ -0,0 +1,198 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2017, Heinrich Schuchardt <xypron.glpk@gmx.de>
|
||||
|
||||
# Test efi API implementation
|
||||
|
||||
import pytest
|
||||
import u_boot_utils
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
|
||||
def test_efi_selftest(u_boot_console):
|
||||
"""Test the UEFI implementation
|
||||
|
||||
:param u_boot_console: U-Boot console
|
||||
|
||||
This function executes all selftests that are not marked as on request.
|
||||
"""
|
||||
u_boot_console.run_command(cmd='setenv efi_selftest')
|
||||
u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
|
||||
if m != 0:
|
||||
raise Exception('Failures occurred during the EFI selftest')
|
||||
u_boot_console.restart_uboot();
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
|
||||
@pytest.mark.buildconfigspec('of_control')
|
||||
@pytest.mark.notbuildconfigspec('generate_acpi_table')
|
||||
def test_efi_selftest_device_tree(u_boot_console):
|
||||
u_boot_console.run_command(cmd='setenv efi_selftest list')
|
||||
output = u_boot_console.run_command('bootefi selftest')
|
||||
assert '\'device tree\'' in output
|
||||
u_boot_console.run_command(cmd='setenv efi_selftest device tree')
|
||||
u_boot_console.run_command(cmd='setenv -f serial# Testing DT')
|
||||
u_boot_console.run_command(cmd='bootefi selftest ${fdtcontroladdr}', wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(['serial-number: Testing DT', 'U-Boot'])
|
||||
if m != 0:
|
||||
raise Exception('serial-number missing in device tree')
|
||||
u_boot_console.restart_uboot();
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
|
||||
def test_efi_selftest_watchdog_reboot(u_boot_console):
|
||||
u_boot_console.run_command(cmd='setenv efi_selftest list')
|
||||
output = u_boot_console.run_command('bootefi selftest')
|
||||
assert '\'watchdog reboot\'' in output
|
||||
u_boot_console.run_command(cmd='setenv efi_selftest watchdog reboot')
|
||||
u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(['resetting', 'U-Boot'])
|
||||
if m != 0:
|
||||
raise Exception('Reset failed in \'watchdog reboot\' test')
|
||||
u_boot_console.restart_uboot();
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
|
||||
def test_efi_selftest_text_input(u_boot_console):
|
||||
"""Test the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
|
||||
|
||||
:param u_boot_console: U-Boot console
|
||||
|
||||
This function calls the text input EFI selftest.
|
||||
"""
|
||||
u_boot_console.run_command(cmd='setenv efi_selftest text input')
|
||||
output = u_boot_console.run_command(cmd='bootefi selftest',
|
||||
wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect([r'To terminate type \'x\''])
|
||||
if m != 0:
|
||||
raise Exception('No prompt for \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
u_boot_console.p.timeout = 500
|
||||
# EOT
|
||||
u_boot_console.run_command(cmd=chr(4), wait_for_echo=False,
|
||||
send_nl=False, wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(
|
||||
[r'Unicode char 4 \(unknown\), scan code 0 \(Null\)'])
|
||||
if m != 0:
|
||||
raise Exception('EOT failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
# BS
|
||||
u_boot_console.run_command(cmd=chr(8), wait_for_echo=False,
|
||||
send_nl=False, wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(
|
||||
[r'Unicode char 8 \(BS\), scan code 0 \(Null\)'])
|
||||
if m != 0:
|
||||
raise Exception('BS failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
# TAB
|
||||
u_boot_console.run_command(cmd=chr(9), wait_for_echo=False,
|
||||
send_nl=False, wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(
|
||||
[r'Unicode char 9 \(TAB\), scan code 0 \(Null\)'])
|
||||
if m != 0:
|
||||
raise Exception('BS failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
# a
|
||||
u_boot_console.run_command(cmd='a', wait_for_echo=False, send_nl=False,
|
||||
wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(
|
||||
[r'Unicode char 97 \(\'a\'\), scan code 0 \(Null\)'])
|
||||
if m != 0:
|
||||
raise Exception('\'a\' failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
# UP escape sequence
|
||||
u_boot_console.run_command(cmd=chr(27) + '[A', wait_for_echo=False,
|
||||
send_nl=False, wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(
|
||||
[r'Unicode char 0 \(Null\), scan code 1 \(Up\)'])
|
||||
if m != 0:
|
||||
raise Exception('UP failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
# Euro sign
|
||||
u_boot_console.run_command(cmd=b'\xe2\x82\xac'.decode(), wait_for_echo=False,
|
||||
send_nl=False, wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect([r'Unicode char 8364 \(\''])
|
||||
if m != 0:
|
||||
raise Exception('Euro sign failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
u_boot_console.run_command(cmd='x', wait_for_echo=False, send_nl=False,
|
||||
wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
|
||||
if m != 0:
|
||||
raise Exception('Failures occurred during the EFI selftest')
|
||||
u_boot_console.restart_uboot();
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
|
||||
def test_efi_selftest_text_input_ex(u_boot_console):
|
||||
"""Test the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
|
||||
|
||||
:param u_boot_console: U-Boot console
|
||||
|
||||
This function calls the extended text input EFI selftest.
|
||||
"""
|
||||
u_boot_console.run_command(cmd='setenv efi_selftest extended text input')
|
||||
output = u_boot_console.run_command(cmd='bootefi selftest',
|
||||
wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect([r'To terminate type \'CTRL\+x\''])
|
||||
if m != 0:
|
||||
raise Exception('No prompt for \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
u_boot_console.p.timeout = 500
|
||||
# EOT
|
||||
u_boot_console.run_command(cmd=chr(4), wait_for_echo=False,
|
||||
send_nl=False, wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(
|
||||
[r'Unicode char 100 \(\'d\'\), scan code 0 \(CTRL\+Null\)'])
|
||||
if m != 0:
|
||||
raise Exception('EOT failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
# BS
|
||||
u_boot_console.run_command(cmd=chr(8), wait_for_echo=False,
|
||||
send_nl=False, wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(
|
||||
[r'Unicode char 8 \(BS\), scan code 0 \(\+Null\)'])
|
||||
if m != 0:
|
||||
raise Exception('BS failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
# TAB
|
||||
u_boot_console.run_command(cmd=chr(9), wait_for_echo=False,
|
||||
send_nl=False, wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(
|
||||
[r'Unicode char 9 \(TAB\), scan code 0 \(\+Null\)'])
|
||||
if m != 0:
|
||||
raise Exception('TAB failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
# a
|
||||
u_boot_console.run_command(cmd='a', wait_for_echo=False, send_nl=False,
|
||||
wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(
|
||||
[r'Unicode char 97 \(\'a\'\), scan code 0 \(Null\)'])
|
||||
if m != 0:
|
||||
raise Exception('\'a\' failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
# UP escape sequence
|
||||
u_boot_console.run_command(cmd=chr(27) + '[A', wait_for_echo=False,
|
||||
send_nl=False, wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(
|
||||
[r'Unicode char 0 \(Null\), scan code 1 \(\+Up\)'])
|
||||
if m != 0:
|
||||
raise Exception('UP failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
# Euro sign
|
||||
u_boot_console.run_command(cmd=b'\xe2\x82\xac'.decode(), wait_for_echo=False,
|
||||
send_nl=False, wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect([r'Unicode char 8364 \(\''])
|
||||
if m != 0:
|
||||
raise Exception('Euro sign failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
# SHIFT+ALT+FN 5
|
||||
u_boot_console.run_command(cmd=b'\x1b\x5b\x31\x35\x3b\x34\x7e'.decode(),
|
||||
wait_for_echo=False, send_nl=False,
|
||||
wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(
|
||||
[r'Unicode char 0 \(Null\), scan code 15 \(SHIFT\+ALT\+FN 5\)'])
|
||||
if m != 0:
|
||||
raise Exception('SHIFT+ALT+FN 5 failed in \'text input\' test')
|
||||
u_boot_console.drain_console()
|
||||
u_boot_console.run_command(cmd=chr(24), wait_for_echo=False, send_nl=False,
|
||||
wait_for_prompt=False)
|
||||
m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
|
||||
if m != 0:
|
||||
raise Exception('Failures occurred during the EFI selftest')
|
||||
u_boot_console.restart_uboot();
|
||||
@@ -0,0 +1,338 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2015 Stephen Warren
|
||||
# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
# Test operation of shell commands relating to environment variables.
|
||||
|
||||
import pytest
|
||||
import u_boot_utils
|
||||
|
||||
# FIXME: This might be useful for other tests;
|
||||
# perhaps refactor it into ConsoleBase or some other state object?
|
||||
class StateTestEnv(object):
|
||||
"""Container that represents the state of all U-Boot environment variables.
|
||||
This enables quick determination of existant/non-existant variable
|
||||
names.
|
||||
"""
|
||||
|
||||
def __init__(self, u_boot_console):
|
||||
"""Initialize a new StateTestEnv object.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
self.u_boot_console = u_boot_console
|
||||
self.get_env()
|
||||
self.set_var = self.get_non_existent_var()
|
||||
|
||||
def get_env(self):
|
||||
"""Read all current environment variables from U-Boot.
|
||||
|
||||
Args:
|
||||
None.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
if self.u_boot_console.config.buildconfig.get(
|
||||
'config_version_variable', 'n') == 'y':
|
||||
with self.u_boot_console.disable_check('main_signon'):
|
||||
response = self.u_boot_console.run_command('printenv')
|
||||
else:
|
||||
response = self.u_boot_console.run_command('printenv')
|
||||
self.env = {}
|
||||
for l in response.splitlines():
|
||||
if not '=' in l:
|
||||
continue
|
||||
(var, value) = l.split('=', 1)
|
||||
self.env[var] = value
|
||||
|
||||
def get_existent_var(self):
|
||||
"""Return the name of an environment variable that exists.
|
||||
|
||||
Args:
|
||||
None.
|
||||
|
||||
Returns:
|
||||
The name of an environment variable.
|
||||
"""
|
||||
|
||||
for var in self.env:
|
||||
return var
|
||||
|
||||
def get_non_existent_var(self):
|
||||
"""Return the name of an environment variable that does not exist.
|
||||
|
||||
Args:
|
||||
None.
|
||||
|
||||
Returns:
|
||||
The name of an environment variable.
|
||||
"""
|
||||
|
||||
n = 0
|
||||
while True:
|
||||
var = 'test_env_' + str(n)
|
||||
if var not in self.env:
|
||||
return var
|
||||
n += 1
|
||||
|
||||
ste = None
|
||||
@pytest.fixture(scope='function')
|
||||
def state_test_env(u_boot_console):
|
||||
"""pytest fixture to provide a StateTestEnv object to tests."""
|
||||
|
||||
global ste
|
||||
if not ste:
|
||||
ste = StateTestEnv(u_boot_console)
|
||||
return ste
|
||||
|
||||
def unset_var(state_test_env, var):
|
||||
"""Unset an environment variable.
|
||||
|
||||
This both executes a U-Boot shell command and updates a StateTestEnv
|
||||
object.
|
||||
|
||||
Args:
|
||||
state_test_env: The StateTestEnv object to update.
|
||||
var: The variable name to unset.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
state_test_env.u_boot_console.run_command('setenv %s' % var)
|
||||
if var in state_test_env.env:
|
||||
del state_test_env.env[var]
|
||||
|
||||
def set_var(state_test_env, var, value):
|
||||
"""Set an environment variable.
|
||||
|
||||
This both executes a U-Boot shell command and updates a StateTestEnv
|
||||
object.
|
||||
|
||||
Args:
|
||||
state_test_env: The StateTestEnv object to update.
|
||||
var: The variable name to set.
|
||||
value: The value to set the variable to.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
bc = state_test_env.u_boot_console.config.buildconfig
|
||||
if bc.get('config_hush_parser', None):
|
||||
quote = '"'
|
||||
else:
|
||||
quote = ''
|
||||
if ' ' in value:
|
||||
pytest.skip('Space in variable value on non-Hush shell')
|
||||
|
||||
state_test_env.u_boot_console.run_command(
|
||||
'setenv %s %s%s%s' % (var, quote, value, quote))
|
||||
state_test_env.env[var] = value
|
||||
|
||||
def validate_empty(state_test_env, var):
|
||||
"""Validate that a variable is not set, using U-Boot shell commands.
|
||||
|
||||
Args:
|
||||
var: The variable name to test.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
response = state_test_env.u_boot_console.run_command('echo $%s' % var)
|
||||
assert response == ''
|
||||
|
||||
def validate_set(state_test_env, var, value):
|
||||
"""Validate that a variable is set, using U-Boot shell commands.
|
||||
|
||||
Args:
|
||||
var: The variable name to test.
|
||||
value: The value the variable is expected to have.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
# echo does not preserve leading, internal, or trailing whitespace in the
|
||||
# value. printenv does, and hence allows more complete testing.
|
||||
response = state_test_env.u_boot_console.run_command('printenv %s' % var)
|
||||
assert response == ('%s=%s' % (var, value))
|
||||
|
||||
def test_env_echo_exists(state_test_env):
|
||||
"""Test echoing a variable that exists."""
|
||||
|
||||
var = state_test_env.get_existent_var()
|
||||
value = state_test_env.env[var]
|
||||
validate_set(state_test_env, var, value)
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_env_echo_non_existent(state_test_env):
|
||||
"""Test echoing a variable that doesn't exist."""
|
||||
|
||||
var = state_test_env.set_var
|
||||
validate_empty(state_test_env, var)
|
||||
|
||||
def test_env_printenv_non_existent(state_test_env):
|
||||
"""Test printenv error message for non-existant variables."""
|
||||
|
||||
var = state_test_env.set_var
|
||||
c = state_test_env.u_boot_console
|
||||
with c.disable_check('error_notification'):
|
||||
response = c.run_command('printenv %s' % var)
|
||||
assert(response == '## Error: "%s" not defined' % var)
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_env_unset_non_existent(state_test_env):
|
||||
"""Test unsetting a nonexistent variable."""
|
||||
|
||||
var = state_test_env.get_non_existent_var()
|
||||
unset_var(state_test_env, var)
|
||||
validate_empty(state_test_env, var)
|
||||
|
||||
def test_env_set_non_existent(state_test_env):
|
||||
"""Test set a non-existant variable."""
|
||||
|
||||
var = state_test_env.set_var
|
||||
value = 'foo'
|
||||
set_var(state_test_env, var, value)
|
||||
validate_set(state_test_env, var, value)
|
||||
|
||||
def test_env_set_existing(state_test_env):
|
||||
"""Test setting an existant variable."""
|
||||
|
||||
var = state_test_env.set_var
|
||||
value = 'bar'
|
||||
set_var(state_test_env, var, value)
|
||||
validate_set(state_test_env, var, value)
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_env_unset_existing(state_test_env):
|
||||
"""Test unsetting a variable."""
|
||||
|
||||
var = state_test_env.set_var
|
||||
unset_var(state_test_env, var)
|
||||
validate_empty(state_test_env, var)
|
||||
|
||||
def test_env_expansion_spaces(state_test_env):
|
||||
"""Test expanding a variable that contains a space in its value."""
|
||||
|
||||
var_space = None
|
||||
var_test = None
|
||||
try:
|
||||
var_space = state_test_env.get_non_existent_var()
|
||||
set_var(state_test_env, var_space, ' ')
|
||||
|
||||
var_test = state_test_env.get_non_existent_var()
|
||||
value = ' 1${%(var_space)s}${%(var_space)s} 2 ' % locals()
|
||||
set_var(state_test_env, var_test, value)
|
||||
value = ' 1 2 '
|
||||
validate_set(state_test_env, var_test, value)
|
||||
finally:
|
||||
if var_space:
|
||||
unset_var(state_test_env, var_space)
|
||||
if var_test:
|
||||
unset_var(state_test_env, var_test)
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_importenv')
|
||||
def test_env_import_checksum_no_size(state_test_env):
|
||||
"""Test that omitted ('-') size parameter with checksum validation fails the
|
||||
env import function.
|
||||
"""
|
||||
c = state_test_env.u_boot_console
|
||||
ram_base = u_boot_utils.find_ram_base(state_test_env.u_boot_console)
|
||||
addr = '%08x' % ram_base
|
||||
|
||||
with c.disable_check('error_notification'):
|
||||
response = c.run_command('env import -c %s -' % addr)
|
||||
assert(response == '## Error: external checksum format must pass size')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_importenv')
|
||||
def test_env_import_whitelist_checksum_no_size(state_test_env):
|
||||
"""Test that omitted ('-') size parameter with checksum validation fails the
|
||||
env import function when variables are passed as parameters.
|
||||
"""
|
||||
c = state_test_env.u_boot_console
|
||||
ram_base = u_boot_utils.find_ram_base(state_test_env.u_boot_console)
|
||||
addr = '%08x' % ram_base
|
||||
|
||||
with c.disable_check('error_notification'):
|
||||
response = c.run_command('env import -c %s - foo1 foo2 foo4' % addr)
|
||||
assert(response == '## Error: external checksum format must pass size')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_exportenv')
|
||||
@pytest.mark.buildconfigspec('cmd_importenv')
|
||||
def test_env_import_whitelist(state_test_env):
|
||||
"""Test importing only a handful of env variables from an environment."""
|
||||
c = state_test_env.u_boot_console
|
||||
ram_base = u_boot_utils.find_ram_base(state_test_env.u_boot_console)
|
||||
addr = '%08x' % ram_base
|
||||
|
||||
set_var(state_test_env, 'foo1', 'bar1')
|
||||
set_var(state_test_env, 'foo2', 'bar2')
|
||||
set_var(state_test_env, 'foo3', 'bar3')
|
||||
|
||||
c.run_command('env export %s' % addr)
|
||||
|
||||
unset_var(state_test_env, 'foo1')
|
||||
set_var(state_test_env, 'foo2', 'test2')
|
||||
set_var(state_test_env, 'foo4', 'bar4')
|
||||
|
||||
# no foo1 in current env, foo2 overridden, foo3 should be of the value
|
||||
# before exporting and foo4 should be of the value before importing.
|
||||
c.run_command('env import %s - foo1 foo2 foo4' % addr)
|
||||
|
||||
validate_set(state_test_env, 'foo1', 'bar1')
|
||||
validate_set(state_test_env, 'foo2', 'bar2')
|
||||
validate_set(state_test_env, 'foo3', 'bar3')
|
||||
validate_set(state_test_env, 'foo4', 'bar4')
|
||||
|
||||
# Cleanup test environment
|
||||
unset_var(state_test_env, 'foo1')
|
||||
unset_var(state_test_env, 'foo2')
|
||||
unset_var(state_test_env, 'foo3')
|
||||
unset_var(state_test_env, 'foo4')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_exportenv')
|
||||
@pytest.mark.buildconfigspec('cmd_importenv')
|
||||
def test_env_import_whitelist_delete(state_test_env):
|
||||
|
||||
"""Test importing only a handful of env variables from an environment, with.
|
||||
deletion if a var A that is passed to env import is not in the
|
||||
environment to be imported.
|
||||
"""
|
||||
c = state_test_env.u_boot_console
|
||||
ram_base = u_boot_utils.find_ram_base(state_test_env.u_boot_console)
|
||||
addr = '%08x' % ram_base
|
||||
|
||||
set_var(state_test_env, 'foo1', 'bar1')
|
||||
set_var(state_test_env, 'foo2', 'bar2')
|
||||
set_var(state_test_env, 'foo3', 'bar3')
|
||||
|
||||
c.run_command('env export %s' % addr)
|
||||
|
||||
unset_var(state_test_env, 'foo1')
|
||||
set_var(state_test_env, 'foo2', 'test2')
|
||||
set_var(state_test_env, 'foo4', 'bar4')
|
||||
|
||||
# no foo1 in current env, foo2 overridden, foo3 should be of the value
|
||||
# before exporting and foo4 should be empty.
|
||||
c.run_command('env import -d %s - foo1 foo2 foo4' % addr)
|
||||
|
||||
validate_set(state_test_env, 'foo1', 'bar1')
|
||||
validate_set(state_test_env, 'foo2', 'bar2')
|
||||
validate_set(state_test_env, 'foo3', 'bar3')
|
||||
validate_empty(state_test_env, 'foo4')
|
||||
|
||||
# Cleanup test environment
|
||||
unset_var(state_test_env, 'foo1')
|
||||
unset_var(state_test_env, 'foo2')
|
||||
unset_var(state_test_env, 'foo3')
|
||||
unset_var(state_test_env, 'foo4')
|
||||
+457
@@ -0,0 +1,457 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2013, Google Inc.
|
||||
#
|
||||
# Sanity check of the FIT handling in U-Boot
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import struct
|
||||
import u_boot_utils as util
|
||||
|
||||
# Define a base ITS which we can adjust using % and a dictionary
|
||||
base_its = '''
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel@1 {
|
||||
data = /incbin/("%(kernel)s");
|
||||
type = "kernel";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "%(compression)s";
|
||||
load = <0x40000>;
|
||||
entry = <0x8>;
|
||||
};
|
||||
kernel@2 {
|
||||
data = /incbin/("%(loadables1)s");
|
||||
type = "kernel";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
%(loadables1_load)s
|
||||
entry = <0x0>;
|
||||
};
|
||||
fdt@1 {
|
||||
description = "snow";
|
||||
data = /incbin/("%(fdt)s");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
%(fdt_load)s
|
||||
compression = "%(compression)s";
|
||||
signature@1 {
|
||||
algo = "sha1,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
ramdisk@1 {
|
||||
description = "snow";
|
||||
data = /incbin/("%(ramdisk)s");
|
||||
type = "ramdisk";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
%(ramdisk_load)s
|
||||
compression = "%(compression)s";
|
||||
};
|
||||
ramdisk@2 {
|
||||
description = "snow";
|
||||
data = /incbin/("%(loadables2)s");
|
||||
type = "ramdisk";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
%(loadables2_load)s
|
||||
compression = "none";
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf@1";
|
||||
conf@1 {
|
||||
kernel = "kernel@1";
|
||||
fdt = "fdt@1";
|
||||
%(ramdisk_config)s
|
||||
%(loadables_config)s
|
||||
};
|
||||
};
|
||||
};
|
||||
'''
|
||||
|
||||
# Define a base FDT - currently we don't use anything in this
|
||||
base_fdt = '''
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
model = "Sandbox Verified Boot Test";
|
||||
compatible = "sandbox";
|
||||
|
||||
reset@0 {
|
||||
compatible = "sandbox,reset";
|
||||
};
|
||||
|
||||
};
|
||||
'''
|
||||
|
||||
# This is the U-Boot script that is run for each test. First load the FIT,
|
||||
# then run the 'bootm' command, then save out memory from the places where
|
||||
# we expect 'bootm' to write things. Then quit.
|
||||
base_script = '''
|
||||
host load hostfs 0 %(fit_addr)x %(fit)s
|
||||
fdt addr %(fit_addr)x
|
||||
bootm start %(fit_addr)x
|
||||
bootm loados
|
||||
host save hostfs 0 %(kernel_addr)x %(kernel_out)s %(kernel_size)x
|
||||
host save hostfs 0 %(fdt_addr)x %(fdt_out)s %(fdt_size)x
|
||||
host save hostfs 0 %(ramdisk_addr)x %(ramdisk_out)s %(ramdisk_size)x
|
||||
host save hostfs 0 %(loadables1_addr)x %(loadables1_out)s %(loadables1_size)x
|
||||
host save hostfs 0 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x
|
||||
'''
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.buildconfigspec('fit_signature')
|
||||
@pytest.mark.requiredtool('dtc')
|
||||
def test_fit(u_boot_console):
|
||||
def make_fname(leaf):
|
||||
"""Make a temporary filename
|
||||
|
||||
Args:
|
||||
leaf: Leaf name of file to create (within temporary directory)
|
||||
Return:
|
||||
Temporary filename
|
||||
"""
|
||||
|
||||
return os.path.join(cons.config.build_dir, leaf)
|
||||
|
||||
def filesize(fname):
|
||||
"""Get the size of a file
|
||||
|
||||
Args:
|
||||
fname: Filename to check
|
||||
Return:
|
||||
Size of file in bytes
|
||||
"""
|
||||
return os.stat(fname).st_size
|
||||
|
||||
def read_file(fname):
|
||||
"""Read the contents of a file
|
||||
|
||||
Args:
|
||||
fname: Filename to read
|
||||
Returns:
|
||||
Contents of file as a string
|
||||
"""
|
||||
with open(fname, 'rb') as fd:
|
||||
return fd.read()
|
||||
|
||||
def make_dtb():
|
||||
"""Make a sample .dts file and compile it to a .dtb
|
||||
|
||||
Returns:
|
||||
Filename of .dtb file created
|
||||
"""
|
||||
src = make_fname('u-boot.dts')
|
||||
dtb = make_fname('u-boot.dtb')
|
||||
with open(src, 'w') as fd:
|
||||
fd.write(base_fdt)
|
||||
util.run_and_log(cons, ['dtc', src, '-O', 'dtb', '-o', dtb])
|
||||
return dtb
|
||||
|
||||
def make_its(params):
|
||||
"""Make a sample .its file with parameters embedded
|
||||
|
||||
Args:
|
||||
params: Dictionary containing parameters to embed in the %() strings
|
||||
Returns:
|
||||
Filename of .its file created
|
||||
"""
|
||||
its = make_fname('test.its')
|
||||
with open(its, 'w') as fd:
|
||||
print(base_its % params, file=fd)
|
||||
return its
|
||||
|
||||
def make_fit(mkimage, params):
|
||||
"""Make a sample .fit file ready for loading
|
||||
|
||||
This creates a .its script with the selected parameters and uses mkimage to
|
||||
turn this into a .fit image.
|
||||
|
||||
Args:
|
||||
mkimage: Filename of 'mkimage' utility
|
||||
params: Dictionary containing parameters to embed in the %() strings
|
||||
Return:
|
||||
Filename of .fit file created
|
||||
"""
|
||||
fit = make_fname('test.fit')
|
||||
its = make_its(params)
|
||||
util.run_and_log(cons, [mkimage, '-f', its, fit])
|
||||
with open(make_fname('u-boot.dts'), 'w') as fd:
|
||||
fd.write(base_fdt)
|
||||
return fit
|
||||
|
||||
def make_kernel(filename, text):
|
||||
"""Make a sample kernel with test data
|
||||
|
||||
Args:
|
||||
filename: the name of the file you want to create
|
||||
Returns:
|
||||
Full path and filename of the kernel it created
|
||||
"""
|
||||
fname = make_fname(filename)
|
||||
data = ''
|
||||
for i in range(100):
|
||||
data += 'this %s %d is unlikely to boot\n' % (text, i)
|
||||
with open(fname, 'w') as fd:
|
||||
print(data, file=fd)
|
||||
return fname
|
||||
|
||||
def make_ramdisk(filename, text):
|
||||
"""Make a sample ramdisk with test data
|
||||
|
||||
Returns:
|
||||
Filename of ramdisk created
|
||||
"""
|
||||
fname = make_fname(filename)
|
||||
data = ''
|
||||
for i in range(100):
|
||||
data += '%s %d was seldom used in the middle ages\n' % (text, i)
|
||||
with open(fname, 'w') as fd:
|
||||
print(data, file=fd)
|
||||
return fname
|
||||
|
||||
def make_compressed(filename):
|
||||
util.run_and_log(cons, ['gzip', '-f', '-k', filename])
|
||||
return filename + '.gz'
|
||||
|
||||
def find_matching(text, match):
|
||||
"""Find a match in a line of text, and return the unmatched line portion
|
||||
|
||||
This is used to extract a part of a line from some text. The match string
|
||||
is used to locate the line - we use the first line that contains that
|
||||
match text.
|
||||
|
||||
Once we find a match, we discard the match string itself from the line,
|
||||
and return what remains.
|
||||
|
||||
TODO: If this function becomes more generally useful, we could change it
|
||||
to use regex and return groups.
|
||||
|
||||
Args:
|
||||
text: Text to check (list of strings, one for each command issued)
|
||||
match: String to search for
|
||||
Return:
|
||||
String containing unmatched portion of line
|
||||
Exceptions:
|
||||
ValueError: If match is not found
|
||||
|
||||
>>> find_matching(['first line:10', 'second_line:20'], 'first line:')
|
||||
'10'
|
||||
>>> find_matching(['first line:10', 'second_line:20'], 'second line')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Test aborted
|
||||
>>> find_matching('first line:10\', 'second_line:20'], 'second_line:')
|
||||
'20'
|
||||
>>> find_matching('first line:10\', 'second_line:20\nthird_line:30'],
|
||||
'third_line:')
|
||||
'30'
|
||||
"""
|
||||
__tracebackhide__ = True
|
||||
for line in '\n'.join(text).splitlines():
|
||||
pos = line.find(match)
|
||||
if pos != -1:
|
||||
return line[:pos] + line[pos + len(match):]
|
||||
|
||||
pytest.fail("Expected '%s' but not found in output")
|
||||
|
||||
def check_equal(expected_fname, actual_fname, failure_msg):
|
||||
"""Check that a file matches its expected contents
|
||||
|
||||
This is always used on out-buffers whose size is decided by the test
|
||||
script anyway, which in some cases may be larger than what we're
|
||||
actually looking for. So it's safe to truncate it to the size of the
|
||||
expected data.
|
||||
|
||||
Args:
|
||||
expected_fname: Filename containing expected contents
|
||||
actual_fname: Filename containing actual contents
|
||||
failure_msg: Message to print on failure
|
||||
"""
|
||||
expected_data = read_file(expected_fname)
|
||||
actual_data = read_file(actual_fname)
|
||||
if len(expected_data) < len(actual_data):
|
||||
actual_data = actual_data[:len(expected_data)]
|
||||
assert expected_data == actual_data, failure_msg
|
||||
|
||||
def check_not_equal(expected_fname, actual_fname, failure_msg):
|
||||
"""Check that a file does not match its expected contents
|
||||
|
||||
Args:
|
||||
expected_fname: Filename containing expected contents
|
||||
actual_fname: Filename containing actual contents
|
||||
failure_msg: Message to print on failure
|
||||
"""
|
||||
expected_data = read_file(expected_fname)
|
||||
actual_data = read_file(actual_fname)
|
||||
assert expected_data != actual_data, failure_msg
|
||||
|
||||
def run_fit_test(mkimage):
|
||||
"""Basic sanity check of FIT loading in U-Boot
|
||||
|
||||
TODO: Almost everything:
|
||||
- hash algorithms - invalid hash/contents should be detected
|
||||
- signature algorithms - invalid sig/contents should be detected
|
||||
- compression
|
||||
- checking that errors are detected like:
|
||||
- image overwriting
|
||||
- missing images
|
||||
- invalid configurations
|
||||
- incorrect os/arch/type fields
|
||||
- empty data
|
||||
- images too large/small
|
||||
- invalid FDT (e.g. putting a random binary in instead)
|
||||
- default configuration selection
|
||||
- bootm command line parameters should have desired effect
|
||||
- run code coverage to make sure we are testing all the code
|
||||
"""
|
||||
# Set up invariant files
|
||||
control_dtb = make_dtb()
|
||||
kernel = make_kernel('test-kernel.bin', 'kernel')
|
||||
ramdisk = make_ramdisk('test-ramdisk.bin', 'ramdisk')
|
||||
loadables1 = make_kernel('test-loadables1.bin', 'lenrek')
|
||||
loadables2 = make_ramdisk('test-loadables2.bin', 'ksidmar')
|
||||
kernel_out = make_fname('kernel-out.bin')
|
||||
fdt = make_fname('u-boot.dtb')
|
||||
fdt_out = make_fname('fdt-out.dtb')
|
||||
ramdisk_out = make_fname('ramdisk-out.bin')
|
||||
loadables1_out = make_fname('loadables1-out.bin')
|
||||
loadables2_out = make_fname('loadables2-out.bin')
|
||||
|
||||
# Set up basic parameters with default values
|
||||
params = {
|
||||
'fit_addr' : 0x1000,
|
||||
|
||||
'kernel' : kernel,
|
||||
'kernel_out' : kernel_out,
|
||||
'kernel_addr' : 0x40000,
|
||||
'kernel_size' : filesize(kernel),
|
||||
|
||||
'fdt' : fdt,
|
||||
'fdt_out' : fdt_out,
|
||||
'fdt_addr' : 0x80000,
|
||||
'fdt_size' : filesize(control_dtb),
|
||||
'fdt_load' : '',
|
||||
|
||||
'ramdisk' : ramdisk,
|
||||
'ramdisk_out' : ramdisk_out,
|
||||
'ramdisk_addr' : 0xc0000,
|
||||
'ramdisk_size' : filesize(ramdisk),
|
||||
'ramdisk_load' : '',
|
||||
'ramdisk_config' : '',
|
||||
|
||||
'loadables1' : loadables1,
|
||||
'loadables1_out' : loadables1_out,
|
||||
'loadables1_addr' : 0x100000,
|
||||
'loadables1_size' : filesize(loadables1),
|
||||
'loadables1_load' : '',
|
||||
|
||||
'loadables2' : loadables2,
|
||||
'loadables2_out' : loadables2_out,
|
||||
'loadables2_addr' : 0x140000,
|
||||
'loadables2_size' : filesize(loadables2),
|
||||
'loadables2_load' : '',
|
||||
|
||||
'loadables_config' : '',
|
||||
'compression' : 'none',
|
||||
}
|
||||
|
||||
# Make a basic FIT and a script to load it
|
||||
fit = make_fit(mkimage, params)
|
||||
params['fit'] = fit
|
||||
cmd = base_script % params
|
||||
|
||||
# First check that we can load a kernel
|
||||
# We could perhaps reduce duplication with some loss of readability
|
||||
cons.config.dtb = control_dtb
|
||||
cons.restart_uboot()
|
||||
with cons.log.section('Kernel load'):
|
||||
output = cons.run_command_list(cmd.splitlines())
|
||||
check_equal(kernel, kernel_out, 'Kernel not loaded')
|
||||
check_not_equal(control_dtb, fdt_out,
|
||||
'FDT loaded but should be ignored')
|
||||
check_not_equal(ramdisk, ramdisk_out,
|
||||
'Ramdisk loaded but should not be')
|
||||
|
||||
# Find out the offset in the FIT where U-Boot has found the FDT
|
||||
line = find_matching(output, 'Booting using the fdt blob at ')
|
||||
fit_offset = int(line, 16) - params['fit_addr']
|
||||
fdt_magic = struct.pack('>L', 0xd00dfeed)
|
||||
data = read_file(fit)
|
||||
|
||||
# Now find where it actually is in the FIT (skip the first word)
|
||||
real_fit_offset = data.find(fdt_magic, 4)
|
||||
assert fit_offset == real_fit_offset, (
|
||||
'U-Boot loaded FDT from offset %#x, FDT is actually at %#x' %
|
||||
(fit_offset, real_fit_offset))
|
||||
|
||||
# Now a kernel and an FDT
|
||||
with cons.log.section('Kernel + FDT load'):
|
||||
params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr']
|
||||
fit = make_fit(mkimage, params)
|
||||
cons.restart_uboot()
|
||||
output = cons.run_command_list(cmd.splitlines())
|
||||
check_equal(kernel, kernel_out, 'Kernel not loaded')
|
||||
check_equal(control_dtb, fdt_out, 'FDT not loaded')
|
||||
check_not_equal(ramdisk, ramdisk_out,
|
||||
'Ramdisk loaded but should not be')
|
||||
|
||||
# Try a ramdisk
|
||||
with cons.log.section('Kernel + FDT + Ramdisk load'):
|
||||
params['ramdisk_config'] = 'ramdisk = "ramdisk@1";'
|
||||
params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr']
|
||||
fit = make_fit(mkimage, params)
|
||||
cons.restart_uboot()
|
||||
output = cons.run_command_list(cmd.splitlines())
|
||||
check_equal(ramdisk, ramdisk_out, 'Ramdisk not loaded')
|
||||
|
||||
# Configuration with some Loadables
|
||||
with cons.log.section('Kernel + FDT + Ramdisk load + Loadables'):
|
||||
params['loadables_config'] = 'loadables = "kernel@2", "ramdisk@2";'
|
||||
params['loadables1_load'] = ('load = <%#x>;' %
|
||||
params['loadables1_addr'])
|
||||
params['loadables2_load'] = ('load = <%#x>;' %
|
||||
params['loadables2_addr'])
|
||||
fit = make_fit(mkimage, params)
|
||||
cons.restart_uboot()
|
||||
output = cons.run_command_list(cmd.splitlines())
|
||||
check_equal(loadables1, loadables1_out,
|
||||
'Loadables1 (kernel) not loaded')
|
||||
check_equal(loadables2, loadables2_out,
|
||||
'Loadables2 (ramdisk) not loaded')
|
||||
|
||||
# Kernel, FDT and Ramdisk all compressed
|
||||
with cons.log.section('(Kernel + FDT + Ramdisk) compressed'):
|
||||
params['compression'] = 'gzip'
|
||||
params['kernel'] = make_compressed(kernel)
|
||||
params['fdt'] = make_compressed(fdt)
|
||||
params['ramdisk'] = make_compressed(ramdisk)
|
||||
fit = make_fit(mkimage, params)
|
||||
cons.restart_uboot()
|
||||
output = cons.run_command_list(cmd.splitlines())
|
||||
check_equal(kernel, kernel_out, 'Kernel not loaded')
|
||||
check_equal(control_dtb, fdt_out, 'FDT not loaded')
|
||||
check_not_equal(ramdisk, ramdisk_out, 'Ramdisk got decompressed?')
|
||||
check_equal(ramdisk + '.gz', ramdisk_out, 'Ramdist not loaded')
|
||||
|
||||
|
||||
cons = u_boot_console
|
||||
try:
|
||||
# We need to use our own device tree file. Remember to restore it
|
||||
# afterwards.
|
||||
old_dtb = cons.config.dtb
|
||||
mkimage = cons.config.build_dir + '/tools/mkimage'
|
||||
run_fit_test(mkimage)
|
||||
finally:
|
||||
# Go back to the original U-Boot with the correct dtb.
|
||||
cons.config.dtb = old_dtb
|
||||
cons.restart_uboot()
|
||||
@@ -0,0 +1,565 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Copyright (c) 2018, Xilinx Inc.
|
||||
#
|
||||
# Michal Simek
|
||||
# Siva Durga Prasad Paladugu
|
||||
|
||||
import pytest
|
||||
import re
|
||||
import random
|
||||
import u_boot_utils
|
||||
|
||||
"""
|
||||
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.
|
||||
|
||||
For example:
|
||||
|
||||
# True if a DHCP server is attached to the network, and should be tested.
|
||||
env__net_dhcp_server = True
|
||||
|
||||
# A list of environment variables that should be set in order to configure a
|
||||
# static IP. In this test case we atleast need serverip for performing tftpb
|
||||
# to get required files.
|
||||
env__net_static_env_vars = [
|
||||
('ipaddr', '10.0.0.100'),
|
||||
('netmask', '255.255.255.0'),
|
||||
('serverip', '10.0.0.1'),
|
||||
]
|
||||
|
||||
# Details regarding the files that may be read from a TFTP server. .
|
||||
env__fpga_secure_readable_file = {
|
||||
'fn': 'auth_bhdr_ppk1_bit.bin',
|
||||
'enckupfn': 'auth_bhdr_enc_kup_load_bit.bin',
|
||||
'addr': 0x1000000,
|
||||
'keyaddr': 0x100000,
|
||||
'keyfn': 'key.txt',
|
||||
}
|
||||
|
||||
env__fpga_under_test = {
|
||||
'dev': 0,
|
||||
'addr' : 0x1000000,
|
||||
'bitstream_load': 'compress.bin',
|
||||
'bitstream_load_size': 1831960,
|
||||
'bitstream_loadp': 'compress_pr.bin',
|
||||
'bitstream_loadp_size': 423352,
|
||||
'bitstream_loadb': 'compress.bit',
|
||||
'bitstream_loadb_size': 1832086,
|
||||
'bitstream_loadbp': 'compress_pr.bit',
|
||||
'bitstream_loadbp_size': 423491,
|
||||
'mkimage_legacy': 'download.ub',
|
||||
'mkimage_legacy_size': 13321468,
|
||||
'mkimage_legacy_gz': 'download.gz.ub',
|
||||
'mkimage_legacy_gz_size': 53632,
|
||||
'mkimage_fit': 'download-fit.ub',
|
||||
'mkimage_fit_size': 13322784,
|
||||
'loadfs': 'mmc 0 compress.bin',
|
||||
'loadfs_size': 1831960,
|
||||
'loadfs_block_size': 0x10000,
|
||||
}
|
||||
"""
|
||||
|
||||
import test_net
|
||||
|
||||
def check_dev(u_boot_console):
|
||||
f = u_boot_console.config.env.get('env__fpga_under_test', None)
|
||||
if not f:
|
||||
pytest.skip('No FPGA to test')
|
||||
|
||||
dev = f.get('dev', -1)
|
||||
if dev < 0:
|
||||
pytest.fail('No dev specified via env__fpga_under_test')
|
||||
|
||||
return dev, f
|
||||
|
||||
def load_file_from_var(u_boot_console, name):
|
||||
dev, f = check_dev(u_boot_console)
|
||||
|
||||
addr = f.get('addr', -1)
|
||||
if addr < 0:
|
||||
pytest.fail('No address specified via env__fpga_under_test')
|
||||
|
||||
test_net.test_net_dhcp(u_boot_console)
|
||||
test_net.test_net_setup_static(u_boot_console)
|
||||
bit = f['%s' % (name)]
|
||||
bit_size = f['%s_size' % (name)]
|
||||
|
||||
expected_tftp = 'Bytes transferred = %d' % bit_size
|
||||
output = u_boot_console.run_command('tftpboot %x %s' % (addr, bit))
|
||||
assert expected_tftp in output
|
||||
|
||||
return f, dev, addr, bit, bit_size
|
||||
|
||||
###### FPGA FAIL test ######
|
||||
expected_usage = 'fpga - loadable FPGA image support'
|
||||
|
||||
@pytest.mark.xfail
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
def test_fpga_fail(u_boot_console):
|
||||
# Test non valid fpga subcommand
|
||||
expected = 'fpga: non existing command'
|
||||
output = u_boot_console.run_command('fpga broken 0')
|
||||
#assert expected in output
|
||||
assert expected_usage in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
def test_fpga_help(u_boot_console):
|
||||
# Just show help
|
||||
output = u_boot_console.run_command('fpga')
|
||||
assert expected_usage in output
|
||||
|
||||
|
||||
###### FPGA DUMP tests ######
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
def test_fpga_dump(u_boot_console):
|
||||
pytest.skip('Not implemented now')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
def test_fpga_dump_variable(u_boot_console):
|
||||
# Same as above but via "fpga" variable
|
||||
pytest.skip('Not implemented now')
|
||||
|
||||
###### FPGA INFO tests ######
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
def test_fpga_info_fail(u_boot_console):
|
||||
# Maybe this can be skipped completely
|
||||
dev, f = check_dev(u_boot_console)
|
||||
|
||||
# Multiple parameters to fpga info should fail
|
||||
expected = 'fpga: more parameters passed'
|
||||
output = u_boot_console.run_command('fpga info 0 0')
|
||||
#assert expected in output
|
||||
assert expected_usage in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
def test_fpga_info_list(u_boot_console):
|
||||
# Maybe this can be skipped completely
|
||||
dev, f = check_dev(u_boot_console)
|
||||
|
||||
# Code is design in a way that if fpga dev is not passed it should
|
||||
# return list of all fpga devices in the system
|
||||
u_boot_console.run_command('setenv fpga')
|
||||
output = u_boot_console.run_command('fpga info')
|
||||
assert expected_usage not in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
def test_fpga_info(u_boot_console):
|
||||
dev, f = check_dev(u_boot_console)
|
||||
|
||||
output = u_boot_console.run_command('fpga info %x' % (dev))
|
||||
assert expected_usage not in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
def test_fpga_info_variable(u_boot_console):
|
||||
dev, f = check_dev(u_boot_console)
|
||||
|
||||
#
|
||||
# fpga variable is storing device number which doesn't need to be passed
|
||||
#
|
||||
u_boot_console.run_command('setenv fpga %x' % (dev))
|
||||
|
||||
output = u_boot_console.run_command('fpga info')
|
||||
# Variable cleanup
|
||||
u_boot_console.run_command('setenv fpga')
|
||||
assert expected_usage not in output
|
||||
|
||||
###### FPGA LOAD tests ######
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_fpga_load_fail(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_load')
|
||||
|
||||
for cmd in ['dump', 'load', 'loadb']:
|
||||
# missing dev parameter
|
||||
expected = 'fpga: incorrect parameters passed'
|
||||
output = u_boot_console.run_command('fpga %s %x $filesize' % (cmd, addr))
|
||||
#assert expected in output
|
||||
assert expected_usage in output
|
||||
|
||||
# more parameters - 0 at the end
|
||||
expected = 'fpga: more parameters passed'
|
||||
output = u_boot_console.run_command('fpga %s %x %x $filesize 0' % (cmd, dev, addr))
|
||||
#assert expected in output
|
||||
assert expected_usage in output
|
||||
|
||||
# 0 address
|
||||
expected = 'fpga: zero fpga_data address'
|
||||
output = u_boot_console.run_command('fpga %s %x 0 $filesize' % (cmd, dev))
|
||||
#assert expected in output
|
||||
assert expected_usage in output
|
||||
|
||||
# 0 filesize
|
||||
expected = 'fpga: zero size'
|
||||
output = u_boot_console.run_command('fpga %s %x %x 0' % (cmd, dev, addr))
|
||||
#assert expected in output
|
||||
assert expected_usage in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_fpga_load(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_load')
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga load %x %x $filesize && echo %s' % (dev, addr, expected_text))
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadp')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_fpga_loadp(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_load')
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga load %x %x $filesize && echo %s' % (dev, addr, expected_text))
|
||||
assert expected_text in output
|
||||
|
||||
# And load also partial bistream
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_loadp')
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadp %x %x $filesize && echo %s' % (dev, addr, expected_text))
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_fpga_loadb(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_loadb')
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadb %x %x $filesize && echo %s' % (dev, addr, expected_text))
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadbp')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_fpga_loadbp(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_loadb')
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadb %x %x $filesize && echo %s' % (dev, addr, expected_text))
|
||||
assert expected_text in output
|
||||
|
||||
# And load also partial bistream in bit format
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'bitstream_loadbp')
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadbp %x %x $filesize && echo %s' % (dev, addr, expected_text))
|
||||
assert expected_text in output
|
||||
|
||||
###### FPGA LOADMK tests ######
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
@pytest.mark.buildconfigspec('image_format_legacy')
|
||||
def test_fpga_loadmk_fail(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_legacy')
|
||||
|
||||
u_boot_console.run_command('imi %x' % (addr))
|
||||
|
||||
# load image but pass incorrect address to show error message
|
||||
expected = 'Unknown image type'
|
||||
output = u_boot_console.run_command('fpga loadmk %x %x' % (dev, addr + 0x10))
|
||||
assert expected in output
|
||||
|
||||
# Pass more parameters then command expects - 0 at the end
|
||||
output = u_boot_console.run_command('fpga loadmk %x %x 0' % (dev, addr))
|
||||
#assert expected in output
|
||||
assert expected_usage in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
@pytest.mark.buildconfigspec('image_format_legacy')
|
||||
def test_fpga_loadmk_legacy(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_legacy')
|
||||
|
||||
u_boot_console.run_command('imi %x' % (addr))
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadmk %x %x && echo %s' % (dev, addr, expected_text))
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.xfail
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
@pytest.mark.buildconfigspec('image_format_legacy')
|
||||
def test_fpga_loadmk_legacy_variable_fpga(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_legacy')
|
||||
|
||||
u_boot_console.run_command('imi %x' % (addr))
|
||||
|
||||
u_boot_console.run_command('setenv fpga %x' % (dev))
|
||||
|
||||
# this testcase should cover case which looks like it is supported but dev pointer is broken by loading mkimage address
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadmk %x && echo %s' % (addr, expected_text))
|
||||
u_boot_console.run_command('setenv fpga')
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
@pytest.mark.buildconfigspec('image_format_legacy')
|
||||
def test_fpga_loadmk_legacy_variable_fpgadata(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_legacy')
|
||||
|
||||
u_boot_console.run_command('imi %x' % (addr))
|
||||
|
||||
u_boot_console.run_command('setenv fpgadata %x' % (addr))
|
||||
|
||||
# this testcase should cover case which looks like it is supported but dev pointer is broken by loading mkimage address
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadmk %x && echo %s' % (dev, expected_text))
|
||||
u_boot_console.run_command('setenv fpgadata')
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
@pytest.mark.buildconfigspec('image_format_legacy')
|
||||
def test_fpga_loadmk_legacy_variable(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_legacy')
|
||||
|
||||
u_boot_console.run_command('imi %x' % (addr))
|
||||
|
||||
u_boot_console.run_command('setenv fpga %x' % (dev))
|
||||
u_boot_console.run_command('setenv fpgadata %x' % (addr))
|
||||
|
||||
# this testcase should cover case which looks like it is supported but dev pointer is broken by loading mkimage address
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadmk && echo %s' % (expected_text))
|
||||
u_boot_console.run_command('setenv fpga')
|
||||
u_boot_console.run_command('setenv fpgadata')
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
@pytest.mark.buildconfigspec('image_format_legacy')
|
||||
@pytest.mark.buildconfigspec('gzip')
|
||||
def test_fpga_loadmk_legacy_gz(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_legacy_gz')
|
||||
|
||||
u_boot_console.run_command('imi %x' % (addr))
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadmk %x %x && echo %s' % (dev, addr, expected_text))
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
|
||||
@pytest.mark.buildconfigspec('fit')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_fpga_loadmk_fit_external(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_fit_external')
|
||||
|
||||
u_boot_console.run_command('imi %x' % (addr))
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadmk %x %x:fpga && echo %s' % (dev, addr, expected_text))
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
|
||||
@pytest.mark.buildconfigspec('fit')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_fpga_loadmk_fit(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_fit')
|
||||
|
||||
u_boot_console.run_command('imi %x' % (addr))
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadmk %x %x:fpga && echo %s' % (dev, addr, expected_text))
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
|
||||
@pytest.mark.buildconfigspec('fit')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_fpga_loadmk_fit_variable_fpga(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_fit')
|
||||
|
||||
u_boot_console.run_command('imi %x' % (addr))
|
||||
# FIXME this should fail - broken support in past
|
||||
u_boot_console.run_command('setenv fpga %x' % (dev))
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadmk %x:fpga && echo %s' % (addr, expected_text))
|
||||
u_boot_console.run_command('setenv fpga')
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
|
||||
@pytest.mark.buildconfigspec('fit')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_fpga_loadmk_fit_variable_fpgadata(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_fit')
|
||||
|
||||
u_boot_console.run_command('imi %x' % (addr))
|
||||
# FIXME this should fail - broken support in past
|
||||
u_boot_console.run_command('setenv fpgadata %x:fpga' % (addr))
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadmk %x && echo %s' % (dev, expected_text))
|
||||
u_boot_console.run_command('setenv fpgadata')
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_loadmk')
|
||||
@pytest.mark.buildconfigspec('fit')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_fpga_loadmk_fit_variable(u_boot_console):
|
||||
f, dev, addr, bit, bit_size = load_file_from_var(u_boot_console, 'mkimage_fit')
|
||||
|
||||
u_boot_console.run_command('imi %x' % (addr))
|
||||
|
||||
u_boot_console.run_command('setenv fpga %x' % (dev))
|
||||
u_boot_console.run_command('setenv fpgadata %x:fpga' % (addr))
|
||||
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadmk && echo %s' % (expected_text))
|
||||
u_boot_console.run_command('setenv fpga')
|
||||
u_boot_console.run_command('setenv fpgadata')
|
||||
assert expected_text in output
|
||||
|
||||
###### FPGA LOAD tests ######
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
def test_fpga_loadfs_fail(u_boot_console):
|
||||
dev, f = check_dev(u_boot_console)
|
||||
|
||||
addr = f.get('addr', -1)
|
||||
if addr < 0:
|
||||
pytest.fail('No address specified via env__fpga_under_test')
|
||||
|
||||
bit = f['loadfs']
|
||||
bit_size = f['loadfs_size']
|
||||
block_size = f['loadfs_block_size']
|
||||
|
||||
# less params - dev number removed
|
||||
expected = 'fpga: incorrect parameters passed'
|
||||
output = u_boot_console.run_command('fpga loadfs %x %x %x %s' % (addr, bit_size, block_size, bit))
|
||||
#assert expected in output
|
||||
assert expected_usage in output
|
||||
|
||||
# one more param - 0 at the end
|
||||
# This is the longest command that's why there is no message from cmd/fpga.c
|
||||
output = u_boot_console.run_command('fpga loadfs %x %x %x %x %s 0' % (dev, addr, bit_size, block_size, bit))
|
||||
assert expected_usage in output
|
||||
|
||||
# zero address 0
|
||||
expected = 'fpga: zero fpga_data address'
|
||||
output = u_boot_console.run_command('fpga loadfs %x %x %x %x %s' % (dev, 0, bit_size, block_size, bit))
|
||||
#assert expected in output
|
||||
assert expected_usage in output
|
||||
|
||||
# bit_size 0
|
||||
expected = 'fpga: zero size'
|
||||
output = u_boot_console.run_command('fpga loadfs %x %x %x %x %s' % (dev, addr, 0, block_size, bit))
|
||||
#assert expected in output
|
||||
assert expected_usage in output
|
||||
|
||||
# block size 0
|
||||
# FIXME this should pass but it failing too
|
||||
output = u_boot_console.run_command('fpga loadfs %x %x %x %x %s' % (dev, addr, bit_size, 0, bit))
|
||||
assert expected_usage in output
|
||||
|
||||
# non existing bitstream name
|
||||
expected = 'Unable to read file noname'
|
||||
output = u_boot_console.run_command('fpga loadfs %x %x %x %x mmc 0 noname' % (dev, addr, bit_size, block_size))
|
||||
assert expected in output
|
||||
assert expected_usage in output
|
||||
|
||||
# -1 dev number
|
||||
expected = 'fpga_fsload: Invalid device number -1'
|
||||
output = u_boot_console.run_command('fpga loadfs %d %x %x %x mmc 0 noname' % (-1, addr, bit_size, block_size))
|
||||
assert expected in output
|
||||
assert expected_usage in output
|
||||
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
def test_fpga_loadfs(u_boot_console):
|
||||
dev, f = check_dev(u_boot_console)
|
||||
|
||||
addr = f.get('addr', -1)
|
||||
if addr < 0:
|
||||
pytest.fail('No address specified via env__fpga_under_test')
|
||||
|
||||
bit = f['loadfs']
|
||||
bit_size = f['loadfs_size']
|
||||
block_size = f['loadfs_block_size']
|
||||
|
||||
# This should be done better
|
||||
expected_text = 'FPGA loaded successfully'
|
||||
output = u_boot_console.run_command('fpga loadfs %x %x %x %x %s && echo %s' % (dev, addr, bit_size, block_size, bit, expected_text))
|
||||
assert expected_text in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_load_secure')
|
||||
@pytest.mark.buildconfigspec('cmd_net')
|
||||
@pytest.mark.buildconfigspec('cmd_dhcp')
|
||||
@pytest.mark.buildconfigspec('net')
|
||||
def test_fpga_secure_bit_auth(u_boot_console):
|
||||
|
||||
test_net.test_net_dhcp(u_boot_console)
|
||||
test_net.test_net_setup_static(u_boot_console)
|
||||
|
||||
f = u_boot_console.config.env.get('env__fpga_secure_readable_file', None)
|
||||
if not f:
|
||||
pytest.skip('No TFTP readable file to read')
|
||||
|
||||
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
|
||||
|
||||
expected_zynqmpsecure = 'Bitstream successfully loaded'
|
||||
output = u_boot_console.run_command('fpga loads 0 %x $filesize 0 2' % (addr))
|
||||
assert expected_zynqmpsecure in output
|
||||
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_fpga')
|
||||
@pytest.mark.buildconfigspec('cmd_fpga_load_secure')
|
||||
@pytest.mark.buildconfigspec('cmd_net')
|
||||
@pytest.mark.buildconfigspec('cmd_dhcp')
|
||||
@pytest.mark.buildconfigspec('net')
|
||||
def test_fpga_secure_bit_img_auth_kup(u_boot_console):
|
||||
|
||||
test_net.test_net_dhcp(u_boot_console)
|
||||
test_net.test_net_setup_static(u_boot_console)
|
||||
|
||||
f = u_boot_console.config.env.get('env__fpga_secure_readable_file', None)
|
||||
if not f:
|
||||
pytest.skip('No TFTP readable file to read')
|
||||
|
||||
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
|
||||
|
||||
expected_zynqmpsecure = 'Bitstream successfully loaded'
|
||||
output = u_boot_console.run_command('fpga loads 0 %x $filesize 0 1 %x' % (addr, keyaddr))
|
||||
assert expected_zynqmpsecure in output
|
||||
@@ -0,0 +1,602 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2018, Linaro Limited
|
||||
# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import pytest
|
||||
import re
|
||||
from subprocess import call, check_call, check_output, CalledProcessError
|
||||
from fstest_defs import *
|
||||
|
||||
supported_fs_basic = ['fat16', 'fat32', 'ext4']
|
||||
supported_fs_ext = ['fat16', 'fat32']
|
||||
supported_fs_mkdir = ['fat16', 'fat32']
|
||||
supported_fs_unlink = ['fat16', 'fat32']
|
||||
supported_fs_symlink = ['ext4']
|
||||
|
||||
#
|
||||
# Filesystem test specific setup
|
||||
#
|
||||
def pytest_addoption(parser):
|
||||
"""Enable --fs-type option.
|
||||
|
||||
See pytest_configure() about how it works.
|
||||
|
||||
Args:
|
||||
parser: Pytest command-line parser.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
parser.addoption('--fs-type', action='append', default=None,
|
||||
help='Targeting Filesystem Types')
|
||||
|
||||
def pytest_configure(config):
|
||||
"""Restrict a file system(s) to be tested.
|
||||
|
||||
A file system explicitly named with --fs-type option is selected
|
||||
if it belongs to a default supported_fs_xxx list.
|
||||
Multiple options can be specified.
|
||||
|
||||
Args:
|
||||
config: Pytest configuration.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
global supported_fs_basic
|
||||
global supported_fs_ext
|
||||
global supported_fs_mkdir
|
||||
global supported_fs_unlink
|
||||
global supported_fs_symlink
|
||||
|
||||
def intersect(listA, listB):
|
||||
return [x for x in listA if x in listB]
|
||||
|
||||
supported_fs = config.getoption('fs_type')
|
||||
if supported_fs:
|
||||
print('*** FS TYPE modified: %s' % supported_fs)
|
||||
supported_fs_basic = intersect(supported_fs, supported_fs_basic)
|
||||
supported_fs_ext = intersect(supported_fs, supported_fs_ext)
|
||||
supported_fs_mkdir = intersect(supported_fs, supported_fs_mkdir)
|
||||
supported_fs_unlink = intersect(supported_fs, supported_fs_unlink)
|
||||
supported_fs_symlink = intersect(supported_fs, supported_fs_symlink)
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
"""Parametrize fixtures, fs_obj_xxx
|
||||
|
||||
Each fixture will be parametrized with a corresponding support_fs_xxx
|
||||
list.
|
||||
|
||||
Args:
|
||||
metafunc: Pytest test function.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
if 'fs_obj_basic' in metafunc.fixturenames:
|
||||
metafunc.parametrize('fs_obj_basic', supported_fs_basic,
|
||||
indirect=True, scope='module')
|
||||
if 'fs_obj_ext' in metafunc.fixturenames:
|
||||
metafunc.parametrize('fs_obj_ext', supported_fs_ext,
|
||||
indirect=True, scope='module')
|
||||
if 'fs_obj_mkdir' in metafunc.fixturenames:
|
||||
metafunc.parametrize('fs_obj_mkdir', supported_fs_mkdir,
|
||||
indirect=True, scope='module')
|
||||
if 'fs_obj_unlink' in metafunc.fixturenames:
|
||||
metafunc.parametrize('fs_obj_unlink', supported_fs_unlink,
|
||||
indirect=True, scope='module')
|
||||
if 'fs_obj_symlink' in metafunc.fixturenames:
|
||||
metafunc.parametrize('fs_obj_symlink', supported_fs_symlink,
|
||||
indirect=True, scope='module')
|
||||
|
||||
#
|
||||
# Helper functions
|
||||
#
|
||||
def fstype_to_ubname(fs_type):
|
||||
"""Convert a file system type to an U-boot specific string
|
||||
|
||||
A generated string can be used as part of file system related commands
|
||||
or a config name in u-boot. Currently fat16 and fat32 are handled
|
||||
specifically.
|
||||
|
||||
Args:
|
||||
fs_type: File system type.
|
||||
|
||||
Return:
|
||||
A corresponding string for file system type.
|
||||
"""
|
||||
if re.match('fat', fs_type):
|
||||
return 'fat'
|
||||
else:
|
||||
return fs_type
|
||||
|
||||
def check_ubconfig(config, fs_type):
|
||||
"""Check whether a file system is enabled in u-boot configuration.
|
||||
|
||||
This function is assumed to be called in a fixture function so that
|
||||
the whole test cases will be skipped if a given file system is not
|
||||
enabled.
|
||||
|
||||
Args:
|
||||
fs_type: File system type.
|
||||
|
||||
Return:
|
||||
Nothing.
|
||||
"""
|
||||
if not config.buildconfig.get('config_cmd_%s' % fs_type, None):
|
||||
pytest.skip('.config feature "CMD_%s" not enabled' % fs_type.upper())
|
||||
if not config.buildconfig.get('config_%s_write' % fs_type, None):
|
||||
pytest.skip('.config feature "%s_WRITE" not enabled'
|
||||
% fs_type.upper())
|
||||
|
||||
def mk_fs(config, fs_type, size, id):
|
||||
"""Create a file system volume.
|
||||
|
||||
Args:
|
||||
fs_type: File system type.
|
||||
size: Size of file system in MiB.
|
||||
id: Prefix string of volume's file name.
|
||||
|
||||
Return:
|
||||
Nothing.
|
||||
"""
|
||||
fs_img = '%s.%s.img' % (id, fs_type)
|
||||
fs_img = config.persistent_data_dir + '/' + fs_img
|
||||
|
||||
if fs_type == 'fat16':
|
||||
mkfs_opt = '-F 16'
|
||||
elif fs_type == 'fat32':
|
||||
mkfs_opt = '-F 32'
|
||||
elif fs_type == 'ext4':
|
||||
mkfs_opt = '-O ^metadata_csum'
|
||||
else:
|
||||
mkfs_opt = ''
|
||||
|
||||
if re.match('fat', fs_type):
|
||||
fs_lnxtype = 'vfat'
|
||||
else:
|
||||
fs_lnxtype = fs_type
|
||||
|
||||
count = (size + 1048576 - 1) / 1048576
|
||||
|
||||
try:
|
||||
check_call('rm -f %s' % fs_img, shell=True)
|
||||
check_call('dd if=/dev/zero of=%s bs=1M count=%d'
|
||||
% (fs_img, count), shell=True)
|
||||
check_call('mkfs.%s %s %s'
|
||||
% (fs_lnxtype, mkfs_opt, fs_img), shell=True)
|
||||
return fs_img
|
||||
except CalledProcessError:
|
||||
call('rm -f %s' % fs_img, shell=True)
|
||||
raise
|
||||
|
||||
# from test/py/conftest.py
|
||||
def tool_is_in_path(tool):
|
||||
"""Check whether a given command is available on host.
|
||||
|
||||
Args:
|
||||
tool: Command name.
|
||||
|
||||
Return:
|
||||
True if available, False if not.
|
||||
"""
|
||||
for path in os.environ['PATH'].split(os.pathsep):
|
||||
fn = os.path.join(path, tool)
|
||||
if os.path.isfile(fn) and os.access(fn, os.X_OK):
|
||||
return True
|
||||
return False
|
||||
|
||||
fuse_mounted = False
|
||||
|
||||
def mount_fs(fs_type, device, mount_point):
|
||||
"""Mount a volume.
|
||||
|
||||
Args:
|
||||
fs_type: File system type.
|
||||
device: Volume's file name.
|
||||
mount_point: Mount point.
|
||||
|
||||
Return:
|
||||
Nothing.
|
||||
"""
|
||||
global fuse_mounted
|
||||
|
||||
fuse_mounted = False
|
||||
try:
|
||||
if tool_is_in_path('guestmount'):
|
||||
fuse_mounted = True
|
||||
check_call('guestmount -a %s -m /dev/sda %s'
|
||||
% (device, mount_point), shell=True)
|
||||
else:
|
||||
mount_opt = 'loop,rw'
|
||||
if re.match('fat', fs_type):
|
||||
mount_opt += ',umask=0000'
|
||||
|
||||
check_call('sudo mount -o %s %s %s'
|
||||
% (mount_opt, device, mount_point), shell=True)
|
||||
|
||||
# may not be effective for some file systems
|
||||
check_call('sudo chmod a+rw %s' % mount_point, shell=True)
|
||||
except CalledProcessError:
|
||||
raise
|
||||
|
||||
def umount_fs(mount_point):
|
||||
"""Unmount a volume.
|
||||
|
||||
Args:
|
||||
mount_point: Mount point.
|
||||
|
||||
Return:
|
||||
Nothing.
|
||||
"""
|
||||
if fuse_mounted:
|
||||
call('sync')
|
||||
call('guestunmount %s' % mount_point, shell=True)
|
||||
else:
|
||||
call('sudo umount %s' % mount_point, shell=True)
|
||||
|
||||
#
|
||||
# Fixture for basic fs test
|
||||
# derived from test/fs/fs-test.sh
|
||||
#
|
||||
# NOTE: yield_fixture was deprecated since pytest-3.0
|
||||
@pytest.yield_fixture()
|
||||
def fs_obj_basic(request, u_boot_config):
|
||||
"""Set up a file system to be used in basic fs test.
|
||||
|
||||
Args:
|
||||
request: Pytest request object.
|
||||
u_boot_config: U-boot configuration.
|
||||
|
||||
Return:
|
||||
A fixture for basic fs test, i.e. a triplet of file system type,
|
||||
volume file name and a list of MD5 hashes.
|
||||
"""
|
||||
fs_type = request.param
|
||||
fs_img = ''
|
||||
|
||||
fs_ubtype = fstype_to_ubname(fs_type)
|
||||
check_ubconfig(u_boot_config, fs_ubtype)
|
||||
|
||||
mount_dir = u_boot_config.persistent_data_dir + '/mnt'
|
||||
|
||||
small_file = mount_dir + '/' + SMALL_FILE
|
||||
big_file = mount_dir + '/' + BIG_FILE
|
||||
|
||||
try:
|
||||
|
||||
# 3GiB volume
|
||||
fs_img = mk_fs(u_boot_config, fs_type, 0xc0000000, '3GB')
|
||||
|
||||
# Mount the image so we can populate it.
|
||||
check_call('mkdir -p %s' % mount_dir, shell=True)
|
||||
mount_fs(fs_type, fs_img, mount_dir)
|
||||
|
||||
# Create a subdirectory.
|
||||
check_call('mkdir %s/SUBDIR' % mount_dir, shell=True)
|
||||
|
||||
# Create big file in this image.
|
||||
# Note that we work only on the start 1MB, couple MBs in the 2GB range
|
||||
# and the last 1 MB of the huge 2.5GB file.
|
||||
# So, just put random values only in those areas.
|
||||
check_call('dd if=/dev/urandom of=%s bs=1M count=1'
|
||||
% big_file, shell=True)
|
||||
check_call('dd if=/dev/urandom of=%s bs=1M count=2 seek=2047'
|
||||
% big_file, shell=True)
|
||||
check_call('dd if=/dev/urandom of=%s bs=1M count=1 seek=2499'
|
||||
% big_file, shell=True)
|
||||
|
||||
# Create a small file in this image.
|
||||
check_call('dd if=/dev/urandom of=%s bs=1M count=1'
|
||||
% small_file, shell=True)
|
||||
|
||||
# Delete the small file copies which possibly are written as part of a
|
||||
# previous test.
|
||||
# check_call('rm -f "%s.w"' % MB1, shell=True)
|
||||
# check_call('rm -f "%s.w2"' % MB1, shell=True)
|
||||
|
||||
# Generate the md5sums of reads that we will test against small file
|
||||
out = check_output(
|
||||
'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
|
||||
% small_file, shell=True).decode()
|
||||
md5val = [ out.split()[0] ]
|
||||
|
||||
# Generate the md5sums of reads that we will test against big file
|
||||
# One from beginning of file.
|
||||
out = check_output(
|
||||
'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
|
||||
% big_file, shell=True).decode()
|
||||
md5val.append(out.split()[0])
|
||||
|
||||
# One from end of file.
|
||||
out = check_output(
|
||||
'dd if=%s bs=1M skip=2499 count=1 2> /dev/null | md5sum'
|
||||
% big_file, shell=True).decode()
|
||||
md5val.append(out.split()[0])
|
||||
|
||||
# One from the last 1MB chunk of 2GB
|
||||
out = check_output(
|
||||
'dd if=%s bs=1M skip=2047 count=1 2> /dev/null | md5sum'
|
||||
% big_file, shell=True).decode()
|
||||
md5val.append(out.split()[0])
|
||||
|
||||
# One from the start 1MB chunk from 2GB
|
||||
out = check_output(
|
||||
'dd if=%s bs=1M skip=2048 count=1 2> /dev/null | md5sum'
|
||||
% big_file, shell=True).decode()
|
||||
md5val.append(out.split()[0])
|
||||
|
||||
# One 1MB chunk crossing the 2GB boundary
|
||||
out = check_output(
|
||||
'dd if=%s bs=512K skip=4095 count=2 2> /dev/null | md5sum'
|
||||
% big_file, shell=True).decode()
|
||||
md5val.append(out.split()[0])
|
||||
|
||||
umount_fs(mount_dir)
|
||||
except CalledProcessError:
|
||||
pytest.skip('Setup failed for filesystem: ' + fs_type)
|
||||
return
|
||||
else:
|
||||
yield [fs_ubtype, fs_img, md5val]
|
||||
finally:
|
||||
umount_fs(mount_dir)
|
||||
call('rmdir %s' % mount_dir, shell=True)
|
||||
if fs_img:
|
||||
call('rm -f %s' % fs_img, shell=True)
|
||||
|
||||
#
|
||||
# Fixture for extended fs test
|
||||
#
|
||||
# NOTE: yield_fixture was deprecated since pytest-3.0
|
||||
@pytest.yield_fixture()
|
||||
def fs_obj_ext(request, u_boot_config):
|
||||
"""Set up a file system to be used in extended fs test.
|
||||
|
||||
Args:
|
||||
request: Pytest request object.
|
||||
u_boot_config: U-boot configuration.
|
||||
|
||||
Return:
|
||||
A fixture for extended fs test, i.e. a triplet of file system type,
|
||||
volume file name and a list of MD5 hashes.
|
||||
"""
|
||||
fs_type = request.param
|
||||
fs_img = ''
|
||||
|
||||
fs_ubtype = fstype_to_ubname(fs_type)
|
||||
check_ubconfig(u_boot_config, fs_ubtype)
|
||||
|
||||
mount_dir = u_boot_config.persistent_data_dir + '/mnt'
|
||||
|
||||
min_file = mount_dir + '/' + MIN_FILE
|
||||
tmp_file = mount_dir + '/tmpfile'
|
||||
|
||||
try:
|
||||
|
||||
# 128MiB volume
|
||||
fs_img = mk_fs(u_boot_config, fs_type, 0x8000000, '128MB')
|
||||
|
||||
# Mount the image so we can populate it.
|
||||
check_call('mkdir -p %s' % mount_dir, shell=True)
|
||||
mount_fs(fs_type, fs_img, mount_dir)
|
||||
|
||||
# Create a test directory
|
||||
check_call('mkdir %s/dir1' % mount_dir, shell=True)
|
||||
|
||||
# Create a small file and calculate md5
|
||||
check_call('dd if=/dev/urandom of=%s bs=1K count=20'
|
||||
% min_file, shell=True)
|
||||
out = check_output(
|
||||
'dd if=%s bs=1K 2> /dev/null | md5sum'
|
||||
% min_file, shell=True).decode()
|
||||
md5val = [ out.split()[0] ]
|
||||
|
||||
# Calculate md5sum of Test Case 4
|
||||
check_call('dd if=%s of=%s bs=1K count=20'
|
||||
% (min_file, tmp_file), shell=True)
|
||||
check_call('dd if=%s of=%s bs=1K seek=5 count=20'
|
||||
% (min_file, tmp_file), shell=True)
|
||||
out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
|
||||
% tmp_file, shell=True).decode()
|
||||
md5val.append(out.split()[0])
|
||||
|
||||
# Calculate md5sum of Test Case 5
|
||||
check_call('dd if=%s of=%s bs=1K count=20'
|
||||
% (min_file, tmp_file), shell=True)
|
||||
check_call('dd if=%s of=%s bs=1K seek=5 count=5'
|
||||
% (min_file, tmp_file), shell=True)
|
||||
out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
|
||||
% tmp_file, shell=True).decode()
|
||||
md5val.append(out.split()[0])
|
||||
|
||||
# Calculate md5sum of Test Case 7
|
||||
check_call('dd if=%s of=%s bs=1K count=20'
|
||||
% (min_file, tmp_file), shell=True)
|
||||
check_call('dd if=%s of=%s bs=1K seek=20 count=20'
|
||||
% (min_file, tmp_file), shell=True)
|
||||
out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
|
||||
% tmp_file, shell=True).decode()
|
||||
md5val.append(out.split()[0])
|
||||
|
||||
check_call('rm %s' % tmp_file, shell=True)
|
||||
umount_fs(mount_dir)
|
||||
except CalledProcessError:
|
||||
pytest.skip('Setup failed for filesystem: ' + fs_type)
|
||||
return
|
||||
else:
|
||||
yield [fs_ubtype, fs_img, md5val]
|
||||
finally:
|
||||
umount_fs(mount_dir)
|
||||
call('rmdir %s' % mount_dir, shell=True)
|
||||
if fs_img:
|
||||
call('rm -f %s' % fs_img, shell=True)
|
||||
|
||||
#
|
||||
# Fixture for mkdir test
|
||||
#
|
||||
# NOTE: yield_fixture was deprecated since pytest-3.0
|
||||
@pytest.yield_fixture()
|
||||
def fs_obj_mkdir(request, u_boot_config):
|
||||
"""Set up a file system to be used in mkdir test.
|
||||
|
||||
Args:
|
||||
request: Pytest request object.
|
||||
u_boot_config: U-boot configuration.
|
||||
|
||||
Return:
|
||||
A fixture for mkdir test, i.e. a duplet of file system type and
|
||||
volume file name.
|
||||
"""
|
||||
fs_type = request.param
|
||||
fs_img = ''
|
||||
|
||||
fs_ubtype = fstype_to_ubname(fs_type)
|
||||
check_ubconfig(u_boot_config, fs_ubtype)
|
||||
|
||||
try:
|
||||
# 128MiB volume
|
||||
fs_img = mk_fs(u_boot_config, fs_type, 0x8000000, '128MB')
|
||||
except:
|
||||
pytest.skip('Setup failed for filesystem: ' + fs_type)
|
||||
else:
|
||||
yield [fs_ubtype, fs_img]
|
||||
finally:
|
||||
if fs_img:
|
||||
call('rm -f %s' % fs_img, shell=True)
|
||||
|
||||
#
|
||||
# Fixture for unlink test
|
||||
#
|
||||
# NOTE: yield_fixture was deprecated since pytest-3.0
|
||||
@pytest.yield_fixture()
|
||||
def fs_obj_unlink(request, u_boot_config):
|
||||
"""Set up a file system to be used in unlink test.
|
||||
|
||||
Args:
|
||||
request: Pytest request object.
|
||||
u_boot_config: U-boot configuration.
|
||||
|
||||
Return:
|
||||
A fixture for unlink test, i.e. a duplet of file system type and
|
||||
volume file name.
|
||||
"""
|
||||
fs_type = request.param
|
||||
fs_img = ''
|
||||
|
||||
fs_ubtype = fstype_to_ubname(fs_type)
|
||||
check_ubconfig(u_boot_config, fs_ubtype)
|
||||
|
||||
mount_dir = u_boot_config.persistent_data_dir + '/mnt'
|
||||
|
||||
try:
|
||||
|
||||
# 128MiB volume
|
||||
fs_img = mk_fs(u_boot_config, fs_type, 0x8000000, '128MB')
|
||||
|
||||
# Mount the image so we can populate it.
|
||||
check_call('mkdir -p %s' % mount_dir, shell=True)
|
||||
mount_fs(fs_type, fs_img, mount_dir)
|
||||
|
||||
# Test Case 1 & 3
|
||||
check_call('mkdir %s/dir1' % mount_dir, shell=True)
|
||||
check_call('dd if=/dev/urandom of=%s/dir1/file1 bs=1K count=1'
|
||||
% mount_dir, shell=True)
|
||||
check_call('dd if=/dev/urandom of=%s/dir1/file2 bs=1K count=1'
|
||||
% mount_dir, shell=True)
|
||||
|
||||
# Test Case 2
|
||||
check_call('mkdir %s/dir2' % mount_dir, shell=True)
|
||||
for i in range(0, 20):
|
||||
check_call('mkdir %s/dir2/0123456789abcdef%02x'
|
||||
% (mount_dir, i), shell=True)
|
||||
|
||||
# Test Case 4
|
||||
check_call('mkdir %s/dir4' % mount_dir, shell=True)
|
||||
|
||||
# Test Case 5, 6 & 7
|
||||
check_call('mkdir %s/dir5' % mount_dir, shell=True)
|
||||
check_call('dd if=/dev/urandom of=%s/dir5/file1 bs=1K count=1'
|
||||
% mount_dir, shell=True)
|
||||
|
||||
umount_fs(mount_dir)
|
||||
except CalledProcessError:
|
||||
pytest.skip('Setup failed for filesystem: ' + fs_type)
|
||||
return
|
||||
else:
|
||||
yield [fs_ubtype, fs_img]
|
||||
finally:
|
||||
umount_fs(mount_dir)
|
||||
call('rmdir %s' % mount_dir, shell=True)
|
||||
if fs_img:
|
||||
call('rm -f %s' % fs_img, shell=True)
|
||||
|
||||
#
|
||||
# Fixture for symlink fs test
|
||||
#
|
||||
# NOTE: yield_fixture was deprecated since pytest-3.0
|
||||
@pytest.yield_fixture()
|
||||
def fs_obj_symlink(request, u_boot_config):
|
||||
"""Set up a file system to be used in symlink fs test.
|
||||
|
||||
Args:
|
||||
request: Pytest request object.
|
||||
u_boot_config: U-boot configuration.
|
||||
|
||||
Return:
|
||||
A fixture for basic fs test, i.e. a triplet of file system type,
|
||||
volume file name and a list of MD5 hashes.
|
||||
"""
|
||||
fs_type = request.param
|
||||
fs_img = ''
|
||||
|
||||
fs_ubtype = fstype_to_ubname(fs_type)
|
||||
check_ubconfig(u_boot_config, fs_ubtype)
|
||||
|
||||
mount_dir = u_boot_config.persistent_data_dir + '/mnt'
|
||||
|
||||
small_file = mount_dir + '/' + SMALL_FILE
|
||||
medium_file = mount_dir + '/' + MEDIUM_FILE
|
||||
|
||||
try:
|
||||
|
||||
# 3GiB volume
|
||||
fs_img = mk_fs(u_boot_config, fs_type, 0x40000000, '1GB')
|
||||
|
||||
# Mount the image so we can populate it.
|
||||
check_call('mkdir -p %s' % mount_dir, shell=True)
|
||||
mount_fs(fs_type, fs_img, mount_dir)
|
||||
|
||||
# Create a subdirectory.
|
||||
check_call('mkdir %s/SUBDIR' % mount_dir, shell=True)
|
||||
|
||||
# Create a small file in this image.
|
||||
check_call('dd if=/dev/urandom of=%s bs=1M count=1'
|
||||
% small_file, shell=True)
|
||||
|
||||
# Create a medium file in this image.
|
||||
check_call('dd if=/dev/urandom of=%s bs=10M count=1'
|
||||
% medium_file, shell=True)
|
||||
|
||||
# Generate the md5sums of reads that we will test against small file
|
||||
out = check_output(
|
||||
'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
|
||||
% small_file, shell=True).decode()
|
||||
md5val = [out.split()[0]]
|
||||
out = check_output(
|
||||
'dd if=%s bs=10M skip=0 count=1 2> /dev/null | md5sum'
|
||||
% medium_file, shell=True).decode()
|
||||
md5val.extend([out.split()[0]])
|
||||
|
||||
umount_fs(mount_dir)
|
||||
except CalledProcessError:
|
||||
pytest.skip('Setup failed for filesystem: ' + fs_type)
|
||||
return
|
||||
else:
|
||||
yield [fs_ubtype, fs_img, md5val]
|
||||
finally:
|
||||
umount_fs(mount_dir)
|
||||
call('rmdir %s' % mount_dir, shell=True)
|
||||
if fs_img:
|
||||
call('rm -f %s' % fs_img, shell=True)
|
||||
@@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
# $MIN_FILE is the name of the 20KB file in the file system image
|
||||
MIN_FILE='testfile'
|
||||
|
||||
# $SMALL_FILE is the name of the 1MB file in the file system image
|
||||
SMALL_FILE='1MB.file'
|
||||
|
||||
# $MEDIUM_FILE is the name of the 10MB file in the file system image
|
||||
MEDIUM_FILE='10MB.file'
|
||||
|
||||
# $BIG_FILE is the name of the 2.5GB file in the file system image
|
||||
BIG_FILE='2.5GB.file'
|
||||
|
||||
ADDR=0x01000008
|
||||
LENGTH=0x00100000
|
||||
@@ -0,0 +1,13 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2019, Texas Instrument
|
||||
# Author: JJ Hiblot <jjhiblot@ti.com>
|
||||
#
|
||||
|
||||
from subprocess import check_call, CalledProcessError
|
||||
|
||||
def assert_fs_integrity(fs_type, fs_img):
|
||||
try:
|
||||
if fs_type == 'ext4':
|
||||
check_call('fsck.ext4 -n -f %s' % fs_img, shell=True)
|
||||
except CalledProcessError:
|
||||
raise
|
||||
@@ -0,0 +1,292 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2018, Linaro Limited
|
||||
# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
|
||||
#
|
||||
# U-Boot File System:Basic Test
|
||||
|
||||
"""
|
||||
This test verifies basic read/write operation on file system.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import re
|
||||
from fstest_defs import *
|
||||
from fstest_helpers import assert_fs_integrity
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.slow
|
||||
class TestFsBasic(object):
|
||||
def test_fs1(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 1 - ls command, listing a root directory and invalid directory
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 1a - ls'):
|
||||
# Test Case 1 - ls
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sls host 0:0' % fs_type])
|
||||
assert(re.search('2621440000 *%s' % BIG_FILE, ''.join(output)))
|
||||
assert(re.search('1048576 *%s' % SMALL_FILE, ''.join(output)))
|
||||
|
||||
with u_boot_console.log.section('Test Case 1b - ls (invalid dir)'):
|
||||
# In addition, test with a nonexistent directory to see if we crash.
|
||||
output = u_boot_console.run_command(
|
||||
'%sls host 0:0 invalid_d' % fs_type)
|
||||
if fs_type == 'ext4':
|
||||
assert('Can not find directory' in output)
|
||||
else:
|
||||
assert('' == output)
|
||||
|
||||
def test_fs2(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 2 - size command for a small file
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 2a - size (small)'):
|
||||
# 1MB is 0x0010 0000
|
||||
# Test Case 2a - size of small file
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%ssize host 0:0 /%s' % (fs_type, SMALL_FILE),
|
||||
'printenv filesize',
|
||||
'setenv filesize'])
|
||||
assert('filesize=100000' in ''.join(output))
|
||||
|
||||
with u_boot_console.log.section('Test Case 2b - size (/../<file>)'):
|
||||
# Test Case 2b - size of small file via a path using '..'
|
||||
output = u_boot_console.run_command_list([
|
||||
'%ssize host 0:0 /SUBDIR/../%s' % (fs_type, SMALL_FILE),
|
||||
'printenv filesize',
|
||||
'setenv filesize'])
|
||||
assert('filesize=100000' in ''.join(output))
|
||||
|
||||
def test_fs3(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 3 - size command for a large file
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 3 - size (large)'):
|
||||
# 2.5GB (1024*1024*2500) is 0x9C40 0000
|
||||
# Test Case 3 - size of big file
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%ssize host 0:0 /%s' % (fs_type, BIG_FILE),
|
||||
'printenv filesize',
|
||||
'setenv filesize'])
|
||||
assert('filesize=9c400000' in ''.join(output))
|
||||
|
||||
def test_fs4(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 4 - load a small file, 1MB
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 4 - load (small)'):
|
||||
# Test Case 4a - Read full 1MB of small file
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, SMALL_FILE),
|
||||
'printenv filesize'])
|
||||
assert('filesize=100000' in ''.join(output))
|
||||
|
||||
# Test Case 4b - Read full 1MB of small file
|
||||
output = u_boot_console.run_command_list([
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[0] in ''.join(output))
|
||||
|
||||
def test_fs5(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 5 - load, reading first 1MB of 3GB file
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 5 - load (first 1MB)'):
|
||||
# Test Case 5a - First 1MB of big file
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s %x 0x0' % (fs_type, ADDR, BIG_FILE, LENGTH),
|
||||
'printenv filesize'])
|
||||
assert('filesize=100000' in ''.join(output))
|
||||
|
||||
# Test Case 5b - First 1MB of big file
|
||||
output = u_boot_console.run_command_list([
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[1] in ''.join(output))
|
||||
|
||||
def test_fs6(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 6 - load, reading last 1MB of 3GB file
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 6 - load (last 1MB)'):
|
||||
# fails for ext as no offset support
|
||||
# Test Case 6a - Last 1MB of big file
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s %x 0x9c300000'
|
||||
% (fs_type, ADDR, BIG_FILE, LENGTH),
|
||||
'printenv filesize'])
|
||||
assert('filesize=100000' in ''.join(output))
|
||||
|
||||
# Test Case 6b - Last 1MB of big file
|
||||
output = u_boot_console.run_command_list([
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[2] in ''.join(output))
|
||||
|
||||
def test_fs7(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 7 - load, 1MB from the last 1MB in 2GB
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 7 - load (last 1MB in 2GB)'):
|
||||
# fails for ext as no offset support
|
||||
# Test Case 7a - One from the last 1MB chunk of 2GB
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s %x 0x7ff00000'
|
||||
% (fs_type, ADDR, BIG_FILE, LENGTH),
|
||||
'printenv filesize'])
|
||||
assert('filesize=100000' in ''.join(output))
|
||||
|
||||
# Test Case 7b - One from the last 1MB chunk of 2GB
|
||||
output = u_boot_console.run_command_list([
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[3] in ''.join(output))
|
||||
|
||||
def test_fs8(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 8 - load, reading first 1MB in 2GB
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 8 - load (first 1MB in 2GB)'):
|
||||
# fails for ext as no offset support
|
||||
# Test Case 8a - One from the start 1MB chunk from 2GB
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s %x 0x80000000'
|
||||
% (fs_type, ADDR, BIG_FILE, LENGTH),
|
||||
'printenv filesize'])
|
||||
assert('filesize=100000' in ''.join(output))
|
||||
|
||||
# Test Case 8b - One from the start 1MB chunk from 2GB
|
||||
output = u_boot_console.run_command_list([
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[4] in ''.join(output))
|
||||
|
||||
def test_fs9(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 9 - load, 1MB crossing 2GB boundary
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 9 - load (crossing 2GB boundary)'):
|
||||
# fails for ext as no offset support
|
||||
# Test Case 9a - One 1MB chunk crossing the 2GB boundary
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s %x 0x7ff80000'
|
||||
% (fs_type, ADDR, BIG_FILE, LENGTH),
|
||||
'printenv filesize'])
|
||||
assert('filesize=100000' in ''.join(output))
|
||||
|
||||
# Test Case 9b - One 1MB chunk crossing the 2GB boundary
|
||||
output = u_boot_console.run_command_list([
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[5] in ''.join(output))
|
||||
|
||||
def test_fs10(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 10 - load, reading beyond file end'):
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 10 - load (beyond file end)'):
|
||||
# Generic failure case
|
||||
# Test Case 10 - 2MB chunk from the last 1MB of big file
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s 0x00200000 0x9c300000'
|
||||
% (fs_type, ADDR, BIG_FILE),
|
||||
'printenv filesize',
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert('filesize=100000' in ''.join(output))
|
||||
|
||||
def test_fs11(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 11 - write'
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 11 - write'):
|
||||
# Read 1MB from small file
|
||||
# Write it back to test the writes
|
||||
# Test Case 11a - Check that the write succeeded
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, SMALL_FILE),
|
||||
'%swrite host 0:0 %x /%s.w $filesize'
|
||||
% (fs_type, ADDR, SMALL_FILE)])
|
||||
assert('1048576 bytes written' in ''.join(output))
|
||||
|
||||
# Test Case 11b - Check md5 of written to is same
|
||||
# as the one read from
|
||||
output = u_boot_console.run_command_list([
|
||||
'%sload host 0:0 %x /%s.w' % (fs_type, ADDR, SMALL_FILE),
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[0] in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_fs12(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 12 - write to "." directory
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 12 - write (".")'):
|
||||
# Next test case checks writing a file whose dirent
|
||||
# is the first in the block, which is always true for "."
|
||||
# The write should fail, but the lookup should work
|
||||
# Test Case 12 - Check directory traversal
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%swrite host 0:0 %x /. 0x10' % (fs_type, ADDR)])
|
||||
assert('Unable to write' in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_fs13(self, u_boot_console, fs_obj_basic):
|
||||
"""
|
||||
Test Case 13 - write to a file with "/./<filename>"
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_basic
|
||||
with u_boot_console.log.section('Test Case 13 - write ("./<file>")'):
|
||||
# Read 1MB from small file
|
||||
# Write it via "same directory", i.e. "." dirent
|
||||
# Test Case 13a - Check directory traversal
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, SMALL_FILE),
|
||||
'%swrite host 0:0 %x /./%s2 $filesize'
|
||||
% (fs_type, ADDR, SMALL_FILE)])
|
||||
assert('1048576 bytes written' in ''.join(output))
|
||||
|
||||
# Test Case 13b - Check md5 of written to is same
|
||||
# as the one read from
|
||||
output = u_boot_console.run_command_list([
|
||||
'mw.b %x 00 100' % ADDR,
|
||||
'%sload host 0:0 %x /./%s2' % (fs_type, ADDR, SMALL_FILE),
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[0] in ''.join(output))
|
||||
|
||||
# Test Case 13c - Check md5 of written to is same
|
||||
# as the one read from
|
||||
output = u_boot_console.run_command_list([
|
||||
'mw.b %x 00 100' % ADDR,
|
||||
'%sload host 0:0 %x /%s2' % (fs_type, ADDR, SMALL_FILE),
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[0] in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
@@ -0,0 +1,319 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2018, Linaro Limited
|
||||
# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
|
||||
#
|
||||
# U-Boot File System:Exntented Test
|
||||
|
||||
"""
|
||||
This test verifies extended write operation on file system.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import re
|
||||
from fstest_defs import *
|
||||
from fstest_helpers import assert_fs_integrity
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.slow
|
||||
class TestFsExt(object):
|
||||
def test_fs_ext1(self, u_boot_console, fs_obj_ext):
|
||||
"""
|
||||
Test Case 1 - write a file with absolute path
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_ext
|
||||
with u_boot_console.log.section('Test Case 1 - write with abs path'):
|
||||
# Test Case 1a - Check if command successfully returned
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
|
||||
'%swrite host 0:0 %x /dir1/%s.w1 $filesize'
|
||||
% (fs_type, ADDR, MIN_FILE)])
|
||||
assert('20480 bytes written' in ''.join(output))
|
||||
|
||||
# Test Case 1b - Check md5 of file content
|
||||
output = u_boot_console.run_command_list([
|
||||
'mw.b %x 00 100' % ADDR,
|
||||
'%sload host 0:0 %x /dir1/%s.w1' % (fs_type, ADDR, MIN_FILE),
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[0] in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_fs_ext2(self, u_boot_console, fs_obj_ext):
|
||||
"""
|
||||
Test Case 2 - write to a file with relative path
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_ext
|
||||
with u_boot_console.log.section('Test Case 2 - write with rel path'):
|
||||
# Test Case 2a - Check if command successfully returned
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
|
||||
'%swrite host 0:0 %x dir1/%s.w2 $filesize'
|
||||
% (fs_type, ADDR, MIN_FILE)])
|
||||
assert('20480 bytes written' in ''.join(output))
|
||||
|
||||
# Test Case 2b - Check md5 of file content
|
||||
output = u_boot_console.run_command_list([
|
||||
'mw.b %x 00 100' % ADDR,
|
||||
'%sload host 0:0 %x dir1/%s.w2' % (fs_type, ADDR, MIN_FILE),
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[0] in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_fs_ext3(self, u_boot_console, fs_obj_ext):
|
||||
"""
|
||||
Test Case 3 - write to a file with invalid path
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_ext
|
||||
with u_boot_console.log.section('Test Case 3 - write with invalid path'):
|
||||
# Test Case 3 - Check if command expectedly failed
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
|
||||
'%swrite host 0:0 %x /dir1/none/%s.w3 $filesize'
|
||||
% (fs_type, ADDR, MIN_FILE)])
|
||||
assert('Unable to write "/dir1/none/' in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_fs_ext4(self, u_boot_console, fs_obj_ext):
|
||||
"""
|
||||
Test Case 4 - write at non-zero offset, enlarging file size
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_ext
|
||||
with u_boot_console.log.section('Test Case 4 - write at non-zero offset, enlarging file size'):
|
||||
# Test Case 4a - Check if command successfully returned
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
|
||||
'%swrite host 0:0 %x /dir1/%s.w4 $filesize'
|
||||
% (fs_type, ADDR, MIN_FILE)])
|
||||
output = u_boot_console.run_command(
|
||||
'%swrite host 0:0 %x /dir1/%s.w4 $filesize 0x1400'
|
||||
% (fs_type, ADDR, MIN_FILE))
|
||||
assert('20480 bytes written' in output)
|
||||
|
||||
# Test Case 4b - Check size of written file
|
||||
output = u_boot_console.run_command_list([
|
||||
'%ssize host 0:0 /dir1/%s.w4' % (fs_type, MIN_FILE),
|
||||
'printenv filesize',
|
||||
'setenv filesize'])
|
||||
assert('filesize=6400' in ''.join(output))
|
||||
|
||||
# Test Case 4c - Check md5 of file content
|
||||
output = u_boot_console.run_command_list([
|
||||
'mw.b %x 00 100' % ADDR,
|
||||
'%sload host 0:0 %x /dir1/%s.w4' % (fs_type, ADDR, MIN_FILE),
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[1] in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_fs_ext5(self, u_boot_console, fs_obj_ext):
|
||||
"""
|
||||
Test Case 5 - write at non-zero offset, shrinking file size
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_ext
|
||||
with u_boot_console.log.section('Test Case 5 - write at non-zero offset, shrinking file size'):
|
||||
# Test Case 5a - Check if command successfully returned
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
|
||||
'%swrite host 0:0 %x /dir1/%s.w5 $filesize'
|
||||
% (fs_type, ADDR, MIN_FILE)])
|
||||
output = u_boot_console.run_command(
|
||||
'%swrite host 0:0 %x /dir1/%s.w5 0x1400 0x1400'
|
||||
% (fs_type, ADDR, MIN_FILE))
|
||||
assert('5120 bytes written' in output)
|
||||
|
||||
# Test Case 5b - Check size of written file
|
||||
output = u_boot_console.run_command_list([
|
||||
'%ssize host 0:0 /dir1/%s.w5' % (fs_type, MIN_FILE),
|
||||
'printenv filesize',
|
||||
'setenv filesize'])
|
||||
assert('filesize=2800' in ''.join(output))
|
||||
|
||||
# Test Case 5c - Check md5 of file content
|
||||
output = u_boot_console.run_command_list([
|
||||
'mw.b %x 00 100' % ADDR,
|
||||
'%sload host 0:0 %x /dir1/%s.w5' % (fs_type, ADDR, MIN_FILE),
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[2] in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_fs_ext6(self, u_boot_console, fs_obj_ext):
|
||||
"""
|
||||
Test Case 6 - write nothing at the start, truncating to zero
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_ext
|
||||
with u_boot_console.log.section('Test Case 6 - write nothing at the start, truncating to zero'):
|
||||
# Test Case 6a - Check if command successfully returned
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
|
||||
'%swrite host 0:0 %x /dir1/%s.w6 $filesize'
|
||||
% (fs_type, ADDR, MIN_FILE)])
|
||||
output = u_boot_console.run_command(
|
||||
'%swrite host 0:0 %x /dir1/%s.w6 0 0'
|
||||
% (fs_type, ADDR, MIN_FILE))
|
||||
assert('0 bytes written' in output)
|
||||
|
||||
# Test Case 6b - Check size of written file
|
||||
output = u_boot_console.run_command_list([
|
||||
'%ssize host 0:0 /dir1/%s.w6' % (fs_type, MIN_FILE),
|
||||
'printenv filesize',
|
||||
'setenv filesize'])
|
||||
assert('filesize=0' in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_fs_ext7(self, u_boot_console, fs_obj_ext):
|
||||
"""
|
||||
Test Case 7 - write at the end (append)
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_ext
|
||||
with u_boot_console.log.section('Test Case 7 - write at the end (append)'):
|
||||
# Test Case 7a - Check if command successfully returned
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
|
||||
'%swrite host 0:0 %x /dir1/%s.w7 $filesize'
|
||||
% (fs_type, ADDR, MIN_FILE)])
|
||||
output = u_boot_console.run_command(
|
||||
'%swrite host 0:0 %x /dir1/%s.w7 $filesize $filesize'
|
||||
% (fs_type, ADDR, MIN_FILE))
|
||||
assert('20480 bytes written' in output)
|
||||
|
||||
# Test Case 7b - Check size of written file
|
||||
output = u_boot_console.run_command_list([
|
||||
'%ssize host 0:0 /dir1/%s.w7' % (fs_type, MIN_FILE),
|
||||
'printenv filesize',
|
||||
'setenv filesize'])
|
||||
assert('filesize=a000' in ''.join(output))
|
||||
|
||||
# Test Case 7c - Check md5 of file content
|
||||
output = u_boot_console.run_command_list([
|
||||
'mw.b %x 00 100' % ADDR,
|
||||
'%sload host 0:0 %x /dir1/%s.w7' % (fs_type, ADDR, MIN_FILE),
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[3] in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_fs_ext8(self, u_boot_console, fs_obj_ext):
|
||||
"""
|
||||
Test Case 8 - write at offset beyond the end of file
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_ext
|
||||
with u_boot_console.log.section('Test Case 8 - write beyond the end'):
|
||||
# Test Case 8a - Check if command expectedly failed
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
|
||||
'%swrite host 0:0 %x /dir1/%s.w8 $filesize'
|
||||
% (fs_type, ADDR, MIN_FILE)])
|
||||
output = u_boot_console.run_command(
|
||||
'%swrite host 0:0 %x /dir1/%s.w8 0x1400 %x'
|
||||
% (fs_type, ADDR, MIN_FILE, 0x100000 + 0x1400))
|
||||
assert('Unable to write "/dir1' in output)
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_fs_ext9(self, u_boot_console, fs_obj_ext):
|
||||
"""
|
||||
Test Case 9 - write to a non-existing file at non-zero offset
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_ext
|
||||
with u_boot_console.log.section('Test Case 9 - write to non-existing file with non-zero offset'):
|
||||
# Test Case 9a - Check if command expectedly failed
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
|
||||
'%swrite host 0:0 %x /dir1/%s.w9 0x1400 0x1400'
|
||||
% (fs_type, ADDR, MIN_FILE)])
|
||||
assert('Unable to write "/dir1' in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_fs_ext10(self, u_boot_console, fs_obj_ext):
|
||||
"""
|
||||
'Test Case 10 - create/delete as many directories under root directory
|
||||
as amount of directory entries goes beyond one cluster size)'
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_ext
|
||||
with u_boot_console.log.section('Test Case 10 - create/delete (many)'):
|
||||
# Test Case 10a - Create many files
|
||||
# Please note that the size of directory entry is 32 bytes.
|
||||
# So one typical cluster may holds 64 (2048/32) entries.
|
||||
output = u_boot_console.run_command(
|
||||
'host bind 0 %s' % fs_img)
|
||||
|
||||
for i in range(0, 66):
|
||||
output = u_boot_console.run_command(
|
||||
'%swrite host 0:0 %x /FILE0123456789_%02x 100'
|
||||
% (fs_type, ADDR, i))
|
||||
output = u_boot_console.run_command('%sls host 0:0 /' % fs_type)
|
||||
assert('FILE0123456789_00' in output)
|
||||
assert('FILE0123456789_41' in output)
|
||||
|
||||
# Test Case 10b - Delete many files
|
||||
for i in range(0, 66):
|
||||
output = u_boot_console.run_command(
|
||||
'%srm host 0:0 /FILE0123456789_%02x'
|
||||
% (fs_type, i))
|
||||
output = u_boot_console.run_command('%sls host 0:0 /' % fs_type)
|
||||
assert(not 'FILE0123456789_00' in output)
|
||||
assert(not 'FILE0123456789_41' in output)
|
||||
|
||||
# Test Case 10c - Create many files again
|
||||
# Please note no.64 and 65 are intentionally re-created
|
||||
for i in range(64, 128):
|
||||
output = u_boot_console.run_command(
|
||||
'%swrite host 0:0 %x /FILE0123456789_%02x 100'
|
||||
% (fs_type, ADDR, i))
|
||||
output = u_boot_console.run_command('%sls host 0:0 /' % fs_type)
|
||||
assert('FILE0123456789_40' in output)
|
||||
assert('FILE0123456789_79' in output)
|
||||
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_fs_ext11(self, u_boot_console, fs_obj_ext):
|
||||
"""
|
||||
'Test Case 11 - create/delete as many directories under non-root
|
||||
directory as amount of directory entries goes beyond one cluster size)'
|
||||
"""
|
||||
fs_type,fs_img,md5val = fs_obj_ext
|
||||
with u_boot_console.log.section('Test Case 11 - create/delete (many)'):
|
||||
# Test Case 11a - Create many files
|
||||
# Please note that the size of directory entry is 32 bytes.
|
||||
# So one typical cluster may holds 64 (2048/32) entries.
|
||||
output = u_boot_console.run_command(
|
||||
'host bind 0 %s' % fs_img)
|
||||
|
||||
for i in range(0, 66):
|
||||
output = u_boot_console.run_command(
|
||||
'%swrite host 0:0 %x /dir1/FILE0123456789_%02x 100'
|
||||
% (fs_type, ADDR, i))
|
||||
output = u_boot_console.run_command('%sls host 0:0 /dir1' % fs_type)
|
||||
assert('FILE0123456789_00' in output)
|
||||
assert('FILE0123456789_41' in output)
|
||||
|
||||
# Test Case 11b - Delete many files
|
||||
for i in range(0, 66):
|
||||
output = u_boot_console.run_command(
|
||||
'%srm host 0:0 /dir1/FILE0123456789_%02x'
|
||||
% (fs_type, i))
|
||||
output = u_boot_console.run_command('%sls host 0:0 /dir1' % fs_type)
|
||||
assert(not 'FILE0123456789_00' in output)
|
||||
assert(not 'FILE0123456789_41' in output)
|
||||
|
||||
# Test Case 11c - Create many files again
|
||||
# Please note no.64 and 65 are intentionally re-created
|
||||
for i in range(64, 128):
|
||||
output = u_boot_console.run_command(
|
||||
'%swrite host 0:0 %x /dir1/FILE0123456789_%02x 100'
|
||||
% (fs_type, ADDR, i))
|
||||
output = u_boot_console.run_command('%sls host 0:0 /dir1' % fs_type)
|
||||
assert('FILE0123456789_40' in output)
|
||||
assert('FILE0123456789_79' in output)
|
||||
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
@@ -0,0 +1,121 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2018, Linaro Limited
|
||||
# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
|
||||
#
|
||||
# U-Boot File System:mkdir Test
|
||||
|
||||
"""
|
||||
This test verifies mkdir operation on file system.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from fstest_helpers import assert_fs_integrity
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.slow
|
||||
class TestMkdir(object):
|
||||
def test_mkdir1(self, u_boot_console, fs_obj_mkdir):
|
||||
"""
|
||||
Test Case 1 - create a directory under a root
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_mkdir
|
||||
with u_boot_console.log.section('Test Case 1 - mkdir'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%smkdir host 0:0 dir1' % fs_type,
|
||||
'%sls host 0:0 /' % fs_type])
|
||||
assert('dir1/' in ''.join(output))
|
||||
|
||||
output = u_boot_console.run_command(
|
||||
'%sls host 0:0 dir1' % fs_type)
|
||||
assert('./' in output)
|
||||
assert('../' in output)
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
|
||||
def test_mkdir2(self, u_boot_console, fs_obj_mkdir):
|
||||
"""
|
||||
Test Case 2 - create a directory under a sub-directory
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_mkdir
|
||||
with u_boot_console.log.section('Test Case 2 - mkdir (sub-sub directory)'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%smkdir host 0:0 dir1/dir2' % fs_type,
|
||||
'%sls host 0:0 dir1' % fs_type])
|
||||
assert('dir2/' in ''.join(output))
|
||||
|
||||
output = u_boot_console.run_command(
|
||||
'%sls host 0:0 dir1/dir2' % fs_type)
|
||||
assert('./' in output)
|
||||
assert('../' in output)
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_mkdir3(self, u_boot_console, fs_obj_mkdir):
|
||||
"""
|
||||
Test Case 3 - trying to create a directory with a non-existing
|
||||
path should fail
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_mkdir
|
||||
with u_boot_console.log.section('Test Case 3 - mkdir (non-existing path)'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%smkdir host 0:0 none/dir3' % fs_type])
|
||||
assert('Unable to create a directory' in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_mkdir4(self, u_boot_console, fs_obj_mkdir):
|
||||
"""
|
||||
Test Case 4 - trying to create "." should fail
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_mkdir
|
||||
with u_boot_console.log.section('Test Case 4 - mkdir (".")'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%smkdir host 0:0 .' % fs_type])
|
||||
assert('Unable to create a directory' in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_mkdir5(self, u_boot_console, fs_obj_mkdir):
|
||||
"""
|
||||
Test Case 5 - trying to create ".." should fail
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_mkdir
|
||||
with u_boot_console.log.section('Test Case 5 - mkdir ("..")'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%smkdir host 0:0 ..' % fs_type])
|
||||
assert('Unable to create a directory' in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_mkdir6(self, u_boot_console, fs_obj_mkdir):
|
||||
"""
|
||||
'Test Case 6 - create as many directories as amount of directory
|
||||
entries goes beyond a cluster size)'
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_mkdir
|
||||
with u_boot_console.log.section('Test Case 6 - mkdir (create many)'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%smkdir host 0:0 dir6' % fs_type,
|
||||
'%sls host 0:0 /' % fs_type])
|
||||
assert('dir6/' in ''.join(output))
|
||||
|
||||
for i in range(0, 20):
|
||||
output = u_boot_console.run_command(
|
||||
'%smkdir host 0:0 dir6/0123456789abcdef%02x'
|
||||
% (fs_type, i))
|
||||
output = u_boot_console.run_command('%sls host 0:0 dir6' % fs_type)
|
||||
assert('0123456789abcdef00/' in output)
|
||||
assert('0123456789abcdef13/' in output)
|
||||
|
||||
output = u_boot_console.run_command(
|
||||
'%sls host 0:0 dir6/0123456789abcdef13/.' % fs_type)
|
||||
assert('./' in output)
|
||||
assert('../' in output)
|
||||
|
||||
output = u_boot_console.run_command(
|
||||
'%sls host 0:0 dir6/0123456789abcdef13/..' % fs_type)
|
||||
assert('0123456789abcdef00/' in output)
|
||||
assert('0123456789abcdef13/' in output)
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
@@ -0,0 +1,130 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2019, Texas Instrument
|
||||
# Author: Jean-Jacques Hiblot <jjhiblot@ti.com>
|
||||
#
|
||||
# U-Boot File System:symlink Test
|
||||
|
||||
"""
|
||||
This test verifies unlink operation (deleting a file or a directory)
|
||||
on file system.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import re
|
||||
from fstest_defs import *
|
||||
from fstest_helpers import assert_fs_integrity
|
||||
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.slow
|
||||
class TestSymlink(object):
|
||||
def test_symlink1(self, u_boot_console, fs_obj_symlink):
|
||||
"""
|
||||
Test Case 1 - create a link. and follow it when reading
|
||||
"""
|
||||
fs_type, fs_img, md5val = fs_obj_symlink
|
||||
with u_boot_console.log.section('Test Case 1 - create link and read'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'setenv filesize',
|
||||
'ln host 0:0 %s /%s.link ' % (SMALL_FILE, SMALL_FILE),
|
||||
])
|
||||
assert('' in ''.join(output))
|
||||
|
||||
output = u_boot_console.run_command_list([
|
||||
'%sload host 0:0 %x /%s.link' % (fs_type, ADDR, SMALL_FILE),
|
||||
'printenv filesize'])
|
||||
assert('filesize=100000' in ''.join(output))
|
||||
|
||||
# Test Case 4b - Read full 1MB of small file
|
||||
output = u_boot_console.run_command_list([
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[0] in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_symlink2(self, u_boot_console, fs_obj_symlink):
|
||||
"""
|
||||
Test Case 2 - create chained links
|
||||
"""
|
||||
fs_type, fs_img, md5val = fs_obj_symlink
|
||||
with u_boot_console.log.section('Test Case 2 - create chained links'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'setenv filesize',
|
||||
'ln host 0:0 %s /%s.link1 ' % (SMALL_FILE, SMALL_FILE),
|
||||
'ln host 0:0 /%s.link1 /SUBDIR/%s.link2' % (
|
||||
SMALL_FILE, SMALL_FILE),
|
||||
'ln host 0:0 SUBDIR/%s.link2 /%s.link3' % (
|
||||
SMALL_FILE, SMALL_FILE),
|
||||
])
|
||||
assert('' in ''.join(output))
|
||||
|
||||
output = u_boot_console.run_command_list([
|
||||
'%sload host 0:0 %x /%s.link3' % (fs_type, ADDR, SMALL_FILE),
|
||||
'printenv filesize'])
|
||||
assert('filesize=100000' in ''.join(output))
|
||||
|
||||
# Test Case 4b - Read full 1MB of small file
|
||||
output = u_boot_console.run_command_list([
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[0] in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_symlink3(self, u_boot_console, fs_obj_symlink):
|
||||
"""
|
||||
Test Case 3 - replace file/link with link
|
||||
"""
|
||||
fs_type, fs_img, md5val = fs_obj_symlink
|
||||
with u_boot_console.log.section('Test Case 1 - create link and read'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'setenv filesize',
|
||||
'ln host 0:0 %s /%s ' % (MEDIUM_FILE, SMALL_FILE),
|
||||
'ln host 0:0 %s /%s.link ' % (MEDIUM_FILE, MEDIUM_FILE),
|
||||
])
|
||||
assert('' in ''.join(output))
|
||||
|
||||
output = u_boot_console.run_command_list([
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, SMALL_FILE),
|
||||
'printenv filesize'])
|
||||
assert('filesize=a00000' in ''.join(output))
|
||||
|
||||
output = u_boot_console.run_command_list([
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[1] in ''.join(output))
|
||||
|
||||
output = u_boot_console.run_command_list([
|
||||
'ln host 0:0 %s.link /%s ' % (MEDIUM_FILE, SMALL_FILE),
|
||||
'%sload host 0:0 %x /%s' % (fs_type, ADDR, SMALL_FILE),
|
||||
'printenv filesize'])
|
||||
assert('filesize=a00000' in ''.join(output))
|
||||
|
||||
output = u_boot_console.run_command_list([
|
||||
'md5sum %x $filesize' % ADDR,
|
||||
'setenv filesize'])
|
||||
assert(md5val[1] in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_symlink4(self, u_boot_console, fs_obj_symlink):
|
||||
"""
|
||||
Test Case 4 - create a broken link
|
||||
"""
|
||||
fs_type, fs_img, md5val = fs_obj_symlink
|
||||
with u_boot_console.log.section('Test Case 1 - create link and read'):
|
||||
|
||||
output = u_boot_console.run_command_list([
|
||||
'setenv filesize',
|
||||
'ln host 0:0 nowhere /link ',
|
||||
])
|
||||
assert('' in ''.join(output))
|
||||
|
||||
output = u_boot_console.run_command(
|
||||
'%sload host 0:0 %x /link' %
|
||||
(fs_type, ADDR))
|
||||
with u_boot_console.disable_check('error_notification'):
|
||||
output = u_boot_console.run_command('printenv filesize')
|
||||
assert('"filesize" not defined' in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
@@ -0,0 +1,118 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2018, Linaro Limited
|
||||
# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
|
||||
#
|
||||
# U-Boot File System:unlink Test
|
||||
|
||||
"""
|
||||
This test verifies unlink operation (deleting a file or a directory)
|
||||
on file system.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from fstest_helpers import assert_fs_integrity
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.slow
|
||||
class TestUnlink(object):
|
||||
def test_unlink1(self, u_boot_console, fs_obj_unlink):
|
||||
"""
|
||||
Test Case 1 - delete a file
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_unlink
|
||||
with u_boot_console.log.section('Test Case 1 - unlink (file)'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%srm host 0:0 dir1/file1' % fs_type,
|
||||
'%sls host 0:0 dir1/file1' % fs_type])
|
||||
assert('' == ''.join(output))
|
||||
|
||||
output = u_boot_console.run_command(
|
||||
'%sls host 0:0 dir1/' % fs_type)
|
||||
assert(not 'file1' in output)
|
||||
assert('file2' in output)
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_unlink2(self, u_boot_console, fs_obj_unlink):
|
||||
"""
|
||||
Test Case 2 - delete many files
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_unlink
|
||||
with u_boot_console.log.section('Test Case 2 - unlink (many)'):
|
||||
output = u_boot_console.run_command('host bind 0 %s' % fs_img)
|
||||
|
||||
for i in range(0, 20):
|
||||
output = u_boot_console.run_command_list([
|
||||
'%srm host 0:0 dir2/0123456789abcdef%02x' % (fs_type, i),
|
||||
'%sls host 0:0 dir2/0123456789abcdef%02x' % (fs_type, i)])
|
||||
assert('' == ''.join(output))
|
||||
|
||||
output = u_boot_console.run_command(
|
||||
'%sls host 0:0 dir2' % fs_type)
|
||||
assert('0 file(s), 2 dir(s)' in output)
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_unlink3(self, u_boot_console, fs_obj_unlink):
|
||||
"""
|
||||
Test Case 3 - trying to delete a non-existing file should fail
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_unlink
|
||||
with u_boot_console.log.section('Test Case 3 - unlink (non-existing)'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%srm host 0:0 dir1/nofile' % fs_type])
|
||||
assert('nofile: doesn\'t exist' in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_unlink4(self, u_boot_console, fs_obj_unlink):
|
||||
"""
|
||||
Test Case 4 - delete an empty directory
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_unlink
|
||||
with u_boot_console.log.section('Test Case 4 - unlink (directory)'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%srm host 0:0 dir4' % fs_type])
|
||||
assert('' == ''.join(output))
|
||||
|
||||
output = u_boot_console.run_command(
|
||||
'%sls host 0:0 /' % fs_type)
|
||||
assert(not 'dir4' in output)
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_unlink5(self, u_boot_console, fs_obj_unlink):
|
||||
"""
|
||||
Test Case 5 - trying to deleting a non-empty directory ".."
|
||||
should fail
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_unlink
|
||||
with u_boot_console.log.section('Test Case 5 - unlink ("non-empty directory")'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%srm host 0:0 dir5' % fs_type])
|
||||
assert('directory is not empty' in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_unlink6(self, u_boot_console, fs_obj_unlink):
|
||||
"""
|
||||
Test Case 6 - trying to deleting a "." should fail
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_unlink
|
||||
with u_boot_console.log.section('Test Case 6 - unlink (".")'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%srm host 0:0 dir5/.' % fs_type])
|
||||
assert('directory is not empty' in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
|
||||
def test_unlink7(self, u_boot_console, fs_obj_unlink):
|
||||
"""
|
||||
Test Case 7 - trying to deleting a ".." should fail
|
||||
"""
|
||||
fs_type,fs_img = fs_obj_unlink
|
||||
with u_boot_console.log.section('Test Case 7 - unlink ("..")'):
|
||||
output = u_boot_console.run_command_list([
|
||||
'host bind 0 %s' % fs_img,
|
||||
'%srm host 0:0 dir5/..' % fs_type])
|
||||
assert('directory is not empty' in ''.join(output))
|
||||
assert_fs_integrity(fs_type, fs_img)
|
||||
@@ -0,0 +1,178 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2017 Alison Chaiken
|
||||
# Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
# Test GPT manipulation commands.
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import u_boot_utils
|
||||
|
||||
"""
|
||||
These tests rely on a 4 MB disk image, which is automatically created by
|
||||
the test.
|
||||
"""
|
||||
|
||||
class GptTestDiskImage(object):
|
||||
"""Disk Image used by the GPT tests."""
|
||||
|
||||
def __init__(self, u_boot_console):
|
||||
"""Initialize a new GptTestDiskImage object.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
filename = 'test_gpt_disk_image.bin'
|
||||
|
||||
persistent = u_boot_console.config.persistent_data_dir + '/' + filename
|
||||
self.path = u_boot_console.config.result_dir + '/' + filename
|
||||
|
||||
with u_boot_utils.persistent_file_helper(u_boot_console.log, persistent):
|
||||
if os.path.exists(persistent):
|
||||
u_boot_console.log.action('Disk image file ' + persistent +
|
||||
' already exists')
|
||||
else:
|
||||
u_boot_console.log.action('Generating ' + persistent)
|
||||
fd = os.open(persistent, os.O_RDWR | os.O_CREAT)
|
||||
os.ftruncate(fd, 4194304)
|
||||
os.close(fd)
|
||||
cmd = ('sgdisk',
|
||||
'--disk-guid=375a56f7-d6c9-4e81-b5f0-09d41ca89efe',
|
||||
persistent)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
# part1 offset 1MB size 1MB
|
||||
cmd = ('sgdisk', '--new=1:2048:4095', '--change-name=1:part1',
|
||||
persistent)
|
||||
# part2 offset 2MB size 1.5MB
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
cmd = ('sgdisk', '--new=2:4096:7167', '--change-name=2:part2',
|
||||
persistent)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
cmd = ('sgdisk', '--load-backup=' + persistent)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
|
||||
cmd = ('cp', persistent, self.path)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
|
||||
gtdi = None
|
||||
@pytest.fixture(scope='function')
|
||||
def state_disk_image(u_boot_console):
|
||||
"""pytest fixture to provide a GptTestDiskImage object to tests.
|
||||
This is function-scoped because it uses u_boot_console, which is also
|
||||
function-scoped. However, we don't need to actually do any function-scope
|
||||
work, so this simply returns the same object over and over each time."""
|
||||
|
||||
global gtdi
|
||||
if not gtdi:
|
||||
gtdi = GptTestDiskImage(u_boot_console)
|
||||
return gtdi
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.buildconfigspec('cmd_gpt')
|
||||
@pytest.mark.buildconfigspec('cmd_part')
|
||||
@pytest.mark.requiredtool('sgdisk')
|
||||
def test_gpt_read(state_disk_image, u_boot_console):
|
||||
"""Test the gpt read command."""
|
||||
|
||||
u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
|
||||
output = u_boot_console.run_command('gpt read host 0')
|
||||
assert 'Start 1MiB, size 1MiB' in output
|
||||
assert 'Block size 512, name part1' in output
|
||||
assert 'Start 2MiB, size 1MiB' in output
|
||||
assert 'Block size 512, name part2' in output
|
||||
output = u_boot_console.run_command('part list host 0')
|
||||
assert '0x00000800 0x00000fff "part1"' in output
|
||||
assert '0x00001000 0x00001bff "part2"' in output
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.buildconfigspec('cmd_gpt')
|
||||
@pytest.mark.requiredtool('sgdisk')
|
||||
def test_gpt_verify(state_disk_image, u_boot_console):
|
||||
"""Test the gpt verify command."""
|
||||
|
||||
u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
|
||||
output = u_boot_console.run_command('gpt verify host 0')
|
||||
assert 'Verify GPT: success!' in output
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.buildconfigspec('cmd_gpt')
|
||||
@pytest.mark.requiredtool('sgdisk')
|
||||
def test_gpt_guid(state_disk_image, u_boot_console):
|
||||
"""Test the gpt guid command."""
|
||||
|
||||
u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
|
||||
output = u_boot_console.run_command('gpt guid host 0')
|
||||
assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.buildconfigspec('cmd_gpt')
|
||||
@pytest.mark.requiredtool('sgdisk')
|
||||
def test_gpt_save_guid(state_disk_image, u_boot_console):
|
||||
"""Test the gpt guid command to save GUID into a string."""
|
||||
|
||||
if u_boot_console.config.buildconfig.get('config_cmd_gpt', 'n') != 'y':
|
||||
pytest.skip('gpt command not supported')
|
||||
u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
|
||||
output = u_boot_console.run_command('gpt guid host 0 newguid')
|
||||
output = u_boot_console.run_command('printenv newguid')
|
||||
assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.buildconfigspec('cmd_gpt')
|
||||
@pytest.mark.buildconfigspec('cmd_gpt_rename')
|
||||
@pytest.mark.buildconfigspec('cmd_part')
|
||||
@pytest.mark.requiredtool('sgdisk')
|
||||
def test_gpt_rename_partition(state_disk_image, u_boot_console):
|
||||
"""Test the gpt rename command to write partition names."""
|
||||
|
||||
u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
|
||||
u_boot_console.run_command('gpt rename host 0 1 first')
|
||||
output = u_boot_console.run_command('gpt read host 0')
|
||||
assert 'name first' in output
|
||||
u_boot_console.run_command('gpt rename host 0 2 second')
|
||||
output = u_boot_console.run_command('gpt read host 0')
|
||||
assert 'name second' in output
|
||||
output = u_boot_console.run_command('part list host 0')
|
||||
assert '0x00000800 0x00000fff "first"' in output
|
||||
assert '0x00001000 0x00001bff "second"' in output
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.buildconfigspec('cmd_gpt')
|
||||
@pytest.mark.buildconfigspec('cmd_gpt_rename')
|
||||
@pytest.mark.buildconfigspec('cmd_part')
|
||||
@pytest.mark.requiredtool('sgdisk')
|
||||
def test_gpt_swap_partitions(state_disk_image, u_boot_console):
|
||||
"""Test the gpt swap command to exchange two partition names."""
|
||||
|
||||
u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
|
||||
output = u_boot_console.run_command('part list host 0')
|
||||
assert '0x00000800 0x00000fff "first"' in output
|
||||
assert '0x00001000 0x00001bff "second"' in output
|
||||
u_boot_console.run_command('gpt swap host 0 first second')
|
||||
output = u_boot_console.run_command('part list host 0')
|
||||
assert '0x00000800 0x00000fff "second"' in output
|
||||
assert '0x00001000 0x00001bff "first"' in output
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.buildconfigspec('cmd_gpt')
|
||||
@pytest.mark.buildconfigspec('cmd_part')
|
||||
@pytest.mark.requiredtool('sgdisk')
|
||||
def test_gpt_write(state_disk_image, u_boot_console):
|
||||
"""Test the gpt write command."""
|
||||
|
||||
u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
|
||||
output = u_boot_console.run_command('gpt write host 0 "name=all,size=0"')
|
||||
assert 'Writing GPT: success!' in output
|
||||
output = u_boot_console.run_command('part list host 0')
|
||||
assert '0x00000022 0x00001fde "all"' in output
|
||||
output = u_boot_console.run_command('gpt write host 0 "uuid_disk=375a56f7-d6c9-4e81-b5f0-09d41ca89efe;name=first,start=1M,size=1M;name=second,start=0x200000,size=0x180000;"')
|
||||
assert 'Writing GPT: success!' in output
|
||||
output = u_boot_console.run_command('part list host 0')
|
||||
assert '0x00000800 0x00000fff "first"' in output
|
||||
assert '0x00001000 0x00001bff "second"' in output
|
||||
output = u_boot_console.run_command('gpt guid host 0')
|
||||
assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output
|
||||
@@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2016 Google, Inc
|
||||
|
||||
import pytest
|
||||
|
||||
# Magic number to check that SPL handoff is working
|
||||
TEST_HANDOFF_MAGIC = 0x14f93c7b
|
||||
|
||||
@pytest.mark.boardspec('sandbox_spl')
|
||||
@pytest.mark.buildconfigspec('spl')
|
||||
def test_handoff(u_boot_console):
|
||||
"""Test that of-platdata can be generated and used in sandbox"""
|
||||
cons = u_boot_console
|
||||
response = cons.run_command('sb handoff')
|
||||
assert ('SPL handoff magic %x' % TEST_HANDOFF_MAGIC) in response
|
||||
@@ -0,0 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2015 Stephen Warren
|
||||
# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
def test_help(u_boot_console):
|
||||
"""Test that the "help" command can be executed."""
|
||||
|
||||
u_boot_console.run_command('help')
|
||||
@@ -0,0 +1,161 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
# Test operation of the "if" shell command.
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import pytest
|
||||
|
||||
pytestmark = pytest.mark.buildconfigspec('hush_parser')
|
||||
|
||||
# The list of "if test" conditions to test.
|
||||
subtests = (
|
||||
# Base if functionality.
|
||||
|
||||
('true', True),
|
||||
('false', False),
|
||||
|
||||
# Basic operators.
|
||||
|
||||
('test aaa = aaa', True),
|
||||
('test aaa = bbb', False),
|
||||
|
||||
('test aaa != bbb', True),
|
||||
('test aaa != aaa', False),
|
||||
|
||||
('test aaa < bbb', True),
|
||||
('test bbb < aaa', False),
|
||||
|
||||
('test bbb > aaa', True),
|
||||
('test aaa > bbb', False),
|
||||
|
||||
('test 123 -eq 123', True),
|
||||
('test 123 -eq 456', False),
|
||||
|
||||
('test 123 -ne 456', True),
|
||||
('test 123 -ne 123', False),
|
||||
|
||||
('test 123 -lt 456', True),
|
||||
('test 123 -lt 123', False),
|
||||
('test 456 -lt 123', False),
|
||||
|
||||
('test 123 -le 456', True),
|
||||
('test 123 -le 123', True),
|
||||
('test 456 -le 123', False),
|
||||
|
||||
('test 456 -gt 123', True),
|
||||
('test 123 -gt 123', False),
|
||||
('test 123 -gt 456', False),
|
||||
|
||||
('test 456 -ge 123', True),
|
||||
('test 123 -ge 123', True),
|
||||
('test 123 -ge 456', False),
|
||||
|
||||
('test -z ""', True),
|
||||
('test -z "aaa"', False),
|
||||
|
||||
('test -n "aaa"', True),
|
||||
('test -n ""', False),
|
||||
|
||||
# Inversion of simple tests.
|
||||
|
||||
('test ! aaa = aaa', False),
|
||||
('test ! aaa = bbb', True),
|
||||
('test ! ! aaa = aaa', True),
|
||||
('test ! ! aaa = bbb', False),
|
||||
|
||||
# Binary operators.
|
||||
|
||||
('test aaa != aaa -o bbb != bbb', False),
|
||||
('test aaa != aaa -o bbb = bbb', True),
|
||||
('test aaa = aaa -o bbb != bbb', True),
|
||||
('test aaa = aaa -o bbb = bbb', True),
|
||||
|
||||
('test aaa != aaa -a bbb != bbb', False),
|
||||
('test aaa != aaa -a bbb = bbb', False),
|
||||
('test aaa = aaa -a bbb != bbb', False),
|
||||
('test aaa = aaa -a bbb = bbb', True),
|
||||
|
||||
# Inversion within binary operators.
|
||||
|
||||
('test ! aaa != aaa -o ! bbb != bbb', True),
|
||||
('test ! aaa != aaa -o ! bbb = bbb', True),
|
||||
('test ! aaa = aaa -o ! bbb != bbb', True),
|
||||
('test ! aaa = aaa -o ! bbb = bbb', False),
|
||||
|
||||
('test ! ! aaa != aaa -o ! ! bbb != bbb', False),
|
||||
('test ! ! aaa != aaa -o ! ! bbb = bbb', True),
|
||||
('test ! ! aaa = aaa -o ! ! bbb != bbb', True),
|
||||
('test ! ! aaa = aaa -o ! ! bbb = bbb', True),
|
||||
|
||||
# -z operator.
|
||||
|
||||
('test -z "$ut_var_nonexistent"', True),
|
||||
('test -z "$ut_var_exists"', False),
|
||||
)
|
||||
|
||||
def exec_hush_if(u_boot_console, expr, result):
|
||||
"""Execute a shell "if" command, and validate its result."""
|
||||
|
||||
config = u_boot_console.config.buildconfig
|
||||
maxargs = int(config.get('config_sys_maxargs', '0'))
|
||||
args = len(expr.split(' ')) - 1
|
||||
if args > maxargs:
|
||||
u_boot_console.log.warning('CONFIG_SYS_MAXARGS too low; need ' +
|
||||
str(args))
|
||||
pytest.skip()
|
||||
|
||||
cmd = 'if ' + expr + '; then echo true; else echo false; fi'
|
||||
response = u_boot_console.run_command(cmd)
|
||||
assert response.strip() == str(result).lower()
|
||||
|
||||
def test_hush_if_test_setup(u_boot_console):
|
||||
"""Set up environment variables used during the "if" tests."""
|
||||
|
||||
u_boot_console.run_command('setenv ut_var_nonexistent')
|
||||
u_boot_console.run_command('setenv ut_var_exists 1')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
@pytest.mark.parametrize('expr,result', subtests)
|
||||
def test_hush_if_test(u_boot_console, expr, result):
|
||||
"""Test a single "if test" condition."""
|
||||
|
||||
exec_hush_if(u_boot_console, expr, result)
|
||||
|
||||
def test_hush_if_test_teardown(u_boot_console):
|
||||
"""Clean up environment variables used during the "if" tests."""
|
||||
|
||||
u_boot_console.run_command('setenv ut_var_exists')
|
||||
|
||||
# We might test this on real filesystems via UMS, DFU, 'save', etc.
|
||||
# Of those, only UMS currently allows file removal though.
|
||||
@pytest.mark.buildconfigspec('cmd_echo')
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
def test_hush_if_test_host_file_exists(u_boot_console):
|
||||
"""Test the "if test -e" shell command."""
|
||||
|
||||
test_file = u_boot_console.config.result_dir + \
|
||||
'/creating_this_file_breaks_u_boot_tests'
|
||||
|
||||
try:
|
||||
os.unlink(test_file)
|
||||
except:
|
||||
pass
|
||||
assert not os.path.exists(test_file)
|
||||
|
||||
expr = 'test -e hostfs - ' + test_file
|
||||
exec_hush_if(u_boot_console, expr, False)
|
||||
|
||||
try:
|
||||
with open(test_file, 'wb'):
|
||||
pass
|
||||
assert os.path.exists(test_file)
|
||||
|
||||
expr = 'test -e hostfs - ' + test_file
|
||||
exec_hush_if(u_boot_console, expr, True)
|
||||
finally:
|
||||
os.unlink(test_file)
|
||||
|
||||
expr = 'test -e hostfs - ' + test_file
|
||||
exec_hush_if(u_boot_console, expr, False)
|
||||
@@ -0,0 +1,132 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2016, Google Inc.
|
||||
#
|
||||
# U-Boot Verified Boot Test
|
||||
|
||||
"""
|
||||
This tests U-Boot logging. It uses the 'log test' command with various options
|
||||
and checks that the output is correct.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
LOGL_FIRST, LOGL_WARNING, LOGL_INFO = (0, 4, 6)
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_log')
|
||||
def test_log(u_boot_console):
|
||||
"""Test that U-Boot logging works correctly."""
|
||||
def check_log_entries(lines, mask, max_level=LOGL_INFO):
|
||||
"""Check that the expected log records appear in the output
|
||||
|
||||
Args:
|
||||
lines: iterator containing lines to check
|
||||
mask: bit mask to select which lines to check for:
|
||||
bit 0: standard log line
|
||||
bit 1: _log line
|
||||
max_level: maximum log level to expect in the output
|
||||
"""
|
||||
for i in range(max_level):
|
||||
if mask & 1:
|
||||
assert 'log_run() log %d' % i == next(lines)
|
||||
if mask & 3:
|
||||
assert 'func() _log %d' % i == next(lines)
|
||||
|
||||
def run_test(testnum):
|
||||
"""Run a particular test number (the 'log test' command)
|
||||
|
||||
Args:
|
||||
testnum: Test number to run
|
||||
Returns:
|
||||
iterator containing the lines output from the command
|
||||
"""
|
||||
with cons.log.section('basic'):
|
||||
output = u_boot_console.run_command('log test %d' % testnum)
|
||||
split = output.replace('\r', '').splitlines()
|
||||
lines = iter(split)
|
||||
assert 'test %d' % testnum == next(lines)
|
||||
return lines
|
||||
|
||||
def test0():
|
||||
lines = run_test(0)
|
||||
check_log_entries(lines, 3)
|
||||
|
||||
def test1():
|
||||
lines = run_test(1)
|
||||
check_log_entries(lines, 3)
|
||||
|
||||
def test2():
|
||||
lines = run_test(2)
|
||||
|
||||
def test3():
|
||||
lines = run_test(3)
|
||||
check_log_entries(lines, 2)
|
||||
|
||||
def test4():
|
||||
lines = run_test(4)
|
||||
assert next(lines, None) == None
|
||||
|
||||
def test5():
|
||||
lines = run_test(5)
|
||||
check_log_entries(lines, 2)
|
||||
|
||||
def test6():
|
||||
lines = run_test(6)
|
||||
check_log_entries(lines, 3)
|
||||
|
||||
def test7():
|
||||
lines = run_test(7)
|
||||
check_log_entries(lines, 3, LOGL_WARNING)
|
||||
|
||||
def test8():
|
||||
lines = run_test(8)
|
||||
check_log_entries(lines, 3)
|
||||
|
||||
def test9():
|
||||
lines = run_test(9)
|
||||
check_log_entries(lines, 3)
|
||||
|
||||
def test10():
|
||||
lines = run_test(10)
|
||||
for i in range(7):
|
||||
assert 'log_test() level %d' % i == next(lines)
|
||||
|
||||
# TODO(sjg@chromium.org): Consider structuring this as separate tests
|
||||
cons = u_boot_console
|
||||
test0()
|
||||
test1()
|
||||
test2()
|
||||
test3()
|
||||
test4()
|
||||
test5()
|
||||
test6()
|
||||
test7()
|
||||
test8()
|
||||
test9()
|
||||
test10()
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_log')
|
||||
def test_log_format(u_boot_console):
|
||||
"""Test the 'log format' and 'log rec' commands"""
|
||||
def run_with_format(fmt, expected_output):
|
||||
"""Set up the log format and then write a log record
|
||||
|
||||
Args:
|
||||
fmt: Format to use for 'log format'
|
||||
expected_output: Expected output from the 'log rec' command
|
||||
"""
|
||||
output = cons.run_command('log format %s' % fmt)
|
||||
assert output == ''
|
||||
output = cons.run_command('log rec arch notice file.c 123 func msg')
|
||||
assert output == expected_output
|
||||
|
||||
cons = u_boot_console
|
||||
with cons.log.section('format'):
|
||||
run_with_format('all', 'NOTICE.arch,file.c:123-func() msg')
|
||||
output = cons.run_command('log format')
|
||||
assert output == 'Log format: clFLfm'
|
||||
|
||||
run_with_format('fm', 'func() msg')
|
||||
run_with_format('clfm', 'NOTICE.arch,func() msg')
|
||||
run_with_format('FLfm', 'file.c:123-func() msg')
|
||||
run_with_format('lm', 'NOTICE. msg')
|
||||
run_with_format('m', 'msg')
|
||||
@@ -0,0 +1,36 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2015 Stephen Warren
|
||||
# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
import pytest
|
||||
import u_boot_utils
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_memory')
|
||||
def test_md(u_boot_console):
|
||||
"""Test that md reads memory as expected, and that memory can be modified
|
||||
using the mw command."""
|
||||
|
||||
ram_base = u_boot_utils.find_ram_base(u_boot_console)
|
||||
addr = '%08x' % ram_base
|
||||
val = 'a5f09876'
|
||||
expected_response = addr + ': ' + val
|
||||
u_boot_console.run_command('mw ' + addr + ' 0 10')
|
||||
response = u_boot_console.run_command('md ' + addr + ' 10')
|
||||
assert(not (expected_response in response))
|
||||
u_boot_console.run_command('mw ' + addr + ' ' + val)
|
||||
response = u_boot_console.run_command('md ' + addr + ' 10')
|
||||
assert(expected_response in response)
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_memory')
|
||||
def test_md_repeat(u_boot_console):
|
||||
"""Test command repeat (via executing an empty command) operates correctly
|
||||
for "md"; the command must repeat and dump an incrementing address."""
|
||||
|
||||
ram_base = u_boot_utils.find_ram_base(u_boot_console)
|
||||
addr_base = '%08x' % ram_base
|
||||
words = 0x10
|
||||
addr_repeat = '%08x' % (ram_base + (words * 4))
|
||||
u_boot_console.run_command('md %s %x' % (addr_base, words))
|
||||
response = u_boot_console.run_command('')
|
||||
expected_response = addr_repeat + ': '
|
||||
assert(expected_response in response)
|
||||
@@ -0,0 +1,286 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
# Test U-Boot's "mmc read" command. The test reads data from the eMMC or SD
|
||||
# card, and validates the no errors occurred, and that the expected data was
|
||||
# read if the test configuration contains a CRC of the expected data.
|
||||
|
||||
import pytest
|
||||
import time
|
||||
import u_boot_utils
|
||||
|
||||
"""
|
||||
This test relies on boardenv_* to containing configuration values to define
|
||||
which MMC devices should be tested. For example:
|
||||
|
||||
# Configuration data for test_mmc_dev, test_mmc_rescan, test_mmc_info; defines
|
||||
# whole MMC devices that mmc dev/rescan/info commands may operate upon.
|
||||
env__mmc_dev_configs = (
|
||||
{
|
||||
'fixture_id': 'emmc-boot0',
|
||||
'is_emmc': True,
|
||||
'devid': 0,
|
||||
'partid': 1,
|
||||
'info_device': ???,
|
||||
'info_speed': ???,
|
||||
'info_mode': ???,
|
||||
'info_buswidth': ???.
|
||||
},
|
||||
{
|
||||
'fixture_id': 'emmc-boot1',
|
||||
'is_emmc': True,
|
||||
'devid': 0,
|
||||
'partid': 2,
|
||||
'info_device': ???,
|
||||
'info_speed': ???,
|
||||
'info_mode': ???,
|
||||
'info_buswidth': ???.
|
||||
},
|
||||
{
|
||||
'fixture_id': 'emmc-data',
|
||||
'is_emmc': True,
|
||||
'devid': 0,
|
||||
'partid': 0,
|
||||
'info_device': ???,
|
||||
'info_speed': ???,
|
||||
'info_mode': ???,
|
||||
'info_buswidth': ???.
|
||||
},
|
||||
{
|
||||
'fixture_id': 'sd',
|
||||
'is_emmc': False,
|
||||
'devid': 1,
|
||||
'partid': None,
|
||||
'info_device': ???,
|
||||
'info_speed': ???,
|
||||
'info_mode': ???,
|
||||
'info_buswidth': ???.
|
||||
},
|
||||
}
|
||||
|
||||
# Configuration data for test_mmc_rd; defines regions of the MMC (entire
|
||||
# devices, or ranges of sectors) which can be read:
|
||||
env__mmc_rd_configs = (
|
||||
{
|
||||
'fixture_id': 'emmc-boot0',
|
||||
'is_emmc': True,
|
||||
'devid': 0,
|
||||
'partid': 1,
|
||||
'sector': 0x10,
|
||||
'count': 1,
|
||||
},
|
||||
{
|
||||
'fixture_id': 'emmc-boot1',
|
||||
'is_emmc': True,
|
||||
'devid': 0,
|
||||
'partid': 2,
|
||||
'sector': 0x10,
|
||||
'count': 1,
|
||||
},
|
||||
{
|
||||
'fixture_id': 'emmc-data',
|
||||
'is_emmc': True,
|
||||
'devid': 0,
|
||||
'partid': 0,
|
||||
'sector': 0x10,
|
||||
'count': 0x1000,
|
||||
},
|
||||
{
|
||||
'fixture_id': 'sd-mbr',
|
||||
'is_emmc': False,
|
||||
'devid': 1,
|
||||
'partid': None,
|
||||
'sector': 0,
|
||||
'count': 1,
|
||||
'crc32': '8f6ecf0d',
|
||||
},
|
||||
{
|
||||
'fixture_id': 'sd-large',
|
||||
'is_emmc': False,
|
||||
'devid': 1,
|
||||
'partid': None,
|
||||
'sector': 0x10,
|
||||
'count': 0x1000,
|
||||
},
|
||||
)
|
||||
"""
|
||||
|
||||
def mmc_dev(u_boot_console, is_emmc, devid, partid):
|
||||
"""Run the "mmc dev" command.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console connection.
|
||||
is_emmc: Whether the device is eMMC
|
||||
devid: Device ID
|
||||
partid: Partition ID
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
# Select MMC device
|
||||
cmd = 'mmc dev %d' % devid
|
||||
if is_emmc:
|
||||
cmd += ' %d' % partid
|
||||
response = u_boot_console.run_command(cmd)
|
||||
assert 'no card present' not in response
|
||||
if is_emmc:
|
||||
partid_response = '(part %d)' % partid
|
||||
else:
|
||||
partid_response = ''
|
||||
good_response = 'mmc%d%s is current device' % (devid, partid_response)
|
||||
assert good_response in response
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_mmc')
|
||||
def test_mmc_dev(u_boot_console, env__mmc_dev_config):
|
||||
"""Test the "mmc dev" command.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console connection.
|
||||
env__mmc_dev_config: The single MMC configuration on which
|
||||
to run the test. See the file-level comment above for details
|
||||
of the format.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
is_emmc = env__mmc_dev_config['is_emmc']
|
||||
devid = env__mmc_dev_config['devid']
|
||||
partid = env__mmc_dev_config.get('partid', 0)
|
||||
|
||||
# Select MMC device
|
||||
mmc_dev(u_boot_console, is_emmc, devid, partid)
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_mmc')
|
||||
def test_mmc_rescan(u_boot_console, env__mmc_dev_config):
|
||||
"""Test the "mmc rescan" command.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console connection.
|
||||
env__mmc_dev_config: The single MMC configuration on which
|
||||
to run the test. See the file-level comment above for details
|
||||
of the format.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
is_emmc = env__mmc_dev_config['is_emmc']
|
||||
devid = env__mmc_dev_config['devid']
|
||||
partid = env__mmc_dev_config.get('partid', 0)
|
||||
|
||||
# Select MMC device
|
||||
mmc_dev(u_boot_console, is_emmc, devid, partid)
|
||||
|
||||
# Rescan MMC device
|
||||
cmd = 'mmc rescan'
|
||||
response = u_boot_console.run_command(cmd)
|
||||
assert 'no card present' not in response
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_mmc')
|
||||
def test_mmc_info(u_boot_console, env__mmc_dev_config):
|
||||
"""Test the "mmc info" command.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console connection.
|
||||
env__mmc_dev_config: The single MMC configuration on which
|
||||
to run the test. See the file-level comment above for details
|
||||
of the format.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
is_emmc = env__mmc_dev_config['is_emmc']
|
||||
devid = env__mmc_dev_config['devid']
|
||||
partid = env__mmc_dev_config.get('partid', 0)
|
||||
info_device = env__mmc_dev_config['info_device']
|
||||
info_speed = env__mmc_dev_config['info_speed']
|
||||
info_mode = env__mmc_dev_config['info_mode']
|
||||
info_buswidth = env__mmc_dev_config['info_buswidth']
|
||||
|
||||
# Select MMC device
|
||||
mmc_dev(u_boot_console, is_emmc, devid, partid)
|
||||
|
||||
# Read MMC device information
|
||||
cmd = 'mmc info'
|
||||
response = u_boot_console.run_command(cmd)
|
||||
good_response = "Device: %s" % info_device
|
||||
assert good_response in response
|
||||
good_response = "Bus Speed: %s" % info_speed
|
||||
assert good_response in response
|
||||
good_response = "Mode : %s" % info_mode
|
||||
assert good_response in response
|
||||
good_response = "Bus Width: %s" % info_buswidth
|
||||
assert good_response in response
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_mmc')
|
||||
def test_mmc_rd(u_boot_console, env__mmc_rd_config):
|
||||
"""Test the "mmc read" command.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console connection.
|
||||
env__mmc_rd_config: The single MMC configuration on which
|
||||
to run the test. See the file-level comment above for details
|
||||
of the format.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
is_emmc = env__mmc_rd_config['is_emmc']
|
||||
devid = env__mmc_rd_config['devid']
|
||||
partid = env__mmc_rd_config.get('partid', 0)
|
||||
sector = env__mmc_rd_config.get('sector', 0)
|
||||
count_sectors = env__mmc_rd_config.get('count', 1)
|
||||
expected_crc32 = env__mmc_rd_config.get('crc32', None)
|
||||
read_duration_max = env__mmc_rd_config.get('read_duration_max', 0)
|
||||
|
||||
count_bytes = count_sectors * 512
|
||||
bcfg = u_boot_console.config.buildconfig
|
||||
has_cmd_memory = bcfg.get('config_cmd_memory', 'n') == 'y'
|
||||
has_cmd_crc32 = bcfg.get('config_cmd_crc32', 'n') == 'y'
|
||||
ram_base = u_boot_utils.find_ram_base(u_boot_console)
|
||||
addr = '0x%08x' % ram_base
|
||||
|
||||
# Select MMC device
|
||||
mmc_dev(u_boot_console, is_emmc, devid, partid)
|
||||
|
||||
# Clear target RAM
|
||||
if expected_crc32:
|
||||
if has_cmd_memory and has_cmd_crc32:
|
||||
cmd = 'mw.b %s 0 0x%x' % (addr, count_bytes)
|
||||
u_boot_console.run_command(cmd)
|
||||
|
||||
cmd = 'crc32 %s 0x%x' % (addr, count_bytes)
|
||||
response = u_boot_console.run_command(cmd)
|
||||
assert expected_crc32 not in response
|
||||
else:
|
||||
u_boot_console.log.warning(
|
||||
'CONFIG_CMD_MEMORY or CONFIG_CMD_CRC32 != y: Skipping RAM clear')
|
||||
|
||||
# Read data
|
||||
cmd = 'mmc read %s %x %x' % (addr, sector, count_sectors)
|
||||
tstart = time.time()
|
||||
response = u_boot_console.run_command(cmd)
|
||||
tend = time.time()
|
||||
good_response = 'MMC read: dev # %d, block # %d, count %d ... %d blocks read: OK' % (
|
||||
devid, sector, count_sectors, count_sectors)
|
||||
assert good_response in response
|
||||
|
||||
# Check target RAM
|
||||
if expected_crc32:
|
||||
if has_cmd_crc32:
|
||||
cmd = 'crc32 %s 0x%x' % (addr, count_bytes)
|
||||
response = u_boot_console.run_command(cmd)
|
||||
assert expected_crc32 in response
|
||||
else:
|
||||
u_boot_console.log.warning('CONFIG_CMD_CRC32 != y: Skipping check')
|
||||
|
||||
# Check if the command did not take too long
|
||||
if read_duration_max:
|
||||
elapsed = tend - tstart
|
||||
u_boot_console.log.info('Reading %d bytes took %f seconds' %
|
||||
(count_bytes, elapsed))
|
||||
assert elapsed <= (read_duration_max - 0.01)
|
||||
@@ -0,0 +1,105 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2019, Texas Instrument
|
||||
# Author: Jean-Jacques Hiblot <jjhiblot@ti.com>
|
||||
|
||||
# Test U-Boot's "mmc write" command. The test generates random data, writes it
|
||||
# to the eMMC or SD card, then reads it back and performs a comparison.
|
||||
|
||||
import pytest
|
||||
import u_boot_utils
|
||||
|
||||
"""
|
||||
This test relies on boardenv_* to containing configuration values to define
|
||||
which MMC devices should be tested. For example:
|
||||
|
||||
env__mmc_wr_configs = (
|
||||
{
|
||||
"fixture_id": "emmc-boot0",
|
||||
"is_emmc": True,
|
||||
"devid": 1,
|
||||
"partid": 1,
|
||||
"sector": 0x10,
|
||||
"count": 100,
|
||||
"test_iterations": 50,
|
||||
},
|
||||
{
|
||||
"fixture_id": "emmc-boot1",
|
||||
"is_emmc": True,
|
||||
"devid": 1,
|
||||
"partid": 2,
|
||||
"sector": 0x10,
|
||||
"count": 100,
|
||||
"test_iterations": 50,
|
||||
},
|
||||
)
|
||||
|
||||
"""
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_mmc')
|
||||
@pytest.mark.buildconfigspec('cmd_memory')
|
||||
@pytest.mark.buildconfigspec('cmd_random')
|
||||
def test_mmc_wr(u_boot_console, env__mmc_wr_config):
|
||||
"""Test the "mmc write" command.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console connection.
|
||||
env__mmc_wr_config: The single MMC configuration on which
|
||||
to run the test. See the file-level comment above for details
|
||||
of the format.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
is_emmc = env__mmc_wr_config['is_emmc']
|
||||
devid = env__mmc_wr_config['devid']
|
||||
partid = env__mmc_wr_config.get('partid', 0)
|
||||
sector = env__mmc_wr_config.get('sector', 0)
|
||||
count_sectors = env__mmc_wr_config.get('count', 1)
|
||||
test_iterations = env__mmc_wr_config.get('test_iterations', 1)
|
||||
|
||||
|
||||
count_bytes = count_sectors * 512
|
||||
bcfg = u_boot_console.config.buildconfig
|
||||
ram_base = u_boot_utils.find_ram_base(u_boot_console)
|
||||
src_addr = '0x%08x' % ram_base
|
||||
dst_addr = '0x%08x' % (ram_base + count_bytes)
|
||||
|
||||
|
||||
for i in range(test_iterations):
|
||||
# Generate random data
|
||||
cmd = 'random %s %x' % (src_addr, count_bytes)
|
||||
response = u_boot_console.run_command(cmd)
|
||||
good_response = '%d bytes filled with random data' % (count_bytes)
|
||||
assert good_response in response
|
||||
|
||||
# Select MMC device
|
||||
cmd = 'mmc dev %d' % devid
|
||||
if is_emmc:
|
||||
cmd += ' %d' % partid
|
||||
response = u_boot_console.run_command(cmd)
|
||||
assert 'no card present' not in response
|
||||
if is_emmc:
|
||||
partid_response = "(part %d)" % partid
|
||||
else:
|
||||
partid_response = ""
|
||||
good_response = 'mmc%d%s is current device' % (devid, partid_response)
|
||||
assert good_response in response
|
||||
|
||||
# Write data
|
||||
cmd = 'mmc write %s %x %x' % (src_addr, sector, count_sectors)
|
||||
response = u_boot_console.run_command(cmd)
|
||||
good_response = 'MMC write: dev # %d, block # %d, count %d ... %d blocks written: OK' % (devid, sector, count_sectors, count_sectors)
|
||||
assert good_response in response
|
||||
|
||||
# Read data
|
||||
cmd = 'mmc read %s %x %x' % (dst_addr, sector, count_sectors)
|
||||
response = u_boot_console.run_command(cmd)
|
||||
good_response = 'MMC read: dev # %d, block # %d, count %d ... %d blocks read: OK' % (devid, sector, count_sectors, count_sectors)
|
||||
assert good_response in response
|
||||
|
||||
# Compare src and dst data
|
||||
cmd = 'cmp.b %s %s %x' % (src_addr, dst_addr, count_bytes)
|
||||
response = u_boot_console.run_command(cmd)
|
||||
good_response = 'Total of %d byte(s) were the same' % (count_bytes)
|
||||
assert good_response in response
|
||||
@@ -0,0 +1,208 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
# Test various network-related functionality, such as the dhcp, ping, and
|
||||
# tftpboot commands.
|
||||
|
||||
import pytest
|
||||
import u_boot_utils
|
||||
|
||||
"""
|
||||
Note: This test relies on boardenv_* containing configuration values to define
|
||||
which the network environment available for testing. Without this, this test
|
||||
will be automatically skipped.
|
||||
|
||||
For example:
|
||||
|
||||
# Boolean indicating whether the Ethernet device is attached to USB, and hence
|
||||
# USB enumeration needs to be performed prior to network tests.
|
||||
# This variable may be omitted if its value is False.
|
||||
env__net_uses_usb = False
|
||||
|
||||
# Boolean indicating whether the Ethernet device is attached to PCI, and hence
|
||||
# PCI enumeration needs to be performed prior to network tests.
|
||||
# This variable may be omitted if its value is False.
|
||||
env__net_uses_pci = True
|
||||
|
||||
# True if a DHCP server is attached to the network, and should be tested.
|
||||
# If DHCP testing is not possible or desired, this variable may be omitted or
|
||||
# set to False.
|
||||
env__net_dhcp_server = True
|
||||
|
||||
# A list of environment variables that should be set in order to configure a
|
||||
# static IP. If solely relying on DHCP, this variable may be omitted or set to
|
||||
# an empty list.
|
||||
env__net_static_env_vars = [
|
||||
('ipaddr', '10.0.0.100'),
|
||||
('netmask', '255.255.255.0'),
|
||||
('serverip', '10.0.0.1'),
|
||||
]
|
||||
|
||||
# Details regarding a file that may be read from a TFTP server. This variable
|
||||
# may be omitted or set to None if TFTP testing is not possible or desired.
|
||||
env__net_tftp_readable_file = {
|
||||
'fn': 'ubtest-readable.bin',
|
||||
'addr': 0x10000000,
|
||||
'size': 5058624,
|
||||
'crc32': 'c2244b26',
|
||||
}
|
||||
|
||||
# Details regarding a file that may be read from a NFS server. This variable
|
||||
# may be omitted or set to None if NFS testing is not possible or desired.
|
||||
env__net_nfs_readable_file = {
|
||||
'fn': 'ubtest-readable.bin',
|
||||
'addr': 0x10000000,
|
||||
'size': 5058624,
|
||||
'crc32': 'c2244b26',
|
||||
}
|
||||
"""
|
||||
|
||||
net_set_up = False
|
||||
|
||||
def test_net_pre_commands(u_boot_console):
|
||||
"""Execute any commands required to enable network hardware.
|
||||
|
||||
These commands are provided by the boardenv_* file; see the comment at the
|
||||
beginning of this file.
|
||||
"""
|
||||
|
||||
init_usb = u_boot_console.config.env.get('env__net_uses_usb', False)
|
||||
if init_usb:
|
||||
u_boot_console.run_command('usb start')
|
||||
|
||||
init_pci = u_boot_console.config.env.get('env__net_uses_pci', False)
|
||||
if init_pci:
|
||||
u_boot_console.run_command('pci enum')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_dhcp')
|
||||
def test_net_dhcp(u_boot_console):
|
||||
"""Test the dhcp command.
|
||||
|
||||
The boardenv_* file may be used to enable/disable this test; see the
|
||||
comment at the beginning of this file.
|
||||
"""
|
||||
|
||||
test_dhcp = u_boot_console.config.env.get('env__net_dhcp_server', False)
|
||||
if not test_dhcp:
|
||||
pytest.skip('No DHCP server available')
|
||||
|
||||
u_boot_console.run_command('setenv autoload no')
|
||||
output = u_boot_console.run_command('dhcp')
|
||||
assert 'DHCP client bound to address ' in output
|
||||
|
||||
global net_set_up
|
||||
net_set_up = True
|
||||
|
||||
@pytest.mark.buildconfigspec('net')
|
||||
def test_net_setup_static(u_boot_console):
|
||||
"""Set up a static IP configuration.
|
||||
|
||||
The configuration is provided by the boardenv_* file; see the comment at
|
||||
the beginning of this file.
|
||||
"""
|
||||
|
||||
env_vars = u_boot_console.config.env.get('env__net_static_env_vars', None)
|
||||
if not env_vars:
|
||||
pytest.skip('No static network configuration is defined')
|
||||
|
||||
for (var, val) in env_vars:
|
||||
u_boot_console.run_command('setenv %s %s' % (var, val))
|
||||
|
||||
global net_set_up
|
||||
net_set_up = True
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_ping')
|
||||
def test_net_ping(u_boot_console):
|
||||
"""Test the ping command.
|
||||
|
||||
The $serverip (as set up by either test_net_dhcp or test_net_setup_static)
|
||||
is pinged. The test validates that the host is alive, as reported by the
|
||||
ping command's output.
|
||||
"""
|
||||
|
||||
if not net_set_up:
|
||||
pytest.skip('Network not initialized')
|
||||
|
||||
output = u_boot_console.run_command('ping $serverip')
|
||||
assert 'is alive' in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_net')
|
||||
def test_net_tftpboot(u_boot_console):
|
||||
"""Test the tftpboot command.
|
||||
|
||||
A file is downloaded from the TFTP server, its size and optionally its
|
||||
CRC32 are validated.
|
||||
|
||||
The details of the file to download are provided by the boardenv_* file;
|
||||
see the comment at the beginning of this file.
|
||||
"""
|
||||
|
||||
if not net_set_up:
|
||||
pytest.skip('Network not initialized')
|
||||
|
||||
f = u_boot_console.config.env.get('env__net_tftp_readable_file', None)
|
||||
if not f:
|
||||
pytest.skip('No TFTP readable file to read')
|
||||
|
||||
addr = f.get('addr', None)
|
||||
|
||||
fn = f['fn']
|
||||
if not addr:
|
||||
output = u_boot_console.run_command('tftpboot %s' % (fn))
|
||||
else:
|
||||
output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
|
||||
expected_text = 'Bytes transferred = '
|
||||
sz = f.get('size', None)
|
||||
if sz:
|
||||
expected_text += '%d' % sz
|
||||
assert expected_text in output
|
||||
|
||||
expected_crc = f.get('crc32', None)
|
||||
if not expected_crc:
|
||||
return
|
||||
|
||||
if u_boot_console.config.buildconfig.get('config_cmd_crc32', 'n') != 'y':
|
||||
return
|
||||
|
||||
output = u_boot_console.run_command('crc32 $fileaddr $filesize')
|
||||
assert expected_crc in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_nfs')
|
||||
def test_net_nfs(u_boot_console):
|
||||
"""Test the nfs command.
|
||||
|
||||
A file is downloaded from the NFS server, its size and optionally its
|
||||
CRC32 are validated.
|
||||
|
||||
The details of the file to download are provided by the boardenv_* file;
|
||||
see the comment at the beginning of this file.
|
||||
"""
|
||||
|
||||
if not net_set_up:
|
||||
pytest.skip('Network not initialized')
|
||||
|
||||
f = u_boot_console.config.env.get('env__net_nfs_readable_file', None)
|
||||
if not f:
|
||||
pytest.skip('No NFS readable file to read')
|
||||
|
||||
addr = f.get('addr', None)
|
||||
if not addr:
|
||||
addr = u_boot_utils.find_ram_base(u_boot_console)
|
||||
|
||||
fn = f['fn']
|
||||
output = u_boot_console.run_command('nfs %x %s' % (addr, fn))
|
||||
expected_text = 'Bytes transferred = '
|
||||
sz = f.get('size', None)
|
||||
if sz:
|
||||
expected_text += '%d' % sz
|
||||
assert expected_text in output
|
||||
|
||||
expected_crc = f.get('crc32', None)
|
||||
if not expected_crc:
|
||||
return
|
||||
|
||||
if u_boot_console.config.buildconfig.get('config_cmd_crc32', 'n') != 'y':
|
||||
return
|
||||
|
||||
output = u_boot_console.run_command('crc32 %x $filesize' % addr)
|
||||
assert expected_crc in output
|
||||
@@ -0,0 +1,70 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2016 Google, Inc
|
||||
|
||||
import pytest
|
||||
import u_boot_utils as util
|
||||
|
||||
OF_PLATDATA_OUTPUT = '''
|
||||
of-platdata probe:
|
||||
bool 1
|
||||
byte 05
|
||||
bytearray 06 00 00
|
||||
int 1
|
||||
intarray 2 3 4 0
|
||||
longbytearray 09 0a 0b 0c 0d 0e 0f 10 11
|
||||
string message
|
||||
stringarray "multi-word" "message" ""
|
||||
of-platdata probe:
|
||||
bool 0
|
||||
byte 08
|
||||
bytearray 01 23 34
|
||||
int 3
|
||||
intarray 5 0 0 0
|
||||
longbytearray 09 00 00 00 00 00 00 00 00
|
||||
string message2
|
||||
stringarray "another" "multi-word" "message"
|
||||
of-platdata probe:
|
||||
bool 0
|
||||
byte 00
|
||||
bytearray 00 00 00
|
||||
int 0
|
||||
intarray 0 0 0 0
|
||||
longbytearray 00 00 00 00 00 00 00 00 00
|
||||
string <NULL>
|
||||
stringarray "one" "" ""
|
||||
of-platdata probe:
|
||||
bool 0
|
||||
byte 00
|
||||
bytearray 00 00 00
|
||||
int 0
|
||||
intarray 0 0 0 0
|
||||
longbytearray 00 00 00 00 00 00 00 00 00
|
||||
string <NULL>
|
||||
stringarray "spl" "" ""
|
||||
'''
|
||||
|
||||
@pytest.mark.buildconfigspec('spl_of_platdata')
|
||||
def test_ofplatdata(u_boot_console):
|
||||
"""Test that of-platdata can be generated and used in sandbox"""
|
||||
cons = u_boot_console
|
||||
cons.restart_uboot_with_flags(['--show_of_platdata'])
|
||||
output = cons.get_spawn_output().replace('\r', '')
|
||||
assert OF_PLATDATA_OUTPUT in output
|
||||
|
||||
@pytest.mark.buildconfigspec('spl_of_platdata')
|
||||
def test_spl_devicetree(u_boot_console):
|
||||
"""Test content of spl device-tree"""
|
||||
cons = u_boot_console
|
||||
dtb = cons.config.build_dir + '/spl/u-boot-spl.dtb'
|
||||
fdtgrep = cons.config.build_dir + '/tools/fdtgrep'
|
||||
output = util.run_and_log(cons, [fdtgrep, '-l', dtb])
|
||||
|
||||
assert "u-boot,dm-pre-reloc" not in output
|
||||
assert "u-boot,dm-pre-proper" not in output
|
||||
assert "u-boot,dm-spl" not in output
|
||||
assert "u-boot,dm-tpl" not in output
|
||||
|
||||
assert "spl-test4" in output
|
||||
assert "spl-test5" not in output
|
||||
assert "spl-test6" not in output
|
||||
assert "spl-test7" in output
|
||||
@@ -0,0 +1,66 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
import pytest
|
||||
import u_boot_utils
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_pinmux')
|
||||
def test_pinmux_usage_1(u_boot_console):
|
||||
"""Test that 'pinmux' command without parameters displays
|
||||
pinmux usage."""
|
||||
output = u_boot_console.run_command('pinmux')
|
||||
assert 'Usage:' in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_pinmux')
|
||||
def test_pinmux_usage_2(u_boot_console):
|
||||
"""Test that 'pinmux status' executed without previous "pinmux dev"
|
||||
command displays pinmux usage."""
|
||||
output = u_boot_console.run_command('pinmux status')
|
||||
assert 'Usage:' in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_pinmux')
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
def test_pinmux_status_all(u_boot_console):
|
||||
"""Test that 'pinmux status -a' displays pin's muxing."""
|
||||
output = u_boot_console.run_command('pinmux status -a')
|
||||
assert ('SCL : I2C SCL' in output)
|
||||
assert ('SDA : I2C SDA' in output)
|
||||
assert ('TX : Uart TX' in output)
|
||||
assert ('RX : Uart RX' in output)
|
||||
assert ('W1 : 1-wire gpio' in output)
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_pinmux')
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
def test_pinmux_list(u_boot_console):
|
||||
"""Test that 'pinmux list' returns the pin-controller list."""
|
||||
output = u_boot_console.run_command('pinmux list')
|
||||
assert 'sandbox_pinctrl' in output
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_pinmux')
|
||||
def test_pinmux_dev_bad(u_boot_console):
|
||||
"""Test that 'pinmux dev' returns an error when trying to select a
|
||||
wrong pin controller."""
|
||||
pincontroller = 'bad_pin_controller_name'
|
||||
output = u_boot_console.run_command('pinmux dev ' + pincontroller)
|
||||
expected_output = 'Can\'t get the pin-controller: ' + pincontroller + '!'
|
||||
assert (expected_output in output)
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_pinmux')
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
def test_pinmux_dev(u_boot_console):
|
||||
"""Test that 'pinmux dev' select the wanted pin controller."""
|
||||
pincontroller = 'pinctrl'
|
||||
output = u_boot_console.run_command('pinmux dev ' + pincontroller)
|
||||
expected_output = 'dev: ' + pincontroller
|
||||
assert (expected_output in output)
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_pinmux')
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
def test_pinmux_status(u_boot_console):
|
||||
"""Test that 'pinmux status' displays selected pincontroller's pin
|
||||
muxing descriptions."""
|
||||
output = u_boot_console.run_command('pinmux status')
|
||||
assert ('SCL : I2C SCL' in output)
|
||||
assert ('SDA : I2C SDA' in output)
|
||||
assert ('TX : Uart TX' in output)
|
||||
assert ('RX : Uart RX' in output)
|
||||
assert ('W1 : 1-wire gpio' in output)
|
||||
@@ -0,0 +1,21 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2015 Stephen Warren
|
||||
# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
import pytest
|
||||
import signal
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.buildconfigspec('sysreset')
|
||||
def test_reset(u_boot_console):
|
||||
"""Test that the "reset" command exits sandbox process."""
|
||||
|
||||
u_boot_console.run_command('reset', wait_for_prompt=False)
|
||||
assert(u_boot_console.validate_exited())
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
def test_ctrl_c(u_boot_console):
|
||||
"""Test that sending SIGINT to sandbox causes it to exit."""
|
||||
|
||||
u_boot_console.kill(signal.SIGINT)
|
||||
assert(u_boot_console.validate_exited())
|
||||
@@ -0,0 +1,217 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2016, Xilinx Inc. Michal Simek
|
||||
# Copyright (c) 2017, Xiphos Systems Corp. All rights reserved.
|
||||
|
||||
import re
|
||||
import pytest
|
||||
import random
|
||||
import u_boot_utils
|
||||
|
||||
"""
|
||||
Note: This test relies on boardenv_* containing configuration values to define
|
||||
which SPI Flash areas are available for testing. Without this, this test will
|
||||
be automatically skipped.
|
||||
For example:
|
||||
|
||||
# A list of sections of Flash memory to be tested.
|
||||
env__sf_configs = (
|
||||
{
|
||||
# Where in SPI Flash should the test operate.
|
||||
'offset': 0x00000000,
|
||||
# This value is optional.
|
||||
# If present, specifies the [[bus:]cs] argument used in `sf probe`
|
||||
# If missing, defaults to 0.
|
||||
'id': '0:1',
|
||||
# This value is optional.
|
||||
# If set as a number, specifies the speed of the SPI Flash.
|
||||
# If set as an array of 2, specifies a range for a random speed.
|
||||
# If missing, defaults to 0.
|
||||
'speed': 1000000,
|
||||
# This value is optional.
|
||||
# If present, specifies the size to use for read/write operations.
|
||||
# If missing, the SPI Flash page size is used as a default (based on
|
||||
# the `sf probe` output).
|
||||
'len': 0x10000,
|
||||
# This value is optional.
|
||||
# If present, specifies if the test can write to Flash offset
|
||||
# If missing, defaults to False.
|
||||
'writeable': False,
|
||||
# This value is optional.
|
||||
# If present, specifies the expected CRC32 value of the flash area.
|
||||
# If missing, extra check is ignored.
|
||||
'crc32': 0xCAFECAFE,
|
||||
},
|
||||
)
|
||||
"""
|
||||
|
||||
def sf_prepare(u_boot_console, env__sf_config):
|
||||
"""Check global state of the SPI Flash before running any test.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console connection.
|
||||
env__sf_config: The single SPI Flash device configuration on which to
|
||||
run the tests.
|
||||
|
||||
Returns:
|
||||
sf_params: a dictionary of SPI Flash parameters.
|
||||
"""
|
||||
|
||||
sf_params = {}
|
||||
sf_params['ram_base'] = u_boot_utils.find_ram_base(u_boot_console)
|
||||
|
||||
probe_id = env__sf_config.get('id', 0)
|
||||
speed = env__sf_config.get('speed', 0)
|
||||
if isinstance(speed, int):
|
||||
sf_params['speed'] = speed
|
||||
else:
|
||||
assert len(speed) == 2, "If speed is a list, it must have 2 entries"
|
||||
sf_params['speed'] = random.randint(speed[0], speed[1])
|
||||
|
||||
cmd = 'sf probe %d %d' % (probe_id, sf_params['speed'])
|
||||
|
||||
output = u_boot_console.run_command(cmd)
|
||||
assert 'SF: Detected' in output, 'No Flash device available'
|
||||
|
||||
m = re.search('page size (.+?) Bytes', output)
|
||||
assert m, 'SPI Flash page size not recognized'
|
||||
sf_params['page_size'] = int(m.group(1))
|
||||
|
||||
m = re.search('erase size (.+?) KiB', output)
|
||||
assert m, 'SPI Flash erase size not recognized'
|
||||
sf_params['erase_size'] = int(m.group(1))
|
||||
sf_params['erase_size'] *= 1024
|
||||
|
||||
m = re.search('total (.+?) MiB', output)
|
||||
assert m, 'SPI Flash total size not recognized'
|
||||
sf_params['total_size'] = int(m.group(1))
|
||||
sf_params['total_size'] *= 1024 * 1024
|
||||
|
||||
assert 'offset' in env__sf_config, \
|
||||
'\'offset\' is required for this test.'
|
||||
sf_params['len'] = env__sf_config.get('len', sf_params['erase_size'])
|
||||
|
||||
assert not env__sf_config['offset'] % sf_params['erase_size'], \
|
||||
'offset not multiple of erase size.'
|
||||
assert not sf_params['len'] % sf_params['erase_size'], \
|
||||
'erase length not multiple of erase size.'
|
||||
|
||||
assert not (env__sf_config.get('writeable', False) and
|
||||
'crc32' in env__sf_config), \
|
||||
'Cannot check crc32 on writeable sections'
|
||||
|
||||
return sf_params
|
||||
|
||||
def sf_read(u_boot_console, env__sf_config, sf_params):
|
||||
"""Helper function used to read and compute the CRC32 value of a section of
|
||||
SPI Flash memory.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console connection.
|
||||
env__sf_config: The single SPI Flash device configuration on which to
|
||||
run the tests.
|
||||
sf_params: SPI Flash parameters.
|
||||
|
||||
Returns:
|
||||
CRC32 value of SPI Flash section
|
||||
"""
|
||||
|
||||
addr = sf_params['ram_base']
|
||||
offset = env__sf_config['offset']
|
||||
count = sf_params['len']
|
||||
pattern = random.randint(0, 0xFF)
|
||||
crc_expected = env__sf_config.get('crc32', None)
|
||||
|
||||
cmd = 'mw.b %08x %02x %x' % (addr, pattern, count)
|
||||
u_boot_console.run_command(cmd)
|
||||
crc_pattern = u_boot_utils.crc32(u_boot_console, addr, count)
|
||||
if crc_expected:
|
||||
assert crc_pattern != crc_expected
|
||||
|
||||
cmd = 'sf read %08x %08x %x' % (addr, offset, count)
|
||||
response = u_boot_console.run_command(cmd)
|
||||
assert 'Read: OK' in response, 'Read operation failed'
|
||||
crc_readback = u_boot_utils.crc32(u_boot_console, addr, count)
|
||||
assert crc_pattern != crc_readback, 'sf read did not update RAM content.'
|
||||
if crc_expected:
|
||||
assert crc_readback == crc_expected
|
||||
|
||||
return crc_readback
|
||||
|
||||
def sf_update(u_boot_console, env__sf_config, sf_params):
|
||||
"""Helper function used to update a section of SPI Flash memory.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console connection.
|
||||
env__sf_config: The single SPI Flash device configuration on which to
|
||||
run the tests.
|
||||
|
||||
Returns:
|
||||
CRC32 value of SPI Flash section
|
||||
"""
|
||||
|
||||
addr = sf_params['ram_base']
|
||||
offset = env__sf_config['offset']
|
||||
count = sf_params['len']
|
||||
pattern = int(random.random() * 0xFF)
|
||||
|
||||
cmd = 'mw.b %08x %02x %x' % (addr, pattern, count)
|
||||
u_boot_console.run_command(cmd)
|
||||
crc_pattern = u_boot_utils.crc32(u_boot_console, addr, count)
|
||||
|
||||
cmd = 'sf update %08x %08x %x' % (addr, offset, count)
|
||||
u_boot_console.run_command(cmd)
|
||||
crc_readback = sf_read(u_boot_console, env__sf_config, sf_params)
|
||||
|
||||
assert crc_readback == crc_pattern
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_sf')
|
||||
@pytest.mark.buildconfigspec('cmd_crc32')
|
||||
@pytest.mark.buildconfigspec('cmd_memory')
|
||||
def test_sf_read(u_boot_console, env__sf_config):
|
||||
sf_params = sf_prepare(u_boot_console, env__sf_config)
|
||||
sf_read(u_boot_console, env__sf_config, sf_params)
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_sf')
|
||||
@pytest.mark.buildconfigspec('cmd_crc32')
|
||||
@pytest.mark.buildconfigspec('cmd_memory')
|
||||
def test_sf_read_twice(u_boot_console, env__sf_config):
|
||||
sf_params = sf_prepare(u_boot_console, env__sf_config)
|
||||
|
||||
crc1 = sf_read(u_boot_console, env__sf_config, sf_params)
|
||||
sf_params['ram_base'] += 0x100
|
||||
crc2 = sf_read(u_boot_console, env__sf_config, sf_params)
|
||||
|
||||
assert crc1 == crc2, 'CRC32 of two successive read operation do not match'
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_sf')
|
||||
@pytest.mark.buildconfigspec('cmd_crc32')
|
||||
@pytest.mark.buildconfigspec('cmd_memory')
|
||||
def test_sf_erase(u_boot_console, env__sf_config):
|
||||
if not env__sf_config.get('writeable', False):
|
||||
pytest.skip('Flash config is tagged as not writeable')
|
||||
|
||||
sf_params = sf_prepare(u_boot_console, env__sf_config)
|
||||
addr = sf_params['ram_base']
|
||||
offset = env__sf_config['offset']
|
||||
count = sf_params['len']
|
||||
|
||||
cmd = 'sf erase %08x %x' % (offset, count)
|
||||
output = u_boot_console.run_command(cmd)
|
||||
assert 'Erased: OK' in output, 'Erase operation failed'
|
||||
|
||||
cmd = 'mw.b %08x ff %x' % (addr, count)
|
||||
u_boot_console.run_command(cmd)
|
||||
crc_ffs = u_boot_utils.crc32(u_boot_console, addr, count)
|
||||
|
||||
crc_read = sf_read(u_boot_console, env__sf_config, sf_params)
|
||||
assert crc_ffs == crc_read, 'Unexpected CRC32 after erase operation.'
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_sf')
|
||||
@pytest.mark.buildconfigspec('cmd_crc32')
|
||||
@pytest.mark.buildconfigspec('cmd_memory')
|
||||
def test_sf_update(u_boot_console, env__sf_config):
|
||||
if not env__sf_config.get('writeable', False):
|
||||
pytest.skip('Flash config is tagged as not writeable')
|
||||
|
||||
sf_params = sf_prepare(u_boot_console, env__sf_config)
|
||||
sf_update(u_boot_console, env__sf_config, sf_params)
|
||||
@@ -0,0 +1,45 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
# Test basic shell functionality, such as commands separate by semi-colons.
|
||||
|
||||
import pytest
|
||||
|
||||
pytestmark = pytest.mark.buildconfigspec('cmd_echo')
|
||||
|
||||
def test_shell_execute(u_boot_console):
|
||||
"""Test any shell command."""
|
||||
|
||||
response = u_boot_console.run_command('echo hello')
|
||||
assert response.strip() == 'hello'
|
||||
|
||||
def test_shell_semicolon_two(u_boot_console):
|
||||
"""Test two shell commands separate by a semi-colon."""
|
||||
|
||||
cmd = 'echo hello; echo world'
|
||||
response = u_boot_console.run_command(cmd)
|
||||
# This validation method ignores the exact whitespace between the strings
|
||||
assert response.index('hello') < response.index('world')
|
||||
|
||||
def test_shell_semicolon_three(u_boot_console):
|
||||
"""Test three shell commands separate by a semi-colon, with variable
|
||||
expansion dependencies between them."""
|
||||
|
||||
cmd = 'setenv list 1; setenv list ${list}2; setenv list ${list}3; ' + \
|
||||
'echo ${list}'
|
||||
response = u_boot_console.run_command(cmd)
|
||||
assert response.strip() == '123'
|
||||
u_boot_console.run_command('setenv list')
|
||||
|
||||
def test_shell_run(u_boot_console):
|
||||
"""Test the "run" shell command."""
|
||||
|
||||
u_boot_console.run_command('setenv foo "setenv monty 1; setenv python 2"')
|
||||
u_boot_console.run_command('run foo')
|
||||
response = u_boot_console.run_command('echo $monty')
|
||||
assert response.strip() == '1'
|
||||
response = u_boot_console.run_command('echo $python')
|
||||
assert response.strip() == '2'
|
||||
u_boot_console.run_command('setenv foo')
|
||||
u_boot_console.run_command('setenv monty')
|
||||
u_boot_console.run_command('setenv python')
|
||||
@@ -0,0 +1,35 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
import pytest
|
||||
import time
|
||||
|
||||
"""
|
||||
Note: This test doesn't rely on boardenv_* configuration values but they can
|
||||
change test behavior.
|
||||
|
||||
# Setup env__sleep_accurate to False if time is not accurate on your platform
|
||||
env__sleep_accurate = False
|
||||
|
||||
"""
|
||||
|
||||
def test_sleep(u_boot_console):
|
||||
"""Test the sleep command, and validate that it sleeps for approximately
|
||||
the correct amount of time."""
|
||||
|
||||
sleep_skip = u_boot_console.config.env.get('env__sleep_accurate', True)
|
||||
if not sleep_skip:
|
||||
pytest.skip('sleep is not accurate')
|
||||
|
||||
if u_boot_console.config.buildconfig.get('config_cmd_misc', 'n') != 'y':
|
||||
pytest.skip('sleep command not supported')
|
||||
# 3s isn't too long, but is enough to cross a few second boundaries.
|
||||
sleep_time = 3
|
||||
tstart = time.time()
|
||||
u_boot_console.run_command('sleep %d' % sleep_time)
|
||||
tend = time.time()
|
||||
elapsed = tend - tstart
|
||||
assert elapsed >= (sleep_time - 0.01)
|
||||
if not u_boot_console.config.gdbserver:
|
||||
# 0.25s margin is hopefully enough to account for any system overhead.
|
||||
assert elapsed < (sleep_time + 0.25)
|
||||
@@ -0,0 +1,233 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2018, Bootlin
|
||||
# Author: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
|
||||
import os.path
|
||||
import pytest
|
||||
import u_boot_utils
|
||||
import re
|
||||
import time
|
||||
|
||||
"""
|
||||
Test the TPMv2.x related commands. You must have a working hardware setup in
|
||||
order to do these tests.
|
||||
|
||||
Notes:
|
||||
* These tests will prove the password mechanism. The TPM chip must be cleared of
|
||||
any password.
|
||||
* Commands like pcr_setauthpolicy and pcr_resetauthpolicy are not implemented
|
||||
here because they would fail the tests in most cases (TPMs do not implement them
|
||||
and return an error).
|
||||
"""
|
||||
|
||||
updates = 0
|
||||
|
||||
def force_init(u_boot_console, force=False):
|
||||
"""When a test fails, U-Boot is reset. Because TPM stack must be initialized
|
||||
after each reboot, we must ensure these lines are always executed before
|
||||
trying any command or they will fail with no reason. Executing 'tpm init'
|
||||
twice will spawn an error used to detect that the TPM was not reset and no
|
||||
initialization code should be run.
|
||||
"""
|
||||
output = u_boot_console.run_command('tpm2 init')
|
||||
if force or not 'Error' in output:
|
||||
u_boot_console.run_command('echo --- start of init ---')
|
||||
u_boot_console.run_command('tpm2 startup TPM2_SU_CLEAR')
|
||||
u_boot_console.run_command('tpm2 self_test full')
|
||||
u_boot_console.run_command('tpm2 clear TPM2_RH_LOCKOUT')
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
if not output.endswith('0'):
|
||||
u_boot_console.run_command('tpm2 clear TPM2_RH_PLATFORM')
|
||||
u_boot_console.run_command('echo --- end of init ---')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_tpm_v2')
|
||||
def test_tpm2_init(u_boot_console):
|
||||
"""Init the software stack to use TPMv2 commands."""
|
||||
|
||||
u_boot_console.run_command('tpm2 init')
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_tpm_v2')
|
||||
def test_tpm2_startup(u_boot_console):
|
||||
"""Execute a TPM2_Startup command.
|
||||
|
||||
Initiate the TPM internal state machine.
|
||||
"""
|
||||
|
||||
u_boot_console.run_command('tpm2 startup TPM2_SU_CLEAR')
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_tpm_v2')
|
||||
def test_tpm2_self_test_full(u_boot_console):
|
||||
"""Execute a TPM2_SelfTest (full) command.
|
||||
|
||||
Ask the TPM to perform all self tests to also enable full capabilities.
|
||||
"""
|
||||
|
||||
u_boot_console.run_command('tpm2 self_test full')
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_tpm_v2')
|
||||
def test_tpm2_continue_self_test(u_boot_console):
|
||||
"""Execute a TPM2_SelfTest (continued) command.
|
||||
|
||||
Ask the TPM to finish its self tests (alternative to the full test) in order
|
||||
to enter a fully operational state.
|
||||
"""
|
||||
|
||||
u_boot_console.run_command('tpm2 self_test continue')
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_tpm_v2')
|
||||
def test_tpm2_clear(u_boot_console):
|
||||
"""Execute a TPM2_Clear command.
|
||||
|
||||
Ask the TPM to reset entirely its internal state (including internal
|
||||
configuration, passwords, counters and DAM parameters). This is half of the
|
||||
TAKE_OWNERSHIP command from TPMv1.
|
||||
|
||||
Use the LOCKOUT hierarchy for this. The LOCKOUT/PLATFORM hierarchies must
|
||||
not have a password set, otherwise this test will fail. ENDORSEMENT and
|
||||
PLATFORM hierarchies are also available.
|
||||
"""
|
||||
|
||||
u_boot_console.run_command('tpm2 clear TPM2_RH_LOCKOUT')
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
|
||||
u_boot_console.run_command('tpm2 clear TPM2_RH_PLATFORM')
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_tpm_v2')
|
||||
def test_tpm2_change_auth(u_boot_console):
|
||||
"""Execute a TPM2_HierarchyChangeAuth command.
|
||||
|
||||
Ask the TPM to change the owner, ie. set a new password: 'unicorn'
|
||||
|
||||
Use the LOCKOUT hierarchy for this. ENDORSEMENT and PLATFORM hierarchies are
|
||||
also available.
|
||||
"""
|
||||
|
||||
force_init(u_boot_console)
|
||||
|
||||
u_boot_console.run_command('tpm2 change_auth TPM2_RH_LOCKOUT unicorn')
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
|
||||
u_boot_console.run_command('tpm2 clear TPM2_RH_LOCKOUT unicorn')
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
u_boot_console.run_command('tpm2 clear TPM2_RH_PLATFORM')
|
||||
assert output.endswith('0')
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_tpm_v2')
|
||||
def test_tpm2_get_capability(u_boot_console):
|
||||
"""Execute a TPM_GetCapability command.
|
||||
|
||||
Display one capability. In our test case, let's display the default DAM
|
||||
lockout counter that should be 0 since the CLEAR:
|
||||
- TPM_CAP_TPM_PROPERTIES = 0x6
|
||||
- TPM_PT_LOCKOUT_COUNTER (1st parameter) = PTR_VAR + 14
|
||||
|
||||
There is no expected default values because it would depend on the chip
|
||||
used. We can still save them in order to check they have changed later.
|
||||
"""
|
||||
|
||||
force_init(u_boot_console)
|
||||
ram = u_boot_utils.find_ram_base(u_boot_console)
|
||||
|
||||
read_cap = u_boot_console.run_command('tpm2 get_capability 0x6 0x20e 0x200 1') #0x%x 1' % ram)
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
assert 'Property 0x0000020e: 0x00000000' in read_cap
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_tpm_v2')
|
||||
def test_tpm2_dam_parameters(u_boot_console):
|
||||
"""Execute a TPM2_DictionaryAttackParameters command.
|
||||
|
||||
Change Dictionary Attack Mitigation (DAM) parameters. Ask the TPM to change:
|
||||
- Max number of failed authentication before lockout: 3
|
||||
- Time before the failure counter is automatically decremented: 10 sec
|
||||
- Time after a lockout failure before it can be attempted again: 0 sec
|
||||
|
||||
For an unknown reason, the DAM parameters must be changed before changing
|
||||
the authentication, otherwise the lockout will be engaged after the first
|
||||
failed authentication attempt.
|
||||
"""
|
||||
|
||||
force_init(u_boot_console)
|
||||
ram = u_boot_utils.find_ram_base(u_boot_console)
|
||||
|
||||
# Set the DAM parameters to known values
|
||||
u_boot_console.run_command('tpm2 dam_parameters 3 10 0')
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
|
||||
# Check the values have been saved
|
||||
read_cap = u_boot_console.run_command('tpm2 get_capability 0x6 0x20f 0x%x 3' % ram)
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
assert 'Property 0x0000020f: 0x00000003' in read_cap
|
||||
assert 'Property 0x00000210: 0x0000000a' in read_cap
|
||||
assert 'Property 0x00000211: 0x00000000' in read_cap
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_tpm_v2')
|
||||
def test_tpm2_pcr_read(u_boot_console):
|
||||
"""Execute a TPM2_PCR_Read command.
|
||||
|
||||
Perform a PCR read of the 0th PCR. Must be zero.
|
||||
"""
|
||||
|
||||
force_init(u_boot_console)
|
||||
ram = u_boot_utils.find_ram_base(u_boot_console)
|
||||
|
||||
read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % ram)
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
|
||||
# Save the number of PCR updates
|
||||
str = re.findall(r'\d+ known updates', read_pcr)[0]
|
||||
global updates
|
||||
updates = int(re.findall(r'\d+', str)[0])
|
||||
|
||||
# Check the output value
|
||||
assert 'PCR #0 content' in read_pcr
|
||||
assert '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' in read_pcr
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_tpm_v2')
|
||||
def test_tpm2_pcr_extend(u_boot_console):
|
||||
"""Execute a TPM2_PCR_Extend command.
|
||||
|
||||
Perform a PCR extension with a known hash in memory (zeroed since the board
|
||||
must have been rebooted).
|
||||
|
||||
No authentication mechanism is used here, not protecting against packet
|
||||
replay, yet.
|
||||
"""
|
||||
|
||||
force_init(u_boot_console)
|
||||
ram = u_boot_utils.find_ram_base(u_boot_console)
|
||||
|
||||
u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
|
||||
read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % ram)
|
||||
output = u_boot_console.run_command('echo $?')
|
||||
assert output.endswith('0')
|
||||
assert 'f5 a5 fd 42 d1 6a 20 30 27 98 ef 6e d3 09 97 9b' in read_pcr
|
||||
assert '43 00 3d 23 20 d9 f0 e8 ea 98 31 a9 27 59 fb 4b' in read_pcr
|
||||
|
||||
str = re.findall(r'\d+ known updates', read_pcr)[0]
|
||||
new_updates = int(re.findall(r'\d+', str)[0])
|
||||
assert (updates + 1) == new_updates
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_tpm_v2')
|
||||
def test_tpm2_cleanup(u_boot_console):
|
||||
"""Ensure the TPM is cleared from password or test related configuration."""
|
||||
|
||||
force_init(u_boot_console, True)
|
||||
@@ -0,0 +1,236 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
# Test U-Boot's "ums" command. The test starts UMS in U-Boot, waits for USB
|
||||
# device enumeration on the host, reads a small block of data from the UMS
|
||||
# block device, optionally mounts a partition and performs filesystem-based
|
||||
# read/write tests, and finally aborts the "ums" command in U-Boot.
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import pytest
|
||||
import re
|
||||
import time
|
||||
import u_boot_utils
|
||||
|
||||
"""
|
||||
Note: This test relies on:
|
||||
|
||||
a) boardenv_* to contain configuration values to define which USB ports are
|
||||
available for testing. Without this, this test will be automatically skipped.
|
||||
For example:
|
||||
|
||||
# Leave this list empty if you have no block_devs below with writable
|
||||
# partitions defined.
|
||||
env__mount_points = (
|
||||
'/mnt/ubtest-mnt-p2371-2180-na',
|
||||
)
|
||||
|
||||
env__usb_dev_ports = (
|
||||
{
|
||||
'fixture_id': 'micro_b',
|
||||
'tgt_usb_ctlr': '0',
|
||||
'host_ums_dev_node': '/dev/disk/by-path/pci-0000:00:14.0-usb-0:13:1.0-scsi-0:0:0:0',
|
||||
},
|
||||
)
|
||||
|
||||
env__block_devs = (
|
||||
# eMMC; always present
|
||||
{
|
||||
'fixture_id': 'emmc',
|
||||
'type': 'mmc',
|
||||
'id': '0',
|
||||
# The following two properties are optional.
|
||||
# If present, the partition will be mounted and a file written-to and
|
||||
# read-from it. If missing, only a simple block read test will be
|
||||
# performed.
|
||||
'writable_fs_partition': 1,
|
||||
'writable_fs_subdir': 'tmp/',
|
||||
},
|
||||
# SD card; present since I plugged one in
|
||||
{
|
||||
'fixture_id': 'sd',
|
||||
'type': 'mmc',
|
||||
'id': '1'
|
||||
},
|
||||
)
|
||||
|
||||
b) udev rules to set permissions on devices nodes, so that sudo is not
|
||||
required. For example:
|
||||
|
||||
ACTION=="add", SUBSYSTEM=="block", SUBSYSTEMS=="usb", KERNELS=="3-13", MODE:="666"
|
||||
|
||||
(You may wish to change the group ID instead of setting the permissions wide
|
||||
open. All that matters is that the user ID running the test can access the
|
||||
device.)
|
||||
|
||||
c) /etc/fstab entries to allow the block device to be mounted without requiring
|
||||
root permissions. For example:
|
||||
|
||||
/dev/disk/by-path/pci-0000:00:14.0-usb-0:13:1.0-scsi-0:0:0:0-part1 /mnt/ubtest-mnt-p2371-2180-na ext4 noauto,user,nosuid,nodev
|
||||
|
||||
This entry is only needed if any block_devs above contain a
|
||||
writable_fs_partition value.
|
||||
"""
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_usb_mass_storage')
|
||||
def test_ums(u_boot_console, env__usb_dev_port, env__block_devs):
|
||||
"""Test the "ums" command; the host system must be able to enumerate a UMS
|
||||
device when "ums" is running, block and optionally file I/O are tested,
|
||||
and this device must disappear when "ums" is aborted.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console connection.
|
||||
env__usb_dev_port: The single USB device-mode port specification on
|
||||
which to run the test. See the file-level comment above for
|
||||
details of the format.
|
||||
env__block_devs: The list of block devices that the target U-Boot
|
||||
device has attached. See the file-level comment above for details
|
||||
of the format.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
have_writable_fs_partition = 'writable_fs_partition' in env__block_devs[0]
|
||||
if not have_writable_fs_partition:
|
||||
# If 'writable_fs_subdir' is missing, we'll skip all parts of the
|
||||
# testing which mount filesystems.
|
||||
u_boot_console.log.warning(
|
||||
'boardenv missing "writable_fs_partition"; ' +
|
||||
'UMS testing will be limited.')
|
||||
|
||||
tgt_usb_ctlr = env__usb_dev_port['tgt_usb_ctlr']
|
||||
host_ums_dev_node = env__usb_dev_port['host_ums_dev_node']
|
||||
|
||||
# We're interested in testing USB device mode on each port, not the cross-
|
||||
# product of that with each device. So, just pick the first entry in the
|
||||
# device list here. We'll test each block device somewhere else.
|
||||
tgt_dev_type = env__block_devs[0]['type']
|
||||
tgt_dev_id = env__block_devs[0]['id']
|
||||
if have_writable_fs_partition:
|
||||
mount_point = u_boot_console.config.env['env__mount_points'][0]
|
||||
mount_subdir = env__block_devs[0]['writable_fs_subdir']
|
||||
part_num = env__block_devs[0]['writable_fs_partition']
|
||||
host_ums_part_node = '%s-part%d' % (host_ums_dev_node, part_num)
|
||||
else:
|
||||
host_ums_part_node = host_ums_dev_node
|
||||
|
||||
test_f = u_boot_utils.PersistentRandomFile(u_boot_console, 'ums.bin',
|
||||
1024 * 1024);
|
||||
if have_writable_fs_partition:
|
||||
mounted_test_fn = mount_point + '/' + mount_subdir + test_f.fn
|
||||
|
||||
def start_ums():
|
||||
"""Start U-Boot's ums shell command.
|
||||
|
||||
This also waits for the host-side USB enumeration process to complete.
|
||||
|
||||
Args:
|
||||
None.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
u_boot_console.log.action(
|
||||
'Starting long-running U-Boot ums shell command')
|
||||
cmd = 'ums %s %s %s' % (tgt_usb_ctlr, tgt_dev_type, tgt_dev_id)
|
||||
u_boot_console.run_command(cmd, wait_for_prompt=False)
|
||||
u_boot_console.wait_for(re.compile('UMS: LUN.*[\r\n]'))
|
||||
fh = u_boot_utils.wait_until_open_succeeds(host_ums_part_node)
|
||||
u_boot_console.log.action('Reading raw data from UMS device')
|
||||
fh.read(4096)
|
||||
fh.close()
|
||||
|
||||
def mount():
|
||||
"""Mount the block device that U-Boot exports.
|
||||
|
||||
Args:
|
||||
None.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
u_boot_console.log.action('Mounting exported UMS device')
|
||||
cmd = ('/bin/mount', host_ums_part_node)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
|
||||
def umount(ignore_errors):
|
||||
"""Unmount the block device that U-Boot exports.
|
||||
|
||||
Args:
|
||||
ignore_errors: Ignore any errors. This is useful if an error has
|
||||
already been detected, and the code is performing best-effort
|
||||
cleanup. In this case, we do not want to mask the original
|
||||
error by "honoring" any new errors.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
u_boot_console.log.action('Unmounting UMS device')
|
||||
cmd = ('/bin/umount', host_ums_part_node)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd, ignore_errors)
|
||||
|
||||
def stop_ums(ignore_errors):
|
||||
"""Stop U-Boot's ums shell command from executing.
|
||||
|
||||
This also waits for the host-side USB de-enumeration process to
|
||||
complete.
|
||||
|
||||
Args:
|
||||
ignore_errors: Ignore any errors. This is useful if an error has
|
||||
already been detected, and the code is performing best-effort
|
||||
cleanup. In this case, we do not want to mask the original
|
||||
error by "honoring" any new errors.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
u_boot_console.log.action(
|
||||
'Stopping long-running U-Boot ums shell command')
|
||||
u_boot_console.ctrlc()
|
||||
u_boot_utils.wait_until_file_open_fails(host_ums_part_node,
|
||||
ignore_errors)
|
||||
|
||||
ignore_cleanup_errors = True
|
||||
try:
|
||||
start_ums()
|
||||
if not have_writable_fs_partition:
|
||||
# Skip filesystem-based testing if not configured
|
||||
return
|
||||
try:
|
||||
mount()
|
||||
u_boot_console.log.action('Writing test file via UMS')
|
||||
cmd = ('rm', '-f', mounted_test_fn)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
if os.path.exists(mounted_test_fn):
|
||||
raise Exception('Could not rm target UMS test file')
|
||||
cmd = ('cp', test_f.abs_fn, mounted_test_fn)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
ignore_cleanup_errors = False
|
||||
finally:
|
||||
umount(ignore_errors=ignore_cleanup_errors)
|
||||
finally:
|
||||
stop_ums(ignore_errors=ignore_cleanup_errors)
|
||||
|
||||
ignore_cleanup_errors = True
|
||||
try:
|
||||
start_ums()
|
||||
try:
|
||||
mount()
|
||||
u_boot_console.log.action('Reading test file back via UMS')
|
||||
read_back_hash = u_boot_utils.md5sum_file(mounted_test_fn)
|
||||
cmd = ('rm', '-f', mounted_test_fn)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
ignore_cleanup_errors = False
|
||||
finally:
|
||||
umount(ignore_errors=ignore_cleanup_errors)
|
||||
finally:
|
||||
stop_ums(ignore_errors=ignore_cleanup_errors)
|
||||
|
||||
written_hash = test_f.content_hash
|
||||
assert(written_hash == read_back_hash)
|
||||
@@ -0,0 +1,13 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2015 Stephen Warren
|
||||
# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
def test_unknown_command(u_boot_console):
|
||||
"""Test that executing an unknown command causes U-Boot to print an
|
||||
error."""
|
||||
|
||||
# The "unknown command" error is actively expected here,
|
||||
# so error detection for it is disabled.
|
||||
with u_boot_console.disable_check('unknown_command'):
|
||||
response = u_boot_console.run_command('non_existent_cmd')
|
||||
assert('Unknown command \'non_existent_cmd\' - try \'help\'' in response)
|
||||
@@ -0,0 +1,28 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
import os.path
|
||||
import pytest
|
||||
|
||||
@pytest.mark.buildconfigspec('ut_dm')
|
||||
def test_ut_dm_init(u_boot_console):
|
||||
"""Initialize data for ut dm tests."""
|
||||
|
||||
fn = u_boot_console.config.source_dir + '/testflash.bin'
|
||||
if not os.path.exists(fn):
|
||||
data = b'this is a test'
|
||||
data += b'\x00' * ((4 * 1024 * 1024) - len(data))
|
||||
with open(fn, 'wb') as fh:
|
||||
fh.write(data)
|
||||
|
||||
fn = u_boot_console.config.source_dir + '/spi.bin'
|
||||
if not os.path.exists(fn):
|
||||
data = b'\x00' * (2 * 1024 * 1024)
|
||||
with open(fn, 'wb') as fh:
|
||||
fh.write(data)
|
||||
|
||||
def test_ut(u_boot_console, ut_subtest):
|
||||
"""Execute a "ut" subtest."""
|
||||
|
||||
output = u_boot_console.run_command('ut ' + ut_subtest)
|
||||
assert output.endswith('Failures: 0')
|
||||
@@ -0,0 +1,293 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2016, Google Inc.
|
||||
#
|
||||
# U-Boot Verified Boot Test
|
||||
|
||||
"""
|
||||
This tests verified boot in the following ways:
|
||||
|
||||
For image verification:
|
||||
- Create FIT (unsigned) with mkimage
|
||||
- Check that verification shows that no keys are verified
|
||||
- Sign image
|
||||
- Check that verification shows that a key is now verified
|
||||
|
||||
For configuration verification:
|
||||
- Corrupt signature and check for failure
|
||||
- Create FIT (with unsigned configuration) with mkimage
|
||||
- Check that image verification works
|
||||
- Sign the FIT and mark the key as 'required' for verification
|
||||
- Check that image verification works
|
||||
- Corrupt the signature
|
||||
- Check that image verification no-longer works
|
||||
|
||||
Tests run with both SHA1 and SHA256 hashing.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import sys
|
||||
import struct
|
||||
import u_boot_utils as util
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.buildconfigspec('fit_signature')
|
||||
@pytest.mark.requiredtool('dtc')
|
||||
@pytest.mark.requiredtool('fdtget')
|
||||
@pytest.mark.requiredtool('fdtput')
|
||||
@pytest.mark.requiredtool('openssl')
|
||||
def test_vboot(u_boot_console):
|
||||
"""Test verified boot signing with mkimage and verification with 'bootm'.
|
||||
|
||||
This works using sandbox only as it needs to update the device tree used
|
||||
by U-Boot to hold public keys from the signing process.
|
||||
|
||||
The SHA1 and SHA256 tests are combined into a single test since the
|
||||
key-generation process is quite slow and we want to avoid doing it twice.
|
||||
"""
|
||||
def dtc(dts):
|
||||
"""Run the device tree compiler to compile a .dts file
|
||||
|
||||
The output file will be the same as the input file but with a .dtb
|
||||
extension.
|
||||
|
||||
Args:
|
||||
dts: Device tree file to compile.
|
||||
"""
|
||||
dtb = dts.replace('.dts', '.dtb')
|
||||
util.run_and_log(cons, 'dtc %s %s%s -O dtb '
|
||||
'-o %s%s' % (dtc_args, datadir, dts, tmpdir, dtb))
|
||||
|
||||
def run_bootm(sha_algo, test_type, expect_string, boots):
|
||||
"""Run a 'bootm' command U-Boot.
|
||||
|
||||
This always starts a fresh U-Boot instance since the device tree may
|
||||
contain a new public key.
|
||||
|
||||
Args:
|
||||
test_type: A string identifying the test type.
|
||||
expect_string: A string which is expected in the output.
|
||||
sha_algo: Either 'sha1' or 'sha256', to select the algorithm to
|
||||
use.
|
||||
boots: A boolean that is True if Linux should boot and False if
|
||||
we are expected to not boot
|
||||
"""
|
||||
cons.restart_uboot()
|
||||
with cons.log.section('Verified boot %s %s' % (sha_algo, test_type)):
|
||||
output = cons.run_command_list(
|
||||
['host load hostfs - 100 %stest.fit' % tmpdir,
|
||||
'fdt addr 100',
|
||||
'bootm 100'])
|
||||
assert(expect_string in ''.join(output))
|
||||
if boots:
|
||||
assert('sandbox: continuing, as we cannot run' in ''.join(output))
|
||||
else:
|
||||
assert('sandbox: continuing, as we cannot run' not in ''.join(output))
|
||||
|
||||
def make_fit(its):
|
||||
"""Make a new FIT from the .its source file.
|
||||
|
||||
This runs 'mkimage -f' to create a new FIT.
|
||||
|
||||
Args:
|
||||
its: Filename containing .its source.
|
||||
"""
|
||||
util.run_and_log(cons, [mkimage, '-D', dtc_args, '-f',
|
||||
'%s%s' % (datadir, its), fit])
|
||||
|
||||
def sign_fit(sha_algo):
|
||||
"""Sign the FIT
|
||||
|
||||
Signs the FIT and writes the signature into it. It also writes the
|
||||
public key into the dtb.
|
||||
|
||||
Args:
|
||||
sha_algo: Either 'sha1' or 'sha256', to select the algorithm to
|
||||
use.
|
||||
"""
|
||||
cons.log.action('%s: Sign images' % sha_algo)
|
||||
util.run_and_log(cons, [mkimage, '-F', '-k', tmpdir, '-K', dtb,
|
||||
'-r', fit])
|
||||
|
||||
def sign_fit_norequire(sha_algo):
|
||||
"""Sign the FIT
|
||||
|
||||
Signs the FIT and writes the signature into it. It also writes the
|
||||
public key into the dtb.
|
||||
|
||||
Args:
|
||||
sha_algo: Either 'sha1' or 'sha256', to select the algorithm to
|
||||
use.
|
||||
"""
|
||||
cons.log.action('%s: Sign images' % sha_algo)
|
||||
util.run_and_log(cons, [mkimage, '-F', '-k', tmpdir, '-K', dtb,
|
||||
fit])
|
||||
|
||||
def replace_fit_totalsize(size):
|
||||
"""Replace FIT header's totalsize with something greater.
|
||||
|
||||
The totalsize must be less than or equal to FIT_SIGNATURE_MAX_SIZE.
|
||||
If the size is greater, the signature verification should return false.
|
||||
|
||||
Args:
|
||||
size: The new totalsize of the header
|
||||
|
||||
Returns:
|
||||
prev_size: The previous totalsize read from the header
|
||||
"""
|
||||
total_size = 0
|
||||
with open(fit, 'r+b') as handle:
|
||||
handle.seek(4)
|
||||
total_size = handle.read(4)
|
||||
handle.seek(4)
|
||||
handle.write(struct.pack(">I", size))
|
||||
return struct.unpack(">I", total_size)[0]
|
||||
|
||||
def test_with_algo(sha_algo, padding):
|
||||
"""Test verified boot with the given hash algorithm.
|
||||
|
||||
This is the main part of the test code. The same procedure is followed
|
||||
for both hashing algorithms.
|
||||
|
||||
Args:
|
||||
sha_algo: Either 'sha1' or 'sha256', to select the algorithm to
|
||||
use.
|
||||
"""
|
||||
# Compile our device tree files for kernel and U-Boot. These are
|
||||
# regenerated here since mkimage will modify them (by adding a
|
||||
# public key) below.
|
||||
dtc('sandbox-kernel.dts')
|
||||
dtc('sandbox-u-boot.dts')
|
||||
|
||||
# Build the FIT, but don't sign anything yet
|
||||
cons.log.action('%s: Test FIT with signed images' % sha_algo)
|
||||
make_fit('sign-images-%s%s.its' % (sha_algo , padding))
|
||||
run_bootm(sha_algo, 'unsigned images', 'dev-', True)
|
||||
|
||||
# Sign images with our dev keys
|
||||
sign_fit(sha_algo)
|
||||
run_bootm(sha_algo, 'signed images', 'dev+', True)
|
||||
|
||||
# Create a fresh .dtb without the public keys
|
||||
dtc('sandbox-u-boot.dts')
|
||||
|
||||
cons.log.action('%s: Test FIT with signed configuration' % sha_algo)
|
||||
make_fit('sign-configs-%s%s.its' % (sha_algo , padding))
|
||||
run_bootm(sha_algo, 'unsigned config', '%s+ OK' % sha_algo, True)
|
||||
|
||||
# Sign images with our dev keys
|
||||
sign_fit(sha_algo)
|
||||
run_bootm(sha_algo, 'signed config', 'dev+', True)
|
||||
|
||||
cons.log.action('%s: Check signed config on the host' % sha_algo)
|
||||
|
||||
util.run_and_log(cons, [fit_check_sign, '-f', fit, '-k', tmpdir,
|
||||
'-k', dtb])
|
||||
|
||||
# Replace header bytes
|
||||
bcfg = u_boot_console.config.buildconfig
|
||||
max_size = int(bcfg.get('config_fit_signature_max_size', 0x10000000), 0)
|
||||
existing_size = replace_fit_totalsize(max_size + 1)
|
||||
run_bootm(sha_algo, 'Signed config with bad hash', 'Bad Data Hash', False)
|
||||
cons.log.action('%s: Check overflowed FIT header totalsize' % sha_algo)
|
||||
|
||||
# Replace with existing header bytes
|
||||
replace_fit_totalsize(existing_size)
|
||||
run_bootm(sha_algo, 'signed config', 'dev+', True)
|
||||
cons.log.action('%s: Check default FIT header totalsize' % sha_algo)
|
||||
|
||||
# Increment the first byte of the signature, which should cause failure
|
||||
sig = util.run_and_log(cons, 'fdtget -t bx %s %s value' %
|
||||
(fit, sig_node))
|
||||
byte_list = sig.split()
|
||||
byte = int(byte_list[0], 16)
|
||||
byte_list[0] = '%x' % (byte + 1)
|
||||
sig = ' '.join(byte_list)
|
||||
util.run_and_log(cons, 'fdtput -t bx %s %s value %s' %
|
||||
(fit, sig_node, sig))
|
||||
|
||||
run_bootm(sha_algo, 'Signed config with bad hash', 'Bad Data Hash', False)
|
||||
|
||||
cons.log.action('%s: Check bad config on the host' % sha_algo)
|
||||
util.run_and_log_expect_exception(cons, [fit_check_sign, '-f', fit,
|
||||
'-k', dtb], 1, 'Failed to verify required signature')
|
||||
|
||||
def test_required_key(sha_algo, padding):
|
||||
"""Test verified boot with the given hash algorithm.
|
||||
|
||||
This function test if u-boot reject an image when a required
|
||||
key isn't used to sign a FIT.
|
||||
|
||||
Args:
|
||||
sha_algo: Either 'sha1' or 'sha256', to select the algorithm to
|
||||
use.
|
||||
"""
|
||||
# Compile our device tree files for kernel and U-Boot. These are
|
||||
# regenerated here since mkimage will modify them (by adding a
|
||||
# public key) below.
|
||||
dtc('sandbox-kernel.dts')
|
||||
dtc('sandbox-u-boot.dts')
|
||||
|
||||
# Build the FIT with prod key (keys required)
|
||||
# Build the FIT with dev key (keys NOT required)
|
||||
# The dtb contain the key prod and dev and the key prod are set as required.
|
||||
# Then try to boot the FIT with dev key
|
||||
# This FIT should not be accepted by u-boot because the key prod is required
|
||||
cons.log.action('%s: Test FIT with configs images' % sha_algo)
|
||||
make_fit('sign-configs-%s%s-prod.its' % (sha_algo , padding))
|
||||
sign_fit(sha_algo)
|
||||
make_fit('sign-configs-%s%s.its' % (sha_algo , padding))
|
||||
sign_fit(sha_algo)
|
||||
|
||||
run_bootm(sha_algo, 'signed configs', '', False)
|
||||
|
||||
cons = u_boot_console
|
||||
tmpdir = cons.config.result_dir + '/'
|
||||
tmp = tmpdir + 'vboot.tmp'
|
||||
datadir = cons.config.source_dir + '/test/py/tests/vboot/'
|
||||
fit = '%stest.fit' % tmpdir
|
||||
mkimage = cons.config.build_dir + '/tools/mkimage'
|
||||
fit_check_sign = cons.config.build_dir + '/tools/fit_check_sign'
|
||||
dtc_args = '-I dts -O dtb -i %s' % tmpdir
|
||||
dtb = '%ssandbox-u-boot.dtb' % tmpdir
|
||||
sig_node = '/configurations/conf-1/signature'
|
||||
|
||||
# Create an RSA key pair
|
||||
public_exponent = 65537
|
||||
util.run_and_log(cons, 'openssl genpkey -algorithm RSA -out %sdev.key '
|
||||
'-pkeyopt rsa_keygen_bits:2048 '
|
||||
'-pkeyopt rsa_keygen_pubexp:%d' %
|
||||
(tmpdir, public_exponent))
|
||||
|
||||
# Create a certificate containing the public key
|
||||
util.run_and_log(cons, 'openssl req -batch -new -x509 -key %sdev.key -out '
|
||||
'%sdev.crt' % (tmpdir, tmpdir))
|
||||
|
||||
# Create an RSA key pair (prod)
|
||||
public_exponent = 65537
|
||||
util.run_and_log(cons, 'openssl genpkey -algorithm RSA -out %sprod.key '
|
||||
'-pkeyopt rsa_keygen_bits:2048 '
|
||||
'-pkeyopt rsa_keygen_pubexp:%d' %
|
||||
(tmpdir, public_exponent))
|
||||
|
||||
# Create a certificate containing the public key (prod)
|
||||
util.run_and_log(cons, 'openssl req -batch -new -x509 -key %sprod.key -out '
|
||||
'%sprod.crt' % (tmpdir, tmpdir))
|
||||
|
||||
# Create a number kernel image with zeroes
|
||||
with open('%stest-kernel.bin' % tmpdir, 'w') as fd:
|
||||
fd.write(5000 * chr(0))
|
||||
|
||||
try:
|
||||
# We need to use our own device tree file. Remember to restore it
|
||||
# afterwards.
|
||||
old_dtb = cons.config.dtb
|
||||
cons.config.dtb = dtb
|
||||
test_with_algo('sha1','')
|
||||
test_with_algo('sha1','-pss')
|
||||
test_with_algo('sha256','')
|
||||
test_with_algo('sha256','-pss')
|
||||
test_required_key('sha256','-pss')
|
||||
finally:
|
||||
# Go back to the original U-Boot with the correct dtb.
|
||||
cons.config.dtb = old_dtb
|
||||
cons.restart_uboot()
|
||||
@@ -0,0 +1,7 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
model = "Sandbox Verified Boot Test";
|
||||
compatible = "sandbox";
|
||||
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
model = "Sandbox Verified Boot Test";
|
||||
compatible = "sandbox";
|
||||
|
||||
reset@0 {
|
||||
compatible = "sandbox,reset";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
hash-1 {
|
||||
algo = "sha1";
|
||||
};
|
||||
};
|
||||
fdt-1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
hash-1 {
|
||||
algo = "sha1";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
conf-1 {
|
||||
kernel = "kernel";
|
||||
fdt = "fdt-1";
|
||||
signature {
|
||||
algo = "sha1,rsa2048";
|
||||
padding = "pss";
|
||||
key-name-hint = "dev";
|
||||
sign-images = "fdt", "kernel";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
hash-1 {
|
||||
algo = "sha1";
|
||||
};
|
||||
};
|
||||
fdt-1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
hash-1 {
|
||||
algo = "sha1";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
conf-1 {
|
||||
kernel = "kernel";
|
||||
fdt = "fdt-1";
|
||||
signature {
|
||||
algo = "sha1,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
sign-images = "fdt", "kernel";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
hash-1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
fdt-1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
hash-1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
conf-1 {
|
||||
kernel = "kernel";
|
||||
fdt = "fdt-1";
|
||||
signature {
|
||||
algo = "sha256,rsa2048";
|
||||
padding = "pss";
|
||||
key-name-hint = "prod";
|
||||
sign-images = "fdt", "kernel";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
hash-1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
fdt-1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
hash-1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
conf-1 {
|
||||
kernel = "kernel";
|
||||
fdt = "fdt-1";
|
||||
signature {
|
||||
algo = "sha256,rsa2048";
|
||||
padding = "pss";
|
||||
key-name-hint = "dev";
|
||||
sign-images = "fdt", "kernel";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
hash-1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
fdt-1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
hash-1 {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
conf-1 {
|
||||
kernel = "kernel";
|
||||
fdt = "fdt-1";
|
||||
signature {
|
||||
algo = "sha256,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
sign-images = "fdt", "kernel";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
signature {
|
||||
algo = "sha1,rsa2048";
|
||||
padding = "pss";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
fdt-1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
signature {
|
||||
algo = "sha1,rsa2048";
|
||||
padding = "pss";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
conf-1 {
|
||||
kernel = "kernel";
|
||||
fdt = "fdt-1";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
signature {
|
||||
algo = "sha1,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
fdt-1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
signature {
|
||||
algo = "sha1,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
conf-1 {
|
||||
kernel = "kernel";
|
||||
fdt = "fdt-1";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
signature {
|
||||
algo = "sha256,rsa2048";
|
||||
padding = "pss";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
fdt-1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
signature {
|
||||
algo = "sha256,rsa2048";
|
||||
padding = "pss";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
conf-1 {
|
||||
kernel = "kernel";
|
||||
fdt = "fdt-1";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
description = "Chrome OS kernel image with one or more FDT blobs";
|
||||
#address-cells = <1>;
|
||||
|
||||
images {
|
||||
kernel {
|
||||
data = /incbin/("test-kernel.bin");
|
||||
type = "kernel_noload";
|
||||
arch = "sandbox";
|
||||
os = "linux";
|
||||
compression = "none";
|
||||
load = <0x4>;
|
||||
entry = <0x8>;
|
||||
kernel-version = <1>;
|
||||
signature {
|
||||
algo = "sha256,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
fdt-1 {
|
||||
description = "snow";
|
||||
data = /incbin/("sandbox-kernel.dtb");
|
||||
type = "flat_dt";
|
||||
arch = "sandbox";
|
||||
compression = "none";
|
||||
fdt-version = <1>;
|
||||
signature {
|
||||
algo = "sha256,rsa2048";
|
||||
key-name-hint = "dev";
|
||||
};
|
||||
};
|
||||
};
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
conf-1 {
|
||||
kernel = "kernel";
|
||||
fdt = "fdt-1";
|
||||
};
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user