1# SPDX-License-Identifier: GPL-2.0 2# Copyright (C) 2020 Bootlin 3# Author: Joao Marcos Costa <joaomarcos.costa@bootlin.com> 4 5import os 6import shutil 7import subprocess 8 9""" standard test images table: Each table item is a key:value pair 10representing the output image name and its respective mksquashfs options. 11This table should be modified only when adding support for new compression 12algorithms. The 'default' case takes no options but the input and output 13names, so it must be assigned with an empty string. 14""" 15STANDARD_TABLE = { 16 'default' : '', 17 'lzo_comp_frag' : '', 18 'lzo_frag' : '', 19 'lzo_no_frag' : '', 20 'zstd_comp_frag' : '', 21 'zstd_frag' : '', 22 'zstd_no_frag' : '', 23 'gzip_comp_frag' : '', 24 'gzip_frag' : '', 25 'gzip_no_frag' : '' 26} 27 28""" EXTRA_TABLE: Set this table's keys and values if you want to make squashfs 29images with your own customized options. 30""" 31EXTRA_TABLE = {} 32 33# path to source directory used to make squashfs test images 34SQFS_SRC_DIR = 'sqfs_src_dir' 35 36def get_opts_list(): 37 """ Combines fragmentation and compression options into a list of strings. 38 39 opts_list's firts item is an empty string as STANDARD_TABLE's first item is 40 the 'default' case. 41 42 Returns: 43 A list of strings whose items are formed by a compression and a 44 fragmentation option joined by a whitespace. 45 """ 46 # supported compression options only 47 comp_opts = ['-comp lzo', '-comp zstd', '-comp gzip'] 48 # file fragmentation options 49 frag_opts = ['-always-use-fragments', '-always-use-fragments -noF', '-no-fragments'] 50 51 opts_list = [' '] 52 for comp_opt in comp_opts: 53 for frag_opt in frag_opts: 54 opts_list.append(' '.join([comp_opt, frag_opt])) 55 56 return opts_list 57 58def init_standard_table(): 59 """ Initializes STANDARD_TABLE values. 60 61 STANDARD_TABLE's keys are pre-defined, and init_standard_table() assigns 62 the right value for each one of them. 63 """ 64 opts_list = get_opts_list() 65 66 for key, value in zip(STANDARD_TABLE.keys(), opts_list): 67 STANDARD_TABLE[key] = value 68 69def generate_file(file_name, file_size): 70 """ Generates a file filled with 'x'. 71 72 Args: 73 file_name: the file's name. 74 file_size: the content's length and therefore the file size. 75 """ 76 content = 'x' * file_size 77 78 file = open(file_name, 'w') 79 file.write(content) 80 file.close() 81 82def generate_sqfs_src_dir(build_dir): 83 """ Generates the source directory used to make the SquashFS images. 84 85 The source directory is generated at build_dir, and it has the following 86 structure: 87 sqfs_src_dir/ 88 ├── empty-dir/ 89 ├── f1000 90 ├── f4096 91 ├── f5096 92 ├── subdir/ 93 │ └── subdir-file 94 └── sym -> subdir 95 96 3 directories, 4 files 97 98 The files in the root dir. are prefixed with an 'f' followed by its size. 99 100 Args: 101 build_dir: u-boot's build-sandbox directory. 102 """ 103 104 root = os.path.join(build_dir, SQFS_SRC_DIR) 105 # make root directory 106 os.makedirs(root) 107 108 # 4096: minimum block size 109 file_name = 'f4096' 110 generate_file(os.path.join(root, file_name), 4096) 111 112 # 5096: minimum block size + 1000 chars (fragment) 113 file_name = 'f5096' 114 generate_file(os.path.join(root, file_name), 5096) 115 116 # 1000: less than minimum block size (fragment only) 117 file_name = 'f1000' 118 generate_file(os.path.join(root, file_name), 1000) 119 120 # sub-directory with a single file inside 121 subdir_path = os.path.join(root, 'subdir') 122 os.makedirs(subdir_path) 123 generate_file(os.path.join(subdir_path, 'subdir-file'), 100) 124 125 # symlink (target: sub-directory) 126 os.symlink('subdir', os.path.join(root, 'sym')) 127 128 # empty directory 129 os.makedirs(os.path.join(root, 'empty-dir')) 130 131def mksquashfs(args): 132 """ Runs mksquashfs command. 133 134 Args: 135 args: mksquashfs options (e.g.: compression and fragmentation). 136 """ 137 subprocess.run(['mksquashfs ' + args], shell=True, check=True, 138 stdout=subprocess.DEVNULL) 139 140def get_mksquashfs_version(): 141 """ Parses the output of mksquashfs -version. 142 143 Returns: 144 mksquashfs's version as a float. 145 """ 146 out = subprocess.run(['mksquashfs -version'], shell=True, check=True, 147 capture_output=True, text=True) 148 # 'out' is: mksquashfs version X (yyyy/mm/dd) ... 149 return out.stdout.split()[2].split('.')[0:2] 150 151def check_mksquashfs_version(): 152 """ Checks if mksquashfs meets the required version. """ 153 154 version = get_mksquashfs_version(); 155 if int(version[0]) < 4 or int(version[0]) == 4 and int(version[1]) < 4 : 156 print('Error: mksquashfs is too old, required version: 4.4') 157 raise AssertionError 158 159def make_all_images(build_dir): 160 """ Makes the SquashFS images used in the test suite. 161 162 The image names and respective mksquashfs options are defined in STANDARD_TABLE 163 and EXTRA_TABLE. The destination is defined by 'build_dir'. 164 165 Args: 166 build_dir: u-boot's build-sandbox directory. 167 """ 168 169 init_standard_table() 170 input_path = os.path.join(build_dir, SQFS_SRC_DIR) 171 172 # make squashfs images according to STANDARD_TABLE 173 for out, opts in zip(STANDARD_TABLE.keys(), STANDARD_TABLE.values()): 174 output_path = os.path.join(build_dir, out) 175 mksquashfs(' '.join([input_path, output_path, opts])) 176 177 # make squashfs images according to EXTRA_TABLE 178 for out, opts in zip(EXTRA_TABLE.keys(), EXTRA_TABLE.values()): 179 output_path = os.path.join(build_dir, out) 180 mksquashfs(' '.join([input_path, output_path, opts])) 181 182def clean_all_images(build_dir): 183 """ Deletes the SquashFS images at build_dir. 184 185 Args: 186 build_dir: u-boot's build-sandbox directory. 187 """ 188 189 for image_name in STANDARD_TABLE: 190 image_path = os.path.join(build_dir, image_name) 191 os.remove(image_path) 192 193 for image_name in EXTRA_TABLE: 194 image_path = os.path.join(build_dir, image_name) 195 os.remove(image_path) 196 197def clean_sqfs_src_dir(build_dir): 198 """ Deletes the source directory at build_dir. 199 200 Args: 201 build_dir: u-boot's build-sandbox directory. 202 """ 203 path = os.path.join(build_dir, SQFS_SRC_DIR) 204 shutil.rmtree(path) 205