| # SPDX-License-Identifier: GPL-2.0 | |
| # Copyright (C) 2020 Bootlin | |
| # Author: Joao Marcos Costa <joaomarcos.costa@bootlin.com> | |
| import os | |
| import shutil | |
| import subprocess | |
| """ standard test images table: Each table item is a key:value pair | |
| representing the output image name and its respective mksquashfs options. | |
| This table should be modified only when adding support for new compression | |
| algorithms. The 'default' case takes no options but the input and output | |
| names, so it must be assigned with an empty string. | |
| """ | |
| STANDARD_TABLE = { | |
| 'default' : '', | |
| 'lzo_comp_frag' : '', | |
| 'lzo_frag' : '', | |
| 'lzo_no_frag' : '', | |
| 'zstd_comp_frag' : '', | |
| 'zstd_frag' : '', | |
| 'zstd_no_frag' : '', | |
| 'gzip_comp_frag' : '', | |
| 'gzip_frag' : '', | |
| 'gzip_no_frag' : '' | |
| } | |
| """ EXTRA_TABLE: Set this table's keys and values if you want to make squashfs | |
| images with your own customized options. | |
| """ | |
| EXTRA_TABLE = {} | |
| # path to source directory used to make squashfs test images | |
| SQFS_SRC_DIR = 'sqfs_src_dir' | |
| def get_opts_list(): | |
| """ Combines fragmentation and compression options into a list of strings. | |
| opts_list's firts item is an empty string as STANDARD_TABLE's first item is | |
| the 'default' case. | |
| Returns: | |
| A list of strings whose items are formed by a compression and a | |
| fragmentation option joined by a whitespace. | |
| """ | |
| # supported compression options only | |
| comp_opts = ['-comp lzo', '-comp zstd', '-comp gzip'] | |
| # file fragmentation options | |
| frag_opts = ['-always-use-fragments', '-always-use-fragments -noF', '-no-fragments'] | |
| opts_list = [' '] | |
| for comp_opt in comp_opts: | |
| for frag_opt in frag_opts: | |
| opts_list.append(' '.join([comp_opt, frag_opt])) | |
| return opts_list | |
| def init_standard_table(): | |
| """ Initializes STANDARD_TABLE values. | |
| STANDARD_TABLE's keys are pre-defined, and init_standard_table() assigns | |
| the right value for each one of them. | |
| """ | |
| opts_list = get_opts_list() | |
| for key, value in zip(STANDARD_TABLE.keys(), opts_list): | |
| STANDARD_TABLE[key] = value | |
| def generate_file(file_name, file_size): | |
| """ Generates a file filled with 'x'. | |
| Args: | |
| file_name: the file's name. | |
| file_size: the content's length and therefore the file size. | |
| """ | |
| content = 'x' * file_size | |
| file = open(file_name, 'w') | |
| file.write(content) | |
| file.close() | |
| def generate_sqfs_src_dir(build_dir): | |
| """ Generates the source directory used to make the SquashFS images. | |
| The source directory is generated at build_dir, and it has the following | |
| structure: | |
| sqfs_src_dir/ | |
| ├── empty-dir/ | |
| ├── f1000 | |
| ├── f4096 | |
| ├── f5096 | |
| ├── subdir/ | |
| │ └── subdir-file | |
| └── sym -> subdir | |
| 3 directories, 4 files | |
| The files in the root dir. are prefixed with an 'f' followed by its size. | |
| Args: | |
| build_dir: u-boot's build-sandbox directory. | |
| """ | |
| root = os.path.join(build_dir, SQFS_SRC_DIR) | |
| # make root directory | |
| os.makedirs(root) | |
| # 4096: minimum block size | |
| file_name = 'f4096' | |
| generate_file(os.path.join(root, file_name), 4096) | |
| # 5096: minimum block size + 1000 chars (fragment) | |
| file_name = 'f5096' | |
| generate_file(os.path.join(root, file_name), 5096) | |
| # 1000: less than minimum block size (fragment only) | |
| file_name = 'f1000' | |
| generate_file(os.path.join(root, file_name), 1000) | |
| # sub-directory with a single file inside | |
| subdir_path = os.path.join(root, 'subdir') | |
| os.makedirs(subdir_path) | |
| generate_file(os.path.join(subdir_path, 'subdir-file'), 100) | |
| # symlink (target: sub-directory) | |
| os.symlink('subdir', os.path.join(root, 'sym')) | |
| # empty directory | |
| os.makedirs(os.path.join(root, 'empty-dir')) | |
| def mksquashfs(args): | |
| """ Runs mksquashfs command. | |
| Args: | |
| args: mksquashfs options (e.g.: compression and fragmentation). | |
| """ | |
| subprocess.run(['mksquashfs ' + args], shell=True, check=True, | |
| stdout=subprocess.DEVNULL) | |
| def get_mksquashfs_version(): | |
| """ Parses the output of mksquashfs -version. | |
| Returns: | |
| mksquashfs's version as a float. | |
| """ | |
| out = subprocess.run(['mksquashfs -version'], shell=True, check=True, | |
| capture_output=True, text=True) | |
| # 'out' is: mksquashfs version X (yyyy/mm/dd) ... | |
| return out.stdout.split()[2].split('.')[0:2] | |
| def check_mksquashfs_version(): | |
| """ Checks if mksquashfs meets the required version. """ | |
| version = get_mksquashfs_version(); | |
| if int(version[0]) < 4 or int(version[0]) == 4 and int(version[1]) < 4 : | |
| print('Error: mksquashfs is too old, required version: 4.4') | |
| raise AssertionError | |
| def make_all_images(build_dir): | |
| """ Makes the SquashFS images used in the test suite. | |
| The image names and respective mksquashfs options are defined in STANDARD_TABLE | |
| and EXTRA_TABLE. The destination is defined by 'build_dir'. | |
| Args: | |
| build_dir: u-boot's build-sandbox directory. | |
| """ | |
| init_standard_table() | |
| input_path = os.path.join(build_dir, SQFS_SRC_DIR) | |
| # make squashfs images according to STANDARD_TABLE | |
| for out, opts in zip(STANDARD_TABLE.keys(), STANDARD_TABLE.values()): | |
| output_path = os.path.join(build_dir, out) | |
| mksquashfs(' '.join([input_path, output_path, opts])) | |
| # make squashfs images according to EXTRA_TABLE | |
| for out, opts in zip(EXTRA_TABLE.keys(), EXTRA_TABLE.values()): | |
| output_path = os.path.join(build_dir, out) | |
| mksquashfs(' '.join([input_path, output_path, opts])) | |
| def clean_all_images(build_dir): | |
| """ Deletes the SquashFS images at build_dir. | |
| Args: | |
| build_dir: u-boot's build-sandbox directory. | |
| """ | |
| for image_name in STANDARD_TABLE: | |
| image_path = os.path.join(build_dir, image_name) | |
| os.remove(image_path) | |
| for image_name in EXTRA_TABLE: | |
| image_path = os.path.join(build_dir, image_name) | |
| os.remove(image_path) | |
| def clean_sqfs_src_dir(build_dir): | |
| """ Deletes the source directory at build_dir. | |
| Args: | |
| build_dir: u-boot's build-sandbox directory. | |
| """ | |
| path = os.path.join(build_dir, SQFS_SRC_DIR) | |
| shutil.rmtree(path) |