From: Simon Glass Date: Sat, 4 Apr 2026 14:03:05 +0000 (-0600) Subject: test: Add a helper class to create disk images X-Git-Tag: v2026.07-rc1~33^2~13 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=7c69117337412d2477bc3f72e4042bca4a4e66b3;p=thirdparty%2Fu-boot.git test: Add a helper class to create disk images Provide a way to create disk images which consist of multiple filesystem images. Include a cur_dir option to place the disk image in the current directory rather than in the persistent-data directory. This matches the behaviour of setup_image() which places disk images in source_dir where sandbox expects to find them. This flag is a temporary feature and should be removed once all tests are migrated to use the persistent-data directory instead. Signed-off-by: Simon Glass --- diff --git a/test/py/tests/fs_helper.py b/test/py/tests/fs_helper.py index 800376b1e7d..e323a97b220 100644 --- a/test/py/tests/fs_helper.py +++ b/test/py/tests/fs_helper.py @@ -97,6 +97,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