Merge tag 'signed-efi-next' of git://github.com/agraf/u-boot
[oweals/u-boot.git] / test / py / tests / test_dfu.py
index 6c1a363b02df0823d06eee1c0b3e5aa35183657c..fba67d585b9faff1db1cade330a0597360b74b95 100644 (file)
@@ -12,7 +12,7 @@ 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
@@ -21,6 +21,7 @@ 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
@@ -29,13 +30,48 @@ env__usb_dev_ports = (
     },
 )
 
+# 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:
 
@@ -44,12 +80,19 @@ ACTION=="add", SUBSYSTEM=="block", SUBSYSTEMS=="usb", KERNELS=="3-13", MODE:="66
 (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 = (
+test_sizes_default = (
     64 - 1,
     64,
     64 + 1,
@@ -71,7 +114,7 @@ first_usb_dev_port = None
 
 @pytest.mark.buildconfigspec('cmd_dfu')
 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
+    """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.
 
@@ -86,10 +129,10 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
 
     Returns:
         Nothing.
-    '''
+    """
 
     def start_dfu():
-        '''Start U-Boot's dfu shell command.
+        """Start U-Boot's dfu shell command.
 
         This also waits for the host-side USB enumeration process to complete.
 
@@ -98,8 +141,10 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
 
         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:
@@ -109,7 +154,11 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
         u_boot_console.log.action(
             'Starting long-running U-Boot dfu shell command')
 
-        cmd = 'setenv dfu_alt_info "%s"' % env__dfu_config['alt_info']
+        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']
@@ -120,7 +169,7 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
         fh.close()
 
     def stop_dfu(ignore_errors):
-        '''Stop U-Boot's dfu shell command from executing.
+        """Stop U-Boot's dfu shell command from executing.
 
         This also waits for the host-side USB de-enumeration process to
         complete.
@@ -133,7 +182,7 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
 
         Returns:
             Nothing.
-        '''
+        """
 
         try:
             u_boot_console.log.action(
@@ -148,7 +197,7 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
                 raise
 
     def run_dfu_util(alt_setting, fn, up_dn_load_arg):
-        '''Invoke dfu-util on the host.
+        """Invoke dfu-util on the host.
 
         Args:
             alt_setting: The DFU "alternate setting" identifier to interact
@@ -159,16 +208,16 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
 
         Returns:
             Nothing.
-        '''
+        """
 
-        cmd = ['dfu-util', '-a', str(alt_setting), up_dn_load_arg, fn]
+        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.
+        """Write a file to the target board using DFU.
 
         Args:
             alt_setting: The DFU "alternate setting" identifier to interact
@@ -177,12 +226,12 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
 
         Returns:
             Nothing.
-        '''
+        """
 
         run_dfu_util(alt_setting, fn, '-D')
 
     def dfu_read(alt_setting, fn):
-        '''Read a file from the target board using DFU.
+        """Read a file from the target board using DFU.
 
         Args:
             alt_setting: The DFU "alternate setting" identifier to interact
@@ -191,7 +240,7 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
 
         Returns:
             Nothing.
-        '''
+        """
 
         # dfu-util fails reads/uploads if the host file already exists
         if os.path.exists(fn):
@@ -199,7 +248,7 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
         run_dfu_util(alt_setting, fn, '-U')
 
     def dfu_write_read_check(size):
-        '''Test DFU transfers of a specific size of data
+        """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
@@ -210,7 +259,7 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
 
         Returns:
             Nothing.
-        '''
+        """
 
         test_f = u_boot_utils.PersistentRandomFile(u_boot_console,
             'dfu_%d.bin' % size, size)
@@ -218,15 +267,15 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
 
         u_boot_console.log.action('Writing test data to DFU primary ' +
             'altsetting')
-        dfu_write(0, test_f.abs_fn)
+        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(1, dummy_f.abs_fn)
+        dfu_write(alt_setting_dummy_file, dummy_f.abs_fn)
 
         u_boot_console.log.action('Reading DFU primary altsetting for ' +
             'comparison')
-        dfu_read(0, readback_fn)
+        dfu_read(alt_setting_test_file, readback_fn)
 
         u_boot_console.log.action('Comparing written and read data')
         written_hash = test_f.content_hash
@@ -242,23 +291,26 @@ def test_dfu(u_boot_console, env__usb_dev_port, env__dfu_config):
     if not first_usb_dev_port:
         first_usb_dev_port = env__usb_dev_port
     if env__usb_dev_port == first_usb_dev_port:
-        sizes = test_sizes
+        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(0, dummy_f.abs_fn)
+        dfu_write(alt_setting_test_file, dummy_f.abs_fn)
 
         for size in sizes:
-            with u_boot_console.log.section("Data size %d" % size):
+            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.