206 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			206 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
| # 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 float(out.stdout.split()[2])
 | |
| 
 | |
| def check_mksquashfs_version():
 | |
|     """ Checks if mksquashfs meets the required version. """
 | |
| 
 | |
|     required_version = 4.4
 | |
|     if get_mksquashfs_version() < required_version:
 | |
|         print('Error: mksquashfs is too old.')
 | |
|         print('Required version: {}'.format(required_version))
 | |
|         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)
 |