206 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			206 lines
		
	
	
		
			6.2 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].split('-')[0])
 | 
						|
 | 
						|
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)
 |