]> git.sur5r.net Git - u-boot/blob - test/py/tests/test_ums.py
Merge branch 'master' of git://git.denx.de/u-boot-tegra
[u-boot] / test / py / tests / test_ums.py
1 # Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
2 #
3 # SPDX-License-Identifier: GPL-2.0
4
5 # Test U-Boot's "ums" command. The test starts UMS in U-Boot, waits for USB
6 # device enumeration on the host, reads a small block of data from the UMS
7 # block device, optionally mounts a partition and performs filesystem-based
8 # read/write tests, and finally aborts the "ums" command in U-Boot.
9
10 import os
11 import os.path
12 import pytest
13 import re
14 import time
15 import u_boot_utils
16
17 """
18 Note: This test relies on:
19
20 a) boardenv_* to contain configuration values to define which USB ports are
21 available for testing. Without this, this test will be automatically skipped.
22 For example:
23
24 # Leave this list empty if you have no block_devs below with writable
25 # partitions defined.
26 env__mount_points = (
27     "/mnt/ubtest-mnt-p2371-2180-na",
28 )
29
30 env__usb_dev_ports = (
31     {
32         "fixture_id": "micro_b",
33         "tgt_usb_ctlr": "0",
34         "host_ums_dev_node": "/dev/disk/by-path/pci-0000:00:14.0-usb-0:13:1.0-scsi-0:0:0:0",
35     },
36 )
37
38 env__block_devs = (
39     # eMMC; always present
40     {
41         "fixture_id": "emmc",
42         "type": "mmc",
43         "id": "0",
44         # The following two properties are optional.
45         # If present, the partition will be mounted and a file written-to and
46         # read-from it. If missing, only a simple block read test will be
47         # performed.
48         "writable_fs_partition": 1,
49         "writable_fs_subdir": "tmp/",
50     },
51     # SD card; present since I plugged one in
52     {
53         "fixture_id": "sd",
54         "type": "mmc",
55         "id": "1"
56     },
57 )
58
59 b) udev rules to set permissions on devices nodes, so that sudo is not
60 required. For example:
61
62 ACTION=="add", SUBSYSTEM=="block", SUBSYSTEMS=="usb", KERNELS=="3-13", MODE:="666"
63
64 (You may wish to change the group ID instead of setting the permissions wide
65 open. All that matters is that the user ID running the test can access the
66 device.)
67
68 c) /etc/fstab entries to allow the block device to be mounted without requiring
69 root permissions. For example:
70
71 /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
72
73 This entry is only needed if any block_devs above contain a
74 writable_fs_partition value.
75 """
76
77 @pytest.mark.buildconfigspec('cmd_usb_mass_storage')
78 def test_ums(u_boot_console, env__usb_dev_port, env__block_devs):
79     """Test the "ums" command; the host system must be able to enumerate a UMS
80     device when "ums" is running, block and optionally file I/O are tested,
81     and this device must disappear when "ums" is aborted.
82
83     Args:
84         u_boot_console: A U-Boot console connection.
85         env__usb_dev_port: The single USB device-mode port specification on
86             which to run the test. See the file-level comment above for
87             details of the format.
88         env__block_devs: The list of block devices that the target U-Boot
89             device has attached. See the file-level comment above for details
90             of the format.
91
92     Returns:
93         Nothing.
94     """
95
96     have_writable_fs_partition = 'writable_fs_partition' in env__block_devs[0]
97     if not have_writable_fs_partition:
98         # If 'writable_fs_subdir' is missing, we'll skip all parts of the
99         # testing which mount filesystems.
100         u_boot_console.log.warning(
101             'boardenv missing "writable_fs_partition"; ' +
102             'UMS testing will be limited.')
103
104     tgt_usb_ctlr = env__usb_dev_port['tgt_usb_ctlr']
105     host_ums_dev_node = env__usb_dev_port['host_ums_dev_node']
106
107     # We're interested in testing USB device mode on each port, not the cross-
108     # product of that with each device. So, just pick the first entry in the
109     # device list here. We'll test each block device somewhere else.
110     tgt_dev_type = env__block_devs[0]['type']
111     tgt_dev_id = env__block_devs[0]['id']
112     if have_writable_fs_partition:
113         mount_point = u_boot_console.config.env['env__mount_points'][0]
114         mount_subdir = env__block_devs[0]['writable_fs_subdir']
115         part_num = env__block_devs[0]['writable_fs_partition']
116         host_ums_part_node = '%s-part%d' % (host_ums_dev_node, part_num)
117     else:
118         host_ums_part_node = host_ums_dev_node
119
120     test_f = u_boot_utils.PersistentRandomFile(u_boot_console, 'ums.bin',
121         1024 * 1024);
122     if have_writable_fs_partition:
123         mounted_test_fn = mount_point + '/' + mount_subdir + test_f.fn
124
125     def start_ums():
126         """Start U-Boot's ums shell command.
127
128         This also waits for the host-side USB enumeration process to complete.
129
130         Args:
131             None.
132
133         Returns:
134             Nothing.
135         """
136
137         u_boot_console.log.action(
138             'Starting long-running U-Boot ums shell command')
139         cmd = 'ums %s %s %s' % (tgt_usb_ctlr, tgt_dev_type, tgt_dev_id)
140         u_boot_console.run_command(cmd, wait_for_prompt=False)
141         u_boot_console.wait_for(re.compile('UMS: LUN.*[\r\n]'))
142         fh = u_boot_utils.wait_until_open_succeeds(host_ums_part_node)
143         u_boot_console.log.action('Reading raw data from UMS device')
144         fh.read(4096)
145         fh.close()
146
147     def mount():
148         """Mount the block device that U-Boot exports.
149
150         Args:
151             None.
152
153         Returns:
154             Nothing.
155         """
156
157         u_boot_console.log.action('Mounting exported UMS device')
158         cmd = ('/bin/mount', host_ums_part_node)
159         u_boot_utils.run_and_log(u_boot_console, cmd)
160
161     def umount(ignore_errors):
162         """Unmount the block device that U-Boot exports.
163
164         Args:
165             ignore_errors: Ignore any errors. This is useful if an error has
166                 already been detected, and the code is performing best-effort
167                 cleanup. In this case, we do not want to mask the original
168                 error by "honoring" any new errors.
169
170         Returns:
171             Nothing.
172         """
173
174         u_boot_console.log.action('Unmounting UMS device')
175         cmd = ('/bin/umount', host_ums_part_node)
176         u_boot_utils.run_and_log(u_boot_console, cmd, ignore_errors)
177
178     def stop_ums(ignore_errors):
179         """Stop U-Boot's ums shell command from executing.
180
181         This also waits for the host-side USB de-enumeration process to
182         complete.
183
184         Args:
185             ignore_errors: Ignore any errors. This is useful if an error has
186                 already been detected, and the code is performing best-effort
187                 cleanup. In this case, we do not want to mask the original
188                 error by "honoring" any new errors.
189
190         Returns:
191             Nothing.
192         """
193
194         u_boot_console.log.action(
195             'Stopping long-running U-Boot ums shell command')
196         u_boot_console.ctrlc()
197         u_boot_utils.wait_until_file_open_fails(host_ums_part_node,
198             ignore_errors)
199
200     ignore_cleanup_errors = True
201     try:
202         start_ums()
203         if not have_writable_fs_partition:
204             # Skip filesystem-based testing if not configured
205             return
206         try:
207             mount()
208             u_boot_console.log.action('Writing test file via UMS')
209             cmd = ('rm', '-f', mounted_test_fn)
210             u_boot_utils.run_and_log(u_boot_console, cmd)
211             if os.path.exists(mounted_test_fn):
212                 raise Exception('Could not rm target UMS test file')
213             cmd = ('cp', test_f.abs_fn, mounted_test_fn)
214             u_boot_utils.run_and_log(u_boot_console, cmd)
215             ignore_cleanup_errors = False
216         finally:
217             umount(ignore_errors=ignore_cleanup_errors)
218     finally:
219         stop_ums(ignore_errors=ignore_cleanup_errors)
220
221     ignore_cleanup_errors = True
222     try:
223         start_ums()
224         try:
225             mount()
226             u_boot_console.log.action('Reading test file back via UMS')
227             read_back_hash = u_boot_utils.md5sum_file(mounted_test_fn)
228             cmd = ('rm', '-f', mounted_test_fn)
229             u_boot_utils.run_and_log(u_boot_console, cmd)
230             ignore_cleanup_errors = False
231         finally:
232             umount(ignore_errors=ignore_cleanup_errors)
233     finally:
234         stop_ums(ignore_errors=ignore_cleanup_errors)
235
236     written_hash = test_f.content_hash
237     assert(written_hash == read_back_hash)