diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/cmd/unzip.c | 12 | ||||
| -rw-r--r-- | test/py/tests/fs_helper.py | 95 | ||||
| -rw-r--r-- | test/py/tests/test_cat.py | 27 | ||||
| -rw-r--r-- | test/py/tests/test_efi_bootmgr.py | 38 | ||||
| -rwxr-xr-x | test/py/tests/test_fit.py | 431 | ||||
| -rw-r--r-- | test/py/tests/test_fs/conftest.py | 198 | ||||
| -rw-r--r-- | test/py/tests/test_ut.py | 190 | ||||
| -rw-r--r-- | test/py/tests/test_xxd.py | 28 |
8 files changed, 530 insertions, 489 deletions
diff --git a/test/cmd/unzip.c b/test/cmd/unzip.c index b67c5ba1956..623a2785884 100644 --- a/test/cmd/unzip.c +++ b/test/cmd/unzip.c @@ -105,7 +105,7 @@ static int dm_test_cmd_zip_gzwrite(struct unit_test_state *uts) { struct udevice *dev; ofnode root, node; - int i, ret; + int i, j, ret; /* Enable the mmc9 node for this test */ root = oftree_root(oftree_default()); @@ -119,6 +119,16 @@ static int dm_test_cmd_zip_gzwrite(struct unit_test_state *uts) return ret; } + /* Test various sizes of decompression chunk sizes */ + for (j = 0; j < ARRAY_SIZE(sizes); j++) { + env_set_ulong("gzwrite_chunk", sizes[j]); + for (i = 0; i < ARRAY_SIZE(sizes); i++) { + ret = do_test_cmd_zip_unzip(uts, sizes[i], true); + if (ret) + return ret; + } + } + return 0; } DM_TEST(dm_test_cmd_zip_gzwrite, UTF_CONSOLE); diff --git a/test/py/tests/fs_helper.py b/test/py/tests/fs_helper.py index 800376b1e7d..ee779474ce6 100644 --- a/test/py/tests/fs_helper.py +++ b/test/py/tests/fs_helper.py @@ -66,8 +66,9 @@ class FsHelper: """Make a new filesystem and copy in the files""" self.setup() self._do_cleanup = True + src_dir = self.srcdir if os.listdir(self.srcdir) else None self.fs_img = mk_fs(self.config, self.fs_type, self.size_mb << 20, - self.prefix, self.srcdir, quiet=self.quiet) + self.prefix, src_dir, quiet=self.quiet) def setup(self): """Set up the srcdir ready to receive files""" @@ -97,6 +98,98 @@ class FsHelper: self.cleanup() +class DiskHelper: + """Helper class for creating disk images containing filesytems + + Usage: + with DiskHelper(ubman.config, 0, 'mmc') as img, \ + FsHelper(ubman.config, 'ext1', 1, 'mmc') as fsh: + # Write files to fsh.srcdir + ... + + # Create the filesystem + fsh.mk_fs() + + # Add this filesystem to the disk + img.add_fs(fsh, DiskHelper.VFAT) + + # Add more filesystems as needed (add another 'with' clause) + ... + + # Get the final disk image + data = img.create() + """ + + # Partition-type codes + VFAT = 0xc + EXT4 = 0x83 + + def __init__(self, config, devnum, prefix, cur_dir=False): + """Set up a new disk image + + Args: + config (u_boot_config): U-Boot configuration + devnum (int): Device number (for filename) + prefix (str): Prefix string of volume's file name + cur_dir (bool): True to put the file in the current directory, + instead of the persistent-data directory + """ + self.fs_list = [] + self.fname = os.path.join('' if cur_dir else config.persistent_data_dir, + f'{prefix}{devnum}.img') + + def add_fs(self, fs_img, part_type, bootable=False): + """Add a new filesystem + + Args: + fs_img (FsHelper): Filesystem to add + part_type (DiskHelper.FAT or DiskHelper.EXT4): Partition type + bootable (bool): True to set the 'bootable' flat + """ + self.fs_list.append([fs_img, part_type, bootable]) + + def create(self): + """Create the disk image + + Create an image with a partition table and the filesystems + """ + spec = '' + pos = 1 # Reserve 1MB for the partition table itself + for fsi, part_type, bootable in self.fs_list: + if spec: + spec += '\n' + spec += f'type={part_type:x}, size={fsi.size_mb}M, start={pos}M' + if bootable: + spec += ', bootable' + pos += fsi.size_mb + + img_size = pos + try: + check_call(f'qemu-img create {self.fname} {img_size}M', shell=True) + check_call(f'printf "{spec}" | sfdisk {self.fname}', shell=True) + except CalledProcessError: + os.remove(self.fname) + raise + + pos = 1 # Reserve 1MB for the partition table itself + for fsi, part_type, bootable in self.fs_list: + check_call( + f'dd if={fsi.fs_img} of={self.fname} bs=1M seek={pos} conv=notrunc', + shell=True) + pos += fsi.size_mb + return self.fname + + def cleanup(self, remove_full_img=False): + """Remove created file""" + os.remove(self.fname) + + def __enter__(self): + return self + + def __exit__(self, extype, value, traceback): + self.cleanup() + + def mk_fs(config, fs_type, size, prefix, src_dir=None, fs_img=None, quiet=False): """Create a file system volume diff --git a/test/py/tests/test_cat.py b/test/py/tests/test_cat.py index 252c3d50a02..f793b9fe0a1 100644 --- a/test/py/tests/test_cat.py +++ b/test/py/tests/test_cat.py @@ -4,8 +4,7 @@ """ import pytest -from subprocess import call, check_call, CalledProcessError -from tests import fs_helper +from tests.fs_helper import FsHelper @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('cmd_cat') @@ -15,23 +14,11 @@ def test_cat(ubman): Args: ubman -- U-Boot console """ - try: - scratch_dir = ubman.config.persistent_data_dir + '/scratch' + with FsHelper(ubman.config, 'vfat', 1, 'test_cat') as fsh: + with open(f'{fsh.srcdir}/hello', 'w', encoding = 'ascii') as outf: + outf.write('hello world\n') + fsh.mk_fs() - check_call('mkdir -p %s' % scratch_dir, shell=True) - - with open(scratch_dir + '/hello', 'w', encoding = 'ascii') as file: - file.write('hello world\n') - - cat_data = fs_helper.mk_fs(ubman.config, 'vfat', 0x100000, - 'test_cat', scratch_dir) - response = ubman.run_command_list([ f'host bind 0 {cat_data}', - 'cat host 0 hello']) + response = ubman.run_command_list([f'host bind 0 {fsh.fs_img}', + 'cat host 0 hello']) assert 'hello world' in response - except CalledProcessError as err: - pytest.skip('Preparing test_cat image failed') - call('rm -f %s' % cat_data, shell=True) - return - finally: - call('rm -rf %s' % scratch_dir, shell=True) - call('rm -f %s' % cat_data, shell=True) diff --git a/test/py/tests/test_efi_bootmgr.py b/test/py/tests/test_efi_bootmgr.py index 4c10cbdf17d..7d1f3f16d00 100644 --- a/test/py/tests/test_efi_bootmgr.py +++ b/test/py/tests/test_efi_bootmgr.py @@ -5,7 +5,7 @@ import shutil import pytest from subprocess import call, check_call, CalledProcessError -from tests import fs_helper +from tests.fs_helper import DiskHelper, FsHelper @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('cmd_efidebug') @@ -20,22 +20,19 @@ def test_efi_bootmgr(ubman): Args: ubman -- U-Boot console """ - try: - efi_bootmgr_data, mnt = fs_helper.setup_image(ubman, 0, 0xc, - basename='test_efi_bootmgr') - - with open(mnt + '/initrd-1.img', 'w', encoding = 'ascii') as file: - file.write("initrd 1") - - with open(mnt + '/initrd-2.img', 'w', encoding = 'ascii') as file: - file.write("initrd 2") - - shutil.copyfile(ubman.config.build_dir + '/lib/efi_loader/initrddump.efi', - mnt + '/initrddump.efi') - - fsfile = fs_helper.mk_fs(ubman.config, 'vfat', 0x100000, - 'test_efi_bootmgr', mnt) - check_call(f'dd if={fsfile} of={efi_bootmgr_data} bs=1M seek=1', shell=True) + with DiskHelper(ubman.config, 0, 'test_efi_bootmgr') as img, \ + FsHelper(ubman.config, 'vfat', 1, 'test_efi_bootmgr') as fsh: + with open(f'{fsh.srcdir}/initrd-1.img', 'w', encoding = 'ascii') as outf: + outf.write("initrd 1") + with open(f'{fsh.srcdir}/initrd-2.img', 'w', encoding = 'ascii') as outf: + outf.write("initrd 2") + shutil.copyfile( + ubman.config.build_dir + '/lib/efi_loader/initrddump.efi', + f'{fsh.srcdir}/initrddump.efi') + fsh.mk_fs() + + img.add_fs(fsh, DiskHelper.VFAT) + efi_bootmgr_data = img.create() ubman.run_command(cmd = f'host bind 0 {efi_bootmgr_data}') @@ -61,10 +58,3 @@ def test_efi_bootmgr(ubman): ubman.run_command(cmd = 'efidebug boot rm 0001') ubman.run_command(cmd = 'efidebug boot rm 0002') - except CalledProcessError as err: - pytest.skip('Preparing test_efi_bootmgr image failed') - call('rm -f %s' % efi_bootmgr_data, shell=True) - return - finally: - call('rm -rf %s' % mnt, shell=True) - call('rm -f %s' % efi_bootmgr_data, shell=True) diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py index 619f73153a0..bcaaa6a5fc4 100755 --- a/test/py/tests/test_fit.py +++ b/test/py/tests/test_fit.py @@ -1,16 +1,17 @@ # SPDX-License-Identifier: GPL-2.0+ # Copyright (c) 2013, Google Inc. -# -# Sanity check of the FIT handling in U-Boot + +"""Sanity check of the FIT handling in U-Boot""" import os -import pytest import struct -import utils + +import pytest import fit_util +import utils # Define a base ITS which we can adjust using % and a dictionary -base_its = ''' +BASE_ITS = ''' /dts-v1/; / { @@ -70,7 +71,7 @@ base_its = ''' configurations { default = "conf-1"; conf-1 { - kernel = "kernel-1"; + %(kernel_config)s fdt = "fdt-1"; %(ramdisk_config)s %(loadables_config)s @@ -80,7 +81,7 @@ base_its = ''' ''' # Define a base FDT - currently we don't use anything in this -base_fdt = ''' +BASE_FDT = ''' /dts-v1/; / { @@ -103,7 +104,8 @@ base_fdt = ''' # 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 = ''' +BASE_SCRIPT = ''' +mw.b 0 0 160000 host load hostfs 0 %(fit_addr)x %(fit)s fdt addr %(fit_addr)x bootm start %(fit_addr)x @@ -116,59 +118,83 @@ host save hostfs 0 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x ''' @pytest.mark.boardspec('sandbox') [email protected]('fit_signature') [email protected]('fit') @pytest.mark.requiredtool('dtc') -def test_fit(ubman): - def make_fname(leaf): +class TestFitImage: + """Test class for FIT image handling 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 + """ + + def make_fname(self, ubman, leaf): """Make a temporary filename Args: - leaf: Leaf name of file to create (within temporary directory) + ubman (ConsoleBase): U-Boot fixture + leaf (str): Leaf name of file to create (within temporary directory) + Return: - Temporary filename + str: Temporary filename """ return os.path.join(ubman.config.build_dir, leaf) - def filesize(fname): + def filesize(self, fname): """Get the size of a file Args: - fname: Filename to check + fname (str): Filename to check + Return: - Size of file in bytes + int: Size of file in bytes """ return os.stat(fname).st_size - def read_file(fname): + def read_file(self, fname): """Read the contents of a file Args: - fname: Filename to read - Returns: - Contents of file as a string + fname (str): Filename to read + + Return: + str: Contents of file """ with open(fname, 'rb') as fd: return fd.read() - def make_ramdisk(filename, text): + def make_ramdisk(self, ubman, filename, text): """Make a sample ramdisk with test data Returns: - Filename of ramdisk created + str: Filename of ramdisk created """ - fname = make_fname(filename) + fname = self.make_fname(ubman, 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: + data += f'{text} {i} was seldom used in the middle ages\n' + with open(fname, 'w', encoding='ascii') as fd: print(data, file=fd) return fname - def make_compressed(filename): + def make_compressed(self, ubman, filename): + """Compress a file using gzip""" utils.run_and_log(ubman, ['gzip', '-f', '-k', filename]) return filename + '.gz' - def find_matching(text, match): + def find_matching(self, 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 @@ -182,25 +208,30 @@ def test_fit(ubman): to use regex and return groups. Args: - text: Text to check (list of strings, one for each command issued) - match: String to search for + text (list of str): Text to check, one for each command issued + match (str): String to search for + Return: - String containing unmatched portion of line - Exceptions: + str: unmatched portion of line + + Raises: 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' + .. code-block:: python + + >>> 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' """ + # pylint: disable=W0612 __tracebackhide__ = True for line in '\n'.join(text).splitlines(): pos = line.find(match) @@ -208,202 +239,202 @@ def test_fit(ubman): return line[:pos] + line[pos + len(match):] pytest.fail("Expected '%s' but not found in output") + return '<no-match>' - def check_equal(expected_fname, actual_fname, failure_msg): + def check_equal(self, params, expected_key, actual_key, 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) + expected_data = self.read_file(params[expected_key]) + actual_data = self.read_file(params[actual_key]) 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) + def check_not_equal(self, params, expected_key, actual_key, failure_msg): + """Check that a file does not match its expected contents""" + expected_data = self.read_file(params[expected_key]) + actual_data = self.read_file(params[actual_key]) 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 = fit_util.make_dtb(ubman, base_fdt, 'u-boot') + @pytest.fixture() + def fsetup(self, ubman): + """Set up files and default parameters for FIT tests""" + mkimage = os.path.join(ubman.config.build_dir, 'tools/mkimage') + fdt_data = fit_util.make_dtb(ubman, BASE_FDT, 'u-boot') kernel = fit_util.make_kernel(ubman, 'test-kernel.bin', 'kernel') - ramdisk = make_ramdisk('test-ramdisk.bin', 'ramdisk') - loadables1 = fit_util.make_kernel(ubman, '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 = { + ramdisk = self.make_ramdisk(ubman, 'test-ramdisk.bin', 'ramdisk') + loadables1 = fit_util.make_kernel(ubman, 'test-loadables1.bin', + 'lenrek') + loadables2 = self.make_ramdisk(ubman, 'test-loadables2.bin', + 'ksidmar') + + yield { + 'mkimage' : mkimage, 'fit_addr' : 0x1000, 'kernel' : kernel, - 'kernel_out' : kernel_out, + 'kernel_out' : self.make_fname(ubman, 'kernel-out.bin'), 'kernel_addr' : 0x40000, - 'kernel_size' : filesize(kernel), + 'kernel_size' : self.filesize(kernel), + 'kernel_config' : 'kernel = "kernel-1";', - 'fdt' : fdt, - 'fdt_out' : fdt_out, + 'fdt_data' : fdt_data, + 'fdt' : self.make_fname(ubman, 'u-boot.dtb'), + 'fdt_out' : self.make_fname(ubman, 'fdt-out.dtb'), 'fdt_addr' : 0x80000, - 'fdt_size' : filesize(control_dtb), + 'fdt_size' : self.filesize(fdt_data), 'fdt_load' : '', 'ramdisk' : ramdisk, - 'ramdisk_out' : ramdisk_out, + 'ramdisk_out' : self.make_fname(ubman, 'ramdisk-out.bin'), 'ramdisk_addr' : 0xc0000, - 'ramdisk_size' : filesize(ramdisk), + 'ramdisk_size' : self.filesize(ramdisk), 'ramdisk_load' : '', 'ramdisk_config' : '', 'loadables1' : loadables1, - 'loadables1_out' : loadables1_out, + 'loadables1_out' : self.make_fname(ubman, 'loadables1-out.bin'), 'loadables1_addr' : 0x100000, - 'loadables1_size' : filesize(loadables1), + 'loadables1_size' : self.filesize(loadables1), 'loadables1_load' : '', 'loadables2' : loadables2, - 'loadables2_out' : loadables2_out, + 'loadables2_out' : self.make_fname(ubman, 'loadables2-out.bin'), 'loadables2_addr' : 0x140000, - 'loadables2_size' : filesize(loadables2), + 'loadables2_size' : self.filesize(loadables2), 'loadables2_load' : '', 'loadables_config' : '', 'compression' : 'none', } - # Make a basic FIT and a script to load it - fit = fit_util.make_fit(ubman, mkimage, base_its, params) + def prepare(self, ubman, fsetup, **kwargs): + """Build a FIT with given overrides + + Args: + ubman (ConsoleBase): U-Boot fixture + fsetup (dict): Default parameters from the fsetup fixture + kwargs: Parameter overrides for this particular test + + Return: + tuple: + list of str: Commands to run for the test + dict: Parameters used by the test + str: Filename of the FIT that was created + """ + params = {**fsetup, **kwargs} + fit = fit_util.make_fit(ubman, params['mkimage'], BASE_ITS, 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 - ubman.config.dtb = control_dtb - ubman.restart_uboot() - with ubman.log.section('Kernel load'): - output = ubman.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)) - - # Check if bootargs strings substitution works - output = ubman.run_command_list([ - 'env set bootargs \\\"\'my_boot_var=${foo}\'\\\"', - 'env set foo bar', - 'bootm prep', - 'env print bootargs']) - assert 'bootargs="my_boot_var=bar"' in output, "Bootargs strings not substituted" - - # Now a kernel and an FDT - with ubman.log.section('Kernel + FDT load'): - params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr'] - fit = fit_util.make_fit(ubman, mkimage, base_its, params) - ubman.restart_uboot() - output = ubman.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 ubman.log.section('Kernel + FDT + Ramdisk load'): - params['ramdisk_config'] = 'ramdisk = "ramdisk-1";' - params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr'] - fit = fit_util.make_fit(ubman, mkimage, base_its, params) - ubman.restart_uboot() - output = ubman.run_command_list(cmd.splitlines()) - check_equal(ramdisk, ramdisk_out, 'Ramdisk not loaded') - - # Configuration with some Loadables - with ubman.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 = fit_util.make_fit(ubman, mkimage, base_its, params) - ubman.restart_uboot() - output = ubman.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 ubman.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 = fit_util.make_fit(ubman, mkimage, base_its, params) - ubman.restart_uboot() - output = ubman.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') - - - # We need to use our own device tree file. Remember to restore it - # afterwards. - old_dtb = ubman.config.dtb - try: - mkimage = ubman.config.build_dir + '/tools/mkimage' - run_fit_test(mkimage) - finally: - # Go back to the original U-Boot with the correct dtb. - ubman.config.dtb = old_dtb - ubman.restart_uboot() + cmds = (BASE_SCRIPT % params).splitlines() + return cmds, params, fit + + def test_fit_kernel_load(self, ubman, fsetup): + """Test loading a FIT image with only a kernel""" + cmds, params, fit = self.prepare(ubman, fsetup) + + output = ubman.run_command_list(cmds) + self.check_equal(params, 'kernel', 'kernel_out', 'Kernel not loaded') + self.check_not_equal(params, 'fdt_data', 'fdt_out', + 'FDT loaded but should be ignored') + self.check_not_equal(params, 'ramdisk', 'ramdisk_out', + 'Ramdisk loaded but should not be') + + # Find out the offset in the FIT where U-Boot has found the FDT + line = self.find_matching(output, 'Booting using the fdt blob at ') + fit_offset = int(line, 16) - params['fit_addr'] + fdt_magic = struct.pack('>L', 0xd00dfeed) + data = self.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)) + + # Check bootargs string substitution + output = ubman.run_command_list([ + 'env set bootargs \\"\'my_boot_var=${foo}\'\\"', + 'env set foo bar', + 'bootm prep', + 'env print bootargs']) + assert 'bootargs="my_boot_var=bar"' in output, \ + "Bootargs strings not substituted" + + def test_fit_kernel_fdt_load(self, ubman, fsetup): + """Test loading a FIT image with a kernel and FDT""" + cmds, params, _ = self.prepare( + ubman, fsetup, + fdt_load='load = <%#x>;' % fsetup['fdt_addr']) + + ubman.run_command_list(cmds) + self.check_equal(params, 'kernel', 'kernel_out', 'Kernel not loaded') + self.check_equal(params, 'fdt_data', 'fdt_out', 'FDT not loaded') + self.check_not_equal(params, 'ramdisk', 'ramdisk_out', + 'Ramdisk loaded but should not be') + + def test_fit_kernel_fdt_ramdisk_load(self, ubman, fsetup): + """Test loading a FIT image with kernel, FDT, and ramdisk""" + cmds, params, _ = self.prepare( + ubman, fsetup, + fdt_load='load = <%#x>;' % fsetup['fdt_addr'], + ramdisk_config='ramdisk = "ramdisk-1";', + ramdisk_load='load = <%#x>;' % fsetup['ramdisk_addr']) + + ubman.run_command_list(cmds) + self.check_equal(params, 'ramdisk', 'ramdisk_out', + 'Ramdisk not loaded') + + def test_fit_loadables_load(self, ubman, fsetup): + """Test a configuration with loadables""" + cmds, params, _ = self.prepare( + ubman, fsetup, + fdt_load='load = <%#x>;' % fsetup['fdt_addr'], + ramdisk_config='ramdisk = "ramdisk-1";', + ramdisk_load='load = <%#x>;' % fsetup['ramdisk_addr'], + loadables_config='loadables = "kernel-2", "ramdisk-2";', + loadables1_load='load = <%#x>;' % fsetup['loadables1_addr'], + loadables2_load='load = <%#x>;' % fsetup['loadables2_addr']) + + ubman.run_command_list(cmds) + self.check_equal(params, 'loadables1', 'loadables1_out', + 'Loadables1 (kernel) not loaded') + self.check_equal(params, 'loadables2', 'loadables2_out', + 'Loadables2 (ramdisk) not loaded') + + def test_fit_compressed_images_load(self, ubman, fsetup): + """Test loading compressed kernel, FDT, and ramdisk images""" + cmds, params, _ = self.prepare( + ubman, fsetup, + fdt_load='load = <%#x>;' % fsetup['fdt_addr'], + ramdisk_config='ramdisk = "ramdisk-1";', + ramdisk_load='load = <%#x>;' % fsetup['ramdisk_addr'], + compression='gzip', + kernel=self.make_compressed(ubman, fsetup['kernel']), + fdt=self.make_compressed(ubman, fsetup['fdt']), + ramdisk=self.make_compressed(ubman, fsetup['ramdisk'])) + + ubman.run_command_list(cmds) + self.check_equal(fsetup, 'kernel', 'kernel_out', + 'Kernel not loaded') + self.check_equal(fsetup, 'fdt_data', 'fdt_out', 'FDT not loaded') + self.check_not_equal(fsetup, 'ramdisk', 'ramdisk_out', + 'Ramdisk got decompressed?') + self.check_equal(params, 'ramdisk', 'ramdisk_out', + 'Ramdisk not loaded') + + def test_fit_no_kernel_load(self, ubman, fsetup): + """Test that bootm fails when no kernel is specified""" + cmds = self.prepare( + ubman, fsetup, + fdt_load='load = <%#x>;' % fsetup['fdt_addr'], + kernel_config='', + ramdisk_config='', + ramdisk_load='')[0] + + output = ubman.run_command_list(cmds) + assert "can't get kernel image!" in '\n'.join(output) diff --git a/test/py/tests/test_fs/conftest.py b/test/py/tests/test_fs/conftest.py index 0205048e73a..ba125cc7073 100644 --- a/test/py/tests/test_fs/conftest.py +++ b/test/py/tests/test_fs/conftest.py @@ -9,7 +9,7 @@ import re from subprocess import call, check_call, check_output, CalledProcessError from fstest_defs import * # pylint: disable=E0611 -from tests import fs_helper +from tests.fs_helper import FsHelper supported_fs_basic = ['fat16', 'fat32', 'exfat', 'ext4', 'fs_generic'] supported_fs_ext = ['fat12', 'fat16', 'fat32', 'exfat', 'fs_generic'] @@ -200,33 +200,26 @@ def fs_obj_basic(request, u_boot_config): fs_type = request.param fs_cmd_prefix = fstype_to_prefix(fs_type) fs_cmd_write = 'save' if fs_type == 'fs_generic' or fs_type == 'exfat' else 'write' - fs_img = '' fs_ubtype = fstype_to_ubname(fs_type) check_ubconfig(u_boot_config, fs_ubtype) - scratch_dir = u_boot_config.persistent_data_dir + '/scratch' - - small_file = scratch_dir + '/' + SMALL_FILE - big_file = scratch_dir + '/' + BIG_FILE - + fsh = FsHelper(u_boot_config, fs_type, 3072, '3GB') try: - check_call('mkdir -p %s' % scratch_dir, shell=True) - except CalledProcessError as err: - pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err)) - call('rm -f %s' % fs_img, shell=True) - return + fsh.setup() + + small_file = fsh.srcdir + '/' + SMALL_FILE + big_file = fsh.srcdir + '/' + BIG_FILE - try: # Create a subdirectory. - check_call('mkdir %s/SUBDIR' % scratch_dir, shell=True) + check_call('mkdir %s/SUBDIR' % fsh.srcdir, 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) + % 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' @@ -234,65 +227,54 @@ def fs_obj_basic(request, u_boot_config): # 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) + % small_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() + % 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() + % 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() + % 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() + % 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() + % 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() + % big_file, shell=True).decode() md5val.append(out.split()[0]) - try: - # 3GiB volume - fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0xc0000000, '3GB', scratch_dir) - except CalledProcessError as err: - pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err)) - return + fsh.mk_fs() except CalledProcessError as err: pytest.skip('Setup failed for filesystem: ' + fs_type + '. {}'.format(err)) return else: - yield [fs_ubtype, fs_cmd_prefix, fs_cmd_write, fs_img, md5val] + yield [fs_ubtype, fs_cmd_prefix, fs_cmd_write, fsh.fs_img, md5val] finally: - call('rm -rf %s' % scratch_dir, shell=True) - call('rm -f %s' % fs_img, shell=True) + fsh.cleanup() # # Fixture for extended fs test @@ -312,26 +294,19 @@ def fs_obj_ext(request, u_boot_config): fs_type = request.param fs_cmd_prefix = fstype_to_prefix(fs_type) fs_cmd_write = 'save' if fs_type == 'fs_generic' or fs_type == 'exfat' else 'write' - fs_img = '' fs_ubtype = fstype_to_ubname(fs_type) check_ubconfig(u_boot_config, fs_ubtype) - scratch_dir = u_boot_config.persistent_data_dir + '/scratch' - - min_file = scratch_dir + '/' + MIN_FILE - tmp_file = scratch_dir + '/tmpfile' - + fsh = FsHelper(u_boot_config, fs_type, 128, '128MB') try: - check_call('mkdir -p %s' % scratch_dir, shell=True) - except CalledProcessError as err: - pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err)) - call('rm -f %s' % fs_img, shell=True) - return + fsh.setup() + + min_file = fsh.srcdir + '/' + MIN_FILE + tmp_file = fsh.srcdir + '/tmpfile' - try: # Create a test directory - check_call('mkdir %s/dir1' % scratch_dir, shell=True) + check_call('mkdir %s/dir1' % fsh.srcdir, shell=True) # Create a small file and calculate md5 check_call('dd if=/dev/urandom of=%s bs=1K count=20' @@ -370,21 +345,15 @@ def fs_obj_ext(request, u_boot_config): check_call('rm %s' % tmp_file, shell=True) - try: - # 128MiB volume - fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x8000000, '128MB', scratch_dir) - except CalledProcessError as err: - pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err)) - return + fsh.mk_fs() except CalledProcessError: pytest.skip('Setup failed for filesystem: ' + fs_type) return else: - yield [fs_ubtype, fs_cmd_prefix, fs_cmd_write, fs_img, md5val] + yield [fs_ubtype, fs_cmd_prefix, fs_cmd_write, fsh.fs_img, md5val] finally: - call('rm -rf %s' % scratch_dir, shell=True) - call('rm -f %s' % fs_img, shell=True) + fsh.cleanup() # # Fixture for mkdir test @@ -403,20 +372,19 @@ def fs_obj_mkdir(request, u_boot_config): """ fs_type = request.param fs_cmd_prefix = fstype_to_prefix(fs_type) - fs_img = '' fs_ubtype = fstype_to_ubname(fs_type) check_ubconfig(u_boot_config, fs_ubtype) + fsh = FsHelper(u_boot_config, fs_type, 128, '128MB') try: - # 128MiB volume - fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x8000000, '128MB', None) + fsh.mk_fs() except: pytest.skip('Setup failed for filesystem: ' + fs_type) return else: - yield [fs_ubtype, fs_cmd_prefix, fs_img] - call('rm -f %s' % fs_img, shell=True) + yield [fs_ubtype, fs_cmd_prefix, fsh.fs_img] + fsh.cleanup() # # Fixture for unlink test @@ -435,57 +403,44 @@ def fs_obj_unlink(request, u_boot_config): """ fs_type = request.param fs_cmd_prefix = fstype_to_prefix(fs_type) - fs_img = '' fs_ubtype = fstype_to_ubname(fs_type) check_ubconfig(u_boot_config, fs_ubtype) - scratch_dir = u_boot_config.persistent_data_dir + '/scratch' - + fsh = FsHelper(u_boot_config, fs_type, 128, '128MB') try: - check_call('mkdir -p %s' % scratch_dir, shell=True) - except CalledProcessError as err: - pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err)) - call('rm -f %s' % fs_img, shell=True) - return + fsh.setup() - try: # Test Case 1 & 3 - check_call('mkdir %s/dir1' % scratch_dir, shell=True) + check_call('mkdir %s/dir1' % fsh.srcdir, shell=True) check_call('dd if=/dev/urandom of=%s/dir1/file1 bs=1K count=1' - % scratch_dir, shell=True) + % fsh.srcdir, shell=True) check_call('dd if=/dev/urandom of=%s/dir1/file2 bs=1K count=1' - % scratch_dir, shell=True) + % fsh.srcdir, shell=True) # Test Case 2 - check_call('mkdir %s/dir2' % scratch_dir, shell=True) + check_call('mkdir %s/dir2' % fsh.srcdir, shell=True) for i in range(0, 20): check_call('mkdir %s/dir2/0123456789abcdef%02x' - % (scratch_dir, i), shell=True) + % (fsh.srcdir, i), shell=True) # Test Case 4 - check_call('mkdir %s/dir4' % scratch_dir, shell=True) + check_call('mkdir %s/dir4' % fsh.srcdir, shell=True) # Test Case 5, 6 & 7 - check_call('mkdir %s/dir5' % scratch_dir, shell=True) + check_call('mkdir %s/dir5' % fsh.srcdir, shell=True) check_call('dd if=/dev/urandom of=%s/dir5/file1 bs=1K count=1' - % scratch_dir, shell=True) + % fsh.srcdir, shell=True) - try: - # 128MiB volume - fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x8000000, '128MB', scratch_dir) - except CalledProcessError as err: - pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err)) - return + fsh.mk_fs() except CalledProcessError: pytest.skip('Setup failed for filesystem: ' + fs_type) return else: - yield [fs_ubtype, fs_cmd_prefix, fs_img] + yield [fs_ubtype, fs_cmd_prefix, fsh.fs_img] finally: - call('rm -rf %s' % scratch_dir, shell=True) - call('rm -f %s' % fs_img, shell=True) + fsh.cleanup() # # Fixture for symlink fs test @@ -503,26 +458,19 @@ def fs_obj_symlink(request, u_boot_config): 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) - scratch_dir = u_boot_config.persistent_data_dir + '/scratch' - - small_file = scratch_dir + '/' + SMALL_FILE - medium_file = scratch_dir + '/' + MEDIUM_FILE - + fsh = FsHelper(u_boot_config, fs_type, 1024, '1GB') try: - check_call('mkdir -p %s' % scratch_dir, shell=True) - except CalledProcessError as err: - pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err)) - call('rm -f %s' % fs_img, shell=True) - return + fsh.setup() + + small_file = fsh.srcdir + '/' + SMALL_FILE + medium_file = fsh.srcdir + '/' + MEDIUM_FILE - try: # Create a subdirectory. - check_call('mkdir %s/SUBDIR' % scratch_dir, shell=True) + check_call('mkdir %s/SUBDIR' % fsh.srcdir, shell=True) # Create a small file in this image. check_call('dd if=/dev/urandom of=%s bs=1M count=1' @@ -542,21 +490,15 @@ def fs_obj_symlink(request, u_boot_config): % medium_file, shell=True).decode() md5val.extend([out.split()[0]]) - try: - # 1GiB volume - fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x40000000, '1GB', scratch_dir) - except CalledProcessError as err: - pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err)) - return + fsh.mk_fs() except CalledProcessError: pytest.skip('Setup failed for filesystem: ' + fs_type) return else: - yield [fs_ubtype, fs_img, md5val] + yield [fs_ubtype, fsh.fs_img, md5val] finally: - call('rm -rf %s' % scratch_dir, shell=True) - call('rm -f %s' % fs_img, shell=True) + fsh.cleanup() # # Fixture for rename test @@ -584,21 +526,15 @@ def fs_obj_rename(request, u_boot_config): return out.decode().split()[0] 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 + '/scratch' - + fsh = FsHelper(u_boot_config, fs_type, 128, '128MB') try: - check_call('mkdir -p %s' % mount_dir, shell=True) - except CalledProcessError as err: - pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err)) - call('rm -f %s' % fs_img, shell=True) - return + fsh.setup() + mount_dir = fsh.srcdir - try: md5val = {} # Test Case 1 check_call('mkdir %s/test1' % mount_dir, shell=True) @@ -657,21 +593,15 @@ def fs_obj_rename(request, u_boot_config): new_rand_file('%s/test11/dir1/file1' % mount_dir) md5val['test11'] = file_hash('%s/test11/dir1/file1' % mount_dir) - try: - # 128MiB volume - fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x8000000, '128MB', mount_dir) - except CalledProcessError as err: - pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err)) - return + fsh.mk_fs() except CalledProcessError: pytest.skip('Setup failed for filesystem: ' + fs_type) return else: - yield [fs_ubtype, fs_img, md5val] + yield [fs_ubtype, fsh.fs_img, md5val] finally: - call('rm -rf %s' % mount_dir, shell=True) - call('rm -f %s' % fs_img, shell=True) + fsh.cleanup() # # Fixture for fat test @@ -697,19 +627,19 @@ def fs_obj_fat(request, u_boot_config): MIN_FAT16_SIZE = 8208 * 1024 fs_type = request.param - fs_img = '' fs_ubtype = fstype_to_ubname(fs_type) check_ubconfig(u_boot_config, fs_ubtype) fs_size = MAX_FAT12_SIZE if fs_type == 'fat12' else MIN_FAT16_SIZE + size_mb = (fs_size + (1 << 20) - 1) >> 20 + fsh = FsHelper(u_boot_config, fs_type, size_mb, f'{fs_size}') try: - # the volume size depends on the filesystem - fs_img = fs_helper.mk_fs(u_boot_config, fs_type, fs_size, f'{fs_size}', None, 1024) + fsh.mk_fs() except: pytest.skip('Setup failed for filesystem: ' + fs_type) return else: - yield [fs_ubtype, fs_img] - call('rm -f %s' % fs_img, shell=True) + yield [fs_ubtype, fsh.fs_img] + fsh.cleanup() diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 98641a46c1d..dce5a37dd35 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -17,6 +17,7 @@ import pytest import utils # pylint: disable=E0611 from tests import fs_helper +from fs_helper import DiskHelper, FsHelper from test_android import test_abootimg def mkdir_cond(dirname): @@ -45,7 +46,6 @@ def setup_bootmenu_image(ubman): This is modelled on Armbian 22.08 Jammy """ mmc_dev = 4 - fname, mnt = fs_helper.setup_image(ubman, mmc_dev, 0x83) script = '''# DO NOT EDIT THIS FILE # @@ -121,7 +121,9 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r} # Recompile with: # mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr ''' - bootdir = os.path.join(mnt, 'boot') + fsh = FsHelper(ubman.config, 'ext4', 18, 'mmc') + fsh.setup() + bootdir = os.path.join(fsh.srcdir, 'boot') mkdir_cond(bootdir) cmd_fname = os.path.join(bootdir, 'boot.cmd') scr_fname = os.path.join(bootdir, 'boot.scr') @@ -150,36 +152,30 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r} utils.run_and_log( ubman, f'echo here {kernel} {symlink}') os.symlink(kernel, symlink) + fsh.mk_fs() + img = DiskHelper(ubman.config, mmc_dev, 'mmc', True) + img.add_fs(fsh, DiskHelper.EXT4) + img.create() + fsh.cleanup() - fsfile = 'ext18M.img' - utils.run_and_log(ubman, f'fallocate -l 18M {fsfile}') - utils.run_and_log(ubman, f'mkfs.ext4 {fsfile} -d {mnt}') - copy_partition(ubman, fsfile, fname) - utils.run_and_log(ubman, f'rm -rf {mnt}') - utils.run_and_log(ubman, f'rm -f {fsfile}') -def setup_bootflow_image(ubman): - """Create a 20MB disk image with a single FAT partition""" - mmc_dev = 1 - fname, mnt = fs_helper.setup_image(ubman, mmc_dev, 0xc, second_part=True) +def setup_extlinux_image(ubman, devnum, basename, vmlinux, initrd, dtbdir, + script): + """Create a 20MB disk image with a single FAT partition - vmlinux = 'vmlinuz-5.3.7-301.fc31.armv7hl' - initrd = 'initramfs-5.3.7-301.fc31.armv7hl.img' - dtbdir = 'dtb-5.3.7-301.fc31.armv7hl' - script = '''# extlinux.conf generated by appliance-creator -ui menu.c32 -menu autoboot Welcome to Fedora-Workstation-armhfp-31-1.9. Automatic boot in # second{,s}. Press a key for options. -menu title Fedora-Workstation-armhfp-31-1.9 Boot Options. -menu hidden -timeout 20 -totaltimeout 600 + Args: + ubman (ConsoleBase): Console to use + devnum (int): Device number to use, e.g. 1 + basename (str): Base name to use in the filename, e.g. 'mmc' + vmlinux (str): Kernel filename + initrd (str): Ramdisk filename + dtbdir (str or None): Devicetree filename + script (str): Script to place in the extlinux.conf file + """ + fsh = FsHelper(ubman.config, 'vfat', 18, prefix=basename) + fsh.setup() -label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) - kernel /%s - append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB - fdtdir /%s/ - initrd /%s''' % (vmlinux, dtbdir, initrd) - ext = os.path.join(mnt, 'extlinux') + ext = os.path.join(fsh.srcdir, 'extlinux') mkdir_cond(ext) conf = os.path.join(ext, 'extlinux.conf') @@ -191,24 +187,57 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) fd.write(gzip.compress(b'vmlinux')) mkimage = ubman.config.build_dir + '/tools/mkimage' utils.run_and_log( - ubman, f'{mkimage} -f auto -d {inf} {os.path.join(mnt, vmlinux)}') + ubman, f'{mkimage} -f auto -d {inf} {os.path.join(fsh.srcdir, vmlinux)}') - with open(os.path.join(mnt, initrd), 'w', encoding='ascii') as fd: + with open(os.path.join(fsh.srcdir, initrd), 'w', encoding='ascii') as fd: print('initrd', file=fd) - mkdir_cond(os.path.join(mnt, dtbdir)) + if dtbdir: + mkdir_cond(os.path.join(fsh.srcdir, dtbdir)) - dtb_file = os.path.join(mnt, f'{dtbdir}/sandbox.dtb') - utils.run_and_log( - ubman, f'dtc -o {dtb_file}', stdin=b'/dts-v1/; / {};') + dtb_file = os.path.join(fsh.srcdir, f'{dtbdir}/sandbox.dtb') + utils.run_and_log( + ubman, f'dtc -o {dtb_file}', stdin=b'/dts-v1/; / {};') + + fsh.mk_fs() + + img = DiskHelper(ubman.config, devnum, basename, True) + img.add_fs(fsh, DiskHelper.VFAT, bootable=True) + + ext4 = FsHelper(ubman.config, 'ext4', 1, prefix=basename) + ext4.setup() + ext4.mk_fs() + + img.add_fs(ext4, DiskHelper.EXT4) + img.create() + fsh.cleanup() + +def setup_fedora_image(ubman, devnum, basename): + """Create a 20MB Fedora disk image with a single FAT partition + + Args: + ubman (ConsoleBase): Console to use + devnum (int): Device number to use, e.g. 1 + basename (str): Base name to use in the filename, e.g. 'mmc' + """ + vmlinux = 'vmlinuz-5.3.7-301.fc31.armv7hl' + initrd = 'initramfs-5.3.7-301.fc31.armv7hl.img' + dtbdir = 'dtb-5.3.7-301.fc31.armv7hl' + script = '''# extlinux.conf generated by appliance-creator +ui menu.c32 +menu autoboot Welcome to Fedora-Workstation-armhfp-31-1.9. Automatic boot in # second{,s}. Press a key for options. +menu title Fedora-Workstation-armhfp-31-1.9 Boot Options. +menu hidden +timeout 20 +totaltimeout 600 - fsfile = 'vfat18M.img' - utils.run_and_log(ubman, f'fallocate -l 18M {fsfile}') - utils.run_and_log(ubman, f'mkfs.vfat {fsfile}') - utils.run_and_log(ubman, ['sh', '-c', f'mcopy -i {fsfile} {mnt}/* ::/']) - copy_partition(ubman, fsfile, fname) - utils.run_and_log(ubman, f'rm -rf {mnt}') - utils.run_and_log(ubman, f'rm -f {fsfile}') +label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + kernel /%s + append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB + fdtdir /%s/ + initrd /%s''' % (vmlinux, dtbdir, initrd) + setup_extlinux_image(ubman, devnum, basename, vmlinux, initrd, dtbdir, + script) def setup_cros_image(ubman): """Create a 20MB disk image with ChromiumOS partitions""" @@ -513,8 +542,8 @@ def test_ut_dm_init(ubman): utils.run_and_log( ubman, f'sfdisk {fn}', stdin=b'type=83') - fs_helper.mk_fs(ubman.config, 'ext2', 0x200000, '2MB', None) - fs_helper.mk_fs(ubman.config, 'fat32', 0x100000, '1MB', None) + FsHelper(ubman.config, 'ext2', 2, '2MB').mk_fs() + FsHelper(ubman.config, 'fat32', 1, '1MB').mk_fs() mmc_dev = 6 fn = os.path.join(ubman.config.source_dir, f'mmc{mmc_dev}.img') @@ -532,11 +561,9 @@ def test_ut_dm_init(ubman): def setup_efi_image(ubman): """Create a 20MB disk image with an EFI app on it""" devnum = 1 - basename = 'flash' - fname, mnt = fs_helper.setup_image(ubman, devnum, 0xc, second_part=True, - basename=basename) - - efi_dir = os.path.join(mnt, 'EFI') + fsh = FsHelper(ubman.config, 'vfat', 18, 'flash') + fsh.setup() + efi_dir = os.path.join(fsh.srcdir, 'EFI') mkdir_cond(efi_dir) bootdir = os.path.join(efi_dir, 'BOOT') mkdir_cond(bootdir) @@ -546,66 +573,53 @@ def setup_efi_image(ubman): with open(efi_src, 'rb') as inf: with open(efi_dst, 'wb') as outf: outf.write(inf.read()) - fsfile = 'vfat18M.img' - utils.run_and_log(ubman, f'fallocate -l 18M {fsfile}') - utils.run_and_log(ubman, f'mkfs.vfat {fsfile}') - utils.run_and_log(ubman, ['sh', '-c', f'mcopy -vs -i {fsfile} {mnt}/* ::/']) - copy_partition(ubman, fsfile, fname) - utils.run_and_log(ubman, f'rm -rf {mnt}') - utils.run_and_log(ubman, f'rm -f {fsfile}') + + fsh.mk_fs() + + img = DiskHelper(ubman.config, devnum, 'flash', True) + img.add_fs(fsh, DiskHelper.VFAT) + img.create() + fsh.cleanup() + def setup_rauc_image(ubman): """Create a 40MB disk image with an A/B RAUC system on it""" mmc_dev = 10 - fname = os.path.join(ubman.config.source_dir, f'mmc{mmc_dev}.img') - mnt = ubman.config.persistent_data_dir - - spec = 'type=c, size=8M, start=1M, bootable\n' \ - 'type=83, size=10M\n' \ - 'type=c, size=8M, bootable\n' \ - 'type=83, size=10M' - utils.run_and_log(ubman, f'qemu-img create {fname} 40M') - utils.run_and_log(ubman, ['sh', '-c', f'printf "{spec}" | sfdisk {fname}']) + boot = FsHelper(ubman.config, 'fat32', 8, 'rauc_boot') + boot.setup() # Generate boot script script = '# dummy boot script' - bootdir = os.path.join(mnt, 'boot') - utils.run_and_log(ubman, f'mkdir -p {bootdir}') - cmd_fname = os.path.join(bootdir, 'boot.cmd') - scr_fname = os.path.join(bootdir, 'boot.scr') + cmd_fname = os.path.join(boot.srcdir, 'boot.cmd') + scr_fname = os.path.join(boot.srcdir, 'boot.scr') with open(cmd_fname, 'w', encoding='ascii') as outf: print(script, file=outf) mkimage = os.path.join(ubman.config.build_dir, 'tools/mkimage') utils.run_and_log( ubman, f'{mkimage} -C none -A arm -T script -d {cmd_fname} {scr_fname}') - utils.run_and_log(ubman, f'rm -f {cmd_fname}') - - # Generate empty rootfs - rootdir = os.path.join(mnt, 'root') - utils.run_and_log(ubman, f'mkdir -p {rootdir}') - - # Create boot filesystem image with boot script in it and copy to disk image - fsfile = f'rauc_boot.fat32.img' - fs_helper.mk_fs(ubman.config, 'fat32', 0x800000, fsfile.split('.')[0], bootdir) - utils.run_and_log(ubman, f'dd if={mnt}/{fsfile} of=mmc{mmc_dev}.img bs=1M seek=1 conv=notrunc') - utils.run_and_log(ubman, f'dd if={mnt}/{fsfile} of=mmc{mmc_dev}.img bs=1M seek=19 conv=notrunc') - utils.run_and_log(ubman, f'rm -f {scr_fname}') - - # Create empty root filesystem image and copy to disk image - fsfile = f'rauc_root.ext4.img' - fs_helper.mk_fs(ubman.config, 'ext4', 0xa00000, fsfile.split('.')[0], rootdir) - utils.run_and_log(ubman, f'dd if={mnt}/{fsfile} of=mmc{mmc_dev}.img bs=1M seek=9 conv=notrunc') - utils.run_and_log(ubman, f'dd if={mnt}/{fsfile} of=mmc{mmc_dev}.img bs=1M seek=27 conv=notrunc') - utils.run_and_log(ubman, f'rm -f {fsfile}') + os.remove(cmd_fname) + boot.mk_fs() + + root = FsHelper(ubman.config, 'ext4', 10, 'rauc_root') + root.mk_fs() + + img = DiskHelper(ubman.config, mmc_dev, 'mmc', True) + img.add_fs(boot, DiskHelper.VFAT, bootable=True) + img.add_fs(root, DiskHelper.EXT4) + img.add_fs(boot, DiskHelper.VFAT, bootable=True) + img.add_fs(root, DiskHelper.EXT4) + img.create() + boot.cleanup() + root.cleanup() @pytest.mark.buildconfigspec('cmd_bootflow') @pytest.mark.buildconfigspec('sandbox') def test_ut_dm_init_bootstd(ubman): """Initialise data for bootflow tests""" - setup_bootflow_image(ubman) + setup_fedora_image(ubman, 1, 'mmc') setup_bootmenu_image(ubman) setup_cedit_file(ubman) setup_cros_image(ubman) diff --git a/test/py/tests/test_xxd.py b/test/py/tests/test_xxd.py index c457c54146c..a5f63f006fe 100644 --- a/test/py/tests/test_xxd.py +++ b/test/py/tests/test_xxd.py @@ -4,8 +4,7 @@ """ import pytest -from subprocess import call, check_call, CalledProcessError -from tests import fs_helper +from tests.fs_helper import FsHelper @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('cmd_xxd') @@ -15,26 +14,13 @@ def test_xxd(ubman): Args: ubman -- U-Boot console """ - try: - scratch_dir = ubman.config.persistent_data_dir + '/scratch' - - check_call('mkdir -p %s' % scratch_dir, shell=True) - - with open(scratch_dir + '/hello', 'w', encoding = 'ascii') as file: - file.write('hello world\n\x00\x01\x02\x03\x04\x05') - - xxd_data = fs_helper.mk_fs(ubman.config, 'vfat', 0x100000, - 'test_xxd', scratch_dir) - response = ubman.run_command_list([ f'host bind 0 {xxd_data}', - 'xxd host 0 hello']) + with FsHelper(ubman.config, 'vfat', 1, 'test_xxd') as fsh: + with open(f'{fsh.srcdir}/hello', 'w', encoding = 'ascii') as outf: + outf.write('hello world\n\x00\x01\x02\x03\x04\x05') + fsh.mk_fs() + response = ubman.run_command_list([f'host bind 0 {fsh.fs_img}', + 'xxd host 0 hello']) assert '00000000: 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a 00 01 02 03 hello world.....\r\r\n' + \ '00000010: 04 05 ..' \ in response - except CalledProcessError as err: - pytest.skip('Preparing test_xxd image failed') - call('rm -f %s' % xxd_data, shell=True) - return - finally: - call('rm -rf %s' % scratch_dir, shell=True) - call('rm -f %s' % xxd_data, shell=True) |
