* [PATCH v3 1/2] wic: re-implement sector-size support
@ 2026-02-16 2:31 Trevor Woerner
2026-02-16 2:31 ` [PATCH v3 2/2] ufs image class: add Trevor Woerner
2026-02-16 3:09 ` [OE-core] [PATCH v3 1/2] wic: re-implement sector-size support Bruce Ashfield
0 siblings, 2 replies; 8+ messages in thread
From: Trevor Woerner @ 2026-02-16 2:31 UTC (permalink / raw)
To: openembedded-core
The previous implementation to add variable sector-size support:
- required the variable WIC_SECTOR_SIZE either be defined in a
configuration file or be defined in a --vars file
- this means that every invocation of "wic ls", "wic cp", or "wic rm"
needed this variable defined (config or --vars)
- required the user to create separate *wks files for every sector size
they wanted to use
- required the user to specify the mkfs-extraopts by hand to specify the
correct sector size: e.g.
bootloader --ptable gpt
part --fstype ext4 --source rootfs --label rofs-a --mkfs-extraopts "-b 4096"
part --fstype ext4 --source rootfs --use-uuid --mkfs-extraopts "-b 4096"
- specifying --mkfs-extraopts replaces the defaults with the
user-supplied values
- only provided details to support using variable sector-sizes with
ext[234] filesystems
- it would not be possible to generate images with different sector
sizes in the same build since the configuration and *wks files would
need to change and the build re-run for each size
Update the sector-size handling so that:
- the sector-size will now be provided on the cmdline to the "wic ls",
"wic cp", "wic rm", and "wic create" commands: default = 512
- this means the configuration and/or --vars file does not need to be
changed in order to perform those operations on images with different
sector sizes
- support is provided implicitly for mkdosfs and ext[234] partitions
- the user no longer needs to know and supply the sector-size magic in
--mkfs-extraopts (thereby clobbering the other defaults)
AI-Generated: codex/gpt-5.1-codex-max
Signed-off-by: Trevor Woerner <twoerner@gmail.com>
---
changes since v2:
- none
changes since v1:
- none
---
meta/lib/oeqa/selftest/cases/wic.py | 39 ++++---------
scripts/lib/wic/engine.py | 45 +++++++--------
scripts/lib/wic/help.py | 23 +++++---
scripts/lib/wic/partition.py | 55 +++++++++++++++++--
scripts/lib/wic/plugins/imager/direct.py | 18 ++----
scripts/lib/wic/plugins/source/bootimg_efi.py | 5 +-
.../lib/wic/plugins/source/bootimg_pcbios.py | 11 ++--
.../wic/plugins/source/isoimage_isohybrid.py | 5 +-
scripts/wic | 8 +++
9 files changed, 125 insertions(+), 84 deletions(-)
diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py
index ecaee5a29144..7ad61fa700f7 100644
--- a/meta/lib/oeqa/selftest/cases/wic.py
+++ b/meta/lib/oeqa/selftest/cases/wic.py
@@ -935,33 +935,22 @@ bootloader --ptable gpt""")
finally:
os.remove(wks_file)
- def test_wic_sector_size(self):
- """Test generation image sector size"""
-
+ def test_wic_sector_size_cli(self):
+ """Test sector size handling via CLI option."""
+
oldpath = os.environ['PATH']
os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
try:
- # Add WIC_SECTOR_SIZE into config
- config = 'WIC_SECTOR_SIZE = "4096"\n'\
- 'WICVARS:append = " WIC_SECTOR_SIZE"\n'
- self.append_config(config)
bitbake('core-image-minimal')
- # Check WIC_SECTOR_SIZE apply to bitbake variable
- wic_sector_size_str = get_bb_var('WIC_SECTOR_SIZE', 'core-image-minimal')
- wic_sector_size = int(wic_sector_size_str)
- self.assertEqual(4096, wic_sector_size)
-
- self.logger.info("Test wic_sector_size: %d \n" % wic_sector_size)
-
with NamedTemporaryFile("w", suffix=".wks") as wks:
wks.writelines(
['bootloader --ptable gpt\n',
- 'part --fstype ext4 --source rootfs --label rofs-a --mkfs-extraopts "-b 4096"\n',
- 'part --fstype ext4 --source rootfs --use-uuid --mkfs-extraopts "-b 4096"\n'])
+ 'part --fstype ext4 --source rootfs --label rofs-a\n',
+ 'part --fstype ext4 --source rootfs --use-uuid\n'])
wks.flush()
- cmd = "wic create %s -e core-image-minimal -o %s" % (wks.name, self.resultdir)
+ cmd = "wic create %s -e core-image-minimal -o %s --sector-size 4096" % (wks.name, self.resultdir)
runCmd(cmd)
wksname = os.path.splitext(os.path.basename(wks.name))[0]
images = glob(os.path.join(self.resultdir, "%s-*direct" % wksname))
@@ -969,24 +958,18 @@ bootloader --ptable gpt""")
sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
# list partitions
- result = runCmd("wic ls %s -n %s" % (images[0], sysroot))
+ result = runCmd("wic ls %s -n %s --sector-size 4096" % (images[0], sysroot))
self.assertEqual(3, len(result.output.split('\n')))
- # verify partition size with wic
- res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m %s unit b p" % (wic_sector_size, images[0]),
+ # verify partition size with parted output
+ res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m %s unit b p" % (4096, images[0]),
stderr=subprocess.PIPE)
- # parse parted output which looks like this:
- # BYT;\n
- # /var/tmp/wic/build/tmpgjzzefdd-202410281021-sda.direct:78569472B:file:4096:4096:gpt::;\n
- # 1:139264B:39284735B:39145472B:ext4:rofs-a:;\n
- # 2:39284736B:78430207B:39145472B:ext4:primary:;\n
disk_info = res.output.splitlines()[1]
- # Check sector sizes
sector_size_logical = int(disk_info.split(":")[3])
sector_size_physical = int(disk_info.split(":")[4])
- self.assertEqual(wic_sector_size, sector_size_logical, "Logical sector size is not %d." % wic_sector_size)
- self.assertEqual(wic_sector_size, sector_size_physical, "Physical sector size is not %d." % wic_sector_size)
+ self.assertEqual(4096, sector_size_logical, "Logical sector size is not 4096.")
+ self.assertEqual(4096, sector_size_physical, "Physical sector size is not 4096.")
finally:
os.environ['PATH'] = oldpath
diff --git a/scripts/lib/wic/engine.py b/scripts/lib/wic/engine.py
index 9d596be3a723..7753f431f91d 100644
--- a/scripts/lib/wic/engine.py
+++ b/scripts/lib/wic/engine.py
@@ -224,7 +224,7 @@ def wic_list(args, scripts_path):
class Disk:
- def __init__(self, imagepath, native_sysroot, fstypes=('fat', 'ext')):
+ def __init__(self, imagepath, native_sysroot, fstypes=('fat', 'ext'), sector_size=512):
self.imagepath = imagepath
self.native_sysroot = native_sysroot
self.fstypes = fstypes
@@ -233,16 +233,7 @@ class Disk:
self._lsector_size = None
self._psector_size = None
self._ptable_format = None
-
- # define sector size
- sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
- if sector_size_str is not None:
- try:
- self.sector_size = int(sector_size_str)
- except ValueError:
- self.sector_size = None
- else:
- self.sector_size = None
+ self.sector_size = sector_size
# find parted
# read paths from $PATH environment variable
@@ -271,7 +262,7 @@ class Disk:
if self._partitions is None:
self._partitions = OrderedDict()
- if self.sector_size is not None:
+ if self.sector_size:
out = exec_cmd("export PARTED_SECTOR_SIZE=%d; %s -sm %s unit B print" % \
(self.sector_size, self.parted, self.imagepath), True)
else:
@@ -312,11 +303,15 @@ class Disk:
raise WicError("Partition %s is not in the image" % pnum)
part = self.partitions[pnum]
# check if fstype is supported
+ # NOTE: parted is unable to identify dos-type partitions with a 4k sector-size
+ # if the type is empty and a non-default sector size is used, assume 'fat'
+ # fdisk identifies them without issue
+ part_fstype = part.fstype if part.fstype or self.sector_size == 512 else 'fat'
for fstype in self.fstypes:
- if part.fstype.startswith(fstype):
+ if part_fstype.startswith(fstype):
break
else:
- raise WicError("Not supported fstype: {}".format(part.fstype))
+ raise WicError("Not supported fstype: {}".format(part_fstype))
if pnum not in self._partimages:
tmpf = tempfile.NamedTemporaryFile(prefix="wic-part")
dst_fname = tmpf.name
@@ -586,8 +581,9 @@ class Disk:
label = part.get("name")
label_str = "-n {}".format(label) if label else ''
- cmd = "{} {} -C {} {}".format(self.mkdosfs, label_str, partfname,
- part['size'])
+ sector_str = "-S {}".format(self.sector_size) if self.sector_size else ''
+ cmd = "{} {} {} -C {} {}".format(self.mkdosfs, label_str, sector_str, partfname,
+ part['size'])
exec_cmd(cmd)
# copy content from the temporary directory to the new partition
cmd = "{} -snompi {} {}/* ::".format(self.mcopy, partfname, tmpdir)
@@ -609,14 +605,19 @@ class Disk:
def wic_ls(args, native_sysroot):
"""List contents of partitioned image or vfat partition."""
- disk = Disk(args.path.image, native_sysroot)
+ disk = Disk(args.path.image, native_sysroot, sector_size=args.sector_size)
if not args.path.part:
if disk.partitions:
print('Num Start End Size Fstype')
for part in disk.partitions.values():
+ # size values are in bytes from parted; convert to sectors if a custom sector size was requested
+ display_size = part.size
+ if args.sector_size and args.sector_size != disk._lsector_size:
+ display_size = part.size // args.sector_size
print("{:2d} {:12d} {:12d} {:12d} {}".format(\
- part.pnum, part.start, part.end,
- part.size, part.fstype))
+ part.pnum, part.start // args.sector_size,
+ part.end // args.sector_size,
+ display_size, part.fstype))
else:
path = args.path.path or '/'
print(disk.dir(args.path.part, path))
@@ -627,9 +628,9 @@ def wic_cp(args, native_sysroot):
partitioned image.
"""
if isinstance(args.dest, str):
- disk = Disk(args.src.image, native_sysroot)
+ disk = Disk(args.src.image, native_sysroot, sector_size=args.sector_size)
else:
- disk = Disk(args.dest.image, native_sysroot)
+ disk = Disk(args.dest.image, native_sysroot, sector_size=args.sector_size)
disk.copy(args.src, args.dest)
@@ -638,7 +639,7 @@ def wic_rm(args, native_sysroot):
Remove files or directories from the vfat partition of
partitioned image.
"""
- disk = Disk(args.path.image, native_sysroot)
+ disk = Disk(args.path.image, native_sysroot, sector_size=args.sector_size)
disk.remove(args.path.part, args.path.path, args.recursive_delete)
def wic_write(args, native_sysroot):
diff --git a/scripts/lib/wic/help.py b/scripts/lib/wic/help.py
index 6b49a67de938..5d7c40456a80 100644
--- a/scripts/lib/wic/help.py
+++ b/scripts/lib/wic/help.py
@@ -118,7 +118,7 @@ wic_create_usage = """
usage: wic create <wks file or image name> [-o <DIRNAME> | --outdir <DIRNAME>]
[-e | --image-name] [-s, --skip-build-check] [-D, --debug]
[-r, --rootfs-dir] [-b, --bootimg-dir]
- [-k, --kernel-dir] [-n, --native-sysroot] [-f, --build-rootfs]
+ [-k, --kernel-dir] [-n, --native-sysroot] [--sector-size <bytes>] [-f, --build-rootfs]
[-c, --compress-with] [-m, --bmap]
This command creates an OpenEmbedded image based on the 'OE kickstart
@@ -139,13 +139,16 @@ SYNOPSIS
wic create <wks file or image name> [-o <DIRNAME> | --outdir <DIRNAME>]
[-e | --image-name] [-s, --skip-build-check] [-D, --debug]
[-r, --rootfs-dir] [-b, --bootimg-dir]
- [-k, --kernel-dir] [-n, --native-sysroot] [-f, --build-rootfs]
+ [-k, --kernel-dir] [-n, --native-sysroot] [--sector-size <bytes>] [-f, --build-rootfs]
[-c, --compress-with] [-m, --bmap] [--no-fstab-update]
DESCRIPTION
This command creates an OpenEmbedded image based on the 'OE
kickstart commands' found in the <wks file>.
+ Use the --sector-size option to select the sector size (in bytes)
+ used for partition layout calculations (default is 512).
+
In order to do this, wic needs to know the locations of the
various build artifacts required to build the image.
@@ -278,7 +281,7 @@ wic_ls_usage = """
List content of a partitioned image
- usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot <path>]
+ usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot <path>] [--sector-size <bytes>]
This command outputs either list of image partitions or directory contents
of vfat and ext* partitions.
@@ -296,7 +299,7 @@ SYNOPSIS
wic ls <image>
wic ls <image>:<vfat or ext* partition>
wic ls <image>:<vfat or ext* partition><path>
- wic ls <image>:<vfat or ext* partition><path> --native-sysroot <path>
+ wic ls <image>:<vfat or ext* partition><path> --native-sysroot <path> [--sector-size <bytes>]
DESCRIPTION
This command lists either partitions of the image or directory contents
@@ -336,6 +339,8 @@ DESCRIPTION
The -n option is used to specify the path to the native sysroot
containing the tools(parted and mtools) to use.
+ The --sector-size option sets the sector size used for partition math
+ (default is 512 bytes).
"""
@@ -343,7 +348,7 @@ wic_cp_usage = """
Copy files and directories to/from the vfat or ext* partition
- usage: wic cp <src> <dest> [--native-sysroot <path>]
+ usage: wic cp <src> <dest> [--native-sysroot <path>] [--sector-size <bytes>]
source/destination image in format <image>:<partition>[<path>]
@@ -364,7 +369,7 @@ SYNOPSIS
wic cp <src> <dest>:<partition>
wic cp <src>:<partition> <dest>
wic cp <src> <dest-image>:<partition><path>
- wic cp <src> <dest-image>:<partition><path> --native-sysroot <path>
+ wic cp <src> <dest-image>:<partition><path> --native-sysroot <path> [--sector-size <bytes>]
DESCRIPTION
This command copies files or directories either
@@ -408,13 +413,15 @@ DESCRIPTION
The -n option is used to specify the path to the native sysroot
containing the tools(parted and mtools) to use.
+ The --sector-size option sets the sector size used for partition math
+ (default is 512 bytes).
"""
wic_rm_usage = """
Remove files or directories from the vfat or ext* partitions
- usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
+ usage: wic rm <image>:<partition><path> [--native-sysroot <path>] [--sector-size <bytes>]
This command removes files or directories from the vfat or ext* partitions of
the partitioned image.
@@ -466,6 +473,8 @@ DESCRIPTION
The -n option is used to specify the path to the native sysroot
containing the tools(parted and mtools) to use.
+ The --sector-size option sets the sector size used for partition math
+ (default is 512 bytes).
The -r option is used to remove directories and their contents
recursively,this only applies to ext* partition.
diff --git a/scripts/lib/wic/partition.py b/scripts/lib/wic/partition.py
index 8fed686e903e..df6e3271649b 100644
--- a/scripts/lib/wic/partition.py
+++ b/scripts/lib/wic/partition.py
@@ -65,6 +65,50 @@ class Partition():
self.lineno = lineno
self.source_file = ""
+ self.sector_size = 512
+
+ def _mkdosfs_extraopts(self):
+ """
+ Build mkdosfs extra options ensuring the CLI sector size is applied.
+ """
+ extraopts = self.mkfs_extraopts or ''
+ tokens = []
+ skip_next = False
+ for tok in extraopts.split():
+ if skip_next:
+ skip_next = False
+ continue
+ if tok == '-S':
+ skip_next = True
+ continue
+ if tok.startswith('-S'):
+ continue
+ tokens.append(tok)
+ tokens.extend(['-S', str(self.sector_size)])
+ return ' '.join(tokens).strip()
+
+ def _mkfs_ext_extraopts(self, base_opts):
+ """
+ Build mkfs.ext* extra options ensuring the CLI sector size is applied.
+ """
+ extraopts = self.mkfs_extraopts or base_opts
+ # Only add an explicit block size when a non-default sector size is requested.
+ if self.sector_size and self.sector_size != 512:
+ tokens = []
+ skip_next = False
+ for tok in extraopts.split():
+ if skip_next:
+ skip_next = False
+ continue
+ if tok == '-b':
+ skip_next = True
+ continue
+ if tok.startswith('-b'):
+ continue
+ tokens.append(tok)
+ tokens.extend(['-b', str(self.sector_size)])
+ return ' '.join(tokens).strip()
+ return extraopts
def get_extra_block_count(self, current_blocks):
"""
@@ -138,6 +182,8 @@ class Partition():
Prepare content for individual partitions, depending on
partition command parameters.
"""
+ # capture the sector size requested on the CLI for mkdosfs invocations
+ self.sector_size = getattr(creator, 'sector_size', 512) or 512
self.updated_fstab_path = updated_fstab_path
if self.updated_fstab_path and not (self.fstype.startswith("ext") or self.fstype == "msdos"):
self.update_fstab_in_rootfs = True
@@ -293,7 +339,7 @@ class Partition():
with open(rootfs, 'w') as sparse:
os.ftruncate(sparse.fileno(), rootfs_size * 1024)
- extraopts = self.mkfs_extraopts or "-F -i 8192"
+ extraopts = self._mkfs_ext_extraopts("-F -i 8192")
# use hash_seed to generate reproducible ext4 images
(extraopts, pseudo) = self.get_hash_seed_ext4(extraopts, pseudo)
@@ -401,7 +447,7 @@ class Partition():
size_str = ""
- extraopts = self.mkfs_extraopts or '-S 512'
+ extraopts = self._mkdosfs_extraopts()
dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
(label_str, self.fsuuid, size_str, extraopts, rootfs,
@@ -452,7 +498,7 @@ class Partition():
with open(rootfs, 'w') as sparse:
os.ftruncate(sparse.fileno(), size * 1024)
- extraopts = self.mkfs_extraopts or "-i 8192"
+ extraopts = self._mkfs_ext_extraopts("-i 8192")
# use hash_seed to generate reproducible ext4 images
(extraopts, pseudo) = self.get_hash_seed_ext4(extraopts, None)
@@ -498,7 +544,7 @@ class Partition():
size_str = ""
- extraopts = self.mkfs_extraopts or '-S 512'
+ extraopts = self._mkdosfs_extraopts()
dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
(label_str, self.fsuuid, extraopts, size_str, rootfs,
@@ -559,4 +605,3 @@ class Partition():
logger.warn("%s Inodes (of size %d) are too small." %
(get_err_str(self), size))
break
-
diff --git a/scripts/lib/wic/plugins/imager/direct.py b/scripts/lib/wic/plugins/imager/direct.py
index ad922cfbf122..3adc6eee6280 100644
--- a/scripts/lib/wic/plugins/imager/direct.py
+++ b/scripts/lib/wic/plugins/imager/direct.py
@@ -67,6 +67,7 @@ class DirectPlugin(ImagerPlugin):
self._image = None
self.ptable_format = self.ks.bootloader.ptable
self.parts = self.ks.partitions
+ self.sector_size = options.sector_size or 512
# as a convenience, set source to the boot partition source
# instead of forcing it to be set via bootloader --source
@@ -78,7 +79,7 @@ class DirectPlugin(ImagerPlugin):
image_path = self._full_path(self.workdir, self.parts[0].disk, "direct")
self._image = PartitionedImage(image_path, self.ptable_format, self.ks.bootloader.diskid,
self.parts, self.native_sysroot,
- options.extra_space)
+ options.extra_space, self.sector_size)
def setup_workdir(self, workdir):
if workdir:
@@ -294,15 +295,13 @@ MBR_OVERHEAD = 1
# Overhead of the GPT partitioning scheme
GPT_OVERHEAD = 34
-# Size of a sector in bytes
-SECTOR_SIZE = 512
-
class PartitionedImage():
"""
Partitioned image in a file.
"""
- def __init__(self, path, ptable_format, disk_id, partitions, native_sysroot=None, extra_space=0):
+ def __init__(self, path, ptable_format, disk_id, partitions, native_sysroot=None, extra_space=0,
+ sector_size=512):
self.path = path # Path to the image file
self.numpart = 0 # Number of allocated partitions
self.realpart = 0 # Number of partitions in the partition table
@@ -332,14 +331,7 @@ class PartitionedImage():
self.partitions = partitions
self.partimages = []
# Size of a sector used in calculations
- sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
- if sector_size_str is not None:
- try:
- self.sector_size = int(sector_size_str)
- except ValueError:
- self.sector_size = SECTOR_SIZE
- else:
- self.sector_size = SECTOR_SIZE
+ self.sector_size = sector_size or 512
self.native_sysroot = native_sysroot
num_real_partitions = len([p for p in self.partitions if not p.no_table])
diff --git a/scripts/lib/wic/plugins/source/bootimg_efi.py b/scripts/lib/wic/plugins/source/bootimg_efi.py
index 430b0a4b023a..864d6898fc9d 100644
--- a/scripts/lib/wic/plugins/source/bootimg_efi.py
+++ b/scripts/lib/wic/plugins/source/bootimg_efi.py
@@ -415,8 +415,9 @@ class BootimgEFIPlugin(SourcePlugin):
label = part.label if part.label else "ESP"
- dosfs_cmd = "mkdosfs -v -n %s -i %s -C %s %d" % \
- (label, part.fsuuid, bootimg, blocks)
+ sector_size = getattr(creator, 'sector_size', 512) or 512
+ dosfs_cmd = "mkdosfs -v -n %s -i %s -S %d -C %s %d" % \
+ (label, part.fsuuid, sector_size, bootimg, blocks)
exec_native_cmd(dosfs_cmd, native_sysroot)
logger.debug("mkdosfs:\n%s" % (str(out)))
diff --git a/scripts/lib/wic/plugins/source/bootimg_pcbios.py b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
index a7cc5d12c620..32edac47fa09 100644
--- a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
+++ b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
@@ -132,7 +132,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
cls._do_prepare_grub(part, cr_workdir, oe_builddir,
kernel_dir, rootfs_dir, native_sysroot)
elif source_params['loader-bios'] == 'syslinux':
- cls._do_prepare_syslinux(part, cr_workdir, bootimg_dir,
+ cls._do_prepare_syslinux(part, creator, cr_workdir, bootimg_dir,
kernel_dir, native_sysroot)
else:
raise WicError("unrecognized bootimg_pcbios loader: %s" % source_params['loader-bios'])
@@ -142,7 +142,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
except KeyError:
# Required by do_install_disk
cls.loader = 'syslinux'
- cls._do_prepare_syslinux(part, cr_workdir, bootimg_dir,
+ cls._do_prepare_syslinux(part, creator, cr_workdir, bootimg_dir,
kernel_dir, native_sysroot)
@classmethod
@@ -240,7 +240,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
cfg.close()
@classmethod
- def _do_prepare_syslinux(cls, part, cr_workdir, bootimg_dir,
+ def _do_prepare_syslinux(cls, part, creator, cr_workdir, bootimg_dir,
kernel_dir, native_sysroot):
"""
Called to do the actual content population for a partition i.e. it
@@ -292,8 +292,9 @@ class BootimgPcbiosPlugin(SourcePlugin):
label = part.label if part.label else "boot"
- dosfs_cmd = "mkdosfs -n %s -i %s -S 512 -C %s %d" % \
- (label, part.fsuuid, bootimg, blocks)
+ sector_size = getattr(creator, 'sector_size', 512) or 512
+ dosfs_cmd = "mkdosfs -n %s -i %s -S %d -C %s %d" % \
+ (label, part.fsuuid, sector_size, bootimg, blocks)
exec_native_cmd(dosfs_cmd, native_sysroot)
mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
diff --git a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
index fdab188db1f8..9195ef5f3184 100644
--- a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
+++ b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
@@ -367,8 +367,9 @@ class IsoImagePlugin(SourcePlugin):
esp_label = source_params.get('esp_label', 'EFIimg')
- dosfs_cmd = 'mkfs.vfat -n \'%s\' -S 512 -C %s %d' \
- % (esp_label, bootimg, blocks)
+ sector_size = getattr(creator, 'sector_size', 512) or 512
+ dosfs_cmd = "mkfs.vfat -n '%s' -S %d -C %s %d" % \
+ (esp_label, sector_size, bootimg, blocks)
exec_native_cmd(dosfs_cmd, native_sysroot)
mmd_cmd = "mmd -i %s ::/EFI" % bootimg
diff --git a/scripts/wic b/scripts/wic
index 9137208f5e8f..0cef84ef630c 100755
--- a/scripts/wic
+++ b/scripts/wic
@@ -376,6 +376,8 @@ def wic_init_parser_create(subparser):
default="direct", help="the wic imager plugin")
subparser.add_argument("--extra-space", type=int, dest="extra_space",
default=0, help="additional free disk space to add to the image")
+ subparser.add_argument("--sector-size", dest="sector_size", type=int, default=512,
+ help="sector size in bytes (default: 512)")
return
@@ -413,6 +415,8 @@ def imgtype(arg):
def wic_init_parser_ls(subparser):
subparser.add_argument("path", type=imgtype,
help="image spec: <image>[:<vfat partition>[<path>]]")
+ subparser.add_argument("--sector-size", dest="sector_size", type=int, default=512,
+ help="sector size in bytes (default: 512)")
subparser.add_argument("-n", "--native-sysroot",
help="path to the native sysroot containing the tools")
subparser.add_argument("-e", "--image-name", dest="image_name",
@@ -433,6 +437,8 @@ def wic_init_parser_cp(subparser):
help="image spec: <image>:<vfat partition>[<path>] or <file>")
subparser.add_argument("dest",
help="image spec: <image>:<vfat partition>[<path>] or <file>")
+ subparser.add_argument("--sector-size", dest="sector_size", type=int, default=512,
+ help="sector size in bytes (default: 512)")
subparser.add_argument("-n", "--native-sysroot",
help="path to the native sysroot containing the tools")
subparser.add_argument("-e", "--image-name", dest="image_name",
@@ -445,6 +451,8 @@ def wic_init_parser_cp(subparser):
def wic_init_parser_rm(subparser):
subparser.add_argument("path", type=imgpathtype,
help="path: <image>:<vfat partition><path>")
+ subparser.add_argument("--sector-size", dest="sector_size", type=int, default=512,
+ help="sector size in bytes (default: 512)")
subparser.add_argument("-n", "--native-sysroot",
help="path to the native sysroot containing the tools")
subparser.add_argument("-r", dest="recursive_delete", action="store_true", default=False,
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 2/2] ufs image class: add
2026-02-16 2:31 [PATCH v3 1/2] wic: re-implement sector-size support Trevor Woerner
@ 2026-02-16 2:31 ` Trevor Woerner
2026-02-16 3:09 ` [OE-core] [PATCH v3 1/2] wic: re-implement sector-size support Bruce Ashfield
1 sibling, 0 replies; 8+ messages in thread
From: Trevor Woerner @ 2026-02-16 2:31 UTC (permalink / raw)
To: openembedded-core; +Cc: Mark Hatle
Add an image class and wks file that demonstrates generating a wic image
with a 4096-byte sector size.
Signed-off-by: Mark Hatle <mark.hatle@kernel.crashing.org>
Signed-off-by: Trevor Woerner <twoerner@gmail.com>
---
changes since v2:
- tested more scenarios and made sure to fix the warning in every case
changes since v1:
- add Mark as a co-creator (sorry for missing this the first time!)
- provide a fix for the following warning:
WARNING: core-image-minimal-1.0-r0 do_image_wic_ufs: Function do_image_wic_ufs doesn't exist
---
meta/classes-recipe/image.bbclass | 2 +-
meta/classes-recipe/image_types_ufs.bbclass | 221 ++++++++++++++++++++
scripts/lib/wic/canned-wks/mkdisk-ufs.wks | 5 +
3 files changed, 227 insertions(+), 1 deletion(-)
create mode 100644 meta/classes-recipe/image_types_ufs.bbclass
create mode 100644 scripts/lib/wic/canned-wks/mkdisk-ufs.wks
diff --git a/meta/classes-recipe/image.bbclass b/meta/classes-recipe/image.bbclass
index 53f1a9dc45b0..97465836c14a 100644
--- a/meta/classes-recipe/image.bbclass
+++ b/meta/classes-recipe/image.bbclass
@@ -18,7 +18,7 @@ inherit populate_sdk_base
IMGCLASSES += "${@['', 'populate_sdk_ext']['linux' in d.getVar("SDK_OS")]}"
IMGCLASSES += "${@bb.utils.contains_any('IMAGE_FSTYPES', 'live iso hddimg', 'image-live', '', d)}"
IMGCLASSES += "${@bb.utils.contains('IMAGE_FSTYPES', 'container', 'image-container', '', d)}"
-IMGCLASSES += "image_types_wic"
+IMGCLASSES += "image_types_wic image_types_ufs"
IMGCLASSES += "rootfs-postcommands"
IMGCLASSES += "image-postinst-intercepts"
IMGCLASSES += "overlayfs-etc"
diff --git a/meta/classes-recipe/image_types_ufs.bbclass b/meta/classes-recipe/image_types_ufs.bbclass
new file mode 100644
index 000000000000..9a984f084289
--- /dev/null
+++ b/meta/classes-recipe/image_types_ufs.bbclass
@@ -0,0 +1,221 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+# The WICUFSVARS variable is used to define the base list of bitbake variables used in wic code
+# variables from this list are written to <image>.env file
+WICUFSVARS ?= "\
+ APPEND \
+ ASSUME_PROVIDED \
+ BBLAYERS \
+ DEPLOY_DIR_IMAGE \
+ FAKEROOTCMD \
+ HOSTTOOLS_DIR \
+ IMAGE_BASENAME \
+ IMAGE_BOOT_FILES \
+ IMAGE_CLASSES \
+ IMAGE_EFI_BOOT_FILES \
+ IMAGE_EXTRA_PARTITION_FILES \
+ IMAGE_LINK_NAME \
+ IMAGE_ROOTFS \
+ IMGDEPLOYDIR \
+ INITRAMFS_FSTYPES \
+ INITRAMFS_IMAGE \
+ INITRAMFS_IMAGE_BUNDLE \
+ INITRAMFS_LINK_NAME \
+ INITRD \
+ INITRD_LIVE \
+ ISODIR \
+ KERNEL_CONSOLE \
+ KERNEL_IMAGETYPE \
+ MACHINE \
+ PSEUDO_INCLUDE_PATHS \
+ RECIPE_SYSROOT_NATIVE \
+ ROOTFS_SIZE \
+ STAGING_DATADIR \
+ STAGING_DIR \
+ STAGING_DIR_HOST \
+ STAGING_LIBDIR \
+ TARGET_SYS \
+"
+
+inherit_defer ${@bb.utils.contains('INITRAMFS_IMAGE_BUNDLE', '1', 'kernel-artifact-names', '', d)}
+
+WKSUFS_FILE ??= "${WKS_FILE}"
+WKSUFS_FILES ?= "${WKSUFS_FILE} ${IMAGE_BASENAME}.wks"
+WKSUFS_SEARCH_PATH ?= "${THISDIR}:${@':'.join('%s/wic' % p for p in '${BBPATH}'.split(':'))}:${@':'.join('%s/scripts/lib/wic/canned-wks' % l for l in '${BBPATH}:${COREBASE}'.split(':'))}"
+WKSUFS_FULL_PATH = "${@wks_search(d.getVar('WKSUFS_FILES').split(), d.getVar('WKSUFS_SEARCH_PATH')) or ''}"
+
+def wks_search(files, search_path):
+ for f in files:
+ if os.path.isabs(f):
+ if os.path.exists(f):
+ return f
+ else:
+ searched = bb.utils.which(search_path, f)
+ if searched:
+ return searched
+
+def wks_checksums(files, search_path):
+ ret = ""
+ for f in files:
+ found, hist = bb.utils.which(search_path, f, history=True)
+ ret = ret + " " + " ".join(h + ":False" for h in hist[:-1])
+ if found:
+ ret = ret + " " + found + ":True"
+ return ret
+
+
+WICUFS_CREATE_EXTRA_ARGS ?= "${WIC_CREATE_EXTRA_ARGS}"
+
+IMAGE_CMD:wic.ufs () {
+ out="${IMGDEPLOYDIR}/${IMAGE_NAME}"
+ build_wic_ufs="${WORKDIR}/build-wic-ufs"
+ tmp_wic_ufs="${WORKDIR}/tmp-wic-ufs"
+ wks="${WKSUFS_FULL_PATH}"
+ if [ -e "$tmp_wic_ufs" ]; then
+ # Ensure we don't have any junk leftover from a previously interrupted
+ # do_image_wic_ufs execution
+ rm -rf "$tmp_wic_ufs"
+ fi
+ if [ -z "$wks" ]; then
+ bbfatal "No kickstart files from WKSUFS_FILES were found: ${WKSUFS_FILES}. Please set WKSUFS_FILE or WKSUFS_FILES appropriately."
+ fi
+ BUILDDIR="${TOPDIR}" PSEUDO_UNLOAD=1 wic create --debug "$wks" --sector-size 4096 --vars "${STAGING_DIR}/${MACHINE}/imgdata/" -e "${IMAGE_BASENAME}-ufs" -o "$build_wic_ufs/" -w "$tmp_wic_ufs" ${WICUFS_CREATE_EXTRA_ARGS}
+
+ # look to see if the user specifies a custom imager
+ IMAGER=direct
+ eval set -- "${WICUFS_CREATE_EXTRA_ARGS} --"
+ while [ 1 ]; do
+ case "$1" in
+ --imager|-i)
+ shift
+ IMAGER=$1
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+ shift
+ done
+ mv "$build_wic_ufs/$(basename "${wks%.wks}")"*.${IMAGER} "$out.wic.ufs"
+}
+IMAGE_CMD:wic.ufs[vardepsexclude] = "WKSUFS_FULL_PATH WKSUFS_FILES TOPDIR"
+SPDX_IMAGE_PURPOSE:wic.ufs = "diskImage"
+do_image_wic_ufs[cleandirs] = "${WORKDIR}/build-wic-ufs"
+
+# Rebuild when the wks file or vars in WICUFSVARS change
+USING_WIC_UFS = "${@bb.utils.contains_any('IMAGE_FSTYPES', 'wic.ufs ' + ' '.join('wic.ufs.%s' % c for c in '${CONVERSIONTYPES}'.split()), '1', '', d)}"
+WKSUFS_FILE_CHECKSUM = "${@wks_checksums(d.getVar('WKSUFS_FILES').split(), d.getVar('WKSUFS_SEARCH_PATH')) if '${USING_WIC_UFS}' else ''}"
+do_image_wic_ufs[file-checksums] += "${WKSUFS_FILE_CHECKSUM}"
+do_image_wic_ufs[depends] += "${@' '.join('%s-native:do_populate_sysroot' % r for r in ('parted', 'gptfdisk', 'dosfstools', 'mtools'))}"
+
+# We ensure all artfacts are deployed (e.g virtual/bootloader)
+do_image_wic_ufs[recrdeptask] += "do_deploy"
+do_image_wic_ufs[deptask] += "do_image_complete"
+
+WKSUFS_FILE_DEPENDS_DEFAULT = '${@bb.utils.contains_any("BUILD_ARCH", [ 'x86_64', 'i686' ], "syslinux-native", "",d)}'
+WKSUFS_FILE_DEPENDS_DEFAULT += "bmaptool-native cdrtools-native btrfs-tools-native squashfs-tools-native e2fsprogs-native erofs-utils-native"
+# Unified kernel images need objcopy
+WKSUFS_FILE_DEPENDS_DEFAULT += "virtual/cross-binutils"
+WKSUFS_FILE_DEPENDS_BOOTLOADERS = ""
+WKSUFS_FILE_DEPENDS_BOOTLOADERS:aarch64 = "grub-efi systemd-boot"
+WKSUFS_FILE_DEPENDS_BOOTLOADERS:arm = "systemd-boot"
+WKSUFS_FILE_DEPENDS_BOOTLOADERS:x86 = "syslinux grub-efi systemd-boot"
+WKSUFS_FILE_DEPENDS_BOOTLOADERS:x86-64 = "syslinux grub-efi systemd-boot"
+WKSUFS_FILE_DEPENDS_BOOTLOADERS:x86-x32 = "syslinux grub-efi"
+
+WKSUFS_FILE_DEPENDS ??= "${WKSUFS_FILE_DEPENDS_DEFAULT} ${WKSUFS_FILE_DEPENDS_BOOTLOADERS}"
+
+DEPENDS += "${@ '${WKSUFS_FILE_DEPENDS}' if d.getVar('USING_WIC_UFS') else '' }"
+
+python do_write_wksufs_template () {
+ """Write out expanded template contents to WKSUFS_FULL_PATH."""
+ import re
+
+ template_body = d.getVar('_WKSUFS_TEMPLATE')
+
+ # Remove any remnant variable references left behind by the expansion
+ # due to undefined variables
+ expand_var_regexp = re.compile(r"\${[^{}@\n\t :]+}")
+ while True:
+ new_body = re.sub(expand_var_regexp, '', template_body)
+ if new_body == template_body:
+ break
+ else:
+ template_body = new_body
+
+ wks_file = d.getVar('WKSUFS_FULL_PATH')
+ with open(wks_file, 'w') as f:
+ f.write(template_body)
+ f.close()
+ # Copy the finalized wks file to the deploy directory for later use
+ depdir = d.getVar('IMGDEPLOYDIR')
+ basename = d.getVar('IMAGE_BASENAME') + '-ufs'
+ bb.utils.copyfile(wks_file, "%s/%s" % (depdir, basename + '-' + os.path.basename(wks_file)))
+}
+
+do_flush_pseudodb() {
+ ${FAKEROOTENV} ${FAKEROOTCMD} -S
+}
+
+python () {
+ if d.getVar('USING_WIC_UFS'):
+ wksufs_file_u = d.getVar('WKSUFS_FULL_PATH', False)
+ wksufs_file = d.expand(wksufs_file_u)
+ base, ext = os.path.splitext(wksufs_file)
+ if ext == '.in' and os.path.exists(wksufs_file):
+ wksufs_out_file = os.path.join(d.getVar('WORKDIR'), os.path.basename(base))
+ d.setVar('WKSUFS_FULL_PATH', wksufs_out_file)
+ d.setVar('WKSUFS_TEMPLATE_PATH', wksufs_file_u)
+ d.setVar('WKSUFS_FILE_CHECKSUM', '${WKSUFS_TEMPLATE_PATH}:True')
+
+ # We need to re-parse each time the file changes, and bitbake
+ # needs to be told about that explicitly.
+ bb.parse.mark_dependency(d, wksufs_file)
+
+ try:
+ with open(wksufs_file, 'r') as f:
+ body = f.read()
+ except (IOError, OSError) as exc:
+ pass
+ else:
+ # Previously, I used expandWithRefs to get the dependency list
+ # and add it to WICUFSVARS, but there's no point re-parsing the
+ # file in process_wks_template as well, so just put it in
+ # a variable and let the metadata deal with the deps.
+ d.setVar('_WKSUFS_TEMPLATE', body)
+ bb.build.addtask('do_write_wksufs_template', 'do_image_wic_ufs', 'do_image', d)
+ bb.build.addtask('do_image_wic_ufs', 'do_image_complete', 'do_image_wic', d)
+}
+
+#
+# Write environment variables used by wic
+# to tmp/sysroots/<machine>/imgdata/<image>-ufs.env
+#
+python do_rootfs_wicufsenv () {
+ wicufsvars = d.getVar('WICUFSVARS')
+ if not wicufsvars:
+ return
+
+ stdir = d.getVar('STAGING_DIR')
+ outdir = os.path.join(stdir, d.getVar('MACHINE'), 'imgdata')
+ bb.utils.mkdirhier(outdir)
+ basename = d.getVar('IMAGE_BASENAME') + '-ufs'
+ with open(os.path.join(outdir, basename) + '.env', 'w') as envf:
+ for var in wicufsvars.split():
+ value = d.getVar(var)
+ if value:
+ envf.write('%s="%s"\n' % (var, value.strip()))
+ envf.close()
+ # Copy .env file to deploy directory for later use with stand alone wic
+ depdir = d.getVar('IMGDEPLOYDIR')
+ bb.utils.copyfile(os.path.join(outdir, basename) + '.env', os.path.join(depdir, basename) + '.env')
+}
+addtask do_flush_pseudodb after do_rootfs before do_image do_image_qa
+addtask do_rootfs_wicufsenv after do_image before do_image_wic_ufs
+do_rootfs_wicufsenv[vardeps] += "${WICUFSVARS}"
+do_rootfs_wicufsenv[prefuncs] = 'set_image_size'
diff --git a/scripts/lib/wic/canned-wks/mkdisk-ufs.wks b/scripts/lib/wic/canned-wks/mkdisk-ufs.wks
new file mode 100644
index 000000000000..580f0a2045de
--- /dev/null
+++ b/scripts/lib/wic/canned-wks/mkdisk-ufs.wks
@@ -0,0 +1,5 @@
+bootloader --ptable msdos
+
+part /boot --source rootfs --fstype=vfat --label boot --change-directory boot/
+part / --source rootfs --fstype=ext4 --label root --exclude-path boot/
+part swap --fstype=swap --label swap --size 1M
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [OE-core] [PATCH v3 1/2] wic: re-implement sector-size support
2026-02-16 2:31 [PATCH v3 1/2] wic: re-implement sector-size support Trevor Woerner
2026-02-16 2:31 ` [PATCH v3 2/2] ufs image class: add Trevor Woerner
@ 2026-02-16 3:09 ` Bruce Ashfield
2026-02-16 15:37 ` Trevor Woerner
1 sibling, 1 reply; 8+ messages in thread
From: Bruce Ashfield @ 2026-02-16 3:09 UTC (permalink / raw)
To: twoerner; +Cc: openembedded-core
[-- Attachment #1: Type: text/plain, Size: 31551 bytes --]
On Sun, Feb 15, 2026 at 9:32 PM Trevor Woerner via lists.openembedded.org
<twoerner=gmail.com@lists.openembedded.org> wrote:
> The previous implementation to add variable sector-size support:
> - required the variable WIC_SECTOR_SIZE either be defined in a
> configuration file or be defined in a --vars file
> - this means that every invocation of "wic ls", "wic cp", or "wic rm"
> needed this variable defined (config or --vars)
> - required the user to create separate *wks files for every sector size
> they wanted to use
> - required the user to specify the mkfs-extraopts by hand to specify the
> correct sector size: e.g.
> bootloader --ptable gpt
> part --fstype ext4 --source rootfs --label rofs-a --mkfs-extraopts
> "-b 4096"
> part --fstype ext4 --source rootfs --use-uuid --mkfs-extraopts "-b
> 4096"
> - specifying --mkfs-extraopts replaces the defaults with the
> user-supplied values
> - only provided details to support using variable sector-sizes with
> ext[234] filesystems
> - it would not be possible to generate images with different sector
> sizes in the same build since the configuration and *wks files would
> need to change and the build re-run for each size
>
> Update the sector-size handling so that:
> - the sector-size will now be provided on the cmdline to the "wic ls",
> "wic cp", "wic rm", and "wic create" commands: default = 512
> - this means the configuration and/or --vars file does not need to be
> changed in order to perform those operations on images with different
> sector sizes
> - support is provided implicitly for mkdosfs and ext[234] partitions
> - the user no longer needs to know and supply the sector-size magic in
> --mkfs-extraopts (thereby clobbering the other defaults)
>
It wasn't clear to me when scanning the patch. For configuration
files with a sector size, is it now completely ignored ?
Apologies if I missed where existing configs were used to prime
the parameters to the functions.
Bruce
>
> AI-Generated: codex/gpt-5.1-codex-max
> Signed-off-by: Trevor Woerner <twoerner@gmail.com>
> ---
> changes since v2:
> - none
>
> changes since v1:
> - none
> ---
> meta/lib/oeqa/selftest/cases/wic.py | 39 ++++---------
> scripts/lib/wic/engine.py | 45 +++++++--------
> scripts/lib/wic/help.py | 23 +++++---
> scripts/lib/wic/partition.py | 55 +++++++++++++++++--
> scripts/lib/wic/plugins/imager/direct.py | 18 ++----
> scripts/lib/wic/plugins/source/bootimg_efi.py | 5 +-
> .../lib/wic/plugins/source/bootimg_pcbios.py | 11 ++--
> .../wic/plugins/source/isoimage_isohybrid.py | 5 +-
> scripts/wic | 8 +++
> 9 files changed, 125 insertions(+), 84 deletions(-)
>
> diff --git a/meta/lib/oeqa/selftest/cases/wic.py
> b/meta/lib/oeqa/selftest/cases/wic.py
> index ecaee5a29144..7ad61fa700f7 100644
> --- a/meta/lib/oeqa/selftest/cases/wic.py
> +++ b/meta/lib/oeqa/selftest/cases/wic.py
> @@ -935,33 +935,22 @@ bootloader --ptable gpt""")
> finally:
> os.remove(wks_file)
>
> - def test_wic_sector_size(self):
> - """Test generation image sector size"""
> -
> + def test_wic_sector_size_cli(self):
> + """Test sector size handling via CLI option."""
> +
> oldpath = os.environ['PATH']
> os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
>
> try:
> - # Add WIC_SECTOR_SIZE into config
> - config = 'WIC_SECTOR_SIZE = "4096"\n'\
> - 'WICVARS:append = " WIC_SECTOR_SIZE"\n'
> - self.append_config(config)
> bitbake('core-image-minimal')
>
> - # Check WIC_SECTOR_SIZE apply to bitbake variable
> - wic_sector_size_str = get_bb_var('WIC_SECTOR_SIZE',
> 'core-image-minimal')
> - wic_sector_size = int(wic_sector_size_str)
> - self.assertEqual(4096, wic_sector_size)
> -
> - self.logger.info("Test wic_sector_size: %d \n" %
> wic_sector_size)
> -
> with NamedTemporaryFile("w", suffix=".wks") as wks:
> wks.writelines(
> ['bootloader --ptable gpt\n',
> - 'part --fstype ext4 --source rootfs --label rofs-a
> --mkfs-extraopts "-b 4096"\n',
> - 'part --fstype ext4 --source rootfs --use-uuid
> --mkfs-extraopts "-b 4096"\n'])
> + 'part --fstype ext4 --source rootfs --label
> rofs-a\n',
> + 'part --fstype ext4 --source rootfs --use-uuid\n'])
> wks.flush()
> - cmd = "wic create %s -e core-image-minimal -o %s" % (
> wks.name, self.resultdir)
> + cmd = "wic create %s -e core-image-minimal -o %s
> --sector-size 4096" % (wks.name, self.resultdir)
> runCmd(cmd)
> wksname = os.path.splitext(os.path.basename(wks.name))[0]
> images = glob(os.path.join(self.resultdir, "%s-*direct" %
> wksname))
> @@ -969,24 +958,18 @@ bootloader --ptable gpt""")
>
> sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
> # list partitions
> - result = runCmd("wic ls %s -n %s" % (images[0], sysroot))
> + result = runCmd("wic ls %s -n %s --sector-size 4096" %
> (images[0], sysroot))
> self.assertEqual(3, len(result.output.split('\n')))
>
> - # verify partition size with wic
> - res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m %s unit
> b p" % (wic_sector_size, images[0]),
> + # verify partition size with parted output
> + res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m %s unit
> b p" % (4096, images[0]),
> stderr=subprocess.PIPE)
>
> - # parse parted output which looks like this:
> - # BYT;\n
> - #
> /var/tmp/wic/build/tmpgjzzefdd-202410281021-sda.direct:78569472B:file:4096:4096:gpt::;\n
> - # 1:139264B:39284735B:39145472B:ext4:rofs-a:;\n
> - # 2:39284736B:78430207B:39145472B:ext4:primary:;\n
> disk_info = res.output.splitlines()[1]
> - # Check sector sizes
> sector_size_logical = int(disk_info.split(":")[3])
> sector_size_physical = int(disk_info.split(":")[4])
> - self.assertEqual(wic_sector_size, sector_size_logical,
> "Logical sector size is not %d." % wic_sector_size)
> - self.assertEqual(wic_sector_size, sector_size_physical,
> "Physical sector size is not %d." % wic_sector_size)
> + self.assertEqual(4096, sector_size_logical, "Logical sector
> size is not 4096.")
> + self.assertEqual(4096, sector_size_physical, "Physical sector
> size is not 4096.")
>
> finally:
> os.environ['PATH'] = oldpath
> diff --git a/scripts/lib/wic/engine.py b/scripts/lib/wic/engine.py
> index 9d596be3a723..7753f431f91d 100644
> --- a/scripts/lib/wic/engine.py
> +++ b/scripts/lib/wic/engine.py
> @@ -224,7 +224,7 @@ def wic_list(args, scripts_path):
>
>
> class Disk:
> - def __init__(self, imagepath, native_sysroot, fstypes=('fat', 'ext')):
> + def __init__(self, imagepath, native_sysroot, fstypes=('fat', 'ext'),
> sector_size=512):
> self.imagepath = imagepath
> self.native_sysroot = native_sysroot
> self.fstypes = fstypes
> @@ -233,16 +233,7 @@ class Disk:
> self._lsector_size = None
> self._psector_size = None
> self._ptable_format = None
> -
> - # define sector size
> - sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
> - if sector_size_str is not None:
> - try:
> - self.sector_size = int(sector_size_str)
> - except ValueError:
> - self.sector_size = None
> - else:
> - self.sector_size = None
> + self.sector_size = sector_size
>
> # find parted
> # read paths from $PATH environment variable
> @@ -271,7 +262,7 @@ class Disk:
> if self._partitions is None:
> self._partitions = OrderedDict()
>
> - if self.sector_size is not None:
> + if self.sector_size:
> out = exec_cmd("export PARTED_SECTOR_SIZE=%d; %s -sm %s
> unit B print" % \
> (self.sector_size, self.parted,
> self.imagepath), True)
> else:
> @@ -312,11 +303,15 @@ class Disk:
> raise WicError("Partition %s is not in the image" % pnum)
> part = self.partitions[pnum]
> # check if fstype is supported
> + # NOTE: parted is unable to identify dos-type partitions with a
> 4k sector-size
> + # if the type is empty and a non-default sector size is
> used, assume 'fat'
> + # fdisk identifies them without issue
> + part_fstype = part.fstype if part.fstype or self.sector_size ==
> 512 else 'fat'
> for fstype in self.fstypes:
> - if part.fstype.startswith(fstype):
> + if part_fstype.startswith(fstype):
> break
> else:
> - raise WicError("Not supported fstype: {}".format(part.fstype))
> + raise WicError("Not supported fstype: {}".format(part_fstype))
> if pnum not in self._partimages:
> tmpf = tempfile.NamedTemporaryFile(prefix="wic-part")
> dst_fname = tmpf.name
> @@ -586,8 +581,9 @@ class Disk:
> label = part.get("name")
> label_str = "-n {}".format(label) if label
> else ''
>
> - cmd = "{} {} -C {} {}".format(self.mkdosfs,
> label_str, partfname,
> - part['size'])
> + sector_str = "-S {}".format(self.sector_size)
> if self.sector_size else ''
> + cmd = "{} {} {} -C {}
> {}".format(self.mkdosfs, label_str, sector_str, partfname,
> + part['size'])
> exec_cmd(cmd)
> # copy content from the temporary directory
> to the new partition
> cmd = "{} -snompi {} {}/*
> ::".format(self.mcopy, partfname, tmpdir)
> @@ -609,14 +605,19 @@ class Disk:
>
> def wic_ls(args, native_sysroot):
> """List contents of partitioned image or vfat partition."""
> - disk = Disk(args.path.image, native_sysroot)
> + disk = Disk(args.path.image, native_sysroot,
> sector_size=args.sector_size)
> if not args.path.part:
> if disk.partitions:
> print('Num Start End Size Fstype')
> for part in disk.partitions.values():
> + # size values are in bytes from parted; convert to
> sectors if a custom sector size was requested
> + display_size = part.size
> + if args.sector_size and args.sector_size !=
> disk._lsector_size:
> + display_size = part.size // args.sector_size
> print("{:2d} {:12d} {:12d} {:12d} {}".format(\
> - part.pnum, part.start, part.end,
> - part.size, part.fstype))
> + part.pnum, part.start // args.sector_size,
> + part.end // args.sector_size,
> + display_size, part.fstype))
> else:
> path = args.path.path or '/'
> print(disk.dir(args.path.part, path))
> @@ -627,9 +628,9 @@ def wic_cp(args, native_sysroot):
> partitioned image.
> """
> if isinstance(args.dest, str):
> - disk = Disk(args.src.image, native_sysroot)
> + disk = Disk(args.src.image, native_sysroot,
> sector_size=args.sector_size)
> else:
> - disk = Disk(args.dest.image, native_sysroot)
> + disk = Disk(args.dest.image, native_sysroot,
> sector_size=args.sector_size)
> disk.copy(args.src, args.dest)
>
>
> @@ -638,7 +639,7 @@ def wic_rm(args, native_sysroot):
> Remove files or directories from the vfat partition of
> partitioned image.
> """
> - disk = Disk(args.path.image, native_sysroot)
> + disk = Disk(args.path.image, native_sysroot,
> sector_size=args.sector_size)
> disk.remove(args.path.part, args.path.path, args.recursive_delete)
>
> def wic_write(args, native_sysroot):
> diff --git a/scripts/lib/wic/help.py b/scripts/lib/wic/help.py
> index 6b49a67de938..5d7c40456a80 100644
> --- a/scripts/lib/wic/help.py
> +++ b/scripts/lib/wic/help.py
> @@ -118,7 +118,7 @@ wic_create_usage = """
> usage: wic create <wks file or image name> [-o <DIRNAME> | --outdir
> <DIRNAME>]
> [-e | --image-name] [-s, --skip-build-check] [-D, --debug]
> [-r, --rootfs-dir] [-b, --bootimg-dir]
> - [-k, --kernel-dir] [-n, --native-sysroot] [-f, --build-rootfs]
> + [-k, --kernel-dir] [-n, --native-sysroot] [--sector-size
> <bytes>] [-f, --build-rootfs]
> [-c, --compress-with] [-m, --bmap]
>
> This command creates an OpenEmbedded image based on the 'OE kickstart
> @@ -139,13 +139,16 @@ SYNOPSIS
> wic create <wks file or image name> [-o <DIRNAME> | --outdir
> <DIRNAME>]
> [-e | --image-name] [-s, --skip-build-check] [-D, --debug]
> [-r, --rootfs-dir] [-b, --bootimg-dir]
> - [-k, --kernel-dir] [-n, --native-sysroot] [-f, --build-rootfs]
> + [-k, --kernel-dir] [-n, --native-sysroot] [--sector-size <bytes>]
> [-f, --build-rootfs]
> [-c, --compress-with] [-m, --bmap] [--no-fstab-update]
>
> DESCRIPTION
> This command creates an OpenEmbedded image based on the 'OE
> kickstart commands' found in the <wks file>.
>
> + Use the --sector-size option to select the sector size (in bytes)
> + used for partition layout calculations (default is 512).
> +
> In order to do this, wic needs to know the locations of the
> various build artifacts required to build the image.
>
> @@ -278,7 +281,7 @@ wic_ls_usage = """
>
> List content of a partitioned image
>
> - usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot <path>]
> + usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot <path>]
> [--sector-size <bytes>]
>
> This command outputs either list of image partitions or directory
> contents
> of vfat and ext* partitions.
> @@ -296,7 +299,7 @@ SYNOPSIS
> wic ls <image>
> wic ls <image>:<vfat or ext* partition>
> wic ls <image>:<vfat or ext* partition><path>
> - wic ls <image>:<vfat or ext* partition><path> --native-sysroot <path>
> + wic ls <image>:<vfat or ext* partition><path> --native-sysroot <path>
> [--sector-size <bytes>]
>
> DESCRIPTION
> This command lists either partitions of the image or directory
> contents
> @@ -336,6 +339,8 @@ DESCRIPTION
>
> The -n option is used to specify the path to the native sysroot
> containing the tools(parted and mtools) to use.
> + The --sector-size option sets the sector size used for partition math
> + (default is 512 bytes).
>
> """
>
> @@ -343,7 +348,7 @@ wic_cp_usage = """
>
> Copy files and directories to/from the vfat or ext* partition
>
> - usage: wic cp <src> <dest> [--native-sysroot <path>]
> + usage: wic cp <src> <dest> [--native-sysroot <path>] [--sector-size
> <bytes>]
>
> source/destination image in format <image>:<partition>[<path>]
>
> @@ -364,7 +369,7 @@ SYNOPSIS
> wic cp <src> <dest>:<partition>
> wic cp <src>:<partition> <dest>
> wic cp <src> <dest-image>:<partition><path>
> - wic cp <src> <dest-image>:<partition><path> --native-sysroot <path>
> + wic cp <src> <dest-image>:<partition><path> --native-sysroot <path>
> [--sector-size <bytes>]
>
> DESCRIPTION
> This command copies files or directories either
> @@ -408,13 +413,15 @@ DESCRIPTION
>
> The -n option is used to specify the path to the native sysroot
> containing the tools(parted and mtools) to use.
> + The --sector-size option sets the sector size used for partition math
> + (default is 512 bytes).
> """
>
> wic_rm_usage = """
>
> Remove files or directories from the vfat or ext* partitions
>
> - usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
> + usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
> [--sector-size <bytes>]
>
> This command removes files or directories from the vfat or ext*
> partitions of
> the partitioned image.
> @@ -466,6 +473,8 @@ DESCRIPTION
>
> The -n option is used to specify the path to the native sysroot
> containing the tools(parted and mtools) to use.
> + The --sector-size option sets the sector size used for partition math
> + (default is 512 bytes).
>
> The -r option is used to remove directories and their contents
> recursively,this only applies to ext* partition.
> diff --git a/scripts/lib/wic/partition.py b/scripts/lib/wic/partition.py
> index 8fed686e903e..df6e3271649b 100644
> --- a/scripts/lib/wic/partition.py
> +++ b/scripts/lib/wic/partition.py
> @@ -65,6 +65,50 @@ class Partition():
>
> self.lineno = lineno
> self.source_file = ""
> + self.sector_size = 512
> +
> + def _mkdosfs_extraopts(self):
> + """
> + Build mkdosfs extra options ensuring the CLI sector size is
> applied.
> + """
> + extraopts = self.mkfs_extraopts or ''
> + tokens = []
> + skip_next = False
> + for tok in extraopts.split():
> + if skip_next:
> + skip_next = False
> + continue
> + if tok == '-S':
> + skip_next = True
> + continue
> + if tok.startswith('-S'):
> + continue
> + tokens.append(tok)
> + tokens.extend(['-S', str(self.sector_size)])
> + return ' '.join(tokens).strip()
> +
> + def _mkfs_ext_extraopts(self, base_opts):
> + """
> + Build mkfs.ext* extra options ensuring the CLI sector size is
> applied.
> + """
> + extraopts = self.mkfs_extraopts or base_opts
> + # Only add an explicit block size when a non-default sector size
> is requested.
> + if self.sector_size and self.sector_size != 512:
> + tokens = []
> + skip_next = False
> + for tok in extraopts.split():
> + if skip_next:
> + skip_next = False
> + continue
> + if tok == '-b':
> + skip_next = True
> + continue
> + if tok.startswith('-b'):
> + continue
> + tokens.append(tok)
> + tokens.extend(['-b', str(self.sector_size)])
> + return ' '.join(tokens).strip()
> + return extraopts
>
> def get_extra_block_count(self, current_blocks):
> """
> @@ -138,6 +182,8 @@ class Partition():
> Prepare content for individual partitions, depending on
> partition command parameters.
> """
> + # capture the sector size requested on the CLI for mkdosfs
> invocations
> + self.sector_size = getattr(creator, 'sector_size', 512) or 512
> self.updated_fstab_path = updated_fstab_path
> if self.updated_fstab_path and not (self.fstype.startswith("ext")
> or self.fstype == "msdos"):
> self.update_fstab_in_rootfs = True
> @@ -293,7 +339,7 @@ class Partition():
> with open(rootfs, 'w') as sparse:
> os.ftruncate(sparse.fileno(), rootfs_size * 1024)
>
> - extraopts = self.mkfs_extraopts or "-F -i 8192"
> + extraopts = self._mkfs_ext_extraopts("-F -i 8192")
>
> # use hash_seed to generate reproducible ext4 images
> (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts, pseudo)
> @@ -401,7 +447,7 @@ class Partition():
>
> size_str = ""
>
> - extraopts = self.mkfs_extraopts or '-S 512'
> + extraopts = self._mkdosfs_extraopts()
>
> dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
> (label_str, self.fsuuid, size_str, extraopts, rootfs,
> @@ -452,7 +498,7 @@ class Partition():
> with open(rootfs, 'w') as sparse:
> os.ftruncate(sparse.fileno(), size * 1024)
>
> - extraopts = self.mkfs_extraopts or "-i 8192"
> + extraopts = self._mkfs_ext_extraopts("-i 8192")
>
> # use hash_seed to generate reproducible ext4 images
> (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts, None)
> @@ -498,7 +544,7 @@ class Partition():
>
> size_str = ""
>
> - extraopts = self.mkfs_extraopts or '-S 512'
> + extraopts = self._mkdosfs_extraopts()
>
> dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
> (label_str, self.fsuuid, extraopts, size_str, rootfs,
> @@ -559,4 +605,3 @@ class Partition():
> logger.warn("%s Inodes (of size %d) are too small." %
> (get_err_str(self), size))
> break
> -
> diff --git a/scripts/lib/wic/plugins/imager/direct.py
> b/scripts/lib/wic/plugins/imager/direct.py
> index ad922cfbf122..3adc6eee6280 100644
> --- a/scripts/lib/wic/plugins/imager/direct.py
> +++ b/scripts/lib/wic/plugins/imager/direct.py
> @@ -67,6 +67,7 @@ class DirectPlugin(ImagerPlugin):
> self._image = None
> self.ptable_format = self.ks.bootloader.ptable
> self.parts = self.ks.partitions
> + self.sector_size = options.sector_size or 512
>
> # as a convenience, set source to the boot partition source
> # instead of forcing it to be set via bootloader --source
> @@ -78,7 +79,7 @@ class DirectPlugin(ImagerPlugin):
> image_path = self._full_path(self.workdir, self.parts[0].disk,
> "direct")
> self._image = PartitionedImage(image_path, self.ptable_format,
> self.ks.bootloader.diskid,
> self.parts, self.native_sysroot,
> - options.extra_space)
> + options.extra_space,
> self.sector_size)
>
> def setup_workdir(self, workdir):
> if workdir:
> @@ -294,15 +295,13 @@ MBR_OVERHEAD = 1
> # Overhead of the GPT partitioning scheme
> GPT_OVERHEAD = 34
>
> -# Size of a sector in bytes
> -SECTOR_SIZE = 512
> -
> class PartitionedImage():
> """
> Partitioned image in a file.
> """
>
> - def __init__(self, path, ptable_format, disk_id, partitions,
> native_sysroot=None, extra_space=0):
> + def __init__(self, path, ptable_format, disk_id, partitions,
> native_sysroot=None, extra_space=0,
> + sector_size=512):
> self.path = path # Path to the image file
> self.numpart = 0 # Number of allocated partitions
> self.realpart = 0 # Number of partitions in the partition table
> @@ -332,14 +331,7 @@ class PartitionedImage():
> self.partitions = partitions
> self.partimages = []
> # Size of a sector used in calculations
> - sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
> - if sector_size_str is not None:
> - try:
> - self.sector_size = int(sector_size_str)
> - except ValueError:
> - self.sector_size = SECTOR_SIZE
> - else:
> - self.sector_size = SECTOR_SIZE
> + self.sector_size = sector_size or 512
>
> self.native_sysroot = native_sysroot
> num_real_partitions = len([p for p in self.partitions if not
> p.no_table])
> diff --git a/scripts/lib/wic/plugins/source/bootimg_efi.py
> b/scripts/lib/wic/plugins/source/bootimg_efi.py
> index 430b0a4b023a..864d6898fc9d 100644
> --- a/scripts/lib/wic/plugins/source/bootimg_efi.py
> +++ b/scripts/lib/wic/plugins/source/bootimg_efi.py
> @@ -415,8 +415,9 @@ class BootimgEFIPlugin(SourcePlugin):
>
> label = part.label if part.label else "ESP"
>
> - dosfs_cmd = "mkdosfs -v -n %s -i %s -C %s %d" % \
> - (label, part.fsuuid, bootimg, blocks)
> + sector_size = getattr(creator, 'sector_size', 512) or 512
> + dosfs_cmd = "mkdosfs -v -n %s -i %s -S %d -C %s %d" % \
> + (label, part.fsuuid, sector_size, bootimg, blocks)
> exec_native_cmd(dosfs_cmd, native_sysroot)
> logger.debug("mkdosfs:\n%s" % (str(out)))
>
> diff --git a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> index a7cc5d12c620..32edac47fa09 100644
> --- a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> +++ b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> @@ -132,7 +132,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> cls._do_prepare_grub(part, cr_workdir, oe_builddir,
> kernel_dir, rootfs_dir, native_sysroot)
> elif source_params['loader-bios'] == 'syslinux':
> - cls._do_prepare_syslinux(part, cr_workdir, bootimg_dir,
> + cls._do_prepare_syslinux(part, creator, cr_workdir,
> bootimg_dir,
> kernel_dir, native_sysroot)
> else:
> raise WicError("unrecognized bootimg_pcbios loader: %s" %
> source_params['loader-bios'])
> @@ -142,7 +142,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> except KeyError:
> # Required by do_install_disk
> cls.loader = 'syslinux'
> - cls._do_prepare_syslinux(part, cr_workdir, bootimg_dir,
> + cls._do_prepare_syslinux(part, creator, cr_workdir,
> bootimg_dir,
> kernel_dir, native_sysroot)
>
> @classmethod
> @@ -240,7 +240,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> cfg.close()
>
> @classmethod
> - def _do_prepare_syslinux(cls, part, cr_workdir, bootimg_dir,
> + def _do_prepare_syslinux(cls, part, creator, cr_workdir, bootimg_dir,
> kernel_dir, native_sysroot):
> """
> Called to do the actual content population for a partition i.e. it
> @@ -292,8 +292,9 @@ class BootimgPcbiosPlugin(SourcePlugin):
>
> label = part.label if part.label else "boot"
>
> - dosfs_cmd = "mkdosfs -n %s -i %s -S 512 -C %s %d" % \
> - (label, part.fsuuid, bootimg, blocks)
> + sector_size = getattr(creator, 'sector_size', 512) or 512
> + dosfs_cmd = "mkdosfs -n %s -i %s -S %d -C %s %d" % \
> + (label, part.fsuuid, sector_size, bootimg, blocks)
> exec_native_cmd(dosfs_cmd, native_sysroot)
>
> mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
> diff --git a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> index fdab188db1f8..9195ef5f3184 100644
> --- a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> +++ b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> @@ -367,8 +367,9 @@ class IsoImagePlugin(SourcePlugin):
>
> esp_label = source_params.get('esp_label', 'EFIimg')
>
> - dosfs_cmd = 'mkfs.vfat -n \'%s\' -S 512 -C %s %d' \
> - % (esp_label, bootimg, blocks)
> + sector_size = getattr(creator, 'sector_size', 512) or 512
> + dosfs_cmd = "mkfs.vfat -n '%s' -S %d -C %s %d" % \
> + (esp_label, sector_size, bootimg, blocks)
> exec_native_cmd(dosfs_cmd, native_sysroot)
>
> mmd_cmd = "mmd -i %s ::/EFI" % bootimg
> diff --git a/scripts/wic b/scripts/wic
> index 9137208f5e8f..0cef84ef630c 100755
> --- a/scripts/wic
> +++ b/scripts/wic
> @@ -376,6 +376,8 @@ def wic_init_parser_create(subparser):
> default="direct", help="the wic imager plugin")
> subparser.add_argument("--extra-space", type=int, dest="extra_space",
> default=0, help="additional free disk space to add
> to the image")
> + subparser.add_argument("--sector-size", dest="sector_size", type=int,
> default=512,
> + help="sector size in bytes (default: 512)")
> return
>
>
> @@ -413,6 +415,8 @@ def imgtype(arg):
> def wic_init_parser_ls(subparser):
> subparser.add_argument("path", type=imgtype,
> help="image spec: <image>[:<vfat
> partition>[<path>]]")
> + subparser.add_argument("--sector-size", dest="sector_size", type=int,
> default=512,
> + help="sector size in bytes (default: 512)")
> subparser.add_argument("-n", "--native-sysroot",
> help="path to the native sysroot containing the
> tools")
> subparser.add_argument("-e", "--image-name", dest="image_name",
> @@ -433,6 +437,8 @@ def wic_init_parser_cp(subparser):
> help="image spec: <image>:<vfat
> partition>[<path>] or <file>")
> subparser.add_argument("dest",
> help="image spec: <image>:<vfat
> partition>[<path>] or <file>")
> + subparser.add_argument("--sector-size", dest="sector_size", type=int,
> default=512,
> + help="sector size in bytes (default: 512)")
> subparser.add_argument("-n", "--native-sysroot",
> help="path to the native sysroot containing the
> tools")
> subparser.add_argument("-e", "--image-name", dest="image_name",
> @@ -445,6 +451,8 @@ def wic_init_parser_cp(subparser):
> def wic_init_parser_rm(subparser):
> subparser.add_argument("path", type=imgpathtype,
> help="path: <image>:<vfat partition><path>")
> + subparser.add_argument("--sector-size", dest="sector_size", type=int,
> default=512,
> + help="sector size in bytes (default: 512)")
> subparser.add_argument("-n", "--native-sysroot",
> help="path to the native sysroot containing the
> tools")
> subparser.add_argument("-r", dest="recursive_delete",
> action="store_true", default=False,
> --
> 2.51.0
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#231176):
> https://lists.openembedded.org/g/openembedded-core/message/231176
> Mute This Topic: https://lists.openembedded.org/mt/117833550/1050810
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [
> bruce.ashfield@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
>
--
- Thou shalt not follow the NULL pointer, for chaos and madness await thee
at its end
- "Use the force Harry" - Gandalf, Star Trek II
[-- Attachment #2: Type: text/html, Size: 39603 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [OE-core] [PATCH v3 1/2] wic: re-implement sector-size support
2026-02-16 3:09 ` [OE-core] [PATCH v3 1/2] wic: re-implement sector-size support Bruce Ashfield
@ 2026-02-16 15:37 ` Trevor Woerner
2026-02-16 16:01 ` Bruce Ashfield
0 siblings, 1 reply; 8+ messages in thread
From: Trevor Woerner @ 2026-02-16 15:37 UTC (permalink / raw)
To: Bruce Ashfield; +Cc: openembedded-core
On Sun 2026-02-15 @ 10:09:03 PM, Bruce Ashfield wrote:
> On Sun, Feb 15, 2026 at 9:32 PM Trevor Woerner via lists.openembedded.org
> <twoerner=gmail.com@lists.openembedded.org> wrote:
>
> > The previous implementation to add variable sector-size support:
> > - required the variable WIC_SECTOR_SIZE either be defined in a
> > configuration file or be defined in a --vars file
> > - this means that every invocation of "wic ls", "wic cp", or "wic rm"
> > needed this variable defined (config or --vars)
> > - required the user to create separate *wks files for every sector size
> > they wanted to use
> > - required the user to specify the mkfs-extraopts by hand to specify the
> > correct sector size: e.g.
> > bootloader --ptable gpt
> > part --fstype ext4 --source rootfs --label rofs-a --mkfs-extraopts
> > "-b 4096"
> > part --fstype ext4 --source rootfs --use-uuid --mkfs-extraopts "-b
> > 4096"
> > - specifying --mkfs-extraopts replaces the defaults with the
> > user-supplied values
> > - only provided details to support using variable sector-sizes with
> > ext[234] filesystems
> > - it would not be possible to generate images with different sector
> > sizes in the same build since the configuration and *wks files would
> > need to change and the build re-run for each size
> >
> > Update the sector-size handling so that:
> > - the sector-size will now be provided on the cmdline to the "wic ls",
> > "wic cp", "wic rm", and "wic create" commands: default = 512
> > - this means the configuration and/or --vars file does not need to be
> > changed in order to perform those operations on images with different
> > sector sizes
> > - support is provided implicitly for mkdosfs and ext[234] partitions
> > - the user no longer needs to know and supply the sector-size magic in
> > --mkfs-extraopts (thereby clobbering the other defaults)
> >
>
> It wasn't clear to me when scanning the patch. For configuration
> files with a sector size, is it now completely ignored ?
Yes.
While trying to use the existing implementation in actual production
workflows we found a number of shortcomings that are addressed with this
update. Additionally, the ultimate goal is to make wic an independent
utility from oe-core so it can be easily used by external tools
post-build.
If sector-size is not available on the cmdline, then a --vars file would
be needed for every simple wic invocation such as "wic cp", "wic ls",
and "wic rm"... which would be silly. Take a look at the patch I
submitted a week or so ago to see how the oe-selftests would have to be
updated to support this.
If sector-size is available both on the cmdline and in a --vars file
then which one wins? Ultimately having it specified in both places is
only going to lead to confusion as people will be changing it in one
place and not realizing it's also defined (and taking precedence) from
somewhere else. I believe this is currently the case with
--native-sysroot, which probably needs fixing as well since several
oe-selftests are trying to use it, but I doubt it is working the way the
test writers expect.
One parameter specified in one place so a user would not need multiple
sets of configuration files to perform a simple "wic ls" of images with
different sector sizes; simply specify it on the cmdline if you want
something other than 512.
> Apologies if I missed where existing configs were used to prime
> the parameters to the functions.
>
> Bruce
>
>
>
> >
> > AI-Generated: codex/gpt-5.1-codex-max
> > Signed-off-by: Trevor Woerner <twoerner@gmail.com>
> > ---
> > changes since v2:
> > - none
> >
> > changes since v1:
> > - none
> > ---
> > meta/lib/oeqa/selftest/cases/wic.py | 39 ++++---------
> > scripts/lib/wic/engine.py | 45 +++++++--------
> > scripts/lib/wic/help.py | 23 +++++---
> > scripts/lib/wic/partition.py | 55 +++++++++++++++++--
> > scripts/lib/wic/plugins/imager/direct.py | 18 ++----
> > scripts/lib/wic/plugins/source/bootimg_efi.py | 5 +-
> > .../lib/wic/plugins/source/bootimg_pcbios.py | 11 ++--
> > .../wic/plugins/source/isoimage_isohybrid.py | 5 +-
> > scripts/wic | 8 +++
> > 9 files changed, 125 insertions(+), 84 deletions(-)
> >
> > diff --git a/meta/lib/oeqa/selftest/cases/wic.py
> > b/meta/lib/oeqa/selftest/cases/wic.py
> > index ecaee5a29144..7ad61fa700f7 100644
> > --- a/meta/lib/oeqa/selftest/cases/wic.py
> > +++ b/meta/lib/oeqa/selftest/cases/wic.py
> > @@ -935,33 +935,22 @@ bootloader --ptable gpt""")
> > finally:
> > os.remove(wks_file)
> >
> > - def test_wic_sector_size(self):
> > - """Test generation image sector size"""
> > -
> > + def test_wic_sector_size_cli(self):
> > + """Test sector size handling via CLI option."""
> > +
> > oldpath = os.environ['PATH']
> > os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
> >
> > try:
> > - # Add WIC_SECTOR_SIZE into config
> > - config = 'WIC_SECTOR_SIZE = "4096"\n'\
> > - 'WICVARS:append = " WIC_SECTOR_SIZE"\n'
> > - self.append_config(config)
> > bitbake('core-image-minimal')
> >
> > - # Check WIC_SECTOR_SIZE apply to bitbake variable
> > - wic_sector_size_str = get_bb_var('WIC_SECTOR_SIZE',
> > 'core-image-minimal')
> > - wic_sector_size = int(wic_sector_size_str)
> > - self.assertEqual(4096, wic_sector_size)
> > -
> > - self.logger.info("Test wic_sector_size: %d \n" %
> > wic_sector_size)
> > -
> > with NamedTemporaryFile("w", suffix=".wks") as wks:
> > wks.writelines(
> > ['bootloader --ptable gpt\n',
> > - 'part --fstype ext4 --source rootfs --label rofs-a
> > --mkfs-extraopts "-b 4096"\n',
> > - 'part --fstype ext4 --source rootfs --use-uuid
> > --mkfs-extraopts "-b 4096"\n'])
> > + 'part --fstype ext4 --source rootfs --label
> > rofs-a\n',
> > + 'part --fstype ext4 --source rootfs --use-uuid\n'])
> > wks.flush()
> > - cmd = "wic create %s -e core-image-minimal -o %s" % (
> > wks.name, self.resultdir)
> > + cmd = "wic create %s -e core-image-minimal -o %s
> > --sector-size 4096" % (wks.name, self.resultdir)
> > runCmd(cmd)
> > wksname = os.path.splitext(os.path.basename(wks.name))[0]
> > images = glob(os.path.join(self.resultdir, "%s-*direct" %
> > wksname))
> > @@ -969,24 +958,18 @@ bootloader --ptable gpt""")
> >
> > sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
> > # list partitions
> > - result = runCmd("wic ls %s -n %s" % (images[0], sysroot))
> > + result = runCmd("wic ls %s -n %s --sector-size 4096" %
> > (images[0], sysroot))
> > self.assertEqual(3, len(result.output.split('\n')))
> >
> > - # verify partition size with wic
> > - res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m %s unit
> > b p" % (wic_sector_size, images[0]),
> > + # verify partition size with parted output
> > + res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m %s unit
> > b p" % (4096, images[0]),
> > stderr=subprocess.PIPE)
> >
> > - # parse parted output which looks like this:
> > - # BYT;\n
> > - #
> > /var/tmp/wic/build/tmpgjzzefdd-202410281021-sda.direct:78569472B:file:4096:4096:gpt::;\n
> > - # 1:139264B:39284735B:39145472B:ext4:rofs-a:;\n
> > - # 2:39284736B:78430207B:39145472B:ext4:primary:;\n
> > disk_info = res.output.splitlines()[1]
> > - # Check sector sizes
> > sector_size_logical = int(disk_info.split(":")[3])
> > sector_size_physical = int(disk_info.split(":")[4])
> > - self.assertEqual(wic_sector_size, sector_size_logical,
> > "Logical sector size is not %d." % wic_sector_size)
> > - self.assertEqual(wic_sector_size, sector_size_physical,
> > "Physical sector size is not %d." % wic_sector_size)
> > + self.assertEqual(4096, sector_size_logical, "Logical sector
> > size is not 4096.")
> > + self.assertEqual(4096, sector_size_physical, "Physical sector
> > size is not 4096.")
> >
> > finally:
> > os.environ['PATH'] = oldpath
> > diff --git a/scripts/lib/wic/engine.py b/scripts/lib/wic/engine.py
> > index 9d596be3a723..7753f431f91d 100644
> > --- a/scripts/lib/wic/engine.py
> > +++ b/scripts/lib/wic/engine.py
> > @@ -224,7 +224,7 @@ def wic_list(args, scripts_path):
> >
> >
> > class Disk:
> > - def __init__(self, imagepath, native_sysroot, fstypes=('fat', 'ext')):
> > + def __init__(self, imagepath, native_sysroot, fstypes=('fat', 'ext'),
> > sector_size=512):
> > self.imagepath = imagepath
> > self.native_sysroot = native_sysroot
> > self.fstypes = fstypes
> > @@ -233,16 +233,7 @@ class Disk:
> > self._lsector_size = None
> > self._psector_size = None
> > self._ptable_format = None
> > -
> > - # define sector size
> > - sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
> > - if sector_size_str is not None:
> > - try:
> > - self.sector_size = int(sector_size_str)
> > - except ValueError:
> > - self.sector_size = None
> > - else:
> > - self.sector_size = None
> > + self.sector_size = sector_size
> >
> > # find parted
> > # read paths from $PATH environment variable
> > @@ -271,7 +262,7 @@ class Disk:
> > if self._partitions is None:
> > self._partitions = OrderedDict()
> >
> > - if self.sector_size is not None:
> > + if self.sector_size:
> > out = exec_cmd("export PARTED_SECTOR_SIZE=%d; %s -sm %s
> > unit B print" % \
> > (self.sector_size, self.parted,
> > self.imagepath), True)
> > else:
> > @@ -312,11 +303,15 @@ class Disk:
> > raise WicError("Partition %s is not in the image" % pnum)
> > part = self.partitions[pnum]
> > # check if fstype is supported
> > + # NOTE: parted is unable to identify dos-type partitions with a
> > 4k sector-size
> > + # if the type is empty and a non-default sector size is
> > used, assume 'fat'
> > + # fdisk identifies them without issue
> > + part_fstype = part.fstype if part.fstype or self.sector_size ==
> > 512 else 'fat'
> > for fstype in self.fstypes:
> > - if part.fstype.startswith(fstype):
> > + if part_fstype.startswith(fstype):
> > break
> > else:
> > - raise WicError("Not supported fstype: {}".format(part.fstype))
> > + raise WicError("Not supported fstype: {}".format(part_fstype))
> > if pnum not in self._partimages:
> > tmpf = tempfile.NamedTemporaryFile(prefix="wic-part")
> > dst_fname = tmpf.name
> > @@ -586,8 +581,9 @@ class Disk:
> > label = part.get("name")
> > label_str = "-n {}".format(label) if label
> > else ''
> >
> > - cmd = "{} {} -C {} {}".format(self.mkdosfs,
> > label_str, partfname,
> > - part['size'])
> > + sector_str = "-S {}".format(self.sector_size)
> > if self.sector_size else ''
> > + cmd = "{} {} {} -C {}
> > {}".format(self.mkdosfs, label_str, sector_str, partfname,
> > + part['size'])
> > exec_cmd(cmd)
> > # copy content from the temporary directory
> > to the new partition
> > cmd = "{} -snompi {} {}/*
> > ::".format(self.mcopy, partfname, tmpdir)
> > @@ -609,14 +605,19 @@ class Disk:
> >
> > def wic_ls(args, native_sysroot):
> > """List contents of partitioned image or vfat partition."""
> > - disk = Disk(args.path.image, native_sysroot)
> > + disk = Disk(args.path.image, native_sysroot,
> > sector_size=args.sector_size)
> > if not args.path.part:
> > if disk.partitions:
> > print('Num Start End Size Fstype')
> > for part in disk.partitions.values():
> > + # size values are in bytes from parted; convert to
> > sectors if a custom sector size was requested
> > + display_size = part.size
> > + if args.sector_size and args.sector_size !=
> > disk._lsector_size:
> > + display_size = part.size // args.sector_size
> > print("{:2d} {:12d} {:12d} {:12d} {}".format(\
> > - part.pnum, part.start, part.end,
> > - part.size, part.fstype))
> > + part.pnum, part.start // args.sector_size,
> > + part.end // args.sector_size,
> > + display_size, part.fstype))
> > else:
> > path = args.path.path or '/'
> > print(disk.dir(args.path.part, path))
> > @@ -627,9 +628,9 @@ def wic_cp(args, native_sysroot):
> > partitioned image.
> > """
> > if isinstance(args.dest, str):
> > - disk = Disk(args.src.image, native_sysroot)
> > + disk = Disk(args.src.image, native_sysroot,
> > sector_size=args.sector_size)
> > else:
> > - disk = Disk(args.dest.image, native_sysroot)
> > + disk = Disk(args.dest.image, native_sysroot,
> > sector_size=args.sector_size)
> > disk.copy(args.src, args.dest)
> >
> >
> > @@ -638,7 +639,7 @@ def wic_rm(args, native_sysroot):
> > Remove files or directories from the vfat partition of
> > partitioned image.
> > """
> > - disk = Disk(args.path.image, native_sysroot)
> > + disk = Disk(args.path.image, native_sysroot,
> > sector_size=args.sector_size)
> > disk.remove(args.path.part, args.path.path, args.recursive_delete)
> >
> > def wic_write(args, native_sysroot):
> > diff --git a/scripts/lib/wic/help.py b/scripts/lib/wic/help.py
> > index 6b49a67de938..5d7c40456a80 100644
> > --- a/scripts/lib/wic/help.py
> > +++ b/scripts/lib/wic/help.py
> > @@ -118,7 +118,7 @@ wic_create_usage = """
> > usage: wic create <wks file or image name> [-o <DIRNAME> | --outdir
> > <DIRNAME>]
> > [-e | --image-name] [-s, --skip-build-check] [-D, --debug]
> > [-r, --rootfs-dir] [-b, --bootimg-dir]
> > - [-k, --kernel-dir] [-n, --native-sysroot] [-f, --build-rootfs]
> > + [-k, --kernel-dir] [-n, --native-sysroot] [--sector-size
> > <bytes>] [-f, --build-rootfs]
> > [-c, --compress-with] [-m, --bmap]
> >
> > This command creates an OpenEmbedded image based on the 'OE kickstart
> > @@ -139,13 +139,16 @@ SYNOPSIS
> > wic create <wks file or image name> [-o <DIRNAME> | --outdir
> > <DIRNAME>]
> > [-e | --image-name] [-s, --skip-build-check] [-D, --debug]
> > [-r, --rootfs-dir] [-b, --bootimg-dir]
> > - [-k, --kernel-dir] [-n, --native-sysroot] [-f, --build-rootfs]
> > + [-k, --kernel-dir] [-n, --native-sysroot] [--sector-size <bytes>]
> > [-f, --build-rootfs]
> > [-c, --compress-with] [-m, --bmap] [--no-fstab-update]
> >
> > DESCRIPTION
> > This command creates an OpenEmbedded image based on the 'OE
> > kickstart commands' found in the <wks file>.
> >
> > + Use the --sector-size option to select the sector size (in bytes)
> > + used for partition layout calculations (default is 512).
> > +
> > In order to do this, wic needs to know the locations of the
> > various build artifacts required to build the image.
> >
> > @@ -278,7 +281,7 @@ wic_ls_usage = """
> >
> > List content of a partitioned image
> >
> > - usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot <path>]
> > + usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot <path>]
> > [--sector-size <bytes>]
> >
> > This command outputs either list of image partitions or directory
> > contents
> > of vfat and ext* partitions.
> > @@ -296,7 +299,7 @@ SYNOPSIS
> > wic ls <image>
> > wic ls <image>:<vfat or ext* partition>
> > wic ls <image>:<vfat or ext* partition><path>
> > - wic ls <image>:<vfat or ext* partition><path> --native-sysroot <path>
> > + wic ls <image>:<vfat or ext* partition><path> --native-sysroot <path>
> > [--sector-size <bytes>]
> >
> > DESCRIPTION
> > This command lists either partitions of the image or directory
> > contents
> > @@ -336,6 +339,8 @@ DESCRIPTION
> >
> > The -n option is used to specify the path to the native sysroot
> > containing the tools(parted and mtools) to use.
> > + The --sector-size option sets the sector size used for partition math
> > + (default is 512 bytes).
> >
> > """
> >
> > @@ -343,7 +348,7 @@ wic_cp_usage = """
> >
> > Copy files and directories to/from the vfat or ext* partition
> >
> > - usage: wic cp <src> <dest> [--native-sysroot <path>]
> > + usage: wic cp <src> <dest> [--native-sysroot <path>] [--sector-size
> > <bytes>]
> >
> > source/destination image in format <image>:<partition>[<path>]
> >
> > @@ -364,7 +369,7 @@ SYNOPSIS
> > wic cp <src> <dest>:<partition>
> > wic cp <src>:<partition> <dest>
> > wic cp <src> <dest-image>:<partition><path>
> > - wic cp <src> <dest-image>:<partition><path> --native-sysroot <path>
> > + wic cp <src> <dest-image>:<partition><path> --native-sysroot <path>
> > [--sector-size <bytes>]
> >
> > DESCRIPTION
> > This command copies files or directories either
> > @@ -408,13 +413,15 @@ DESCRIPTION
> >
> > The -n option is used to specify the path to the native sysroot
> > containing the tools(parted and mtools) to use.
> > + The --sector-size option sets the sector size used for partition math
> > + (default is 512 bytes).
> > """
> >
> > wic_rm_usage = """
> >
> > Remove files or directories from the vfat or ext* partitions
> >
> > - usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
> > + usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
> > [--sector-size <bytes>]
> >
> > This command removes files or directories from the vfat or ext*
> > partitions of
> > the partitioned image.
> > @@ -466,6 +473,8 @@ DESCRIPTION
> >
> > The -n option is used to specify the path to the native sysroot
> > containing the tools(parted and mtools) to use.
> > + The --sector-size option sets the sector size used for partition math
> > + (default is 512 bytes).
> >
> > The -r option is used to remove directories and their contents
> > recursively,this only applies to ext* partition.
> > diff --git a/scripts/lib/wic/partition.py b/scripts/lib/wic/partition.py
> > index 8fed686e903e..df6e3271649b 100644
> > --- a/scripts/lib/wic/partition.py
> > +++ b/scripts/lib/wic/partition.py
> > @@ -65,6 +65,50 @@ class Partition():
> >
> > self.lineno = lineno
> > self.source_file = ""
> > + self.sector_size = 512
> > +
> > + def _mkdosfs_extraopts(self):
> > + """
> > + Build mkdosfs extra options ensuring the CLI sector size is
> > applied.
> > + """
> > + extraopts = self.mkfs_extraopts or ''
> > + tokens = []
> > + skip_next = False
> > + for tok in extraopts.split():
> > + if skip_next:
> > + skip_next = False
> > + continue
> > + if tok == '-S':
> > + skip_next = True
> > + continue
> > + if tok.startswith('-S'):
> > + continue
> > + tokens.append(tok)
> > + tokens.extend(['-S', str(self.sector_size)])
> > + return ' '.join(tokens).strip()
> > +
> > + def _mkfs_ext_extraopts(self, base_opts):
> > + """
> > + Build mkfs.ext* extra options ensuring the CLI sector size is
> > applied.
> > + """
> > + extraopts = self.mkfs_extraopts or base_opts
> > + # Only add an explicit block size when a non-default sector size
> > is requested.
> > + if self.sector_size and self.sector_size != 512:
> > + tokens = []
> > + skip_next = False
> > + for tok in extraopts.split():
> > + if skip_next:
> > + skip_next = False
> > + continue
> > + if tok == '-b':
> > + skip_next = True
> > + continue
> > + if tok.startswith('-b'):
> > + continue
> > + tokens.append(tok)
> > + tokens.extend(['-b', str(self.sector_size)])
> > + return ' '.join(tokens).strip()
> > + return extraopts
> >
> > def get_extra_block_count(self, current_blocks):
> > """
> > @@ -138,6 +182,8 @@ class Partition():
> > Prepare content for individual partitions, depending on
> > partition command parameters.
> > """
> > + # capture the sector size requested on the CLI for mkdosfs
> > invocations
> > + self.sector_size = getattr(creator, 'sector_size', 512) or 512
> > self.updated_fstab_path = updated_fstab_path
> > if self.updated_fstab_path and not (self.fstype.startswith("ext")
> > or self.fstype == "msdos"):
> > self.update_fstab_in_rootfs = True
> > @@ -293,7 +339,7 @@ class Partition():
> > with open(rootfs, 'w') as sparse:
> > os.ftruncate(sparse.fileno(), rootfs_size * 1024)
> >
> > - extraopts = self.mkfs_extraopts or "-F -i 8192"
> > + extraopts = self._mkfs_ext_extraopts("-F -i 8192")
> >
> > # use hash_seed to generate reproducible ext4 images
> > (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts, pseudo)
> > @@ -401,7 +447,7 @@ class Partition():
> >
> > size_str = ""
> >
> > - extraopts = self.mkfs_extraopts or '-S 512'
> > + extraopts = self._mkdosfs_extraopts()
> >
> > dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
> > (label_str, self.fsuuid, size_str, extraopts, rootfs,
> > @@ -452,7 +498,7 @@ class Partition():
> > with open(rootfs, 'w') as sparse:
> > os.ftruncate(sparse.fileno(), size * 1024)
> >
> > - extraopts = self.mkfs_extraopts or "-i 8192"
> > + extraopts = self._mkfs_ext_extraopts("-i 8192")
> >
> > # use hash_seed to generate reproducible ext4 images
> > (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts, None)
> > @@ -498,7 +544,7 @@ class Partition():
> >
> > size_str = ""
> >
> > - extraopts = self.mkfs_extraopts or '-S 512'
> > + extraopts = self._mkdosfs_extraopts()
> >
> > dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
> > (label_str, self.fsuuid, extraopts, size_str, rootfs,
> > @@ -559,4 +605,3 @@ class Partition():
> > logger.warn("%s Inodes (of size %d) are too small." %
> > (get_err_str(self), size))
> > break
> > -
> > diff --git a/scripts/lib/wic/plugins/imager/direct.py
> > b/scripts/lib/wic/plugins/imager/direct.py
> > index ad922cfbf122..3adc6eee6280 100644
> > --- a/scripts/lib/wic/plugins/imager/direct.py
> > +++ b/scripts/lib/wic/plugins/imager/direct.py
> > @@ -67,6 +67,7 @@ class DirectPlugin(ImagerPlugin):
> > self._image = None
> > self.ptable_format = self.ks.bootloader.ptable
> > self.parts = self.ks.partitions
> > + self.sector_size = options.sector_size or 512
> >
> > # as a convenience, set source to the boot partition source
> > # instead of forcing it to be set via bootloader --source
> > @@ -78,7 +79,7 @@ class DirectPlugin(ImagerPlugin):
> > image_path = self._full_path(self.workdir, self.parts[0].disk,
> > "direct")
> > self._image = PartitionedImage(image_path, self.ptable_format,
> > self.ks.bootloader.diskid,
> > self.parts, self.native_sysroot,
> > - options.extra_space)
> > + options.extra_space,
> > self.sector_size)
> >
> > def setup_workdir(self, workdir):
> > if workdir:
> > @@ -294,15 +295,13 @@ MBR_OVERHEAD = 1
> > # Overhead of the GPT partitioning scheme
> > GPT_OVERHEAD = 34
> >
> > -# Size of a sector in bytes
> > -SECTOR_SIZE = 512
> > -
> > class PartitionedImage():
> > """
> > Partitioned image in a file.
> > """
> >
> > - def __init__(self, path, ptable_format, disk_id, partitions,
> > native_sysroot=None, extra_space=0):
> > + def __init__(self, path, ptable_format, disk_id, partitions,
> > native_sysroot=None, extra_space=0,
> > + sector_size=512):
> > self.path = path # Path to the image file
> > self.numpart = 0 # Number of allocated partitions
> > self.realpart = 0 # Number of partitions in the partition table
> > @@ -332,14 +331,7 @@ class PartitionedImage():
> > self.partitions = partitions
> > self.partimages = []
> > # Size of a sector used in calculations
> > - sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
> > - if sector_size_str is not None:
> > - try:
> > - self.sector_size = int(sector_size_str)
> > - except ValueError:
> > - self.sector_size = SECTOR_SIZE
> > - else:
> > - self.sector_size = SECTOR_SIZE
> > + self.sector_size = sector_size or 512
> >
> > self.native_sysroot = native_sysroot
> > num_real_partitions = len([p for p in self.partitions if not
> > p.no_table])
> > diff --git a/scripts/lib/wic/plugins/source/bootimg_efi.py
> > b/scripts/lib/wic/plugins/source/bootimg_efi.py
> > index 430b0a4b023a..864d6898fc9d 100644
> > --- a/scripts/lib/wic/plugins/source/bootimg_efi.py
> > +++ b/scripts/lib/wic/plugins/source/bootimg_efi.py
> > @@ -415,8 +415,9 @@ class BootimgEFIPlugin(SourcePlugin):
> >
> > label = part.label if part.label else "ESP"
> >
> > - dosfs_cmd = "mkdosfs -v -n %s -i %s -C %s %d" % \
> > - (label, part.fsuuid, bootimg, blocks)
> > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > + dosfs_cmd = "mkdosfs -v -n %s -i %s -S %d -C %s %d" % \
> > + (label, part.fsuuid, sector_size, bootimg, blocks)
> > exec_native_cmd(dosfs_cmd, native_sysroot)
> > logger.debug("mkdosfs:\n%s" % (str(out)))
> >
> > diff --git a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > index a7cc5d12c620..32edac47fa09 100644
> > --- a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > +++ b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > @@ -132,7 +132,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > cls._do_prepare_grub(part, cr_workdir, oe_builddir,
> > kernel_dir, rootfs_dir, native_sysroot)
> > elif source_params['loader-bios'] == 'syslinux':
> > - cls._do_prepare_syslinux(part, cr_workdir, bootimg_dir,
> > + cls._do_prepare_syslinux(part, creator, cr_workdir,
> > bootimg_dir,
> > kernel_dir, native_sysroot)
> > else:
> > raise WicError("unrecognized bootimg_pcbios loader: %s" %
> > source_params['loader-bios'])
> > @@ -142,7 +142,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > except KeyError:
> > # Required by do_install_disk
> > cls.loader = 'syslinux'
> > - cls._do_prepare_syslinux(part, cr_workdir, bootimg_dir,
> > + cls._do_prepare_syslinux(part, creator, cr_workdir,
> > bootimg_dir,
> > kernel_dir, native_sysroot)
> >
> > @classmethod
> > @@ -240,7 +240,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > cfg.close()
> >
> > @classmethod
> > - def _do_prepare_syslinux(cls, part, cr_workdir, bootimg_dir,
> > + def _do_prepare_syslinux(cls, part, creator, cr_workdir, bootimg_dir,
> > kernel_dir, native_sysroot):
> > """
> > Called to do the actual content population for a partition i.e. it
> > @@ -292,8 +292,9 @@ class BootimgPcbiosPlugin(SourcePlugin):
> >
> > label = part.label if part.label else "boot"
> >
> > - dosfs_cmd = "mkdosfs -n %s -i %s -S 512 -C %s %d" % \
> > - (label, part.fsuuid, bootimg, blocks)
> > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > + dosfs_cmd = "mkdosfs -n %s -i %s -S %d -C %s %d" % \
> > + (label, part.fsuuid, sector_size, bootimg, blocks)
> > exec_native_cmd(dosfs_cmd, native_sysroot)
> >
> > mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
> > diff --git a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > index fdab188db1f8..9195ef5f3184 100644
> > --- a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > +++ b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > @@ -367,8 +367,9 @@ class IsoImagePlugin(SourcePlugin):
> >
> > esp_label = source_params.get('esp_label', 'EFIimg')
> >
> > - dosfs_cmd = 'mkfs.vfat -n \'%s\' -S 512 -C %s %d' \
> > - % (esp_label, bootimg, blocks)
> > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > + dosfs_cmd = "mkfs.vfat -n '%s' -S %d -C %s %d" % \
> > + (esp_label, sector_size, bootimg, blocks)
> > exec_native_cmd(dosfs_cmd, native_sysroot)
> >
> > mmd_cmd = "mmd -i %s ::/EFI" % bootimg
> > diff --git a/scripts/wic b/scripts/wic
> > index 9137208f5e8f..0cef84ef630c 100755
> > --- a/scripts/wic
> > +++ b/scripts/wic
> > @@ -376,6 +376,8 @@ def wic_init_parser_create(subparser):
> > default="direct", help="the wic imager plugin")
> > subparser.add_argument("--extra-space", type=int, dest="extra_space",
> > default=0, help="additional free disk space to add
> > to the image")
> > + subparser.add_argument("--sector-size", dest="sector_size", type=int,
> > default=512,
> > + help="sector size in bytes (default: 512)")
> > return
> >
> >
> > @@ -413,6 +415,8 @@ def imgtype(arg):
> > def wic_init_parser_ls(subparser):
> > subparser.add_argument("path", type=imgtype,
> > help="image spec: <image>[:<vfat
> > partition>[<path>]]")
> > + subparser.add_argument("--sector-size", dest="sector_size", type=int,
> > default=512,
> > + help="sector size in bytes (default: 512)")
> > subparser.add_argument("-n", "--native-sysroot",
> > help="path to the native sysroot containing the
> > tools")
> > subparser.add_argument("-e", "--image-name", dest="image_name",
> > @@ -433,6 +437,8 @@ def wic_init_parser_cp(subparser):
> > help="image spec: <image>:<vfat
> > partition>[<path>] or <file>")
> > subparser.add_argument("dest",
> > help="image spec: <image>:<vfat
> > partition>[<path>] or <file>")
> > + subparser.add_argument("--sector-size", dest="sector_size", type=int,
> > default=512,
> > + help="sector size in bytes (default: 512)")
> > subparser.add_argument("-n", "--native-sysroot",
> > help="path to the native sysroot containing the
> > tools")
> > subparser.add_argument("-e", "--image-name", dest="image_name",
> > @@ -445,6 +451,8 @@ def wic_init_parser_cp(subparser):
> > def wic_init_parser_rm(subparser):
> > subparser.add_argument("path", type=imgpathtype,
> > help="path: <image>:<vfat partition><path>")
> > + subparser.add_argument("--sector-size", dest="sector_size", type=int,
> > default=512,
> > + help="sector size in bytes (default: 512)")
> > subparser.add_argument("-n", "--native-sysroot",
> > help="path to the native sysroot containing the
> > tools")
> > subparser.add_argument("-r", dest="recursive_delete",
> > action="store_true", default=False,
> > --
> > 2.51.0
> >
> >
> > -=-=-=-=-=-=-=-=-=-=-=-
> > Links: You receive all messages sent to this group.
> > View/Reply Online (#231176):
> > https://lists.openembedded.org/g/openembedded-core/message/231176
> > Mute This Topic: https://lists.openembedded.org/mt/117833550/1050810
> > Group Owner: openembedded-core+owner@lists.openembedded.org
> > Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [
> > bruce.ashfield@gmail.com]
> > -=-=-=-=-=-=-=-=-=-=-=-
> >
> >
>
> --
> - Thou shalt not follow the NULL pointer, for chaos and madness await thee
> at its end
> - "Use the force Harry" - Gandalf, Star Trek II
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [OE-core] [PATCH v3 1/2] wic: re-implement sector-size support
2026-02-16 15:37 ` Trevor Woerner
@ 2026-02-16 16:01 ` Bruce Ashfield
2026-02-16 17:58 ` Trevor Woerner
0 siblings, 1 reply; 8+ messages in thread
From: Bruce Ashfield @ 2026-02-16 16:01 UTC (permalink / raw)
To: Trevor Woerner; +Cc: openembedded-core
[-- Attachment #1: Type: text/plain, Size: 36563 bytes --]
On Mon, Feb 16, 2026 at 10:37 AM Trevor Woerner <twoerner@gmail.com> wrote:
> On Sun 2026-02-15 @ 10:09:03 PM, Bruce Ashfield wrote:
> > On Sun, Feb 15, 2026 at 9:32 PM Trevor Woerner via
> lists.openembedded.org
> > <twoerner=gmail.com@lists.openembedded.org> wrote:
> >
> > > The previous implementation to add variable sector-size support:
> > > - required the variable WIC_SECTOR_SIZE either be defined in a
> > > configuration file or be defined in a --vars file
> > > - this means that every invocation of "wic ls", "wic cp", or "wic rm"
> > > needed this variable defined (config or --vars)
> > > - required the user to create separate *wks files for every sector size
> > > they wanted to use
> > > - required the user to specify the mkfs-extraopts by hand to specify
> the
> > > correct sector size: e.g.
> > > bootloader --ptable gpt
> > > part --fstype ext4 --source rootfs --label rofs-a
> --mkfs-extraopts
> > > "-b 4096"
> > > part --fstype ext4 --source rootfs --use-uuid --mkfs-extraopts
> "-b
> > > 4096"
> > > - specifying --mkfs-extraopts replaces the defaults with the
> > > user-supplied values
> > > - only provided details to support using variable sector-sizes with
> > > ext[234] filesystems
> > > - it would not be possible to generate images with different sector
> > > sizes in the same build since the configuration and *wks files would
> > > need to change and the build re-run for each size
> > >
> > > Update the sector-size handling so that:
> > > - the sector-size will now be provided on the cmdline to the "wic ls",
> > > "wic cp", "wic rm", and "wic create" commands: default = 512
> > > - this means the configuration and/or --vars file does not need to be
> > > changed in order to perform those operations on images with different
> > > sector sizes
> > > - support is provided implicitly for mkdosfs and ext[234] partitions
> > > - the user no longer needs to know and supply the sector-size magic in
> > > --mkfs-extraopts (thereby clobbering the other defaults)
> > >
> >
> > It wasn't clear to me when scanning the patch. For configuration
> > files with a sector size, is it now completely ignored ?
>
> Yes.
>
> While trying to use the existing implementation in actual production
> workflows we found a number of shortcomings that are addressed with this
> update. Additionally, the ultimate goal is to make wic an independent
> utility from oe-core so it can be easily used by external tools
> post-build.
>
> If sector-size is not available on the cmdline, then a --vars file would
> be needed for every simple wic invocation such as "wic cp", "wic ls",
> and "wic rm"... which would be silly. Take a look at the patch I
> submitted a week or so ago to see how the oe-selftests would have to be
> updated to support this.
>
> If sector-size is available both on the cmdline and in a --vars file
> then which one wins? Ultimately having it specified in both places is
> only going to lead to confusion as people will be changing it in one
> place and not realizing it's also defined (and taking precedence) from
> somewhere else. I believe this is currently the case with
> --native-sysroot, which probably needs fixing as well since several
> oe-selftests are trying to use it, but I doubt it is working the way the
> test writers expect.
> One parameter specified in one place so a user would not need multiple
> sets of configuration files to perform a simple "wic ls" of images with
> different sector sizes; simply specify it on the cmdline if you want
> something other than 512.
>
That's not a good migration path. You can't simply throw away
someone's existing configuration and ask them to update to a
new one. I didn't even see an error thrown with migration
instructions.
There's many different users of things like this, we can't simply
change the interface without some way to migrate.
Bruce
>
> > Apologies if I missed where existing configs were used to prime
> > the parameters to the functions.
> >
> > Bruce
> >
> >
> >
> > >
> > > AI-Generated: codex/gpt-5.1-codex-max
> > > Signed-off-by: Trevor Woerner <twoerner@gmail.com>
> > > ---
> > > changes since v2:
> > > - none
> > >
> > > changes since v1:
> > > - none
> > > ---
> > > meta/lib/oeqa/selftest/cases/wic.py | 39 ++++---------
> > > scripts/lib/wic/engine.py | 45 +++++++--------
> > > scripts/lib/wic/help.py | 23 +++++---
> > > scripts/lib/wic/partition.py | 55 +++++++++++++++++--
> > > scripts/lib/wic/plugins/imager/direct.py | 18 ++----
> > > scripts/lib/wic/plugins/source/bootimg_efi.py | 5 +-
> > > .../lib/wic/plugins/source/bootimg_pcbios.py | 11 ++--
> > > .../wic/plugins/source/isoimage_isohybrid.py | 5 +-
> > > scripts/wic | 8 +++
> > > 9 files changed, 125 insertions(+), 84 deletions(-)
> > >
> > > diff --git a/meta/lib/oeqa/selftest/cases/wic.py
> > > b/meta/lib/oeqa/selftest/cases/wic.py
> > > index ecaee5a29144..7ad61fa700f7 100644
> > > --- a/meta/lib/oeqa/selftest/cases/wic.py
> > > +++ b/meta/lib/oeqa/selftest/cases/wic.py
> > > @@ -935,33 +935,22 @@ bootloader --ptable gpt""")
> > > finally:
> > > os.remove(wks_file)
> > >
> > > - def test_wic_sector_size(self):
> > > - """Test generation image sector size"""
> > > -
> > > + def test_wic_sector_size_cli(self):
> > > + """Test sector size handling via CLI option."""
> > > +
> > > oldpath = os.environ['PATH']
> > > os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
> > >
> > > try:
> > > - # Add WIC_SECTOR_SIZE into config
> > > - config = 'WIC_SECTOR_SIZE = "4096"\n'\
> > > - 'WICVARS:append = " WIC_SECTOR_SIZE"\n'
> > > - self.append_config(config)
> > > bitbake('core-image-minimal')
> > >
> > > - # Check WIC_SECTOR_SIZE apply to bitbake variable
> > > - wic_sector_size_str = get_bb_var('WIC_SECTOR_SIZE',
> > > 'core-image-minimal')
> > > - wic_sector_size = int(wic_sector_size_str)
> > > - self.assertEqual(4096, wic_sector_size)
> > > -
> > > - self.logger.info("Test wic_sector_size: %d \n" %
> > > wic_sector_size)
> > > -
> > > with NamedTemporaryFile("w", suffix=".wks") as wks:
> > > wks.writelines(
> > > ['bootloader --ptable gpt\n',
> > > - 'part --fstype ext4 --source rootfs --label
> rofs-a
> > > --mkfs-extraopts "-b 4096"\n',
> > > - 'part --fstype ext4 --source rootfs --use-uuid
> > > --mkfs-extraopts "-b 4096"\n'])
> > > + 'part --fstype ext4 --source rootfs --label
> > > rofs-a\n',
> > > + 'part --fstype ext4 --source rootfs
> --use-uuid\n'])
> > > wks.flush()
> > > - cmd = "wic create %s -e core-image-minimal -o %s" % (
> > > wks.name, self.resultdir)
> > > + cmd = "wic create %s -e core-image-minimal -o %s
> > > --sector-size 4096" % (wks.name, self.resultdir)
> > > runCmd(cmd)
> > > wksname = os.path.splitext(os.path.basename(wks.name
> ))[0]
> > > images = glob(os.path.join(self.resultdir,
> "%s-*direct" %
> > > wksname))
> > > @@ -969,24 +958,18 @@ bootloader --ptable gpt""")
> > >
> > > sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
> > > # list partitions
> > > - result = runCmd("wic ls %s -n %s" % (images[0], sysroot))
> > > + result = runCmd("wic ls %s -n %s --sector-size 4096" %
> > > (images[0], sysroot))
> > > self.assertEqual(3, len(result.output.split('\n')))
> > >
> > > - # verify partition size with wic
> > > - res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m %s
> unit
> > > b p" % (wic_sector_size, images[0]),
> > > + # verify partition size with parted output
> > > + res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m %s
> unit
> > > b p" % (4096, images[0]),
> > > stderr=subprocess.PIPE)
> > >
> > > - # parse parted output which looks like this:
> > > - # BYT;\n
> > > - #
> > >
> /var/tmp/wic/build/tmpgjzzefdd-202410281021-sda.direct:78569472B:file:4096:4096:gpt::;\n
> > > - # 1:139264B:39284735B:39145472B:ext4:rofs-a:;\n
> > > - # 2:39284736B:78430207B:39145472B:ext4:primary:;\n
> > > disk_info = res.output.splitlines()[1]
> > > - # Check sector sizes
> > > sector_size_logical = int(disk_info.split(":")[3])
> > > sector_size_physical = int(disk_info.split(":")[4])
> > > - self.assertEqual(wic_sector_size, sector_size_logical,
> > > "Logical sector size is not %d." % wic_sector_size)
> > > - self.assertEqual(wic_sector_size, sector_size_physical,
> > > "Physical sector size is not %d." % wic_sector_size)
> > > + self.assertEqual(4096, sector_size_logical, "Logical
> sector
> > > size is not 4096.")
> > > + self.assertEqual(4096, sector_size_physical, "Physical
> sector
> > > size is not 4096.")
> > >
> > > finally:
> > > os.environ['PATH'] = oldpath
> > > diff --git a/scripts/lib/wic/engine.py b/scripts/lib/wic/engine.py
> > > index 9d596be3a723..7753f431f91d 100644
> > > --- a/scripts/lib/wic/engine.py
> > > +++ b/scripts/lib/wic/engine.py
> > > @@ -224,7 +224,7 @@ def wic_list(args, scripts_path):
> > >
> > >
> > > class Disk:
> > > - def __init__(self, imagepath, native_sysroot, fstypes=('fat',
> 'ext')):
> > > + def __init__(self, imagepath, native_sysroot, fstypes=('fat',
> 'ext'),
> > > sector_size=512):
> > > self.imagepath = imagepath
> > > self.native_sysroot = native_sysroot
> > > self.fstypes = fstypes
> > > @@ -233,16 +233,7 @@ class Disk:
> > > self._lsector_size = None
> > > self._psector_size = None
> > > self._ptable_format = None
> > > -
> > > - # define sector size
> > > - sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
> > > - if sector_size_str is not None:
> > > - try:
> > > - self.sector_size = int(sector_size_str)
> > > - except ValueError:
> > > - self.sector_size = None
> > > - else:
> > > - self.sector_size = None
> > > + self.sector_size = sector_size
> > >
> > > # find parted
> > > # read paths from $PATH environment variable
> > > @@ -271,7 +262,7 @@ class Disk:
> > > if self._partitions is None:
> > > self._partitions = OrderedDict()
> > >
> > > - if self.sector_size is not None:
> > > + if self.sector_size:
> > > out = exec_cmd("export PARTED_SECTOR_SIZE=%d; %s -sm
> %s
> > > unit B print" % \
> > > (self.sector_size, self.parted,
> > > self.imagepath), True)
> > > else:
> > > @@ -312,11 +303,15 @@ class Disk:
> > > raise WicError("Partition %s is not in the image" % pnum)
> > > part = self.partitions[pnum]
> > > # check if fstype is supported
> > > + # NOTE: parted is unable to identify dos-type partitions with
> a
> > > 4k sector-size
> > > + # if the type is empty and a non-default sector size is
> > > used, assume 'fat'
> > > + # fdisk identifies them without issue
> > > + part_fstype = part.fstype if part.fstype or self.sector_size
> ==
> > > 512 else 'fat'
> > > for fstype in self.fstypes:
> > > - if part.fstype.startswith(fstype):
> > > + if part_fstype.startswith(fstype):
> > > break
> > > else:
> > > - raise WicError("Not supported fstype:
> {}".format(part.fstype))
> > > + raise WicError("Not supported fstype:
> {}".format(part_fstype))
> > > if pnum not in self._partimages:
> > > tmpf = tempfile.NamedTemporaryFile(prefix="wic-part")
> > > dst_fname = tmpf.name
> > > @@ -586,8 +581,9 @@ class Disk:
> > > label = part.get("name")
> > > label_str = "-n {}".format(label) if label
> > > else ''
> > >
> > > - cmd = "{} {} -C {}
> {}".format(self.mkdosfs,
> > > label_str, partfname,
> > > -
> part['size'])
> > > + sector_str = "-S
> {}".format(self.sector_size)
> > > if self.sector_size else ''
> > > + cmd = "{} {} {} -C {}
> > > {}".format(self.mkdosfs, label_str, sector_str, partfname,
> > > +
> part['size'])
> > > exec_cmd(cmd)
> > > # copy content from the temporary
> directory
> > > to the new partition
> > > cmd = "{} -snompi {} {}/*
> > > ::".format(self.mcopy, partfname, tmpdir)
> > > @@ -609,14 +605,19 @@ class Disk:
> > >
> > > def wic_ls(args, native_sysroot):
> > > """List contents of partitioned image or vfat partition."""
> > > - disk = Disk(args.path.image, native_sysroot)
> > > + disk = Disk(args.path.image, native_sysroot,
> > > sector_size=args.sector_size)
> > > if not args.path.part:
> > > if disk.partitions:
> > > print('Num Start End Size
> Fstype')
> > > for part in disk.partitions.values():
> > > + # size values are in bytes from parted; convert to
> > > sectors if a custom sector size was requested
> > > + display_size = part.size
> > > + if args.sector_size and args.sector_size !=
> > > disk._lsector_size:
> > > + display_size = part.size // args.sector_size
> > > print("{:2d} {:12d} {:12d} {:12d} {}".format(\
> > > - part.pnum, part.start, part.end,
> > > - part.size, part.fstype))
> > > + part.pnum, part.start // args.sector_size,
> > > + part.end // args.sector_size,
> > > + display_size, part.fstype))
> > > else:
> > > path = args.path.path or '/'
> > > print(disk.dir(args.path.part, path))
> > > @@ -627,9 +628,9 @@ def wic_cp(args, native_sysroot):
> > > partitioned image.
> > > """
> > > if isinstance(args.dest, str):
> > > - disk = Disk(args.src.image, native_sysroot)
> > > + disk = Disk(args.src.image, native_sysroot,
> > > sector_size=args.sector_size)
> > > else:
> > > - disk = Disk(args.dest.image, native_sysroot)
> > > + disk = Disk(args.dest.image, native_sysroot,
> > > sector_size=args.sector_size)
> > > disk.copy(args.src, args.dest)
> > >
> > >
> > > @@ -638,7 +639,7 @@ def wic_rm(args, native_sysroot):
> > > Remove files or directories from the vfat partition of
> > > partitioned image.
> > > """
> > > - disk = Disk(args.path.image, native_sysroot)
> > > + disk = Disk(args.path.image, native_sysroot,
> > > sector_size=args.sector_size)
> > > disk.remove(args.path.part, args.path.path, args.recursive_delete)
> > >
> > > def wic_write(args, native_sysroot):
> > > diff --git a/scripts/lib/wic/help.py b/scripts/lib/wic/help.py
> > > index 6b49a67de938..5d7c40456a80 100644
> > > --- a/scripts/lib/wic/help.py
> > > +++ b/scripts/lib/wic/help.py
> > > @@ -118,7 +118,7 @@ wic_create_usage = """
> > > usage: wic create <wks file or image name> [-o <DIRNAME> | --outdir
> > > <DIRNAME>]
> > > [-e | --image-name] [-s, --skip-build-check] [-D, --debug]
> > > [-r, --rootfs-dir] [-b, --bootimg-dir]
> > > - [-k, --kernel-dir] [-n, --native-sysroot] [-f,
> --build-rootfs]
> > > + [-k, --kernel-dir] [-n, --native-sysroot] [--sector-size
> > > <bytes>] [-f, --build-rootfs]
> > > [-c, --compress-with] [-m, --bmap]
> > >
> > > This command creates an OpenEmbedded image based on the 'OE kickstart
> > > @@ -139,13 +139,16 @@ SYNOPSIS
> > > wic create <wks file or image name> [-o <DIRNAME> | --outdir
> > > <DIRNAME>]
> > > [-e | --image-name] [-s, --skip-build-check] [-D, --debug]
> > > [-r, --rootfs-dir] [-b, --bootimg-dir]
> > > - [-k, --kernel-dir] [-n, --native-sysroot] [-f, --build-rootfs]
> > > + [-k, --kernel-dir] [-n, --native-sysroot] [--sector-size
> <bytes>]
> > > [-f, --build-rootfs]
> > > [-c, --compress-with] [-m, --bmap] [--no-fstab-update]
> > >
> > > DESCRIPTION
> > > This command creates an OpenEmbedded image based on the 'OE
> > > kickstart commands' found in the <wks file>.
> > >
> > > + Use the --sector-size option to select the sector size (in bytes)
> > > + used for partition layout calculations (default is 512).
> > > +
> > > In order to do this, wic needs to know the locations of the
> > > various build artifacts required to build the image.
> > >
> > > @@ -278,7 +281,7 @@ wic_ls_usage = """
> > >
> > > List content of a partitioned image
> > >
> > > - usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot <path>]
> > > + usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot <path>]
> > > [--sector-size <bytes>]
> > >
> > > This command outputs either list of image partitions or directory
> > > contents
> > > of vfat and ext* partitions.
> > > @@ -296,7 +299,7 @@ SYNOPSIS
> > > wic ls <image>
> > > wic ls <image>:<vfat or ext* partition>
> > > wic ls <image>:<vfat or ext* partition><path>
> > > - wic ls <image>:<vfat or ext* partition><path> --native-sysroot
> <path>
> > > + wic ls <image>:<vfat or ext* partition><path> --native-sysroot
> <path>
> > > [--sector-size <bytes>]
> > >
> > > DESCRIPTION
> > > This command lists either partitions of the image or directory
> > > contents
> > > @@ -336,6 +339,8 @@ DESCRIPTION
> > >
> > > The -n option is used to specify the path to the native sysroot
> > > containing the tools(parted and mtools) to use.
> > > + The --sector-size option sets the sector size used for partition
> math
> > > + (default is 512 bytes).
> > >
> > > """
> > >
> > > @@ -343,7 +348,7 @@ wic_cp_usage = """
> > >
> > > Copy files and directories to/from the vfat or ext* partition
> > >
> > > - usage: wic cp <src> <dest> [--native-sysroot <path>]
> > > + usage: wic cp <src> <dest> [--native-sysroot <path>] [--sector-size
> > > <bytes>]
> > >
> > > source/destination image in format <image>:<partition>[<path>]
> > >
> > > @@ -364,7 +369,7 @@ SYNOPSIS
> > > wic cp <src> <dest>:<partition>
> > > wic cp <src>:<partition> <dest>
> > > wic cp <src> <dest-image>:<partition><path>
> > > - wic cp <src> <dest-image>:<partition><path> --native-sysroot
> <path>
> > > + wic cp <src> <dest-image>:<partition><path> --native-sysroot
> <path>
> > > [--sector-size <bytes>]
> > >
> > > DESCRIPTION
> > > This command copies files or directories either
> > > @@ -408,13 +413,15 @@ DESCRIPTION
> > >
> > > The -n option is used to specify the path to the native sysroot
> > > containing the tools(parted and mtools) to use.
> > > + The --sector-size option sets the sector size used for partition
> math
> > > + (default is 512 bytes).
> > > """
> > >
> > > wic_rm_usage = """
> > >
> > > Remove files or directories from the vfat or ext* partitions
> > >
> > > - usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
> > > + usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
> > > [--sector-size <bytes>]
> > >
> > > This command removes files or directories from the vfat or ext*
> > > partitions of
> > > the partitioned image.
> > > @@ -466,6 +473,8 @@ DESCRIPTION
> > >
> > > The -n option is used to specify the path to the native sysroot
> > > containing the tools(parted and mtools) to use.
> > > + The --sector-size option sets the sector size used for partition
> math
> > > + (default is 512 bytes).
> > >
> > > The -r option is used to remove directories and their contents
> > > recursively,this only applies to ext* partition.
> > > diff --git a/scripts/lib/wic/partition.py
> b/scripts/lib/wic/partition.py
> > > index 8fed686e903e..df6e3271649b 100644
> > > --- a/scripts/lib/wic/partition.py
> > > +++ b/scripts/lib/wic/partition.py
> > > @@ -65,6 +65,50 @@ class Partition():
> > >
> > > self.lineno = lineno
> > > self.source_file = ""
> > > + self.sector_size = 512
> > > +
> > > + def _mkdosfs_extraopts(self):
> > > + """
> > > + Build mkdosfs extra options ensuring the CLI sector size is
> > > applied.
> > > + """
> > > + extraopts = self.mkfs_extraopts or ''
> > > + tokens = []
> > > + skip_next = False
> > > + for tok in extraopts.split():
> > > + if skip_next:
> > > + skip_next = False
> > > + continue
> > > + if tok == '-S':
> > > + skip_next = True
> > > + continue
> > > + if tok.startswith('-S'):
> > > + continue
> > > + tokens.append(tok)
> > > + tokens.extend(['-S', str(self.sector_size)])
> > > + return ' '.join(tokens).strip()
> > > +
> > > + def _mkfs_ext_extraopts(self, base_opts):
> > > + """
> > > + Build mkfs.ext* extra options ensuring the CLI sector size is
> > > applied.
> > > + """
> > > + extraopts = self.mkfs_extraopts or base_opts
> > > + # Only add an explicit block size when a non-default sector
> size
> > > is requested.
> > > + if self.sector_size and self.sector_size != 512:
> > > + tokens = []
> > > + skip_next = False
> > > + for tok in extraopts.split():
> > > + if skip_next:
> > > + skip_next = False
> > > + continue
> > > + if tok == '-b':
> > > + skip_next = True
> > > + continue
> > > + if tok.startswith('-b'):
> > > + continue
> > > + tokens.append(tok)
> > > + tokens.extend(['-b', str(self.sector_size)])
> > > + return ' '.join(tokens).strip()
> > > + return extraopts
> > >
> > > def get_extra_block_count(self, current_blocks):
> > > """
> > > @@ -138,6 +182,8 @@ class Partition():
> > > Prepare content for individual partitions, depending on
> > > partition command parameters.
> > > """
> > > + # capture the sector size requested on the CLI for mkdosfs
> > > invocations
> > > + self.sector_size = getattr(creator, 'sector_size', 512) or 512
> > > self.updated_fstab_path = updated_fstab_path
> > > if self.updated_fstab_path and not
> (self.fstype.startswith("ext")
> > > or self.fstype == "msdos"):
> > > self.update_fstab_in_rootfs = True
> > > @@ -293,7 +339,7 @@ class Partition():
> > > with open(rootfs, 'w') as sparse:
> > > os.ftruncate(sparse.fileno(), rootfs_size * 1024)
> > >
> > > - extraopts = self.mkfs_extraopts or "-F -i 8192"
> > > + extraopts = self._mkfs_ext_extraopts("-F -i 8192")
> > >
> > > # use hash_seed to generate reproducible ext4 images
> > > (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts,
> pseudo)
> > > @@ -401,7 +447,7 @@ class Partition():
> > >
> > > size_str = ""
> > >
> > > - extraopts = self.mkfs_extraopts or '-S 512'
> > > + extraopts = self._mkdosfs_extraopts()
> > >
> > > dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
> > > (label_str, self.fsuuid, size_str, extraopts,
> rootfs,
> > > @@ -452,7 +498,7 @@ class Partition():
> > > with open(rootfs, 'w') as sparse:
> > > os.ftruncate(sparse.fileno(), size * 1024)
> > >
> > > - extraopts = self.mkfs_extraopts or "-i 8192"
> > > + extraopts = self._mkfs_ext_extraopts("-i 8192")
> > >
> > > # use hash_seed to generate reproducible ext4 images
> > > (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts, None)
> > > @@ -498,7 +544,7 @@ class Partition():
> > >
> > > size_str = ""
> > >
> > > - extraopts = self.mkfs_extraopts or '-S 512'
> > > + extraopts = self._mkdosfs_extraopts()
> > >
> > > dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
> > > (label_str, self.fsuuid, extraopts, size_str,
> rootfs,
> > > @@ -559,4 +605,3 @@ class Partition():
> > > logger.warn("%s Inodes (of size %d) are too
> small." %
> > > (get_err_str(self), size))
> > > break
> > > -
> > > diff --git a/scripts/lib/wic/plugins/imager/direct.py
> > > b/scripts/lib/wic/plugins/imager/direct.py
> > > index ad922cfbf122..3adc6eee6280 100644
> > > --- a/scripts/lib/wic/plugins/imager/direct.py
> > > +++ b/scripts/lib/wic/plugins/imager/direct.py
> > > @@ -67,6 +67,7 @@ class DirectPlugin(ImagerPlugin):
> > > self._image = None
> > > self.ptable_format = self.ks.bootloader.ptable
> > > self.parts = self.ks.partitions
> > > + self.sector_size = options.sector_size or 512
> > >
> > > # as a convenience, set source to the boot partition source
> > > # instead of forcing it to be set via bootloader --source
> > > @@ -78,7 +79,7 @@ class DirectPlugin(ImagerPlugin):
> > > image_path = self._full_path(self.workdir, self.parts[0].disk,
> > > "direct")
> > > self._image = PartitionedImage(image_path, self.ptable_format,
> > > self.ks.bootloader.diskid,
> > > self.parts,
> self.native_sysroot,
> > > - options.extra_space)
> > > + options.extra_space,
> > > self.sector_size)
> > >
> > > def setup_workdir(self, workdir):
> > > if workdir:
> > > @@ -294,15 +295,13 @@ MBR_OVERHEAD = 1
> > > # Overhead of the GPT partitioning scheme
> > > GPT_OVERHEAD = 34
> > >
> > > -# Size of a sector in bytes
> > > -SECTOR_SIZE = 512
> > > -
> > > class PartitionedImage():
> > > """
> > > Partitioned image in a file.
> > > """
> > >
> > > - def __init__(self, path, ptable_format, disk_id, partitions,
> > > native_sysroot=None, extra_space=0):
> > > + def __init__(self, path, ptable_format, disk_id, partitions,
> > > native_sysroot=None, extra_space=0,
> > > + sector_size=512):
> > > self.path = path # Path to the image file
> > > self.numpart = 0 # Number of allocated partitions
> > > self.realpart = 0 # Number of partitions in the partition
> table
> > > @@ -332,14 +331,7 @@ class PartitionedImage():
> > > self.partitions = partitions
> > > self.partimages = []
> > > # Size of a sector used in calculations
> > > - sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
> > > - if sector_size_str is not None:
> > > - try:
> > > - self.sector_size = int(sector_size_str)
> > > - except ValueError:
> > > - self.sector_size = SECTOR_SIZE
> > > - else:
> > > - self.sector_size = SECTOR_SIZE
> > > + self.sector_size = sector_size or 512
> > >
> > > self.native_sysroot = native_sysroot
> > > num_real_partitions = len([p for p in self.partitions if not
> > > p.no_table])
> > > diff --git a/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > b/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > index 430b0a4b023a..864d6898fc9d 100644
> > > --- a/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > +++ b/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > @@ -415,8 +415,9 @@ class BootimgEFIPlugin(SourcePlugin):
> > >
> > > label = part.label if part.label else "ESP"
> > >
> > > - dosfs_cmd = "mkdosfs -v -n %s -i %s -C %s %d" % \
> > > - (label, part.fsuuid, bootimg, blocks)
> > > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > > + dosfs_cmd = "mkdosfs -v -n %s -i %s -S %d -C %s %d" % \
> > > + (label, part.fsuuid, sector_size, bootimg, blocks)
> > > exec_native_cmd(dosfs_cmd, native_sysroot)
> > > logger.debug("mkdosfs:\n%s" % (str(out)))
> > >
> > > diff --git a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > index a7cc5d12c620..32edac47fa09 100644
> > > --- a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > +++ b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > @@ -132,7 +132,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > cls._do_prepare_grub(part, cr_workdir, oe_builddir,
> > > kernel_dir, rootfs_dir,
> native_sysroot)
> > > elif source_params['loader-bios'] == 'syslinux':
> > > - cls._do_prepare_syslinux(part, cr_workdir,
> bootimg_dir,
> > > + cls._do_prepare_syslinux(part, creator, cr_workdir,
> > > bootimg_dir,
> > > kernel_dir, native_sysroot)
> > > else:
> > > raise WicError("unrecognized bootimg_pcbios loader:
> %s" %
> > > source_params['loader-bios'])
> > > @@ -142,7 +142,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > except KeyError:
> > > # Required by do_install_disk
> > > cls.loader = 'syslinux'
> > > - cls._do_prepare_syslinux(part, cr_workdir, bootimg_dir,
> > > + cls._do_prepare_syslinux(part, creator, cr_workdir,
> > > bootimg_dir,
> > > kernel_dir, native_sysroot)
> > >
> > > @classmethod
> > > @@ -240,7 +240,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > cfg.close()
> > >
> > > @classmethod
> > > - def _do_prepare_syslinux(cls, part, cr_workdir, bootimg_dir,
> > > + def _do_prepare_syslinux(cls, part, creator, cr_workdir,
> bootimg_dir,
> > > kernel_dir, native_sysroot):
> > > """
> > > Called to do the actual content population for a partition
> i.e. it
> > > @@ -292,8 +292,9 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > >
> > > label = part.label if part.label else "boot"
> > >
> > > - dosfs_cmd = "mkdosfs -n %s -i %s -S 512 -C %s %d" % \
> > > - (label, part.fsuuid, bootimg, blocks)
> > > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > > + dosfs_cmd = "mkdosfs -n %s -i %s -S %d -C %s %d" % \
> > > + (label, part.fsuuid, sector_size, bootimg, blocks)
> > > exec_native_cmd(dosfs_cmd, native_sysroot)
> > >
> > > mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
> > > diff --git a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > index fdab188db1f8..9195ef5f3184 100644
> > > --- a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > +++ b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > @@ -367,8 +367,9 @@ class IsoImagePlugin(SourcePlugin):
> > >
> > > esp_label = source_params.get('esp_label', 'EFIimg')
> > >
> > > - dosfs_cmd = 'mkfs.vfat -n \'%s\' -S 512 -C %s %d' \
> > > - % (esp_label, bootimg, blocks)
> > > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > > + dosfs_cmd = "mkfs.vfat -n '%s' -S %d -C %s %d" % \
> > > + (esp_label, sector_size, bootimg, blocks)
> > > exec_native_cmd(dosfs_cmd, native_sysroot)
> > >
> > > mmd_cmd = "mmd -i %s ::/EFI" % bootimg
> > > diff --git a/scripts/wic b/scripts/wic
> > > index 9137208f5e8f..0cef84ef630c 100755
> > > --- a/scripts/wic
> > > +++ b/scripts/wic
> > > @@ -376,6 +376,8 @@ def wic_init_parser_create(subparser):
> > > default="direct", help="the wic imager plugin")
> > > subparser.add_argument("--extra-space", type=int,
> dest="extra_space",
> > > default=0, help="additional free disk space to
> add
> > > to the image")
> > > + subparser.add_argument("--sector-size", dest="sector_size",
> type=int,
> > > default=512,
> > > + help="sector size in bytes (default: 512)")
> > > return
> > >
> > >
> > > @@ -413,6 +415,8 @@ def imgtype(arg):
> > > def wic_init_parser_ls(subparser):
> > > subparser.add_argument("path", type=imgtype,
> > > help="image spec: <image>[:<vfat
> > > partition>[<path>]]")
> > > + subparser.add_argument("--sector-size", dest="sector_size",
> type=int,
> > > default=512,
> > > + help="sector size in bytes (default: 512)")
> > > subparser.add_argument("-n", "--native-sysroot",
> > > help="path to the native sysroot containing
> the
> > > tools")
> > > subparser.add_argument("-e", "--image-name", dest="image_name",
> > > @@ -433,6 +437,8 @@ def wic_init_parser_cp(subparser):
> > > help="image spec: <image>:<vfat
> > > partition>[<path>] or <file>")
> > > subparser.add_argument("dest",
> > > help="image spec: <image>:<vfat
> > > partition>[<path>] or <file>")
> > > + subparser.add_argument("--sector-size", dest="sector_size",
> type=int,
> > > default=512,
> > > + help="sector size in bytes (default: 512)")
> > > subparser.add_argument("-n", "--native-sysroot",
> > > help="path to the native sysroot containing
> the
> > > tools")
> > > subparser.add_argument("-e", "--image-name", dest="image_name",
> > > @@ -445,6 +451,8 @@ def wic_init_parser_cp(subparser):
> > > def wic_init_parser_rm(subparser):
> > > subparser.add_argument("path", type=imgpathtype,
> > > help="path: <image>:<vfat partition><path>")
> > > + subparser.add_argument("--sector-size", dest="sector_size",
> type=int,
> > > default=512,
> > > + help="sector size in bytes (default: 512)")
> > > subparser.add_argument("-n", "--native-sysroot",
> > > help="path to the native sysroot containing
> the
> > > tools")
> > > subparser.add_argument("-r", dest="recursive_delete",
> > > action="store_true", default=False,
> > > --
> > > 2.51.0
> > >
> > >
> > > -=-=-=-=-=-=-=-=-=-=-=-
> > > Links: You receive all messages sent to this group.
> > > View/Reply Online (#231176):
> > > https://lists.openembedded.org/g/openembedded-core/message/231176
> > > Mute This Topic: https://lists.openembedded.org/mt/117833550/1050810
> > > Group Owner: openembedded-core+owner@lists.openembedded.org
> > > Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub
> [
> > > bruce.ashfield@gmail.com]
> > > -=-=-=-=-=-=-=-=-=-=-=-
> > >
> > >
> >
> > --
> > - Thou shalt not follow the NULL pointer, for chaos and madness await
> thee
> > at its end
> > - "Use the force Harry" - Gandalf, Star Trek II
>
--
- Thou shalt not follow the NULL pointer, for chaos and madness await thee
at its end
- "Use the force Harry" - Gandalf, Star Trek II
[-- Attachment #2: Type: text/html, Size: 49705 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [OE-core] [PATCH v3 1/2] wic: re-implement sector-size support
2026-02-16 16:01 ` Bruce Ashfield
@ 2026-02-16 17:58 ` Trevor Woerner
2026-02-16 18:49 ` Bruce Ashfield
0 siblings, 1 reply; 8+ messages in thread
From: Trevor Woerner @ 2026-02-16 17:58 UTC (permalink / raw)
To: Bruce Ashfield; +Cc: openembedded-core
On Mon 2026-02-16 @ 11:01:28 AM, Bruce Ashfield wrote:
> On Mon, Feb 16, 2026 at 10:37 AM Trevor Woerner <twoerner@gmail.com> wrote:
>
> > On Sun 2026-02-15 @ 10:09:03 PM, Bruce Ashfield wrote:
> > > On Sun, Feb 15, 2026 at 9:32 PM Trevor Woerner via
> > lists.openembedded.org
> > > <twoerner=gmail.com@lists.openembedded.org> wrote:
> > >
> > > > The previous implementation to add variable sector-size support:
> > > > - required the variable WIC_SECTOR_SIZE either be defined in a
> > > > configuration file or be defined in a --vars file
> > > > - this means that every invocation of "wic ls", "wic cp", or "wic rm"
> > > > needed this variable defined (config or --vars)
> > > > - required the user to create separate *wks files for every sector size
> > > > they wanted to use
> > > > - required the user to specify the mkfs-extraopts by hand to specify
> > the
> > > > correct sector size: e.g.
> > > > bootloader --ptable gpt
> > > > part --fstype ext4 --source rootfs --label rofs-a
> > --mkfs-extraopts
> > > > "-b 4096"
> > > > part --fstype ext4 --source rootfs --use-uuid --mkfs-extraopts
> > "-b
> > > > 4096"
> > > > - specifying --mkfs-extraopts replaces the defaults with the
> > > > user-supplied values
> > > > - only provided details to support using variable sector-sizes with
> > > > ext[234] filesystems
> > > > - it would not be possible to generate images with different sector
> > > > sizes in the same build since the configuration and *wks files would
> > > > need to change and the build re-run for each size
> > > >
> > > > Update the sector-size handling so that:
> > > > - the sector-size will now be provided on the cmdline to the "wic ls",
> > > > "wic cp", "wic rm", and "wic create" commands: default = 512
> > > > - this means the configuration and/or --vars file does not need to be
> > > > changed in order to perform those operations on images with different
> > > > sector sizes
> > > > - support is provided implicitly for mkdosfs and ext[234] partitions
> > > > - the user no longer needs to know and supply the sector-size magic in
> > > > --mkfs-extraopts (thereby clobbering the other defaults)
> > > >
> > >
> > > It wasn't clear to me when scanning the patch. For configuration
> > > files with a sector size, is it now completely ignored ?
> >
> > Yes.
> >
> > While trying to use the existing implementation in actual production
> > workflows we found a number of shortcomings that are addressed with this
> > update. Additionally, the ultimate goal is to make wic an independent
> > utility from oe-core so it can be easily used by external tools
> > post-build.
> >
> > If sector-size is not available on the cmdline, then a --vars file would
> > be needed for every simple wic invocation such as "wic cp", "wic ls",
> > and "wic rm"... which would be silly. Take a look at the patch I
> > submitted a week or so ago to see how the oe-selftests would have to be
> > updated to support this.
> >
> > If sector-size is available both on the cmdline and in a --vars file
> > then which one wins? Ultimately having it specified in both places is
> > only going to lead to confusion as people will be changing it in one
> > place and not realizing it's also defined (and taking precedence) from
> > somewhere else. I believe this is currently the case with
> > --native-sysroot, which probably needs fixing as well since several
> > oe-selftests are trying to use it, but I doubt it is working the way the
> > test writers expect.
>
>
> > One parameter specified in one place so a user would not need multiple
> > sets of configuration files to perform a simple "wic ls" of images with
> > different sector sizes; simply specify it on the cmdline if you want
> > something other than 512.
> >
>
> That's not a good migration path. You can't simply throw away
> someone's existing configuration and ask them to update to a
> new one. I didn't even see an error thrown with migration
> instructions.
>
> There's many different users of things like this, we can't simply
> change the interface without some way to migrate.
I don't disagree with you entirely.
But if the user specifies --sector-size <N> on the cmdline, they will
expect the sector-size to be N. If they don't specify this on the
cmdline, they would rightfully expect the default of 512 to be used...
...unless some configuration file anywhere in their build specifies
WIC_SECTOR_SIZE, in which case wic is supposed to use that value?
I could print a warning if sector size is set via WIC_SECTOR_SIZE?
>
> Bruce
>
>
>
> >
> > > Apologies if I missed where existing configs were used to prime
> > > the parameters to the functions.
> > >
> > > Bruce
> > >
> > >
> > >
> > > >
> > > > AI-Generated: codex/gpt-5.1-codex-max
> > > > Signed-off-by: Trevor Woerner <twoerner@gmail.com>
> > > > ---
> > > > changes since v2:
> > > > - none
> > > >
> > > > changes since v1:
> > > > - none
> > > > ---
> > > > meta/lib/oeqa/selftest/cases/wic.py | 39 ++++---------
> > > > scripts/lib/wic/engine.py | 45 +++++++--------
> > > > scripts/lib/wic/help.py | 23 +++++---
> > > > scripts/lib/wic/partition.py | 55 +++++++++++++++++--
> > > > scripts/lib/wic/plugins/imager/direct.py | 18 ++----
> > > > scripts/lib/wic/plugins/source/bootimg_efi.py | 5 +-
> > > > .../lib/wic/plugins/source/bootimg_pcbios.py | 11 ++--
> > > > .../wic/plugins/source/isoimage_isohybrid.py | 5 +-
> > > > scripts/wic | 8 +++
> > > > 9 files changed, 125 insertions(+), 84 deletions(-)
> > > >
> > > > diff --git a/meta/lib/oeqa/selftest/cases/wic.py
> > > > b/meta/lib/oeqa/selftest/cases/wic.py
> > > > index ecaee5a29144..7ad61fa700f7 100644
> > > > --- a/meta/lib/oeqa/selftest/cases/wic.py
> > > > +++ b/meta/lib/oeqa/selftest/cases/wic.py
> > > > @@ -935,33 +935,22 @@ bootloader --ptable gpt""")
> > > > finally:
> > > > os.remove(wks_file)
> > > >
> > > > - def test_wic_sector_size(self):
> > > > - """Test generation image sector size"""
> > > > -
> > > > + def test_wic_sector_size_cli(self):
> > > > + """Test sector size handling via CLI option."""
> > > > +
> > > > oldpath = os.environ['PATH']
> > > > os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
> > > >
> > > > try:
> > > > - # Add WIC_SECTOR_SIZE into config
> > > > - config = 'WIC_SECTOR_SIZE = "4096"\n'\
> > > > - 'WICVARS:append = " WIC_SECTOR_SIZE"\n'
> > > > - self.append_config(config)
> > > > bitbake('core-image-minimal')
> > > >
> > > > - # Check WIC_SECTOR_SIZE apply to bitbake variable
> > > > - wic_sector_size_str = get_bb_var('WIC_SECTOR_SIZE',
> > > > 'core-image-minimal')
> > > > - wic_sector_size = int(wic_sector_size_str)
> > > > - self.assertEqual(4096, wic_sector_size)
> > > > -
> > > > - self.logger.info("Test wic_sector_size: %d \n" %
> > > > wic_sector_size)
> > > > -
> > > > with NamedTemporaryFile("w", suffix=".wks") as wks:
> > > > wks.writelines(
> > > > ['bootloader --ptable gpt\n',
> > > > - 'part --fstype ext4 --source rootfs --label
> > rofs-a
> > > > --mkfs-extraopts "-b 4096"\n',
> > > > - 'part --fstype ext4 --source rootfs --use-uuid
> > > > --mkfs-extraopts "-b 4096"\n'])
> > > > + 'part --fstype ext4 --source rootfs --label
> > > > rofs-a\n',
> > > > + 'part --fstype ext4 --source rootfs
> > --use-uuid\n'])
> > > > wks.flush()
> > > > - cmd = "wic create %s -e core-image-minimal -o %s" % (
> > > > wks.name, self.resultdir)
> > > > + cmd = "wic create %s -e core-image-minimal -o %s
> > > > --sector-size 4096" % (wks.name, self.resultdir)
> > > > runCmd(cmd)
> > > > wksname = os.path.splitext(os.path.basename(wks.name
> > ))[0]
> > > > images = glob(os.path.join(self.resultdir,
> > "%s-*direct" %
> > > > wksname))
> > > > @@ -969,24 +958,18 @@ bootloader --ptable gpt""")
> > > >
> > > > sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
> > > > # list partitions
> > > > - result = runCmd("wic ls %s -n %s" % (images[0], sysroot))
> > > > + result = runCmd("wic ls %s -n %s --sector-size 4096" %
> > > > (images[0], sysroot))
> > > > self.assertEqual(3, len(result.output.split('\n')))
> > > >
> > > > - # verify partition size with wic
> > > > - res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m %s
> > unit
> > > > b p" % (wic_sector_size, images[0]),
> > > > + # verify partition size with parted output
> > > > + res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m %s
> > unit
> > > > b p" % (4096, images[0]),
> > > > stderr=subprocess.PIPE)
> > > >
> > > > - # parse parted output which looks like this:
> > > > - # BYT;\n
> > > > - #
> > > >
> > /var/tmp/wic/build/tmpgjzzefdd-202410281021-sda.direct:78569472B:file:4096:4096:gpt::;\n
> > > > - # 1:139264B:39284735B:39145472B:ext4:rofs-a:;\n
> > > > - # 2:39284736B:78430207B:39145472B:ext4:primary:;\n
> > > > disk_info = res.output.splitlines()[1]
> > > > - # Check sector sizes
> > > > sector_size_logical = int(disk_info.split(":")[3])
> > > > sector_size_physical = int(disk_info.split(":")[4])
> > > > - self.assertEqual(wic_sector_size, sector_size_logical,
> > > > "Logical sector size is not %d." % wic_sector_size)
> > > > - self.assertEqual(wic_sector_size, sector_size_physical,
> > > > "Physical sector size is not %d." % wic_sector_size)
> > > > + self.assertEqual(4096, sector_size_logical, "Logical
> > sector
> > > > size is not 4096.")
> > > > + self.assertEqual(4096, sector_size_physical, "Physical
> > sector
> > > > size is not 4096.")
> > > >
> > > > finally:
> > > > os.environ['PATH'] = oldpath
> > > > diff --git a/scripts/lib/wic/engine.py b/scripts/lib/wic/engine.py
> > > > index 9d596be3a723..7753f431f91d 100644
> > > > --- a/scripts/lib/wic/engine.py
> > > > +++ b/scripts/lib/wic/engine.py
> > > > @@ -224,7 +224,7 @@ def wic_list(args, scripts_path):
> > > >
> > > >
> > > > class Disk:
> > > > - def __init__(self, imagepath, native_sysroot, fstypes=('fat',
> > 'ext')):
> > > > + def __init__(self, imagepath, native_sysroot, fstypes=('fat',
> > 'ext'),
> > > > sector_size=512):
> > > > self.imagepath = imagepath
> > > > self.native_sysroot = native_sysroot
> > > > self.fstypes = fstypes
> > > > @@ -233,16 +233,7 @@ class Disk:
> > > > self._lsector_size = None
> > > > self._psector_size = None
> > > > self._ptable_format = None
> > > > -
> > > > - # define sector size
> > > > - sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
> > > > - if sector_size_str is not None:
> > > > - try:
> > > > - self.sector_size = int(sector_size_str)
> > > > - except ValueError:
> > > > - self.sector_size = None
> > > > - else:
> > > > - self.sector_size = None
> > > > + self.sector_size = sector_size
> > > >
> > > > # find parted
> > > > # read paths from $PATH environment variable
> > > > @@ -271,7 +262,7 @@ class Disk:
> > > > if self._partitions is None:
> > > > self._partitions = OrderedDict()
> > > >
> > > > - if self.sector_size is not None:
> > > > + if self.sector_size:
> > > > out = exec_cmd("export PARTED_SECTOR_SIZE=%d; %s -sm
> > %s
> > > > unit B print" % \
> > > > (self.sector_size, self.parted,
> > > > self.imagepath), True)
> > > > else:
> > > > @@ -312,11 +303,15 @@ class Disk:
> > > > raise WicError("Partition %s is not in the image" % pnum)
> > > > part = self.partitions[pnum]
> > > > # check if fstype is supported
> > > > + # NOTE: parted is unable to identify dos-type partitions with
> > a
> > > > 4k sector-size
> > > > + # if the type is empty and a non-default sector size is
> > > > used, assume 'fat'
> > > > + # fdisk identifies them without issue
> > > > + part_fstype = part.fstype if part.fstype or self.sector_size
> > ==
> > > > 512 else 'fat'
> > > > for fstype in self.fstypes:
> > > > - if part.fstype.startswith(fstype):
> > > > + if part_fstype.startswith(fstype):
> > > > break
> > > > else:
> > > > - raise WicError("Not supported fstype:
> > {}".format(part.fstype))
> > > > + raise WicError("Not supported fstype:
> > {}".format(part_fstype))
> > > > if pnum not in self._partimages:
> > > > tmpf = tempfile.NamedTemporaryFile(prefix="wic-part")
> > > > dst_fname = tmpf.name
> > > > @@ -586,8 +581,9 @@ class Disk:
> > > > label = part.get("name")
> > > > label_str = "-n {}".format(label) if label
> > > > else ''
> > > >
> > > > - cmd = "{} {} -C {}
> > {}".format(self.mkdosfs,
> > > > label_str, partfname,
> > > > -
> > part['size'])
> > > > + sector_str = "-S
> > {}".format(self.sector_size)
> > > > if self.sector_size else ''
> > > > + cmd = "{} {} {} -C {}
> > > > {}".format(self.mkdosfs, label_str, sector_str, partfname,
> > > > +
> > part['size'])
> > > > exec_cmd(cmd)
> > > > # copy content from the temporary
> > directory
> > > > to the new partition
> > > > cmd = "{} -snompi {} {}/*
> > > > ::".format(self.mcopy, partfname, tmpdir)
> > > > @@ -609,14 +605,19 @@ class Disk:
> > > >
> > > > def wic_ls(args, native_sysroot):
> > > > """List contents of partitioned image or vfat partition."""
> > > > - disk = Disk(args.path.image, native_sysroot)
> > > > + disk = Disk(args.path.image, native_sysroot,
> > > > sector_size=args.sector_size)
> > > > if not args.path.part:
> > > > if disk.partitions:
> > > > print('Num Start End Size
> > Fstype')
> > > > for part in disk.partitions.values():
> > > > + # size values are in bytes from parted; convert to
> > > > sectors if a custom sector size was requested
> > > > + display_size = part.size
> > > > + if args.sector_size and args.sector_size !=
> > > > disk._lsector_size:
> > > > + display_size = part.size // args.sector_size
> > > > print("{:2d} {:12d} {:12d} {:12d} {}".format(\
> > > > - part.pnum, part.start, part.end,
> > > > - part.size, part.fstype))
> > > > + part.pnum, part.start // args.sector_size,
> > > > + part.end // args.sector_size,
> > > > + display_size, part.fstype))
> > > > else:
> > > > path = args.path.path or '/'
> > > > print(disk.dir(args.path.part, path))
> > > > @@ -627,9 +628,9 @@ def wic_cp(args, native_sysroot):
> > > > partitioned image.
> > > > """
> > > > if isinstance(args.dest, str):
> > > > - disk = Disk(args.src.image, native_sysroot)
> > > > + disk = Disk(args.src.image, native_sysroot,
> > > > sector_size=args.sector_size)
> > > > else:
> > > > - disk = Disk(args.dest.image, native_sysroot)
> > > > + disk = Disk(args.dest.image, native_sysroot,
> > > > sector_size=args.sector_size)
> > > > disk.copy(args.src, args.dest)
> > > >
> > > >
> > > > @@ -638,7 +639,7 @@ def wic_rm(args, native_sysroot):
> > > > Remove files or directories from the vfat partition of
> > > > partitioned image.
> > > > """
> > > > - disk = Disk(args.path.image, native_sysroot)
> > > > + disk = Disk(args.path.image, native_sysroot,
> > > > sector_size=args.sector_size)
> > > > disk.remove(args.path.part, args.path.path, args.recursive_delete)
> > > >
> > > > def wic_write(args, native_sysroot):
> > > > diff --git a/scripts/lib/wic/help.py b/scripts/lib/wic/help.py
> > > > index 6b49a67de938..5d7c40456a80 100644
> > > > --- a/scripts/lib/wic/help.py
> > > > +++ b/scripts/lib/wic/help.py
> > > > @@ -118,7 +118,7 @@ wic_create_usage = """
> > > > usage: wic create <wks file or image name> [-o <DIRNAME> | --outdir
> > > > <DIRNAME>]
> > > > [-e | --image-name] [-s, --skip-build-check] [-D, --debug]
> > > > [-r, --rootfs-dir] [-b, --bootimg-dir]
> > > > - [-k, --kernel-dir] [-n, --native-sysroot] [-f,
> > --build-rootfs]
> > > > + [-k, --kernel-dir] [-n, --native-sysroot] [--sector-size
> > > > <bytes>] [-f, --build-rootfs]
> > > > [-c, --compress-with] [-m, --bmap]
> > > >
> > > > This command creates an OpenEmbedded image based on the 'OE kickstart
> > > > @@ -139,13 +139,16 @@ SYNOPSIS
> > > > wic create <wks file or image name> [-o <DIRNAME> | --outdir
> > > > <DIRNAME>]
> > > > [-e | --image-name] [-s, --skip-build-check] [-D, --debug]
> > > > [-r, --rootfs-dir] [-b, --bootimg-dir]
> > > > - [-k, --kernel-dir] [-n, --native-sysroot] [-f, --build-rootfs]
> > > > + [-k, --kernel-dir] [-n, --native-sysroot] [--sector-size
> > <bytes>]
> > > > [-f, --build-rootfs]
> > > > [-c, --compress-with] [-m, --bmap] [--no-fstab-update]
> > > >
> > > > DESCRIPTION
> > > > This command creates an OpenEmbedded image based on the 'OE
> > > > kickstart commands' found in the <wks file>.
> > > >
> > > > + Use the --sector-size option to select the sector size (in bytes)
> > > > + used for partition layout calculations (default is 512).
> > > > +
> > > > In order to do this, wic needs to know the locations of the
> > > > various build artifacts required to build the image.
> > > >
> > > > @@ -278,7 +281,7 @@ wic_ls_usage = """
> > > >
> > > > List content of a partitioned image
> > > >
> > > > - usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot <path>]
> > > > + usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot <path>]
> > > > [--sector-size <bytes>]
> > > >
> > > > This command outputs either list of image partitions or directory
> > > > contents
> > > > of vfat and ext* partitions.
> > > > @@ -296,7 +299,7 @@ SYNOPSIS
> > > > wic ls <image>
> > > > wic ls <image>:<vfat or ext* partition>
> > > > wic ls <image>:<vfat or ext* partition><path>
> > > > - wic ls <image>:<vfat or ext* partition><path> --native-sysroot
> > <path>
> > > > + wic ls <image>:<vfat or ext* partition><path> --native-sysroot
> > <path>
> > > > [--sector-size <bytes>]
> > > >
> > > > DESCRIPTION
> > > > This command lists either partitions of the image or directory
> > > > contents
> > > > @@ -336,6 +339,8 @@ DESCRIPTION
> > > >
> > > > The -n option is used to specify the path to the native sysroot
> > > > containing the tools(parted and mtools) to use.
> > > > + The --sector-size option sets the sector size used for partition
> > math
> > > > + (default is 512 bytes).
> > > >
> > > > """
> > > >
> > > > @@ -343,7 +348,7 @@ wic_cp_usage = """
> > > >
> > > > Copy files and directories to/from the vfat or ext* partition
> > > >
> > > > - usage: wic cp <src> <dest> [--native-sysroot <path>]
> > > > + usage: wic cp <src> <dest> [--native-sysroot <path>] [--sector-size
> > > > <bytes>]
> > > >
> > > > source/destination image in format <image>:<partition>[<path>]
> > > >
> > > > @@ -364,7 +369,7 @@ SYNOPSIS
> > > > wic cp <src> <dest>:<partition>
> > > > wic cp <src>:<partition> <dest>
> > > > wic cp <src> <dest-image>:<partition><path>
> > > > - wic cp <src> <dest-image>:<partition><path> --native-sysroot
> > <path>
> > > > + wic cp <src> <dest-image>:<partition><path> --native-sysroot
> > <path>
> > > > [--sector-size <bytes>]
> > > >
> > > > DESCRIPTION
> > > > This command copies files or directories either
> > > > @@ -408,13 +413,15 @@ DESCRIPTION
> > > >
> > > > The -n option is used to specify the path to the native sysroot
> > > > containing the tools(parted and mtools) to use.
> > > > + The --sector-size option sets the sector size used for partition
> > math
> > > > + (default is 512 bytes).
> > > > """
> > > >
> > > > wic_rm_usage = """
> > > >
> > > > Remove files or directories from the vfat or ext* partitions
> > > >
> > > > - usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
> > > > + usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
> > > > [--sector-size <bytes>]
> > > >
> > > > This command removes files or directories from the vfat or ext*
> > > > partitions of
> > > > the partitioned image.
> > > > @@ -466,6 +473,8 @@ DESCRIPTION
> > > >
> > > > The -n option is used to specify the path to the native sysroot
> > > > containing the tools(parted and mtools) to use.
> > > > + The --sector-size option sets the sector size used for partition
> > math
> > > > + (default is 512 bytes).
> > > >
> > > > The -r option is used to remove directories and their contents
> > > > recursively,this only applies to ext* partition.
> > > > diff --git a/scripts/lib/wic/partition.py
> > b/scripts/lib/wic/partition.py
> > > > index 8fed686e903e..df6e3271649b 100644
> > > > --- a/scripts/lib/wic/partition.py
> > > > +++ b/scripts/lib/wic/partition.py
> > > > @@ -65,6 +65,50 @@ class Partition():
> > > >
> > > > self.lineno = lineno
> > > > self.source_file = ""
> > > > + self.sector_size = 512
> > > > +
> > > > + def _mkdosfs_extraopts(self):
> > > > + """
> > > > + Build mkdosfs extra options ensuring the CLI sector size is
> > > > applied.
> > > > + """
> > > > + extraopts = self.mkfs_extraopts or ''
> > > > + tokens = []
> > > > + skip_next = False
> > > > + for tok in extraopts.split():
> > > > + if skip_next:
> > > > + skip_next = False
> > > > + continue
> > > > + if tok == '-S':
> > > > + skip_next = True
> > > > + continue
> > > > + if tok.startswith('-S'):
> > > > + continue
> > > > + tokens.append(tok)
> > > > + tokens.extend(['-S', str(self.sector_size)])
> > > > + return ' '.join(tokens).strip()
> > > > +
> > > > + def _mkfs_ext_extraopts(self, base_opts):
> > > > + """
> > > > + Build mkfs.ext* extra options ensuring the CLI sector size is
> > > > applied.
> > > > + """
> > > > + extraopts = self.mkfs_extraopts or base_opts
> > > > + # Only add an explicit block size when a non-default sector
> > size
> > > > is requested.
> > > > + if self.sector_size and self.sector_size != 512:
> > > > + tokens = []
> > > > + skip_next = False
> > > > + for tok in extraopts.split():
> > > > + if skip_next:
> > > > + skip_next = False
> > > > + continue
> > > > + if tok == '-b':
> > > > + skip_next = True
> > > > + continue
> > > > + if tok.startswith('-b'):
> > > > + continue
> > > > + tokens.append(tok)
> > > > + tokens.extend(['-b', str(self.sector_size)])
> > > > + return ' '.join(tokens).strip()
> > > > + return extraopts
> > > >
> > > > def get_extra_block_count(self, current_blocks):
> > > > """
> > > > @@ -138,6 +182,8 @@ class Partition():
> > > > Prepare content for individual partitions, depending on
> > > > partition command parameters.
> > > > """
> > > > + # capture the sector size requested on the CLI for mkdosfs
> > > > invocations
> > > > + self.sector_size = getattr(creator, 'sector_size', 512) or 512
> > > > self.updated_fstab_path = updated_fstab_path
> > > > if self.updated_fstab_path and not
> > (self.fstype.startswith("ext")
> > > > or self.fstype == "msdos"):
> > > > self.update_fstab_in_rootfs = True
> > > > @@ -293,7 +339,7 @@ class Partition():
> > > > with open(rootfs, 'w') as sparse:
> > > > os.ftruncate(sparse.fileno(), rootfs_size * 1024)
> > > >
> > > > - extraopts = self.mkfs_extraopts or "-F -i 8192"
> > > > + extraopts = self._mkfs_ext_extraopts("-F -i 8192")
> > > >
> > > > # use hash_seed to generate reproducible ext4 images
> > > > (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts,
> > pseudo)
> > > > @@ -401,7 +447,7 @@ class Partition():
> > > >
> > > > size_str = ""
> > > >
> > > > - extraopts = self.mkfs_extraopts or '-S 512'
> > > > + extraopts = self._mkdosfs_extraopts()
> > > >
> > > > dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
> > > > (label_str, self.fsuuid, size_str, extraopts,
> > rootfs,
> > > > @@ -452,7 +498,7 @@ class Partition():
> > > > with open(rootfs, 'w') as sparse:
> > > > os.ftruncate(sparse.fileno(), size * 1024)
> > > >
> > > > - extraopts = self.mkfs_extraopts or "-i 8192"
> > > > + extraopts = self._mkfs_ext_extraopts("-i 8192")
> > > >
> > > > # use hash_seed to generate reproducible ext4 images
> > > > (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts, None)
> > > > @@ -498,7 +544,7 @@ class Partition():
> > > >
> > > > size_str = ""
> > > >
> > > > - extraopts = self.mkfs_extraopts or '-S 512'
> > > > + extraopts = self._mkdosfs_extraopts()
> > > >
> > > > dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
> > > > (label_str, self.fsuuid, extraopts, size_str,
> > rootfs,
> > > > @@ -559,4 +605,3 @@ class Partition():
> > > > logger.warn("%s Inodes (of size %d) are too
> > small." %
> > > > (get_err_str(self), size))
> > > > break
> > > > -
> > > > diff --git a/scripts/lib/wic/plugins/imager/direct.py
> > > > b/scripts/lib/wic/plugins/imager/direct.py
> > > > index ad922cfbf122..3adc6eee6280 100644
> > > > --- a/scripts/lib/wic/plugins/imager/direct.py
> > > > +++ b/scripts/lib/wic/plugins/imager/direct.py
> > > > @@ -67,6 +67,7 @@ class DirectPlugin(ImagerPlugin):
> > > > self._image = None
> > > > self.ptable_format = self.ks.bootloader.ptable
> > > > self.parts = self.ks.partitions
> > > > + self.sector_size = options.sector_size or 512
> > > >
> > > > # as a convenience, set source to the boot partition source
> > > > # instead of forcing it to be set via bootloader --source
> > > > @@ -78,7 +79,7 @@ class DirectPlugin(ImagerPlugin):
> > > > image_path = self._full_path(self.workdir, self.parts[0].disk,
> > > > "direct")
> > > > self._image = PartitionedImage(image_path, self.ptable_format,
> > > > self.ks.bootloader.diskid,
> > > > self.parts,
> > self.native_sysroot,
> > > > - options.extra_space)
> > > > + options.extra_space,
> > > > self.sector_size)
> > > >
> > > > def setup_workdir(self, workdir):
> > > > if workdir:
> > > > @@ -294,15 +295,13 @@ MBR_OVERHEAD = 1
> > > > # Overhead of the GPT partitioning scheme
> > > > GPT_OVERHEAD = 34
> > > >
> > > > -# Size of a sector in bytes
> > > > -SECTOR_SIZE = 512
> > > > -
> > > > class PartitionedImage():
> > > > """
> > > > Partitioned image in a file.
> > > > """
> > > >
> > > > - def __init__(self, path, ptable_format, disk_id, partitions,
> > > > native_sysroot=None, extra_space=0):
> > > > + def __init__(self, path, ptable_format, disk_id, partitions,
> > > > native_sysroot=None, extra_space=0,
> > > > + sector_size=512):
> > > > self.path = path # Path to the image file
> > > > self.numpart = 0 # Number of allocated partitions
> > > > self.realpart = 0 # Number of partitions in the partition
> > table
> > > > @@ -332,14 +331,7 @@ class PartitionedImage():
> > > > self.partitions = partitions
> > > > self.partimages = []
> > > > # Size of a sector used in calculations
> > > > - sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
> > > > - if sector_size_str is not None:
> > > > - try:
> > > > - self.sector_size = int(sector_size_str)
> > > > - except ValueError:
> > > > - self.sector_size = SECTOR_SIZE
> > > > - else:
> > > > - self.sector_size = SECTOR_SIZE
> > > > + self.sector_size = sector_size or 512
> > > >
> > > > self.native_sysroot = native_sysroot
> > > > num_real_partitions = len([p for p in self.partitions if not
> > > > p.no_table])
> > > > diff --git a/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > > b/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > > index 430b0a4b023a..864d6898fc9d 100644
> > > > --- a/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > > +++ b/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > > @@ -415,8 +415,9 @@ class BootimgEFIPlugin(SourcePlugin):
> > > >
> > > > label = part.label if part.label else "ESP"
> > > >
> > > > - dosfs_cmd = "mkdosfs -v -n %s -i %s -C %s %d" % \
> > > > - (label, part.fsuuid, bootimg, blocks)
> > > > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > > > + dosfs_cmd = "mkdosfs -v -n %s -i %s -S %d -C %s %d" % \
> > > > + (label, part.fsuuid, sector_size, bootimg, blocks)
> > > > exec_native_cmd(dosfs_cmd, native_sysroot)
> > > > logger.debug("mkdosfs:\n%s" % (str(out)))
> > > >
> > > > diff --git a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > > b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > > index a7cc5d12c620..32edac47fa09 100644
> > > > --- a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > > +++ b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > > @@ -132,7 +132,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > > cls._do_prepare_grub(part, cr_workdir, oe_builddir,
> > > > kernel_dir, rootfs_dir,
> > native_sysroot)
> > > > elif source_params['loader-bios'] == 'syslinux':
> > > > - cls._do_prepare_syslinux(part, cr_workdir,
> > bootimg_dir,
> > > > + cls._do_prepare_syslinux(part, creator, cr_workdir,
> > > > bootimg_dir,
> > > > kernel_dir, native_sysroot)
> > > > else:
> > > > raise WicError("unrecognized bootimg_pcbios loader:
> > %s" %
> > > > source_params['loader-bios'])
> > > > @@ -142,7 +142,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > > except KeyError:
> > > > # Required by do_install_disk
> > > > cls.loader = 'syslinux'
> > > > - cls._do_prepare_syslinux(part, cr_workdir, bootimg_dir,
> > > > + cls._do_prepare_syslinux(part, creator, cr_workdir,
> > > > bootimg_dir,
> > > > kernel_dir, native_sysroot)
> > > >
> > > > @classmethod
> > > > @@ -240,7 +240,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > > cfg.close()
> > > >
> > > > @classmethod
> > > > - def _do_prepare_syslinux(cls, part, cr_workdir, bootimg_dir,
> > > > + def _do_prepare_syslinux(cls, part, creator, cr_workdir,
> > bootimg_dir,
> > > > kernel_dir, native_sysroot):
> > > > """
> > > > Called to do the actual content population for a partition
> > i.e. it
> > > > @@ -292,8 +292,9 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > >
> > > > label = part.label if part.label else "boot"
> > > >
> > > > - dosfs_cmd = "mkdosfs -n %s -i %s -S 512 -C %s %d" % \
> > > > - (label, part.fsuuid, bootimg, blocks)
> > > > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > > > + dosfs_cmd = "mkdosfs -n %s -i %s -S %d -C %s %d" % \
> > > > + (label, part.fsuuid, sector_size, bootimg, blocks)
> > > > exec_native_cmd(dosfs_cmd, native_sysroot)
> > > >
> > > > mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
> > > > diff --git a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > > b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > > index fdab188db1f8..9195ef5f3184 100644
> > > > --- a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > > +++ b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > > @@ -367,8 +367,9 @@ class IsoImagePlugin(SourcePlugin):
> > > >
> > > > esp_label = source_params.get('esp_label', 'EFIimg')
> > > >
> > > > - dosfs_cmd = 'mkfs.vfat -n \'%s\' -S 512 -C %s %d' \
> > > > - % (esp_label, bootimg, blocks)
> > > > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > > > + dosfs_cmd = "mkfs.vfat -n '%s' -S %d -C %s %d" % \
> > > > + (esp_label, sector_size, bootimg, blocks)
> > > > exec_native_cmd(dosfs_cmd, native_sysroot)
> > > >
> > > > mmd_cmd = "mmd -i %s ::/EFI" % bootimg
> > > > diff --git a/scripts/wic b/scripts/wic
> > > > index 9137208f5e8f..0cef84ef630c 100755
> > > > --- a/scripts/wic
> > > > +++ b/scripts/wic
> > > > @@ -376,6 +376,8 @@ def wic_init_parser_create(subparser):
> > > > default="direct", help="the wic imager plugin")
> > > > subparser.add_argument("--extra-space", type=int,
> > dest="extra_space",
> > > > default=0, help="additional free disk space to
> > add
> > > > to the image")
> > > > + subparser.add_argument("--sector-size", dest="sector_size",
> > type=int,
> > > > default=512,
> > > > + help="sector size in bytes (default: 512)")
> > > > return
> > > >
> > > >
> > > > @@ -413,6 +415,8 @@ def imgtype(arg):
> > > > def wic_init_parser_ls(subparser):
> > > > subparser.add_argument("path", type=imgtype,
> > > > help="image spec: <image>[:<vfat
> > > > partition>[<path>]]")
> > > > + subparser.add_argument("--sector-size", dest="sector_size",
> > type=int,
> > > > default=512,
> > > > + help="sector size in bytes (default: 512)")
> > > > subparser.add_argument("-n", "--native-sysroot",
> > > > help="path to the native sysroot containing
> > the
> > > > tools")
> > > > subparser.add_argument("-e", "--image-name", dest="image_name",
> > > > @@ -433,6 +437,8 @@ def wic_init_parser_cp(subparser):
> > > > help="image spec: <image>:<vfat
> > > > partition>[<path>] or <file>")
> > > > subparser.add_argument("dest",
> > > > help="image spec: <image>:<vfat
> > > > partition>[<path>] or <file>")
> > > > + subparser.add_argument("--sector-size", dest="sector_size",
> > type=int,
> > > > default=512,
> > > > + help="sector size in bytes (default: 512)")
> > > > subparser.add_argument("-n", "--native-sysroot",
> > > > help="path to the native sysroot containing
> > the
> > > > tools")
> > > > subparser.add_argument("-e", "--image-name", dest="image_name",
> > > > @@ -445,6 +451,8 @@ def wic_init_parser_cp(subparser):
> > > > def wic_init_parser_rm(subparser):
> > > > subparser.add_argument("path", type=imgpathtype,
> > > > help="path: <image>:<vfat partition><path>")
> > > > + subparser.add_argument("--sector-size", dest="sector_size",
> > type=int,
> > > > default=512,
> > > > + help="sector size in bytes (default: 512)")
> > > > subparser.add_argument("-n", "--native-sysroot",
> > > > help="path to the native sysroot containing
> > the
> > > > tools")
> > > > subparser.add_argument("-r", dest="recursive_delete",
> > > > action="store_true", default=False,
> > > > --
> > > > 2.51.0
> > > >
> > > >
> > > > -=-=-=-=-=-=-=-=-=-=-=-
> > > > Links: You receive all messages sent to this group.
> > > > View/Reply Online (#231176):
> > > > https://lists.openembedded.org/g/openembedded-core/message/231176
> > > > Mute This Topic: https://lists.openembedded.org/mt/117833550/1050810
> > > > Group Owner: openembedded-core+owner@lists.openembedded.org
> > > > Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub
> > [
> > > > bruce.ashfield@gmail.com]
> > > > -=-=-=-=-=-=-=-=-=-=-=-
> > > >
> > > >
> > >
> > > --
> > > - Thou shalt not follow the NULL pointer, for chaos and madness await
> > thee
> > > at its end
> > > - "Use the force Harry" - Gandalf, Star Trek II
> >
>
>
> --
> - Thou shalt not follow the NULL pointer, for chaos and madness await thee
> at its end
> - "Use the force Harry" - Gandalf, Star Trek II
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [OE-core] [PATCH v3 1/2] wic: re-implement sector-size support
2026-02-16 17:58 ` Trevor Woerner
@ 2026-02-16 18:49 ` Bruce Ashfield
2026-02-16 19:40 ` Trevor Woerner
0 siblings, 1 reply; 8+ messages in thread
From: Bruce Ashfield @ 2026-02-16 18:49 UTC (permalink / raw)
To: Trevor Woerner; +Cc: openembedded-core
[-- Attachment #1: Type: text/plain, Size: 41605 bytes --]
On Mon, Feb 16, 2026 at 12:58 PM Trevor Woerner <twoerner@gmail.com> wrote:
> On Mon 2026-02-16 @ 11:01:28 AM, Bruce Ashfield wrote:
> > On Mon, Feb 16, 2026 at 10:37 AM Trevor Woerner <twoerner@gmail.com>
> wrote:
> >
> > > On Sun 2026-02-15 @ 10:09:03 PM, Bruce Ashfield wrote:
> > > > On Sun, Feb 15, 2026 at 9:32 PM Trevor Woerner via
> > > lists.openembedded.org
> > > > <twoerner=gmail.com@lists.openembedded.org> wrote:
> > > >
> > > > > The previous implementation to add variable sector-size support:
> > > > > - required the variable WIC_SECTOR_SIZE either be defined in a
> > > > > configuration file or be defined in a --vars file
> > > > > - this means that every invocation of "wic ls", "wic cp", or "wic
> rm"
> > > > > needed this variable defined (config or --vars)
> > > > > - required the user to create separate *wks files for every sector
> size
> > > > > they wanted to use
> > > > > - required the user to specify the mkfs-extraopts by hand to
> specify
> > > the
> > > > > correct sector size: e.g.
> > > > > bootloader --ptable gpt
> > > > > part --fstype ext4 --source rootfs --label rofs-a
> > > --mkfs-extraopts
> > > > > "-b 4096"
> > > > > part --fstype ext4 --source rootfs --use-uuid
> --mkfs-extraopts
> > > "-b
> > > > > 4096"
> > > > > - specifying --mkfs-extraopts replaces the defaults with the
> > > > > user-supplied values
> > > > > - only provided details to support using variable sector-sizes with
> > > > > ext[234] filesystems
> > > > > - it would not be possible to generate images with different sector
> > > > > sizes in the same build since the configuration and *wks files
> would
> > > > > need to change and the build re-run for each size
> > > > >
> > > > > Update the sector-size handling so that:
> > > > > - the sector-size will now be provided on the cmdline to the "wic
> ls",
> > > > > "wic cp", "wic rm", and "wic create" commands: default = 512
> > > > > - this means the configuration and/or --vars file does not need to
> be
> > > > > changed in order to perform those operations on images with
> different
> > > > > sector sizes
> > > > > - support is provided implicitly for mkdosfs and ext[234]
> partitions
> > > > > - the user no longer needs to know and supply the sector-size
> magic in
> > > > > --mkfs-extraopts (thereby clobbering the other defaults)
> > > > >
> > > >
> > > > It wasn't clear to me when scanning the patch. For configuration
> > > > files with a sector size, is it now completely ignored ?
> > >
> > > Yes.
> > >
> > > While trying to use the existing implementation in actual production
> > > workflows we found a number of shortcomings that are addressed with
> this
> > > update. Additionally, the ultimate goal is to make wic an independent
> > > utility from oe-core so it can be easily used by external tools
> > > post-build.
> > >
> > > If sector-size is not available on the cmdline, then a --vars file
> would
> > > be needed for every simple wic invocation such as "wic cp", "wic ls",
> > > and "wic rm"... which would be silly. Take a look at the patch I
> > > submitted a week or so ago to see how the oe-selftests would have to be
> > > updated to support this.
> > >
> > > If sector-size is available both on the cmdline and in a --vars file
> > > then which one wins? Ultimately having it specified in both places is
> > > only going to lead to confusion as people will be changing it in one
> > > place and not realizing it's also defined (and taking precedence) from
> > > somewhere else. I believe this is currently the case with
> > > --native-sysroot, which probably needs fixing as well since several
> > > oe-selftests are trying to use it, but I doubt it is working the way
> the
> > > test writers expect.
> >
> >
> > > One parameter specified in one place so a user would not need multiple
> > > sets of configuration files to perform a simple "wic ls" of images with
> > > different sector sizes; simply specify it on the cmdline if you want
> > > something other than 512.
> > >
> >
> > That's not a good migration path. You can't simply throw away
> > someone's existing configuration and ask them to update to a
> > new one. I didn't even see an error thrown with migration
> > instructions.
> >
> > There's many different users of things like this, we can't simply
> > change the interface without some way to migrate.
>
> I don't disagree with you entirely.
>
> But if the user specifies --sector-size <N> on the cmdline, they will
> expect the sector-size to be N. If they don't specify this on the
> cmdline, they would rightfully expect the default of 512 to be used...
>
At a thought:
If they specify it on the command line. use it.
If they don't specify it on the command line, but there's a variable set
(the old way), use it and output a message that it was taken from the
variable.
If they don't specify it on the command line and no variable is set, use
the default
You don't really even need to fully support the variable everywhere, just
read it once, and then convert it to a command line argument (if there's a
place to do that, you know the code better than I do, maybe that's not
possible).
If someone is migrating to the new way, they can just remove that variable
once they know things are working.
Bruce
>
>
> ...unless some configuration file anywhere in their build specifies
> WIC_SECTOR_SIZE, in which case wic is supposed to use that value?
>
> I could print a warning if sector size is set via WIC_SECTOR_SIZE?
>
> >
> > Bruce
> >
> >
> >
> > >
> > > > Apologies if I missed where existing configs were used to prime
> > > > the parameters to the functions.
> > > >
> > > > Bruce
> > > >
> > > >
> > > >
> > > > >
> > > > > AI-Generated: codex/gpt-5.1-codex-max
> > > > > Signed-off-by: Trevor Woerner <twoerner@gmail.com>
> > > > > ---
> > > > > changes since v2:
> > > > > - none
> > > > >
> > > > > changes since v1:
> > > > > - none
> > > > > ---
> > > > > meta/lib/oeqa/selftest/cases/wic.py | 39 ++++---------
> > > > > scripts/lib/wic/engine.py | 45 +++++++--------
> > > > > scripts/lib/wic/help.py | 23 +++++---
> > > > > scripts/lib/wic/partition.py | 55
> +++++++++++++++++--
> > > > > scripts/lib/wic/plugins/imager/direct.py | 18 ++----
> > > > > scripts/lib/wic/plugins/source/bootimg_efi.py | 5 +-
> > > > > .../lib/wic/plugins/source/bootimg_pcbios.py | 11 ++--
> > > > > .../wic/plugins/source/isoimage_isohybrid.py | 5 +-
> > > > > scripts/wic | 8 +++
> > > > > 9 files changed, 125 insertions(+), 84 deletions(-)
> > > > >
> > > > > diff --git a/meta/lib/oeqa/selftest/cases/wic.py
> > > > > b/meta/lib/oeqa/selftest/cases/wic.py
> > > > > index ecaee5a29144..7ad61fa700f7 100644
> > > > > --- a/meta/lib/oeqa/selftest/cases/wic.py
> > > > > +++ b/meta/lib/oeqa/selftest/cases/wic.py
> > > > > @@ -935,33 +935,22 @@ bootloader --ptable gpt""")
> > > > > finally:
> > > > > os.remove(wks_file)
> > > > >
> > > > > - def test_wic_sector_size(self):
> > > > > - """Test generation image sector size"""
> > > > > -
> > > > > + def test_wic_sector_size_cli(self):
> > > > > + """Test sector size handling via CLI option."""
> > > > > +
> > > > > oldpath = os.environ['PATH']
> > > > > os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
> > > > >
> > > > > try:
> > > > > - # Add WIC_SECTOR_SIZE into config
> > > > > - config = 'WIC_SECTOR_SIZE = "4096"\n'\
> > > > > - 'WICVARS:append = " WIC_SECTOR_SIZE"\n'
> > > > > - self.append_config(config)
> > > > > bitbake('core-image-minimal')
> > > > >
> > > > > - # Check WIC_SECTOR_SIZE apply to bitbake variable
> > > > > - wic_sector_size_str = get_bb_var('WIC_SECTOR_SIZE',
> > > > > 'core-image-minimal')
> > > > > - wic_sector_size = int(wic_sector_size_str)
> > > > > - self.assertEqual(4096, wic_sector_size)
> > > > > -
> > > > > - self.logger.info("Test wic_sector_size: %d \n" %
> > > > > wic_sector_size)
> > > > > -
> > > > > with NamedTemporaryFile("w", suffix=".wks") as wks:
> > > > > wks.writelines(
> > > > > ['bootloader --ptable gpt\n',
> > > > > - 'part --fstype ext4 --source rootfs --label
> > > rofs-a
> > > > > --mkfs-extraopts "-b 4096"\n',
> > > > > - 'part --fstype ext4 --source rootfs
> --use-uuid
> > > > > --mkfs-extraopts "-b 4096"\n'])
> > > > > + 'part --fstype ext4 --source rootfs --label
> > > > > rofs-a\n',
> > > > > + 'part --fstype ext4 --source rootfs
> > > --use-uuid\n'])
> > > > > wks.flush()
> > > > > - cmd = "wic create %s -e core-image-minimal -o %s"
> % (
> > > > > wks.name, self.resultdir)
> > > > > + cmd = "wic create %s -e core-image-minimal -o %s
> > > > > --sector-size 4096" % (wks.name, self.resultdir)
> > > > > runCmd(cmd)
> > > > > wksname = os.path.splitext(os.path.basename(
> wks.name
> > > ))[0]
> > > > > images = glob(os.path.join(self.resultdir,
> > > "%s-*direct" %
> > > > > wksname))
> > > > > @@ -969,24 +958,18 @@ bootloader --ptable gpt""")
> > > > >
> > > > > sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE',
> 'wic-tools')
> > > > > # list partitions
> > > > > - result = runCmd("wic ls %s -n %s" % (images[0],
> sysroot))
> > > > > + result = runCmd("wic ls %s -n %s --sector-size 4096" %
> > > > > (images[0], sysroot))
> > > > > self.assertEqual(3, len(result.output.split('\n')))
> > > > >
> > > > > - # verify partition size with wic
> > > > > - res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m
> %s
> > > unit
> > > > > b p" % (wic_sector_size, images[0]),
> > > > > + # verify partition size with parted output
> > > > > + res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m
> %s
> > > unit
> > > > > b p" % (4096, images[0]),
> > > > > stderr=subprocess.PIPE)
> > > > >
> > > > > - # parse parted output which looks like this:
> > > > > - # BYT;\n
> > > > > - #
> > > > >
> > >
> /var/tmp/wic/build/tmpgjzzefdd-202410281021-sda.direct:78569472B:file:4096:4096:gpt::;\n
> > > > > - # 1:139264B:39284735B:39145472B:ext4:rofs-a:;\n
> > > > > - # 2:39284736B:78430207B:39145472B:ext4:primary:;\n
> > > > > disk_info = res.output.splitlines()[1]
> > > > > - # Check sector sizes
> > > > > sector_size_logical = int(disk_info.split(":")[3])
> > > > > sector_size_physical = int(disk_info.split(":")[4])
> > > > > - self.assertEqual(wic_sector_size, sector_size_logical,
> > > > > "Logical sector size is not %d." % wic_sector_size)
> > > > > - self.assertEqual(wic_sector_size,
> sector_size_physical,
> > > > > "Physical sector size is not %d." % wic_sector_size)
> > > > > + self.assertEqual(4096, sector_size_logical, "Logical
> > > sector
> > > > > size is not 4096.")
> > > > > + self.assertEqual(4096, sector_size_physical, "Physical
> > > sector
> > > > > size is not 4096.")
> > > > >
> > > > > finally:
> > > > > os.environ['PATH'] = oldpath
> > > > > diff --git a/scripts/lib/wic/engine.py b/scripts/lib/wic/engine.py
> > > > > index 9d596be3a723..7753f431f91d 100644
> > > > > --- a/scripts/lib/wic/engine.py
> > > > > +++ b/scripts/lib/wic/engine.py
> > > > > @@ -224,7 +224,7 @@ def wic_list(args, scripts_path):
> > > > >
> > > > >
> > > > > class Disk:
> > > > > - def __init__(self, imagepath, native_sysroot, fstypes=('fat',
> > > 'ext')):
> > > > > + def __init__(self, imagepath, native_sysroot, fstypes=('fat',
> > > 'ext'),
> > > > > sector_size=512):
> > > > > self.imagepath = imagepath
> > > > > self.native_sysroot = native_sysroot
> > > > > self.fstypes = fstypes
> > > > > @@ -233,16 +233,7 @@ class Disk:
> > > > > self._lsector_size = None
> > > > > self._psector_size = None
> > > > > self._ptable_format = None
> > > > > -
> > > > > - # define sector size
> > > > > - sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
> > > > > - if sector_size_str is not None:
> > > > > - try:
> > > > > - self.sector_size = int(sector_size_str)
> > > > > - except ValueError:
> > > > > - self.sector_size = None
> > > > > - else:
> > > > > - self.sector_size = None
> > > > > + self.sector_size = sector_size
> > > > >
> > > > > # find parted
> > > > > # read paths from $PATH environment variable
> > > > > @@ -271,7 +262,7 @@ class Disk:
> > > > > if self._partitions is None:
> > > > > self._partitions = OrderedDict()
> > > > >
> > > > > - if self.sector_size is not None:
> > > > > + if self.sector_size:
> > > > > out = exec_cmd("export PARTED_SECTOR_SIZE=%d; %s
> -sm
> > > %s
> > > > > unit B print" % \
> > > > > (self.sector_size, self.parted,
> > > > > self.imagepath), True)
> > > > > else:
> > > > > @@ -312,11 +303,15 @@ class Disk:
> > > > > raise WicError("Partition %s is not in the image" %
> pnum)
> > > > > part = self.partitions[pnum]
> > > > > # check if fstype is supported
> > > > > + # NOTE: parted is unable to identify dos-type partitions
> with
> > > a
> > > > > 4k sector-size
> > > > > + # if the type is empty and a non-default sector
> size is
> > > > > used, assume 'fat'
> > > > > + # fdisk identifies them without issue
> > > > > + part_fstype = part.fstype if part.fstype or
> self.sector_size
> > > ==
> > > > > 512 else 'fat'
> > > > > for fstype in self.fstypes:
> > > > > - if part.fstype.startswith(fstype):
> > > > > + if part_fstype.startswith(fstype):
> > > > > break
> > > > > else:
> > > > > - raise WicError("Not supported fstype:
> > > {}".format(part.fstype))
> > > > > + raise WicError("Not supported fstype:
> > > {}".format(part_fstype))
> > > > > if pnum not in self._partimages:
> > > > > tmpf = tempfile.NamedTemporaryFile(prefix="wic-part")
> > > > > dst_fname = tmpf.name
> > > > > @@ -586,8 +581,9 @@ class Disk:
> > > > > label = part.get("name")
> > > > > label_str = "-n {}".format(label) if
> label
> > > > > else ''
> > > > >
> > > > > - cmd = "{} {} -C {}
> > > {}".format(self.mkdosfs,
> > > > > label_str, partfname,
> > > > > -
> > > part['size'])
> > > > > + sector_str = "-S
> > > {}".format(self.sector_size)
> > > > > if self.sector_size else ''
> > > > > + cmd = "{} {} {} -C {}
> > > > > {}".format(self.mkdosfs, label_str, sector_str, partfname,
> > > > > +
> > > part['size'])
> > > > > exec_cmd(cmd)
> > > > > # copy content from the temporary
> > > directory
> > > > > to the new partition
> > > > > cmd = "{} -snompi {} {}/*
> > > > > ::".format(self.mcopy, partfname, tmpdir)
> > > > > @@ -609,14 +605,19 @@ class Disk:
> > > > >
> > > > > def wic_ls(args, native_sysroot):
> > > > > """List contents of partitioned image or vfat partition."""
> > > > > - disk = Disk(args.path.image, native_sysroot)
> > > > > + disk = Disk(args.path.image, native_sysroot,
> > > > > sector_size=args.sector_size)
> > > > > if not args.path.part:
> > > > > if disk.partitions:
> > > > > print('Num Start End Size
> > > Fstype')
> > > > > for part in disk.partitions.values():
> > > > > + # size values are in bytes from parted; convert to
> > > > > sectors if a custom sector size was requested
> > > > > + display_size = part.size
> > > > > + if args.sector_size and args.sector_size !=
> > > > > disk._lsector_size:
> > > > > + display_size = part.size // args.sector_size
> > > > > print("{:2d} {:12d} {:12d} {:12d} {}".format(\
> > > > > - part.pnum, part.start, part.end,
> > > > > - part.size, part.fstype))
> > > > > + part.pnum, part.start //
> args.sector_size,
> > > > > + part.end // args.sector_size,
> > > > > + display_size, part.fstype))
> > > > > else:
> > > > > path = args.path.path or '/'
> > > > > print(disk.dir(args.path.part, path))
> > > > > @@ -627,9 +628,9 @@ def wic_cp(args, native_sysroot):
> > > > > partitioned image.
> > > > > """
> > > > > if isinstance(args.dest, str):
> > > > > - disk = Disk(args.src.image, native_sysroot)
> > > > > + disk = Disk(args.src.image, native_sysroot,
> > > > > sector_size=args.sector_size)
> > > > > else:
> > > > > - disk = Disk(args.dest.image, native_sysroot)
> > > > > + disk = Disk(args.dest.image, native_sysroot,
> > > > > sector_size=args.sector_size)
> > > > > disk.copy(args.src, args.dest)
> > > > >
> > > > >
> > > > > @@ -638,7 +639,7 @@ def wic_rm(args, native_sysroot):
> > > > > Remove files or directories from the vfat partition of
> > > > > partitioned image.
> > > > > """
> > > > > - disk = Disk(args.path.image, native_sysroot)
> > > > > + disk = Disk(args.path.image, native_sysroot,
> > > > > sector_size=args.sector_size)
> > > > > disk.remove(args.path.part, args.path.path,
> args.recursive_delete)
> > > > >
> > > > > def wic_write(args, native_sysroot):
> > > > > diff --git a/scripts/lib/wic/help.py b/scripts/lib/wic/help.py
> > > > > index 6b49a67de938..5d7c40456a80 100644
> > > > > --- a/scripts/lib/wic/help.py
> > > > > +++ b/scripts/lib/wic/help.py
> > > > > @@ -118,7 +118,7 @@ wic_create_usage = """
> > > > > usage: wic create <wks file or image name> [-o <DIRNAME> |
> --outdir
> > > > > <DIRNAME>]
> > > > > [-e | --image-name] [-s, --skip-build-check] [-D,
> --debug]
> > > > > [-r, --rootfs-dir] [-b, --bootimg-dir]
> > > > > - [-k, --kernel-dir] [-n, --native-sysroot] [-f,
> > > --build-rootfs]
> > > > > + [-k, --kernel-dir] [-n, --native-sysroot]
> [--sector-size
> > > > > <bytes>] [-f, --build-rootfs]
> > > > > [-c, --compress-with] [-m, --bmap]
> > > > >
> > > > > This command creates an OpenEmbedded image based on the 'OE
> kickstart
> > > > > @@ -139,13 +139,16 @@ SYNOPSIS
> > > > > wic create <wks file or image name> [-o <DIRNAME> | --outdir
> > > > > <DIRNAME>]
> > > > > [-e | --image-name] [-s, --skip-build-check] [-D, --debug]
> > > > > [-r, --rootfs-dir] [-b, --bootimg-dir]
> > > > > - [-k, --kernel-dir] [-n, --native-sysroot] [-f,
> --build-rootfs]
> > > > > + [-k, --kernel-dir] [-n, --native-sysroot] [--sector-size
> > > <bytes>]
> > > > > [-f, --build-rootfs]
> > > > > [-c, --compress-with] [-m, --bmap] [--no-fstab-update]
> > > > >
> > > > > DESCRIPTION
> > > > > This command creates an OpenEmbedded image based on the 'OE
> > > > > kickstart commands' found in the <wks file>.
> > > > >
> > > > > + Use the --sector-size option to select the sector size (in
> bytes)
> > > > > + used for partition layout calculations (default is 512).
> > > > > +
> > > > > In order to do this, wic needs to know the locations of the
> > > > > various build artifacts required to build the image.
> > > > >
> > > > > @@ -278,7 +281,7 @@ wic_ls_usage = """
> > > > >
> > > > > List content of a partitioned image
> > > > >
> > > > > - usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot
> <path>]
> > > > > + usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot
> <path>]
> > > > > [--sector-size <bytes>]
> > > > >
> > > > > This command outputs either list of image partitions or
> directory
> > > > > contents
> > > > > of vfat and ext* partitions.
> > > > > @@ -296,7 +299,7 @@ SYNOPSIS
> > > > > wic ls <image>
> > > > > wic ls <image>:<vfat or ext* partition>
> > > > > wic ls <image>:<vfat or ext* partition><path>
> > > > > - wic ls <image>:<vfat or ext* partition><path> --native-sysroot
> > > <path>
> > > > > + wic ls <image>:<vfat or ext* partition><path> --native-sysroot
> > > <path>
> > > > > [--sector-size <bytes>]
> > > > >
> > > > > DESCRIPTION
> > > > > This command lists either partitions of the image or directory
> > > > > contents
> > > > > @@ -336,6 +339,8 @@ DESCRIPTION
> > > > >
> > > > > The -n option is used to specify the path to the native
> sysroot
> > > > > containing the tools(parted and mtools) to use.
> > > > > + The --sector-size option sets the sector size used for
> partition
> > > math
> > > > > + (default is 512 bytes).
> > > > >
> > > > > """
> > > > >
> > > > > @@ -343,7 +348,7 @@ wic_cp_usage = """
> > > > >
> > > > > Copy files and directories to/from the vfat or ext* partition
> > > > >
> > > > > - usage: wic cp <src> <dest> [--native-sysroot <path>]
> > > > > + usage: wic cp <src> <dest> [--native-sysroot <path>]
> [--sector-size
> > > > > <bytes>]
> > > > >
> > > > > source/destination image in format <image>:<partition>[<path>]
> > > > >
> > > > > @@ -364,7 +369,7 @@ SYNOPSIS
> > > > > wic cp <src> <dest>:<partition>
> > > > > wic cp <src>:<partition> <dest>
> > > > > wic cp <src> <dest-image>:<partition><path>
> > > > > - wic cp <src> <dest-image>:<partition><path> --native-sysroot
> > > <path>
> > > > > + wic cp <src> <dest-image>:<partition><path> --native-sysroot
> > > <path>
> > > > > [--sector-size <bytes>]
> > > > >
> > > > > DESCRIPTION
> > > > > This command copies files or directories either
> > > > > @@ -408,13 +413,15 @@ DESCRIPTION
> > > > >
> > > > > The -n option is used to specify the path to the native
> sysroot
> > > > > containing the tools(parted and mtools) to use.
> > > > > + The --sector-size option sets the sector size used for
> partition
> > > math
> > > > > + (default is 512 bytes).
> > > > > """
> > > > >
> > > > > wic_rm_usage = """
> > > > >
> > > > > Remove files or directories from the vfat or ext* partitions
> > > > >
> > > > > - usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
> > > > > + usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
> > > > > [--sector-size <bytes>]
> > > > >
> > > > > This command removes files or directories from the vfat or ext*
> > > > > partitions of
> > > > > the partitioned image.
> > > > > @@ -466,6 +473,8 @@ DESCRIPTION
> > > > >
> > > > > The -n option is used to specify the path to the native
> sysroot
> > > > > containing the tools(parted and mtools) to use.
> > > > > + The --sector-size option sets the sector size used for
> partition
> > > math
> > > > > + (default is 512 bytes).
> > > > >
> > > > > The -r option is used to remove directories and their contents
> > > > > recursively,this only applies to ext* partition.
> > > > > diff --git a/scripts/lib/wic/partition.py
> > > b/scripts/lib/wic/partition.py
> > > > > index 8fed686e903e..df6e3271649b 100644
> > > > > --- a/scripts/lib/wic/partition.py
> > > > > +++ b/scripts/lib/wic/partition.py
> > > > > @@ -65,6 +65,50 @@ class Partition():
> > > > >
> > > > > self.lineno = lineno
> > > > > self.source_file = ""
> > > > > + self.sector_size = 512
> > > > > +
> > > > > + def _mkdosfs_extraopts(self):
> > > > > + """
> > > > > + Build mkdosfs extra options ensuring the CLI sector size
> is
> > > > > applied.
> > > > > + """
> > > > > + extraopts = self.mkfs_extraopts or ''
> > > > > + tokens = []
> > > > > + skip_next = False
> > > > > + for tok in extraopts.split():
> > > > > + if skip_next:
> > > > > + skip_next = False
> > > > > + continue
> > > > > + if tok == '-S':
> > > > > + skip_next = True
> > > > > + continue
> > > > > + if tok.startswith('-S'):
> > > > > + continue
> > > > > + tokens.append(tok)
> > > > > + tokens.extend(['-S', str(self.sector_size)])
> > > > > + return ' '.join(tokens).strip()
> > > > > +
> > > > > + def _mkfs_ext_extraopts(self, base_opts):
> > > > > + """
> > > > > + Build mkfs.ext* extra options ensuring the CLI sector
> size is
> > > > > applied.
> > > > > + """
> > > > > + extraopts = self.mkfs_extraopts or base_opts
> > > > > + # Only add an explicit block size when a non-default
> sector
> > > size
> > > > > is requested.
> > > > > + if self.sector_size and self.sector_size != 512:
> > > > > + tokens = []
> > > > > + skip_next = False
> > > > > + for tok in extraopts.split():
> > > > > + if skip_next:
> > > > > + skip_next = False
> > > > > + continue
> > > > > + if tok == '-b':
> > > > > + skip_next = True
> > > > > + continue
> > > > > + if tok.startswith('-b'):
> > > > > + continue
> > > > > + tokens.append(tok)
> > > > > + tokens.extend(['-b', str(self.sector_size)])
> > > > > + return ' '.join(tokens).strip()
> > > > > + return extraopts
> > > > >
> > > > > def get_extra_block_count(self, current_blocks):
> > > > > """
> > > > > @@ -138,6 +182,8 @@ class Partition():
> > > > > Prepare content for individual partitions, depending on
> > > > > partition command parameters.
> > > > > """
> > > > > + # capture the sector size requested on the CLI for mkdosfs
> > > > > invocations
> > > > > + self.sector_size = getattr(creator, 'sector_size', 512)
> or 512
> > > > > self.updated_fstab_path = updated_fstab_path
> > > > > if self.updated_fstab_path and not
> > > (self.fstype.startswith("ext")
> > > > > or self.fstype == "msdos"):
> > > > > self.update_fstab_in_rootfs = True
> > > > > @@ -293,7 +339,7 @@ class Partition():
> > > > > with open(rootfs, 'w') as sparse:
> > > > > os.ftruncate(sparse.fileno(), rootfs_size * 1024)
> > > > >
> > > > > - extraopts = self.mkfs_extraopts or "-F -i 8192"
> > > > > + extraopts = self._mkfs_ext_extraopts("-F -i 8192")
> > > > >
> > > > > # use hash_seed to generate reproducible ext4 images
> > > > > (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts,
> > > pseudo)
> > > > > @@ -401,7 +447,7 @@ class Partition():
> > > > >
> > > > > size_str = ""
> > > > >
> > > > > - extraopts = self.mkfs_extraopts or '-S 512'
> > > > > + extraopts = self._mkdosfs_extraopts()
> > > > >
> > > > > dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
> > > > > (label_str, self.fsuuid, size_str, extraopts,
> > > rootfs,
> > > > > @@ -452,7 +498,7 @@ class Partition():
> > > > > with open(rootfs, 'w') as sparse:
> > > > > os.ftruncate(sparse.fileno(), size * 1024)
> > > > >
> > > > > - extraopts = self.mkfs_extraopts or "-i 8192"
> > > > > + extraopts = self._mkfs_ext_extraopts("-i 8192")
> > > > >
> > > > > # use hash_seed to generate reproducible ext4 images
> > > > > (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts,
> None)
> > > > > @@ -498,7 +544,7 @@ class Partition():
> > > > >
> > > > > size_str = ""
> > > > >
> > > > > - extraopts = self.mkfs_extraopts or '-S 512'
> > > > > + extraopts = self._mkdosfs_extraopts()
> > > > >
> > > > > dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
> > > > > (label_str, self.fsuuid, extraopts, size_str,
> > > rootfs,
> > > > > @@ -559,4 +605,3 @@ class Partition():
> > > > > logger.warn("%s Inodes (of size %d) are too
> > > small." %
> > > > > (get_err_str(self), size))
> > > > > break
> > > > > -
> > > > > diff --git a/scripts/lib/wic/plugins/imager/direct.py
> > > > > b/scripts/lib/wic/plugins/imager/direct.py
> > > > > index ad922cfbf122..3adc6eee6280 100644
> > > > > --- a/scripts/lib/wic/plugins/imager/direct.py
> > > > > +++ b/scripts/lib/wic/plugins/imager/direct.py
> > > > > @@ -67,6 +67,7 @@ class DirectPlugin(ImagerPlugin):
> > > > > self._image = None
> > > > > self.ptable_format = self.ks.bootloader.ptable
> > > > > self.parts = self.ks.partitions
> > > > > + self.sector_size = options.sector_size or 512
> > > > >
> > > > > # as a convenience, set source to the boot partition
> source
> > > > > # instead of forcing it to be set via bootloader --source
> > > > > @@ -78,7 +79,7 @@ class DirectPlugin(ImagerPlugin):
> > > > > image_path = self._full_path(self.workdir,
> self.parts[0].disk,
> > > > > "direct")
> > > > > self._image = PartitionedImage(image_path,
> self.ptable_format,
> > > > > self.ks.bootloader.diskid,
> > > > > self.parts,
> > > self.native_sysroot,
> > > > > - options.extra_space)
> > > > > + options.extra_space,
> > > > > self.sector_size)
> > > > >
> > > > > def setup_workdir(self, workdir):
> > > > > if workdir:
> > > > > @@ -294,15 +295,13 @@ MBR_OVERHEAD = 1
> > > > > # Overhead of the GPT partitioning scheme
> > > > > GPT_OVERHEAD = 34
> > > > >
> > > > > -# Size of a sector in bytes
> > > > > -SECTOR_SIZE = 512
> > > > > -
> > > > > class PartitionedImage():
> > > > > """
> > > > > Partitioned image in a file.
> > > > > """
> > > > >
> > > > > - def __init__(self, path, ptable_format, disk_id, partitions,
> > > > > native_sysroot=None, extra_space=0):
> > > > > + def __init__(self, path, ptable_format, disk_id, partitions,
> > > > > native_sysroot=None, extra_space=0,
> > > > > + sector_size=512):
> > > > > self.path = path # Path to the image file
> > > > > self.numpart = 0 # Number of allocated partitions
> > > > > self.realpart = 0 # Number of partitions in the partition
> > > table
> > > > > @@ -332,14 +331,7 @@ class PartitionedImage():
> > > > > self.partitions = partitions
> > > > > self.partimages = []
> > > > > # Size of a sector used in calculations
> > > > > - sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
> > > > > - if sector_size_str is not None:
> > > > > - try:
> > > > > - self.sector_size = int(sector_size_str)
> > > > > - except ValueError:
> > > > > - self.sector_size = SECTOR_SIZE
> > > > > - else:
> > > > > - self.sector_size = SECTOR_SIZE
> > > > > + self.sector_size = sector_size or 512
> > > > >
> > > > > self.native_sysroot = native_sysroot
> > > > > num_real_partitions = len([p for p in self.partitions if
> not
> > > > > p.no_table])
> > > > > diff --git a/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > > > b/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > > > index 430b0a4b023a..864d6898fc9d 100644
> > > > > --- a/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > > > +++ b/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > > > @@ -415,8 +415,9 @@ class BootimgEFIPlugin(SourcePlugin):
> > > > >
> > > > > label = part.label if part.label else "ESP"
> > > > >
> > > > > - dosfs_cmd = "mkdosfs -v -n %s -i %s -C %s %d" % \
> > > > > - (label, part.fsuuid, bootimg, blocks)
> > > > > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > > > > + dosfs_cmd = "mkdosfs -v -n %s -i %s -S %d -C %s %d" % \
> > > > > + (label, part.fsuuid, sector_size, bootimg,
> blocks)
> > > > > exec_native_cmd(dosfs_cmd, native_sysroot)
> > > > > logger.debug("mkdosfs:\n%s" % (str(out)))
> > > > >
> > > > > diff --git a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > > > b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > > > index a7cc5d12c620..32edac47fa09 100644
> > > > > --- a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > > > +++ b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > > > @@ -132,7 +132,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > > > cls._do_prepare_grub(part, cr_workdir,
> oe_builddir,
> > > > > kernel_dir, rootfs_dir,
> > > native_sysroot)
> > > > > elif source_params['loader-bios'] == 'syslinux':
> > > > > - cls._do_prepare_syslinux(part, cr_workdir,
> > > bootimg_dir,
> > > > > + cls._do_prepare_syslinux(part, creator,
> cr_workdir,
> > > > > bootimg_dir,
> > > > > kernel_dir, native_sysroot)
> > > > > else:
> > > > > raise WicError("unrecognized bootimg_pcbios
> loader:
> > > %s" %
> > > > > source_params['loader-bios'])
> > > > > @@ -142,7 +142,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > > > except KeyError:
> > > > > # Required by do_install_disk
> > > > > cls.loader = 'syslinux'
> > > > > - cls._do_prepare_syslinux(part, cr_workdir,
> bootimg_dir,
> > > > > + cls._do_prepare_syslinux(part, creator, cr_workdir,
> > > > > bootimg_dir,
> > > > > kernel_dir, native_sysroot)
> > > > >
> > > > > @classmethod
> > > > > @@ -240,7 +240,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > > > cfg.close()
> > > > >
> > > > > @classmethod
> > > > > - def _do_prepare_syslinux(cls, part, cr_workdir, bootimg_dir,
> > > > > + def _do_prepare_syslinux(cls, part, creator, cr_workdir,
> > > bootimg_dir,
> > > > > kernel_dir, native_sysroot):
> > > > > """
> > > > > Called to do the actual content population for a partition
> > > i.e. it
> > > > > @@ -292,8 +292,9 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > > >
> > > > > label = part.label if part.label else "boot"
> > > > >
> > > > > - dosfs_cmd = "mkdosfs -n %s -i %s -S 512 -C %s %d" % \
> > > > > - (label, part.fsuuid, bootimg, blocks)
> > > > > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > > > > + dosfs_cmd = "mkdosfs -n %s -i %s -S %d -C %s %d" % \
> > > > > + (label, part.fsuuid, sector_size, bootimg,
> blocks)
> > > > > exec_native_cmd(dosfs_cmd, native_sysroot)
> > > > >
> > > > > mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
> > > > > diff --git a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > > > b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > > > index fdab188db1f8..9195ef5f3184 100644
> > > > > --- a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > > > +++ b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > > > @@ -367,8 +367,9 @@ class IsoImagePlugin(SourcePlugin):
> > > > >
> > > > > esp_label = source_params.get('esp_label', 'EFIimg')
> > > > >
> > > > > - dosfs_cmd = 'mkfs.vfat -n \'%s\' -S 512 -C %s %d' \
> > > > > - % (esp_label, bootimg, blocks)
> > > > > + sector_size = getattr(creator, 'sector_size', 512) or
> 512
> > > > > + dosfs_cmd = "mkfs.vfat -n '%s' -S %d -C %s %d" % \
> > > > > + (esp_label, sector_size, bootimg, blocks)
> > > > > exec_native_cmd(dosfs_cmd, native_sysroot)
> > > > >
> > > > > mmd_cmd = "mmd -i %s ::/EFI" % bootimg
> > > > > diff --git a/scripts/wic b/scripts/wic
> > > > > index 9137208f5e8f..0cef84ef630c 100755
> > > > > --- a/scripts/wic
> > > > > +++ b/scripts/wic
> > > > > @@ -376,6 +376,8 @@ def wic_init_parser_create(subparser):
> > > > > default="direct", help="the wic imager
> plugin")
> > > > > subparser.add_argument("--extra-space", type=int,
> > > dest="extra_space",
> > > > > default=0, help="additional free disk space
> to
> > > add
> > > > > to the image")
> > > > > + subparser.add_argument("--sector-size", dest="sector_size",
> > > type=int,
> > > > > default=512,
> > > > > + help="sector size in bytes (default: 512)")
> > > > > return
> > > > >
> > > > >
> > > > > @@ -413,6 +415,8 @@ def imgtype(arg):
> > > > > def wic_init_parser_ls(subparser):
> > > > > subparser.add_argument("path", type=imgtype,
> > > > > help="image spec: <image>[:<vfat
> > > > > partition>[<path>]]")
> > > > > + subparser.add_argument("--sector-size", dest="sector_size",
> > > type=int,
> > > > > default=512,
> > > > > + help="sector size in bytes (default:
> 512)")
> > > > > subparser.add_argument("-n", "--native-sysroot",
> > > > > help="path to the native sysroot
> containing
> > > the
> > > > > tools")
> > > > > subparser.add_argument("-e", "--image-name",
> dest="image_name",
> > > > > @@ -433,6 +437,8 @@ def wic_init_parser_cp(subparser):
> > > > > help="image spec: <image>:<vfat
> > > > > partition>[<path>] or <file>")
> > > > > subparser.add_argument("dest",
> > > > > help="image spec: <image>:<vfat
> > > > > partition>[<path>] or <file>")
> > > > > + subparser.add_argument("--sector-size", dest="sector_size",
> > > type=int,
> > > > > default=512,
> > > > > + help="sector size in bytes (default:
> 512)")
> > > > > subparser.add_argument("-n", "--native-sysroot",
> > > > > help="path to the native sysroot
> containing
> > > the
> > > > > tools")
> > > > > subparser.add_argument("-e", "--image-name",
> dest="image_name",
> > > > > @@ -445,6 +451,8 @@ def wic_init_parser_cp(subparser):
> > > > > def wic_init_parser_rm(subparser):
> > > > > subparser.add_argument("path", type=imgpathtype,
> > > > > help="path: <image>:<vfat
> partition><path>")
> > > > > + subparser.add_argument("--sector-size", dest="sector_size",
> > > type=int,
> > > > > default=512,
> > > > > + help="sector size in bytes (default:
> 512)")
> > > > > subparser.add_argument("-n", "--native-sysroot",
> > > > > help="path to the native sysroot
> containing
> > > the
> > > > > tools")
> > > > > subparser.add_argument("-r", dest="recursive_delete",
> > > > > action="store_true", default=False,
> > > > > --
> > > > > 2.51.0
> > > > >
> > > > >
> > > > > -=-=-=-=-=-=-=-=-=-=-=-
> > > > > Links: You receive all messages sent to this group.
> > > > > View/Reply Online (#231176):
> > > > > https://lists.openembedded.org/g/openembedded-core/message/231176
> > > > > Mute This Topic:
> https://lists.openembedded.org/mt/117833550/1050810
> > > > > Group Owner: openembedded-core+owner@lists.openembedded.org
> > > > > Unsubscribe:
> https://lists.openembedded.org/g/openembedded-core/unsub
> > > [
> > > > > bruce.ashfield@gmail.com]
> > > > > -=-=-=-=-=-=-=-=-=-=-=-
> > > > >
> > > > >
> > > >
> > > > --
> > > > - Thou shalt not follow the NULL pointer, for chaos and madness await
> > > thee
> > > > at its end
> > > > - "Use the force Harry" - Gandalf, Star Trek II
> > >
> >
> >
> > --
> > - Thou shalt not follow the NULL pointer, for chaos and madness await
> thee
> > at its end
> > - "Use the force Harry" - Gandalf, Star Trek II
>
--
- Thou shalt not follow the NULL pointer, for chaos and madness await thee
at its end
- "Use the force Harry" - Gandalf, Star Trek II
[-- Attachment #2: Type: text/html, Size: 59737 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [OE-core] [PATCH v3 1/2] wic: re-implement sector-size support
2026-02-16 18:49 ` Bruce Ashfield
@ 2026-02-16 19:40 ` Trevor Woerner
0 siblings, 0 replies; 8+ messages in thread
From: Trevor Woerner @ 2026-02-16 19:40 UTC (permalink / raw)
To: Bruce Ashfield; +Cc: openembedded-core
On Mon 2026-02-16 @ 01:49:22 PM, Bruce Ashfield wrote:
> On Mon, Feb 16, 2026 at 12:58 PM Trevor Woerner <twoerner@gmail.com> wrote:
>
> > On Mon 2026-02-16 @ 11:01:28 AM, Bruce Ashfield wrote:
> > > On Mon, Feb 16, 2026 at 10:37 AM Trevor Woerner <twoerner@gmail.com>
> > wrote:
> > >
> > > > On Sun 2026-02-15 @ 10:09:03 PM, Bruce Ashfield wrote:
> > > > > On Sun, Feb 15, 2026 at 9:32 PM Trevor Woerner via
> > > > lists.openembedded.org
> > > > > <twoerner=gmail.com@lists.openembedded.org> wrote:
> > > > >
> > > > > > The previous implementation to add variable sector-size support:
> > > > > > - required the variable WIC_SECTOR_SIZE either be defined in a
> > > > > > configuration file or be defined in a --vars file
> > > > > > - this means that every invocation of "wic ls", "wic cp", or "wic
> > rm"
> > > > > > needed this variable defined (config or --vars)
> > > > > > - required the user to create separate *wks files for every sector
> > size
> > > > > > they wanted to use
> > > > > > - required the user to specify the mkfs-extraopts by hand to
> > specify
> > > > the
> > > > > > correct sector size: e.g.
> > > > > > bootloader --ptable gpt
> > > > > > part --fstype ext4 --source rootfs --label rofs-a
> > > > --mkfs-extraopts
> > > > > > "-b 4096"
> > > > > > part --fstype ext4 --source rootfs --use-uuid
> > --mkfs-extraopts
> > > > "-b
> > > > > > 4096"
> > > > > > - specifying --mkfs-extraopts replaces the defaults with the
> > > > > > user-supplied values
> > > > > > - only provided details to support using variable sector-sizes with
> > > > > > ext[234] filesystems
> > > > > > - it would not be possible to generate images with different sector
> > > > > > sizes in the same build since the configuration and *wks files
> > would
> > > > > > need to change and the build re-run for each size
> > > > > >
> > > > > > Update the sector-size handling so that:
> > > > > > - the sector-size will now be provided on the cmdline to the "wic
> > ls",
> > > > > > "wic cp", "wic rm", and "wic create" commands: default = 512
> > > > > > - this means the configuration and/or --vars file does not need to
> > be
> > > > > > changed in order to perform those operations on images with
> > different
> > > > > > sector sizes
> > > > > > - support is provided implicitly for mkdosfs and ext[234]
> > partitions
> > > > > > - the user no longer needs to know and supply the sector-size
> > magic in
> > > > > > --mkfs-extraopts (thereby clobbering the other defaults)
> > > > > >
> > > > >
> > > > > It wasn't clear to me when scanning the patch. For configuration
> > > > > files with a sector size, is it now completely ignored ?
> > > >
> > > > Yes.
> > > >
> > > > While trying to use the existing implementation in actual production
> > > > workflows we found a number of shortcomings that are addressed with
> > this
> > > > update. Additionally, the ultimate goal is to make wic an independent
> > > > utility from oe-core so it can be easily used by external tools
> > > > post-build.
> > > >
> > > > If sector-size is not available on the cmdline, then a --vars file
> > would
> > > > be needed for every simple wic invocation such as "wic cp", "wic ls",
> > > > and "wic rm"... which would be silly. Take a look at the patch I
> > > > submitted a week or so ago to see how the oe-selftests would have to be
> > > > updated to support this.
> > > >
> > > > If sector-size is available both on the cmdline and in a --vars file
> > > > then which one wins? Ultimately having it specified in both places is
> > > > only going to lead to confusion as people will be changing it in one
> > > > place and not realizing it's also defined (and taking precedence) from
> > > > somewhere else. I believe this is currently the case with
> > > > --native-sysroot, which probably needs fixing as well since several
> > > > oe-selftests are trying to use it, but I doubt it is working the way
> > the
> > > > test writers expect.
> > >
> > >
> > > > One parameter specified in one place so a user would not need multiple
> > > > sets of configuration files to perform a simple "wic ls" of images with
> > > > different sector sizes; simply specify it on the cmdline if you want
> > > > something other than 512.
> > > >
> > >
> > > That's not a good migration path. You can't simply throw away
> > > someone's existing configuration and ask them to update to a
> > > new one. I didn't even see an error thrown with migration
> > > instructions.
> > >
> > > There's many different users of things like this, we can't simply
> > > change the interface without some way to migrate.
> >
> > I don't disagree with you entirely.
> >
> > But if the user specifies --sector-size <N> on the cmdline, they will
> > expect the sector-size to be N. If they don't specify this on the
> > cmdline, they would rightfully expect the default of 512 to be used...
> >
>
> At a thought:
>
> If they specify it on the command line. use it.
> If they don't specify it on the command line, but there's a variable set
> (the old way), use it and output a message that it was taken from the
> variable.
> If they don't specify it on the command line and no variable is set, use
> the default
>
> You don't really even need to fully support the variable everywhere, just
> read it once, and then convert it to a command line argument (if there's a
> place to do that, you know the code better than I do, maybe that's not
> possible).
>
> If someone is migrating to the new way, they can just remove that variable
> once they know things are working.
Perfect! This is what my v4 will do :-)
>
> Bruce
>
>
>
> >
> >
> > ...unless some configuration file anywhere in their build specifies
> > WIC_SECTOR_SIZE, in which case wic is supposed to use that value?
> >
> > I could print a warning if sector size is set via WIC_SECTOR_SIZE?
> >
> > >
> > > Bruce
> > >
> > >
> > >
> > > >
> > > > > Apologies if I missed where existing configs were used to prime
> > > > > the parameters to the functions.
> > > > >
> > > > > Bruce
> > > > >
> > > > >
> > > > >
> > > > > >
> > > > > > AI-Generated: codex/gpt-5.1-codex-max
> > > > > > Signed-off-by: Trevor Woerner <twoerner@gmail.com>
> > > > > > ---
> > > > > > changes since v2:
> > > > > > - none
> > > > > >
> > > > > > changes since v1:
> > > > > > - none
> > > > > > ---
> > > > > > meta/lib/oeqa/selftest/cases/wic.py | 39 ++++---------
> > > > > > scripts/lib/wic/engine.py | 45 +++++++--------
> > > > > > scripts/lib/wic/help.py | 23 +++++---
> > > > > > scripts/lib/wic/partition.py | 55
> > +++++++++++++++++--
> > > > > > scripts/lib/wic/plugins/imager/direct.py | 18 ++----
> > > > > > scripts/lib/wic/plugins/source/bootimg_efi.py | 5 +-
> > > > > > .../lib/wic/plugins/source/bootimg_pcbios.py | 11 ++--
> > > > > > .../wic/plugins/source/isoimage_isohybrid.py | 5 +-
> > > > > > scripts/wic | 8 +++
> > > > > > 9 files changed, 125 insertions(+), 84 deletions(-)
> > > > > >
> > > > > > diff --git a/meta/lib/oeqa/selftest/cases/wic.py
> > > > > > b/meta/lib/oeqa/selftest/cases/wic.py
> > > > > > index ecaee5a29144..7ad61fa700f7 100644
> > > > > > --- a/meta/lib/oeqa/selftest/cases/wic.py
> > > > > > +++ b/meta/lib/oeqa/selftest/cases/wic.py
> > > > > > @@ -935,33 +935,22 @@ bootloader --ptable gpt""")
> > > > > > finally:
> > > > > > os.remove(wks_file)
> > > > > >
> > > > > > - def test_wic_sector_size(self):
> > > > > > - """Test generation image sector size"""
> > > > > > -
> > > > > > + def test_wic_sector_size_cli(self):
> > > > > > + """Test sector size handling via CLI option."""
> > > > > > +
> > > > > > oldpath = os.environ['PATH']
> > > > > > os.environ['PATH'] = get_bb_var("PATH", "wic-tools")
> > > > > >
> > > > > > try:
> > > > > > - # Add WIC_SECTOR_SIZE into config
> > > > > > - config = 'WIC_SECTOR_SIZE = "4096"\n'\
> > > > > > - 'WICVARS:append = " WIC_SECTOR_SIZE"\n'
> > > > > > - self.append_config(config)
> > > > > > bitbake('core-image-minimal')
> > > > > >
> > > > > > - # Check WIC_SECTOR_SIZE apply to bitbake variable
> > > > > > - wic_sector_size_str = get_bb_var('WIC_SECTOR_SIZE',
> > > > > > 'core-image-minimal')
> > > > > > - wic_sector_size = int(wic_sector_size_str)
> > > > > > - self.assertEqual(4096, wic_sector_size)
> > > > > > -
> > > > > > - self.logger.info("Test wic_sector_size: %d \n" %
> > > > > > wic_sector_size)
> > > > > > -
> > > > > > with NamedTemporaryFile("w", suffix=".wks") as wks:
> > > > > > wks.writelines(
> > > > > > ['bootloader --ptable gpt\n',
> > > > > > - 'part --fstype ext4 --source rootfs --label
> > > > rofs-a
> > > > > > --mkfs-extraopts "-b 4096"\n',
> > > > > > - 'part --fstype ext4 --source rootfs
> > --use-uuid
> > > > > > --mkfs-extraopts "-b 4096"\n'])
> > > > > > + 'part --fstype ext4 --source rootfs --label
> > > > > > rofs-a\n',
> > > > > > + 'part --fstype ext4 --source rootfs
> > > > --use-uuid\n'])
> > > > > > wks.flush()
> > > > > > - cmd = "wic create %s -e core-image-minimal -o %s"
> > % (
> > > > > > wks.name, self.resultdir)
> > > > > > + cmd = "wic create %s -e core-image-minimal -o %s
> > > > > > --sector-size 4096" % (wks.name, self.resultdir)
> > > > > > runCmd(cmd)
> > > > > > wksname = os.path.splitext(os.path.basename(
> > wks.name
> > > > ))[0]
> > > > > > images = glob(os.path.join(self.resultdir,
> > > > "%s-*direct" %
> > > > > > wksname))
> > > > > > @@ -969,24 +958,18 @@ bootloader --ptable gpt""")
> > > > > >
> > > > > > sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE',
> > 'wic-tools')
> > > > > > # list partitions
> > > > > > - result = runCmd("wic ls %s -n %s" % (images[0],
> > sysroot))
> > > > > > + result = runCmd("wic ls %s -n %s --sector-size 4096" %
> > > > > > (images[0], sysroot))
> > > > > > self.assertEqual(3, len(result.output.split('\n')))
> > > > > >
> > > > > > - # verify partition size with wic
> > > > > > - res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m
> > %s
> > > > unit
> > > > > > b p" % (wic_sector_size, images[0]),
> > > > > > + # verify partition size with parted output
> > > > > > + res = runCmd("export PARTED_SECTOR_SIZE=%d; parted -m
> > %s
> > > > unit
> > > > > > b p" % (4096, images[0]),
> > > > > > stderr=subprocess.PIPE)
> > > > > >
> > > > > > - # parse parted output which looks like this:
> > > > > > - # BYT;\n
> > > > > > - #
> > > > > >
> > > >
> > /var/tmp/wic/build/tmpgjzzefdd-202410281021-sda.direct:78569472B:file:4096:4096:gpt::;\n
> > > > > > - # 1:139264B:39284735B:39145472B:ext4:rofs-a:;\n
> > > > > > - # 2:39284736B:78430207B:39145472B:ext4:primary:;\n
> > > > > > disk_info = res.output.splitlines()[1]
> > > > > > - # Check sector sizes
> > > > > > sector_size_logical = int(disk_info.split(":")[3])
> > > > > > sector_size_physical = int(disk_info.split(":")[4])
> > > > > > - self.assertEqual(wic_sector_size, sector_size_logical,
> > > > > > "Logical sector size is not %d." % wic_sector_size)
> > > > > > - self.assertEqual(wic_sector_size,
> > sector_size_physical,
> > > > > > "Physical sector size is not %d." % wic_sector_size)
> > > > > > + self.assertEqual(4096, sector_size_logical, "Logical
> > > > sector
> > > > > > size is not 4096.")
> > > > > > + self.assertEqual(4096, sector_size_physical, "Physical
> > > > sector
> > > > > > size is not 4096.")
> > > > > >
> > > > > > finally:
> > > > > > os.environ['PATH'] = oldpath
> > > > > > diff --git a/scripts/lib/wic/engine.py b/scripts/lib/wic/engine.py
> > > > > > index 9d596be3a723..7753f431f91d 100644
> > > > > > --- a/scripts/lib/wic/engine.py
> > > > > > +++ b/scripts/lib/wic/engine.py
> > > > > > @@ -224,7 +224,7 @@ def wic_list(args, scripts_path):
> > > > > >
> > > > > >
> > > > > > class Disk:
> > > > > > - def __init__(self, imagepath, native_sysroot, fstypes=('fat',
> > > > 'ext')):
> > > > > > + def __init__(self, imagepath, native_sysroot, fstypes=('fat',
> > > > 'ext'),
> > > > > > sector_size=512):
> > > > > > self.imagepath = imagepath
> > > > > > self.native_sysroot = native_sysroot
> > > > > > self.fstypes = fstypes
> > > > > > @@ -233,16 +233,7 @@ class Disk:
> > > > > > self._lsector_size = None
> > > > > > self._psector_size = None
> > > > > > self._ptable_format = None
> > > > > > -
> > > > > > - # define sector size
> > > > > > - sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
> > > > > > - if sector_size_str is not None:
> > > > > > - try:
> > > > > > - self.sector_size = int(sector_size_str)
> > > > > > - except ValueError:
> > > > > > - self.sector_size = None
> > > > > > - else:
> > > > > > - self.sector_size = None
> > > > > > + self.sector_size = sector_size
> > > > > >
> > > > > > # find parted
> > > > > > # read paths from $PATH environment variable
> > > > > > @@ -271,7 +262,7 @@ class Disk:
> > > > > > if self._partitions is None:
> > > > > > self._partitions = OrderedDict()
> > > > > >
> > > > > > - if self.sector_size is not None:
> > > > > > + if self.sector_size:
> > > > > > out = exec_cmd("export PARTED_SECTOR_SIZE=%d; %s
> > -sm
> > > > %s
> > > > > > unit B print" % \
> > > > > > (self.sector_size, self.parted,
> > > > > > self.imagepath), True)
> > > > > > else:
> > > > > > @@ -312,11 +303,15 @@ class Disk:
> > > > > > raise WicError("Partition %s is not in the image" %
> > pnum)
> > > > > > part = self.partitions[pnum]
> > > > > > # check if fstype is supported
> > > > > > + # NOTE: parted is unable to identify dos-type partitions
> > with
> > > > a
> > > > > > 4k sector-size
> > > > > > + # if the type is empty and a non-default sector
> > size is
> > > > > > used, assume 'fat'
> > > > > > + # fdisk identifies them without issue
> > > > > > + part_fstype = part.fstype if part.fstype or
> > self.sector_size
> > > > ==
> > > > > > 512 else 'fat'
> > > > > > for fstype in self.fstypes:
> > > > > > - if part.fstype.startswith(fstype):
> > > > > > + if part_fstype.startswith(fstype):
> > > > > > break
> > > > > > else:
> > > > > > - raise WicError("Not supported fstype:
> > > > {}".format(part.fstype))
> > > > > > + raise WicError("Not supported fstype:
> > > > {}".format(part_fstype))
> > > > > > if pnum not in self._partimages:
> > > > > > tmpf = tempfile.NamedTemporaryFile(prefix="wic-part")
> > > > > > dst_fname = tmpf.name
> > > > > > @@ -586,8 +581,9 @@ class Disk:
> > > > > > label = part.get("name")
> > > > > > label_str = "-n {}".format(label) if
> > label
> > > > > > else ''
> > > > > >
> > > > > > - cmd = "{} {} -C {}
> > > > {}".format(self.mkdosfs,
> > > > > > label_str, partfname,
> > > > > > -
> > > > part['size'])
> > > > > > + sector_str = "-S
> > > > {}".format(self.sector_size)
> > > > > > if self.sector_size else ''
> > > > > > + cmd = "{} {} {} -C {}
> > > > > > {}".format(self.mkdosfs, label_str, sector_str, partfname,
> > > > > > +
> > > > part['size'])
> > > > > > exec_cmd(cmd)
> > > > > > # copy content from the temporary
> > > > directory
> > > > > > to the new partition
> > > > > > cmd = "{} -snompi {} {}/*
> > > > > > ::".format(self.mcopy, partfname, tmpdir)
> > > > > > @@ -609,14 +605,19 @@ class Disk:
> > > > > >
> > > > > > def wic_ls(args, native_sysroot):
> > > > > > """List contents of partitioned image or vfat partition."""
> > > > > > - disk = Disk(args.path.image, native_sysroot)
> > > > > > + disk = Disk(args.path.image, native_sysroot,
> > > > > > sector_size=args.sector_size)
> > > > > > if not args.path.part:
> > > > > > if disk.partitions:
> > > > > > print('Num Start End Size
> > > > Fstype')
> > > > > > for part in disk.partitions.values():
> > > > > > + # size values are in bytes from parted; convert to
> > > > > > sectors if a custom sector size was requested
> > > > > > + display_size = part.size
> > > > > > + if args.sector_size and args.sector_size !=
> > > > > > disk._lsector_size:
> > > > > > + display_size = part.size // args.sector_size
> > > > > > print("{:2d} {:12d} {:12d} {:12d} {}".format(\
> > > > > > - part.pnum, part.start, part.end,
> > > > > > - part.size, part.fstype))
> > > > > > + part.pnum, part.start //
> > args.sector_size,
> > > > > > + part.end // args.sector_size,
> > > > > > + display_size, part.fstype))
> > > > > > else:
> > > > > > path = args.path.path or '/'
> > > > > > print(disk.dir(args.path.part, path))
> > > > > > @@ -627,9 +628,9 @@ def wic_cp(args, native_sysroot):
> > > > > > partitioned image.
> > > > > > """
> > > > > > if isinstance(args.dest, str):
> > > > > > - disk = Disk(args.src.image, native_sysroot)
> > > > > > + disk = Disk(args.src.image, native_sysroot,
> > > > > > sector_size=args.sector_size)
> > > > > > else:
> > > > > > - disk = Disk(args.dest.image, native_sysroot)
> > > > > > + disk = Disk(args.dest.image, native_sysroot,
> > > > > > sector_size=args.sector_size)
> > > > > > disk.copy(args.src, args.dest)
> > > > > >
> > > > > >
> > > > > > @@ -638,7 +639,7 @@ def wic_rm(args, native_sysroot):
> > > > > > Remove files or directories from the vfat partition of
> > > > > > partitioned image.
> > > > > > """
> > > > > > - disk = Disk(args.path.image, native_sysroot)
> > > > > > + disk = Disk(args.path.image, native_sysroot,
> > > > > > sector_size=args.sector_size)
> > > > > > disk.remove(args.path.part, args.path.path,
> > args.recursive_delete)
> > > > > >
> > > > > > def wic_write(args, native_sysroot):
> > > > > > diff --git a/scripts/lib/wic/help.py b/scripts/lib/wic/help.py
> > > > > > index 6b49a67de938..5d7c40456a80 100644
> > > > > > --- a/scripts/lib/wic/help.py
> > > > > > +++ b/scripts/lib/wic/help.py
> > > > > > @@ -118,7 +118,7 @@ wic_create_usage = """
> > > > > > usage: wic create <wks file or image name> [-o <DIRNAME> |
> > --outdir
> > > > > > <DIRNAME>]
> > > > > > [-e | --image-name] [-s, --skip-build-check] [-D,
> > --debug]
> > > > > > [-r, --rootfs-dir] [-b, --bootimg-dir]
> > > > > > - [-k, --kernel-dir] [-n, --native-sysroot] [-f,
> > > > --build-rootfs]
> > > > > > + [-k, --kernel-dir] [-n, --native-sysroot]
> > [--sector-size
> > > > > > <bytes>] [-f, --build-rootfs]
> > > > > > [-c, --compress-with] [-m, --bmap]
> > > > > >
> > > > > > This command creates an OpenEmbedded image based on the 'OE
> > kickstart
> > > > > > @@ -139,13 +139,16 @@ SYNOPSIS
> > > > > > wic create <wks file or image name> [-o <DIRNAME> | --outdir
> > > > > > <DIRNAME>]
> > > > > > [-e | --image-name] [-s, --skip-build-check] [-D, --debug]
> > > > > > [-r, --rootfs-dir] [-b, --bootimg-dir]
> > > > > > - [-k, --kernel-dir] [-n, --native-sysroot] [-f,
> > --build-rootfs]
> > > > > > + [-k, --kernel-dir] [-n, --native-sysroot] [--sector-size
> > > > <bytes>]
> > > > > > [-f, --build-rootfs]
> > > > > > [-c, --compress-with] [-m, --bmap] [--no-fstab-update]
> > > > > >
> > > > > > DESCRIPTION
> > > > > > This command creates an OpenEmbedded image based on the 'OE
> > > > > > kickstart commands' found in the <wks file>.
> > > > > >
> > > > > > + Use the --sector-size option to select the sector size (in
> > bytes)
> > > > > > + used for partition layout calculations (default is 512).
> > > > > > +
> > > > > > In order to do this, wic needs to know the locations of the
> > > > > > various build artifacts required to build the image.
> > > > > >
> > > > > > @@ -278,7 +281,7 @@ wic_ls_usage = """
> > > > > >
> > > > > > List content of a partitioned image
> > > > > >
> > > > > > - usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot
> > <path>]
> > > > > > + usage: wic ls <image>[:<partition>[<path>]] [--native-sysroot
> > <path>]
> > > > > > [--sector-size <bytes>]
> > > > > >
> > > > > > This command outputs either list of image partitions or
> > directory
> > > > > > contents
> > > > > > of vfat and ext* partitions.
> > > > > > @@ -296,7 +299,7 @@ SYNOPSIS
> > > > > > wic ls <image>
> > > > > > wic ls <image>:<vfat or ext* partition>
> > > > > > wic ls <image>:<vfat or ext* partition><path>
> > > > > > - wic ls <image>:<vfat or ext* partition><path> --native-sysroot
> > > > <path>
> > > > > > + wic ls <image>:<vfat or ext* partition><path> --native-sysroot
> > > > <path>
> > > > > > [--sector-size <bytes>]
> > > > > >
> > > > > > DESCRIPTION
> > > > > > This command lists either partitions of the image or directory
> > > > > > contents
> > > > > > @@ -336,6 +339,8 @@ DESCRIPTION
> > > > > >
> > > > > > The -n option is used to specify the path to the native
> > sysroot
> > > > > > containing the tools(parted and mtools) to use.
> > > > > > + The --sector-size option sets the sector size used for
> > partition
> > > > math
> > > > > > + (default is 512 bytes).
> > > > > >
> > > > > > """
> > > > > >
> > > > > > @@ -343,7 +348,7 @@ wic_cp_usage = """
> > > > > >
> > > > > > Copy files and directories to/from the vfat or ext* partition
> > > > > >
> > > > > > - usage: wic cp <src> <dest> [--native-sysroot <path>]
> > > > > > + usage: wic cp <src> <dest> [--native-sysroot <path>]
> > [--sector-size
> > > > > > <bytes>]
> > > > > >
> > > > > > source/destination image in format <image>:<partition>[<path>]
> > > > > >
> > > > > > @@ -364,7 +369,7 @@ SYNOPSIS
> > > > > > wic cp <src> <dest>:<partition>
> > > > > > wic cp <src>:<partition> <dest>
> > > > > > wic cp <src> <dest-image>:<partition><path>
> > > > > > - wic cp <src> <dest-image>:<partition><path> --native-sysroot
> > > > <path>
> > > > > > + wic cp <src> <dest-image>:<partition><path> --native-sysroot
> > > > <path>
> > > > > > [--sector-size <bytes>]
> > > > > >
> > > > > > DESCRIPTION
> > > > > > This command copies files or directories either
> > > > > > @@ -408,13 +413,15 @@ DESCRIPTION
> > > > > >
> > > > > > The -n option is used to specify the path to the native
> > sysroot
> > > > > > containing the tools(parted and mtools) to use.
> > > > > > + The --sector-size option sets the sector size used for
> > partition
> > > > math
> > > > > > + (default is 512 bytes).
> > > > > > """
> > > > > >
> > > > > > wic_rm_usage = """
> > > > > >
> > > > > > Remove files or directories from the vfat or ext* partitions
> > > > > >
> > > > > > - usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
> > > > > > + usage: wic rm <image>:<partition><path> [--native-sysroot <path>]
> > > > > > [--sector-size <bytes>]
> > > > > >
> > > > > > This command removes files or directories from the vfat or ext*
> > > > > > partitions of
> > > > > > the partitioned image.
> > > > > > @@ -466,6 +473,8 @@ DESCRIPTION
> > > > > >
> > > > > > The -n option is used to specify the path to the native
> > sysroot
> > > > > > containing the tools(parted and mtools) to use.
> > > > > > + The --sector-size option sets the sector size used for
> > partition
> > > > math
> > > > > > + (default is 512 bytes).
> > > > > >
> > > > > > The -r option is used to remove directories and their contents
> > > > > > recursively,this only applies to ext* partition.
> > > > > > diff --git a/scripts/lib/wic/partition.py
> > > > b/scripts/lib/wic/partition.py
> > > > > > index 8fed686e903e..df6e3271649b 100644
> > > > > > --- a/scripts/lib/wic/partition.py
> > > > > > +++ b/scripts/lib/wic/partition.py
> > > > > > @@ -65,6 +65,50 @@ class Partition():
> > > > > >
> > > > > > self.lineno = lineno
> > > > > > self.source_file = ""
> > > > > > + self.sector_size = 512
> > > > > > +
> > > > > > + def _mkdosfs_extraopts(self):
> > > > > > + """
> > > > > > + Build mkdosfs extra options ensuring the CLI sector size
> > is
> > > > > > applied.
> > > > > > + """
> > > > > > + extraopts = self.mkfs_extraopts or ''
> > > > > > + tokens = []
> > > > > > + skip_next = False
> > > > > > + for tok in extraopts.split():
> > > > > > + if skip_next:
> > > > > > + skip_next = False
> > > > > > + continue
> > > > > > + if tok == '-S':
> > > > > > + skip_next = True
> > > > > > + continue
> > > > > > + if tok.startswith('-S'):
> > > > > > + continue
> > > > > > + tokens.append(tok)
> > > > > > + tokens.extend(['-S', str(self.sector_size)])
> > > > > > + return ' '.join(tokens).strip()
> > > > > > +
> > > > > > + def _mkfs_ext_extraopts(self, base_opts):
> > > > > > + """
> > > > > > + Build mkfs.ext* extra options ensuring the CLI sector
> > size is
> > > > > > applied.
> > > > > > + """
> > > > > > + extraopts = self.mkfs_extraopts or base_opts
> > > > > > + # Only add an explicit block size when a non-default
> > sector
> > > > size
> > > > > > is requested.
> > > > > > + if self.sector_size and self.sector_size != 512:
> > > > > > + tokens = []
> > > > > > + skip_next = False
> > > > > > + for tok in extraopts.split():
> > > > > > + if skip_next:
> > > > > > + skip_next = False
> > > > > > + continue
> > > > > > + if tok == '-b':
> > > > > > + skip_next = True
> > > > > > + continue
> > > > > > + if tok.startswith('-b'):
> > > > > > + continue
> > > > > > + tokens.append(tok)
> > > > > > + tokens.extend(['-b', str(self.sector_size)])
> > > > > > + return ' '.join(tokens).strip()
> > > > > > + return extraopts
> > > > > >
> > > > > > def get_extra_block_count(self, current_blocks):
> > > > > > """
> > > > > > @@ -138,6 +182,8 @@ class Partition():
> > > > > > Prepare content for individual partitions, depending on
> > > > > > partition command parameters.
> > > > > > """
> > > > > > + # capture the sector size requested on the CLI for mkdosfs
> > > > > > invocations
> > > > > > + self.sector_size = getattr(creator, 'sector_size', 512)
> > or 512
> > > > > > self.updated_fstab_path = updated_fstab_path
> > > > > > if self.updated_fstab_path and not
> > > > (self.fstype.startswith("ext")
> > > > > > or self.fstype == "msdos"):
> > > > > > self.update_fstab_in_rootfs = True
> > > > > > @@ -293,7 +339,7 @@ class Partition():
> > > > > > with open(rootfs, 'w') as sparse:
> > > > > > os.ftruncate(sparse.fileno(), rootfs_size * 1024)
> > > > > >
> > > > > > - extraopts = self.mkfs_extraopts or "-F -i 8192"
> > > > > > + extraopts = self._mkfs_ext_extraopts("-F -i 8192")
> > > > > >
> > > > > > # use hash_seed to generate reproducible ext4 images
> > > > > > (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts,
> > > > pseudo)
> > > > > > @@ -401,7 +447,7 @@ class Partition():
> > > > > >
> > > > > > size_str = ""
> > > > > >
> > > > > > - extraopts = self.mkfs_extraopts or '-S 512'
> > > > > > + extraopts = self._mkdosfs_extraopts()
> > > > > >
> > > > > > dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
> > > > > > (label_str, self.fsuuid, size_str, extraopts,
> > > > rootfs,
> > > > > > @@ -452,7 +498,7 @@ class Partition():
> > > > > > with open(rootfs, 'w') as sparse:
> > > > > > os.ftruncate(sparse.fileno(), size * 1024)
> > > > > >
> > > > > > - extraopts = self.mkfs_extraopts or "-i 8192"
> > > > > > + extraopts = self._mkfs_ext_extraopts("-i 8192")
> > > > > >
> > > > > > # use hash_seed to generate reproducible ext4 images
> > > > > > (extraopts, pseudo) = self.get_hash_seed_ext4(extraopts,
> > None)
> > > > > > @@ -498,7 +544,7 @@ class Partition():
> > > > > >
> > > > > > size_str = ""
> > > > > >
> > > > > > - extraopts = self.mkfs_extraopts or '-S 512'
> > > > > > + extraopts = self._mkdosfs_extraopts()
> > > > > >
> > > > > > dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \
> > > > > > (label_str, self.fsuuid, extraopts, size_str,
> > > > rootfs,
> > > > > > @@ -559,4 +605,3 @@ class Partition():
> > > > > > logger.warn("%s Inodes (of size %d) are too
> > > > small." %
> > > > > > (get_err_str(self), size))
> > > > > > break
> > > > > > -
> > > > > > diff --git a/scripts/lib/wic/plugins/imager/direct.py
> > > > > > b/scripts/lib/wic/plugins/imager/direct.py
> > > > > > index ad922cfbf122..3adc6eee6280 100644
> > > > > > --- a/scripts/lib/wic/plugins/imager/direct.py
> > > > > > +++ b/scripts/lib/wic/plugins/imager/direct.py
> > > > > > @@ -67,6 +67,7 @@ class DirectPlugin(ImagerPlugin):
> > > > > > self._image = None
> > > > > > self.ptable_format = self.ks.bootloader.ptable
> > > > > > self.parts = self.ks.partitions
> > > > > > + self.sector_size = options.sector_size or 512
> > > > > >
> > > > > > # as a convenience, set source to the boot partition
> > source
> > > > > > # instead of forcing it to be set via bootloader --source
> > > > > > @@ -78,7 +79,7 @@ class DirectPlugin(ImagerPlugin):
> > > > > > image_path = self._full_path(self.workdir,
> > self.parts[0].disk,
> > > > > > "direct")
> > > > > > self._image = PartitionedImage(image_path,
> > self.ptable_format,
> > > > > > self.ks.bootloader.diskid,
> > > > > > self.parts,
> > > > self.native_sysroot,
> > > > > > - options.extra_space)
> > > > > > + options.extra_space,
> > > > > > self.sector_size)
> > > > > >
> > > > > > def setup_workdir(self, workdir):
> > > > > > if workdir:
> > > > > > @@ -294,15 +295,13 @@ MBR_OVERHEAD = 1
> > > > > > # Overhead of the GPT partitioning scheme
> > > > > > GPT_OVERHEAD = 34
> > > > > >
> > > > > > -# Size of a sector in bytes
> > > > > > -SECTOR_SIZE = 512
> > > > > > -
> > > > > > class PartitionedImage():
> > > > > > """
> > > > > > Partitioned image in a file.
> > > > > > """
> > > > > >
> > > > > > - def __init__(self, path, ptable_format, disk_id, partitions,
> > > > > > native_sysroot=None, extra_space=0):
> > > > > > + def __init__(self, path, ptable_format, disk_id, partitions,
> > > > > > native_sysroot=None, extra_space=0,
> > > > > > + sector_size=512):
> > > > > > self.path = path # Path to the image file
> > > > > > self.numpart = 0 # Number of allocated partitions
> > > > > > self.realpart = 0 # Number of partitions in the partition
> > > > table
> > > > > > @@ -332,14 +331,7 @@ class PartitionedImage():
> > > > > > self.partitions = partitions
> > > > > > self.partimages = []
> > > > > > # Size of a sector used in calculations
> > > > > > - sector_size_str = get_bitbake_var('WIC_SECTOR_SIZE')
> > > > > > - if sector_size_str is not None:
> > > > > > - try:
> > > > > > - self.sector_size = int(sector_size_str)
> > > > > > - except ValueError:
> > > > > > - self.sector_size = SECTOR_SIZE
> > > > > > - else:
> > > > > > - self.sector_size = SECTOR_SIZE
> > > > > > + self.sector_size = sector_size or 512
> > > > > >
> > > > > > self.native_sysroot = native_sysroot
> > > > > > num_real_partitions = len([p for p in self.partitions if
> > not
> > > > > > p.no_table])
> > > > > > diff --git a/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > > > > b/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > > > > index 430b0a4b023a..864d6898fc9d 100644
> > > > > > --- a/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > > > > +++ b/scripts/lib/wic/plugins/source/bootimg_efi.py
> > > > > > @@ -415,8 +415,9 @@ class BootimgEFIPlugin(SourcePlugin):
> > > > > >
> > > > > > label = part.label if part.label else "ESP"
> > > > > >
> > > > > > - dosfs_cmd = "mkdosfs -v -n %s -i %s -C %s %d" % \
> > > > > > - (label, part.fsuuid, bootimg, blocks)
> > > > > > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > > > > > + dosfs_cmd = "mkdosfs -v -n %s -i %s -S %d -C %s %d" % \
> > > > > > + (label, part.fsuuid, sector_size, bootimg,
> > blocks)
> > > > > > exec_native_cmd(dosfs_cmd, native_sysroot)
> > > > > > logger.debug("mkdosfs:\n%s" % (str(out)))
> > > > > >
> > > > > > diff --git a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > > > > b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > > > > index a7cc5d12c620..32edac47fa09 100644
> > > > > > --- a/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > > > > +++ b/scripts/lib/wic/plugins/source/bootimg_pcbios.py
> > > > > > @@ -132,7 +132,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > > > > cls._do_prepare_grub(part, cr_workdir,
> > oe_builddir,
> > > > > > kernel_dir, rootfs_dir,
> > > > native_sysroot)
> > > > > > elif source_params['loader-bios'] == 'syslinux':
> > > > > > - cls._do_prepare_syslinux(part, cr_workdir,
> > > > bootimg_dir,
> > > > > > + cls._do_prepare_syslinux(part, creator,
> > cr_workdir,
> > > > > > bootimg_dir,
> > > > > > kernel_dir, native_sysroot)
> > > > > > else:
> > > > > > raise WicError("unrecognized bootimg_pcbios
> > loader:
> > > > %s" %
> > > > > > source_params['loader-bios'])
> > > > > > @@ -142,7 +142,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > > > > except KeyError:
> > > > > > # Required by do_install_disk
> > > > > > cls.loader = 'syslinux'
> > > > > > - cls._do_prepare_syslinux(part, cr_workdir,
> > bootimg_dir,
> > > > > > + cls._do_prepare_syslinux(part, creator, cr_workdir,
> > > > > > bootimg_dir,
> > > > > > kernel_dir, native_sysroot)
> > > > > >
> > > > > > @classmethod
> > > > > > @@ -240,7 +240,7 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > > > > cfg.close()
> > > > > >
> > > > > > @classmethod
> > > > > > - def _do_prepare_syslinux(cls, part, cr_workdir, bootimg_dir,
> > > > > > + def _do_prepare_syslinux(cls, part, creator, cr_workdir,
> > > > bootimg_dir,
> > > > > > kernel_dir, native_sysroot):
> > > > > > """
> > > > > > Called to do the actual content population for a partition
> > > > i.e. it
> > > > > > @@ -292,8 +292,9 @@ class BootimgPcbiosPlugin(SourcePlugin):
> > > > > >
> > > > > > label = part.label if part.label else "boot"
> > > > > >
> > > > > > - dosfs_cmd = "mkdosfs -n %s -i %s -S 512 -C %s %d" % \
> > > > > > - (label, part.fsuuid, bootimg, blocks)
> > > > > > + sector_size = getattr(creator, 'sector_size', 512) or 512
> > > > > > + dosfs_cmd = "mkdosfs -n %s -i %s -S %d -C %s %d" % \
> > > > > > + (label, part.fsuuid, sector_size, bootimg,
> > blocks)
> > > > > > exec_native_cmd(dosfs_cmd, native_sysroot)
> > > > > >
> > > > > > mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir)
> > > > > > diff --git a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > > > > b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > > > > index fdab188db1f8..9195ef5f3184 100644
> > > > > > --- a/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > > > > +++ b/scripts/lib/wic/plugins/source/isoimage_isohybrid.py
> > > > > > @@ -367,8 +367,9 @@ class IsoImagePlugin(SourcePlugin):
> > > > > >
> > > > > > esp_label = source_params.get('esp_label', 'EFIimg')
> > > > > >
> > > > > > - dosfs_cmd = 'mkfs.vfat -n \'%s\' -S 512 -C %s %d' \
> > > > > > - % (esp_label, bootimg, blocks)
> > > > > > + sector_size = getattr(creator, 'sector_size', 512) or
> > 512
> > > > > > + dosfs_cmd = "mkfs.vfat -n '%s' -S %d -C %s %d" % \
> > > > > > + (esp_label, sector_size, bootimg, blocks)
> > > > > > exec_native_cmd(dosfs_cmd, native_sysroot)
> > > > > >
> > > > > > mmd_cmd = "mmd -i %s ::/EFI" % bootimg
> > > > > > diff --git a/scripts/wic b/scripts/wic
> > > > > > index 9137208f5e8f..0cef84ef630c 100755
> > > > > > --- a/scripts/wic
> > > > > > +++ b/scripts/wic
> > > > > > @@ -376,6 +376,8 @@ def wic_init_parser_create(subparser):
> > > > > > default="direct", help="the wic imager
> > plugin")
> > > > > > subparser.add_argument("--extra-space", type=int,
> > > > dest="extra_space",
> > > > > > default=0, help="additional free disk space
> > to
> > > > add
> > > > > > to the image")
> > > > > > + subparser.add_argument("--sector-size", dest="sector_size",
> > > > type=int,
> > > > > > default=512,
> > > > > > + help="sector size in bytes (default: 512)")
> > > > > > return
> > > > > >
> > > > > >
> > > > > > @@ -413,6 +415,8 @@ def imgtype(arg):
> > > > > > def wic_init_parser_ls(subparser):
> > > > > > subparser.add_argument("path", type=imgtype,
> > > > > > help="image spec: <image>[:<vfat
> > > > > > partition>[<path>]]")
> > > > > > + subparser.add_argument("--sector-size", dest="sector_size",
> > > > type=int,
> > > > > > default=512,
> > > > > > + help="sector size in bytes (default:
> > 512)")
> > > > > > subparser.add_argument("-n", "--native-sysroot",
> > > > > > help="path to the native sysroot
> > containing
> > > > the
> > > > > > tools")
> > > > > > subparser.add_argument("-e", "--image-name",
> > dest="image_name",
> > > > > > @@ -433,6 +437,8 @@ def wic_init_parser_cp(subparser):
> > > > > > help="image spec: <image>:<vfat
> > > > > > partition>[<path>] or <file>")
> > > > > > subparser.add_argument("dest",
> > > > > > help="image spec: <image>:<vfat
> > > > > > partition>[<path>] or <file>")
> > > > > > + subparser.add_argument("--sector-size", dest="sector_size",
> > > > type=int,
> > > > > > default=512,
> > > > > > + help="sector size in bytes (default:
> > 512)")
> > > > > > subparser.add_argument("-n", "--native-sysroot",
> > > > > > help="path to the native sysroot
> > containing
> > > > the
> > > > > > tools")
> > > > > > subparser.add_argument("-e", "--image-name",
> > dest="image_name",
> > > > > > @@ -445,6 +451,8 @@ def wic_init_parser_cp(subparser):
> > > > > > def wic_init_parser_rm(subparser):
> > > > > > subparser.add_argument("path", type=imgpathtype,
> > > > > > help="path: <image>:<vfat
> > partition><path>")
> > > > > > + subparser.add_argument("--sector-size", dest="sector_size",
> > > > type=int,
> > > > > > default=512,
> > > > > > + help="sector size in bytes (default:
> > 512)")
> > > > > > subparser.add_argument("-n", "--native-sysroot",
> > > > > > help="path to the native sysroot
> > containing
> > > > the
> > > > > > tools")
> > > > > > subparser.add_argument("-r", dest="recursive_delete",
> > > > > > action="store_true", default=False,
> > > > > > --
> > > > > > 2.51.0
> > > > > >
> > > > > >
> > > > > > -=-=-=-=-=-=-=-=-=-=-=-
> > > > > > Links: You receive all messages sent to this group.
> > > > > > View/Reply Online (#231176):
> > > > > > https://lists.openembedded.org/g/openembedded-core/message/231176
> > > > > > Mute This Topic:
> > https://lists.openembedded.org/mt/117833550/1050810
> > > > > > Group Owner: openembedded-core+owner@lists.openembedded.org
> > > > > > Unsubscribe:
> > https://lists.openembedded.org/g/openembedded-core/unsub
> > > > [
> > > > > > bruce.ashfield@gmail.com]
> > > > > > -=-=-=-=-=-=-=-=-=-=-=-
> > > > > >
> > > > > >
> > > > >
> > > > > --
> > > > > - Thou shalt not follow the NULL pointer, for chaos and madness await
> > > > thee
> > > > > at its end
> > > > > - "Use the force Harry" - Gandalf, Star Trek II
> > > >
> > >
> > >
> > > --
> > > - Thou shalt not follow the NULL pointer, for chaos and madness await
> > thee
> > > at its end
> > > - "Use the force Harry" - Gandalf, Star Trek II
> >
>
>
> --
> - Thou shalt not follow the NULL pointer, for chaos and madness await thee
> at its end
> - "Use the force Harry" - Gandalf, Star Trek II
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-02-16 19:40 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-16 2:31 [PATCH v3 1/2] wic: re-implement sector-size support Trevor Woerner
2026-02-16 2:31 ` [PATCH v3 2/2] ufs image class: add Trevor Woerner
2026-02-16 3:09 ` [OE-core] [PATCH v3 1/2] wic: re-implement sector-size support Bruce Ashfield
2026-02-16 15:37 ` Trevor Woerner
2026-02-16 16:01 ` Bruce Ashfield
2026-02-16 17:58 ` Trevor Woerner
2026-02-16 18:49 ` Bruce Ashfield
2026-02-16 19:40 ` Trevor Woerner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox