* [PATCH v3 1/5] scripts/make_fit: Speed up operation
@ 2025-09-22 22:48 Simon Glass
2025-09-22 22:48 ` [PATCH v3 2/5] scripts/make_fit: Support an initial ramdisk Simon Glass
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Simon Glass @ 2025-09-22 22:48 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Nicolas Schier, Tom Rini, Ahmad Fatoum, J . Neuschäfer,
Masahiro Yamada, Chen-Yu Tsai, Simon Glass, linux-kernel
The kernel is likely at least 16MB so we may as well use that as a step
size when reallocating space for the FIT in memory. Pack the FIT at the
end, so there is no wasted space.
This reduces the time to pack by an order of magnitude, or so.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v3:
- Move the ramdisk chunk into the correct patch
scripts/make_fit.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/scripts/make_fit.py b/scripts/make_fit.py
index 1683e5ec6e67..0f5e7c4b8aed 100755
--- a/scripts/make_fit.py
+++ b/scripts/make_fit.py
@@ -98,7 +98,7 @@ def setup_fit(fsw, name):
fsw (libfdt.FdtSw): Object to use for writing
name (str): Name of kernel image
"""
- fsw.INC_SIZE = 65536
+ fsw.INC_SIZE = 16 << 20
fsw.finish_reservemap()
fsw.begin_node('')
fsw.property_string('description', f'{name} with devicetree set')
@@ -299,7 +299,9 @@ def build_fit(args):
finish_fit(fsw, entries)
# Include the kernel itself in the returned file count
- return fsw.as_fdt().as_bytearray(), seq + 1, size
+ fdt = fsw.as_fdt()
+ fdt.pack()
+ return fdt.as_bytearray(), seq + 1, size
def run_make_fit():
--
2.43.0
base-commit: 846bd2225ec3cfa8be046655e02b9457ed41973e
branch: fita3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 2/5] scripts/make_fit: Support an initial ramdisk
2025-09-22 22:48 [PATCH v3 1/5] scripts/make_fit: Speed up operation Simon Glass
@ 2025-09-22 22:48 ` Simon Glass
2025-09-22 22:48 ` [PATCH v3 3/5] scripts/make_fit: Move dtb processing into a function Simon Glass
` (2 subsequent siblings)
3 siblings, 0 replies; 10+ messages in thread
From: Simon Glass @ 2025-09-22 22:48 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Nicolas Schier, Tom Rini, Ahmad Fatoum, J . Neuschäfer,
Masahiro Yamada, Chen-Yu Tsai, Simon Glass, linux-kernel
FIT (Flat Image Tree) allows an ramdisk to be included in each
configuration. Add support for this to the script.
This feature is not available via 'make image.fit' since the ramdisk
likely needs to be built separately anyway, e.g. using modules from
the kernel build.
Note that the uncompressed size is not correct when a ramdisk is use,
since it is too expensive to decompress the ramdisk.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v3:
- Add a comment at the top of the file about the -r option
- Count the ramdisk in the total files
- Update the commit message
Changes in v2:
- Don't compress the ramdisk as it is already compressed
scripts/make_fit.py | 52 ++++++++++++++++++++++++++++++++++++++-------
1 file changed, 44 insertions(+), 8 deletions(-)
diff --git a/scripts/make_fit.py b/scripts/make_fit.py
index 0f5e7c4b8aed..984371f505bc 100755
--- a/scripts/make_fit.py
+++ b/scripts/make_fit.py
@@ -10,10 +10,14 @@
Usage:
make_fit.py -A arm64 -n 'Linux-6.6' -O linux
-o arch/arm64/boot/image.fit -k /tmp/kern/arch/arm64/boot/image.itk
- @arch/arm64/boot/dts/dtbs-list -E -c gzip
+ -r /boot/initrd.img-6.14.0-27-generic @arch/arm64/boot/dts/dtbs-list
+ -E -c gzip
-Creates a FIT containing the supplied kernel and a set of devicetree files,
-either specified individually or listed in a file (with an '@' prefix).
+Creates a FIT containing the supplied kernel, an optional ramdisk, and a set of
+devicetree files, either specified individually or listed in a file (with an
+'@' prefix).
+
+Use -r to specify an existing ramdisk/initrd file.
Use -E to generate an external FIT (where the data is placed after the
FIT data structure). This allows parsing of the data without loading
@@ -29,8 +33,6 @@ looks at the .cmd files produced by the kernel build.
The resulting FIT can be booted by bootloaders which support FIT, such
as U-Boot, Linuxboot, Tianocore, etc.
-
-Note that this tool does not yet support adding a ramdisk / initrd.
"""
import argparse
@@ -81,6 +83,8 @@ def parse_args():
help='Specifies the operating system')
parser.add_argument('-k', '--kernel', type=str, required=True,
help='Specifies the (uncompressed) kernel input file (.itk)')
+ parser.add_argument('-r', '--ramdisk', type=str,
+ help='Specifies the ramdisk/initrd input file')
parser.add_argument('-v', '--verbose', action='store_true',
help='Enable verbose output')
parser.add_argument('dtbs', type=str, nargs='*',
@@ -133,7 +137,28 @@ def write_kernel(fsw, data, args):
fsw.property_u32('entry', 0)
-def finish_fit(fsw, entries):
+def write_ramdisk(fsw, data, args):
+ """Write out the ramdisk image
+
+ Writes a ramdisk node along with the required properties
+
+ Args:
+ fsw (libfdt.FdtSw): Object to use for writing
+ data (bytes): Data to write (possibly compressed)
+ args (Namespace): Contains necessary strings:
+ arch: FIT architecture, e.g. 'arm64'
+ fit_os: Operating Systems, e.g. 'linux'
+ """
+ with fsw.add_node('ramdisk'):
+ fsw.property_string('description', 'Ramdisk')
+ fsw.property_string('type', 'ramdisk')
+ fsw.property_string('arch', args.arch)
+ fsw.property_string('os', args.os)
+ fsw.property('data', data)
+ fsw.property_u32('load', 0)
+
+
+def finish_fit(fsw, entries, has_ramdisk=False):
"""Finish the FIT ready for use
Writes the /configurations node and subnodes
@@ -143,6 +168,7 @@ def finish_fit(fsw, entries):
entries (list of tuple): List of configurations:
str: Description of model
str: Compatible stringlist
+ has_ramdisk (bool): True if a ramdisk is included in the FIT
"""
fsw.end_node()
seq = 0
@@ -154,6 +180,8 @@ def finish_fit(fsw, entries):
fsw.property_string('description', model)
fsw.property('fdt', bytes(''.join(f'fdt-{x}\x00' for x in files), "ascii"))
fsw.property_string('kernel', 'kernel')
+ if has_ramdisk:
+ fsw.property_string('ramdisk', 'ramdisk')
fsw.end_node()
@@ -274,6 +302,14 @@ def build_fit(args):
size += os.path.getsize(args.kernel)
write_kernel(fsw, comp_data, args)
+ # Handle the ramdisk if provided. Compression is not supported as it is
+ # already compressed.
+ if args.ramdisk:
+ with open(args.ramdisk, 'rb') as inf:
+ data = inf.read()
+ size += len(data)
+ write_ramdisk(fsw, data, args)
+
for fname in args.dtbs:
# Ignore non-DTB (*.dtb) files
if os.path.splitext(fname)[1] != '.dtb':
@@ -296,12 +332,12 @@ def build_fit(args):
entries.append([model, compat, files_seq])
- finish_fit(fsw, entries)
+ finish_fit(fsw, entries, bool(args.ramdisk))
# Include the kernel itself in the returned file count
fdt = fsw.as_fdt()
fdt.pack()
- return fdt.as_bytearray(), seq + 1, size
+ return fdt.as_bytearray(), seq + 1 + bool(args.ramdisk), size
def run_make_fit():
--
2.43.0
base-commit: 846bd2225ec3cfa8be046655e02b9457ed41973e
branch: fita3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 3/5] scripts/make_fit: Move dtb processing into a function
2025-09-22 22:48 [PATCH v3 1/5] scripts/make_fit: Speed up operation Simon Glass
2025-09-22 22:48 ` [PATCH v3 2/5] scripts/make_fit: Support an initial ramdisk Simon Glass
@ 2025-09-22 22:48 ` Simon Glass
2025-09-22 22:48 ` [PATCH v3 4/5] scripts/make_fit: Provide a way to add built modules Simon Glass
2025-09-22 22:48 ` [PATCH v3 5/5] kbuild: Allow adding modules into the FIT ramdisk Simon Glass
3 siblings, 0 replies; 10+ messages in thread
From: Simon Glass @ 2025-09-22 22:48 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Nicolas Schier, Tom Rini, Ahmad Fatoum, J . Neuschäfer,
Masahiro Yamada, Chen-Yu Tsai, Simon Glass, linux-kernel
Since build_fit() is getting quite long, move the dtb processing into a
separate function.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
scripts/make_fit.py | 67 +++++++++++++++++++++++++++++----------------
1 file changed, 44 insertions(+), 23 deletions(-)
diff --git a/scripts/make_fit.py b/scripts/make_fit.py
index 984371f505bc..1a74a9dcd85e 100755
--- a/scripts/make_fit.py
+++ b/scripts/make_fit.py
@@ -277,6 +277,47 @@ def process_dtb(fname, args):
return (model, compat, files)
+
+def _process_dtbs(args, fsw, entries, fdts):
+ """Process all DTB files and add them to the FIT
+
+ Args:
+ args: Program arguments
+ fsw: FIT writer object
+ entries: List to append entries to
+ fdts: Dictionary of processed DTBs
+
+ Returns:
+ tuple:
+ Number of files processed
+ Total size of files processed
+ """
+ seq = 0
+ size = 0
+ for fname in args.dtbs:
+ # Ignore non-DTB (*.dtb) files
+ if os.path.splitext(fname)[1] != '.dtb':
+ continue
+
+ try:
+ (model, compat, files) = process_dtb(fname, args)
+ except Exception as e:
+ sys.stderr.write(f'Error processing {fname}:\n')
+ raise e
+
+ for fn in files:
+ if fn not in fdts:
+ seq += 1
+ size += os.path.getsize(fn)
+ output_dtb(fsw, seq, fn, args.arch, args.compress)
+ fdts[fn] = seq
+
+ files_seq = [fdts[fn] for fn in files]
+ entries.append([model, compat, files_seq])
+
+ return seq, size
+
+
def build_fit(args):
"""Build the FIT from the provided files and arguments
@@ -289,7 +330,6 @@ def build_fit(args):
int: Number of configurations generated
size: Total uncompressed size of data
"""
- seq = 0
size = 0
fsw = libfdt.FdtSw()
setup_fit(fsw, args.name)
@@ -310,34 +350,15 @@ def build_fit(args):
size += len(data)
write_ramdisk(fsw, data, args)
- for fname in args.dtbs:
- # Ignore non-DTB (*.dtb) files
- if os.path.splitext(fname)[1] != '.dtb':
- continue
-
- try:
- (model, compat, files) = process_dtb(fname, args)
- except Exception as e:
- sys.stderr.write(f"Error processing {fname}:\n")
- raise e
-
- for fn in files:
- if fn not in fdts:
- seq += 1
- size += os.path.getsize(fn)
- output_dtb(fsw, seq, fn, args.arch, args.compress)
- fdts[fn] = seq
-
- files_seq = [fdts[fn] for fn in files]
-
- entries.append([model, compat, files_seq])
+ count, fdt_size = _process_dtbs(args, fsw, entries, fdts)
+ size += fdt_size
finish_fit(fsw, entries, bool(args.ramdisk))
# Include the kernel itself in the returned file count
fdt = fsw.as_fdt()
fdt.pack()
- return fdt.as_bytearray(), seq + 1 + bool(args.ramdisk), size
+ return fdt.as_bytearray(), count + 1 + bool(args.ramdisk), size
def run_make_fit():
--
2.43.0
base-commit: 846bd2225ec3cfa8be046655e02b9457ed41973e
branch: fita3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 4/5] scripts/make_fit: Provide a way to add built modules
2025-09-22 22:48 [PATCH v3 1/5] scripts/make_fit: Speed up operation Simon Glass
2025-09-22 22:48 ` [PATCH v3 2/5] scripts/make_fit: Support an initial ramdisk Simon Glass
2025-09-22 22:48 ` [PATCH v3 3/5] scripts/make_fit: Move dtb processing into a function Simon Glass
@ 2025-09-22 22:48 ` Simon Glass
2025-09-25 7:43 ` Ahmad Fatoum
2025-09-22 22:48 ` [PATCH v3 5/5] kbuild: Allow adding modules into the FIT ramdisk Simon Glass
3 siblings, 1 reply; 10+ messages in thread
From: Simon Glass @ 2025-09-22 22:48 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Nicolas Schier, Tom Rini, Ahmad Fatoum, J . Neuschäfer,
Masahiro Yamada, Chen-Yu Tsai, Simon Glass, linux-kernel
Provide arguments to support building a ramdisk from a directory tree of
modules. This is a convenient way to try out a kernel with its modules.
This makes use of the cpio tool rather than attempting to use a python
module or our own code. It also uses 'find' since os.walk() was found to
be quite cumbersome.
Signed-off-by: Simon Glass <sjg@chromium.org>
Suggested-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
(no changes since v1)
scripts/make_fit.py | 127 +++++++++++++++++++++++++++++++++++++++++---
1 file changed, 119 insertions(+), 8 deletions(-)
diff --git a/scripts/make_fit.py b/scripts/make_fit.py
index 1a74a9dcd85e..57667ac9ca3b 100755
--- a/scripts/make_fit.py
+++ b/scripts/make_fit.py
@@ -13,11 +13,17 @@ Usage:
-r /boot/initrd.img-6.14.0-27-generic @arch/arm64/boot/dts/dtbs-list
-E -c gzip
+ # Build with modules ramdisk instead of external ramdisk:
+ make_fit.py -A arm64 -n 'Linux-6.17' -O linux
+ -o arch/arm64/boot/image.fit -k /tmp/kern/arch/arm64/boot/image.itk
+ -m -B /path/to/build/dir @arch/arm64/boot/dts/dtbs-list
+
Creates a FIT containing the supplied kernel, an optional ramdisk, and a set of
devicetree files, either specified individually or listed in a file (with an
'@' prefix).
Use -r to specify an existing ramdisk/initrd file.
+Use -m to build a ramdisk from kernel modules (similar to mkinitramfs).
Use -E to generate an external FIT (where the data is placed after the
FIT data structure). This allows parsing of the data without loading
@@ -38,6 +44,7 @@ as U-Boot, Linuxboot, Tianocore, etc.
import argparse
import collections
import os
+import shutil
import subprocess
import sys
import tempfile
@@ -83,8 +90,18 @@ def parse_args():
help='Specifies the operating system')
parser.add_argument('-k', '--kernel', type=str, required=True,
help='Specifies the (uncompressed) kernel input file (.itk)')
- parser.add_argument('-r', '--ramdisk', type=str,
+
+ # Create mutually exclusive group for ramdisk options
+ rd_group = parser.add_mutually_exclusive_group()
+ rd_group.add_argument('-r', '--ramdisk', type=str,
help='Specifies the ramdisk/initrd input file')
+ rd_group.add_argument('-m', '--modules-ramdisk', action='store_true',
+ help='Build ramdisk from kernel modules (like mkinitramfs)')
+
+ parser.add_argument('-p', '--path', type=str,
+ help='Path where modules are installed (default: temp directory)')
+ parser.add_argument('-B', '--build-dir', type=str,
+ help='Build directory for out-of-tree builds (O= parameter to make)')
parser.add_argument('-v', '--verbose', action='store_true',
help='Enable verbose output')
parser.add_argument('dtbs', type=str, nargs='*',
@@ -240,6 +257,85 @@ def output_dtb(fsw, seq, fname, arch, compress):
fsw.property('data', compressed)
+def build_ramdisk(args, tmpdir):
+ """Build a cpio ramdisk containing kernel modules
+
+ Similar to mkinitramfs, this creates a compressed cpio-archive containing
+ the kernel modules for the current kernel version.
+
+ Args:
+ args (Namespace): Program arguments
+ tmpdir (str): Temporary directory to use for modules installation
+
+ Returns:
+ tuple:
+ bytes: Compressed cpio data containing modules
+ int: total uncompressed size
+ """
+ suppress = None if args.verbose else subprocess.DEVNULL
+ # Use provided tmpdir or custom install path
+ if args.path:
+ mod_path = args.path
+ else:
+ mod_path = os.path.join(tmpdir, 'modules_install')
+ os.makedirs(mod_path, exist_ok=True)
+
+ if args.verbose:
+ print(f'Installing modules to {mod_path}')
+
+ cmd = ['make', '-s', '-j']
+
+ # It seems that the only way to prevent a 'jobserver unavailable' warning
+ # is to remove it from the makeflags
+ env = os.environ.copy()
+ makeflags = env.get('MAKEFLAGS', '')
+ env['MAKEFLAGS'] = ' '.join(f for f in makeflags.split()
+ if not f.startswith('--jobserver-auth'))
+
+ if args.build_dir:
+ cmd.append(f'O={args.build_dir}')
+ cmd.extend(['INSTALL_MOD_PATH=' + mod_path, 'modules_install'])
+ subprocess.check_call(cmd, cwd=os.getcwd(), stdout=suppress, env=env)
+
+ # Find the modules directory that was created (e.g. due to dirty tree)
+ base_dir = os.path.join(mod_path, 'lib', 'modules')
+ if not os.path.exists(base_dir):
+ raise ValueError(f'Modules base directory {base_dir} not found')
+ dirs = [d for d in os.listdir(base_dir)
+ if os.path.isdir(os.path.join(base_dir, d))]
+ if not dirs:
+ raise ValueError(f'No module directories found in {base_dir}')
+ if len(dirs) > 1:
+ raise ValueError(f'Must have only one module directory in {base_dir}')
+
+ # Create initramfs-style directory structure (usr/lib/modules instead of
+ # lib/modules) and move modules into it
+ outdir = os.path.join(tmpdir, 'initramfs')
+ new_dir = os.path.join(outdir, 'usr', 'lib', 'modules')
+ os.makedirs(new_dir, exist_ok=True)
+ shutil.move(os.path.join(base_dir, dirs[0]), os.path.join(new_dir, dirs[0]))
+
+ if args.verbose:
+ print(f'Creating cpio archive from {outdir}')
+
+ with tempfile.NamedTemporaryFile() as cpio_file:
+ # Change to initramfs directory and create cpio archive
+ with subprocess.Popen(['find', '.', '-print0'], cwd=outdir,
+ stdout=subprocess.PIPE) as find:
+ with subprocess.Popen(['cpio', '-o', '-0', '-H', 'newc'],
+ stdin=find.stdout, stdout=cpio_file,
+ stderr=suppress, cwd=outdir) as cpio:
+ find.stdout.close()
+ cpio.wait()
+ find.wait()
+
+ if cpio.returncode != 0:
+ raise RuntimeError('Failed to create cpio archive')
+
+ cpio_file.seek(0) # Reset to beginning for reading
+ return compress_data(cpio_file, args.compress), cpio_file.tell()
+
+
def process_dtb(fname, args):
"""Process an input DTB, decomposing it if requested and is possible
@@ -318,11 +414,12 @@ def _process_dtbs(args, fsw, entries, fdts):
return seq, size
-def build_fit(args):
+def build_fit(args, tmpdir):
"""Build the FIT from the provided files and arguments
Args:
args (Namespace): Program arguments
+ tmpdir (str): Temporary directory for any temporary files
Returns:
tuple:
@@ -344,20 +441,29 @@ def build_fit(args):
# Handle the ramdisk if provided. Compression is not supported as it is
# already compressed.
+ ramdisk_data = None
if args.ramdisk:
with open(args.ramdisk, 'rb') as inf:
- data = inf.read()
- size += len(data)
- write_ramdisk(fsw, data, args)
+ ramdisk_data = inf.read()
+ size += len(ramdisk_data)
+ elif args.modules_ramdisk:
+ if args.verbose:
+ print('Building modules ramdisk...')
+ ramdisk_data, uncomp_size = build_ramdisk(args, tmpdir)
+ size += uncomp_size
+
+ if ramdisk_data:
+ write_ramdisk(fsw, ramdisk_data, args)
count, fdt_size = _process_dtbs(args, fsw, entries, fdts)
size += fdt_size
- finish_fit(fsw, entries, bool(args.ramdisk))
+ finish_fit(fsw, entries, has_ramdisk=bool(ramdisk_data))
- # Include the kernel itself in the returned file count
fdt = fsw.as_fdt()
fdt.pack()
+
+ # Count FDT files, kernel, plus ramdisk if present
return fdt.as_bytearray(), count + 1 + bool(args.ramdisk), size
@@ -365,7 +471,12 @@ def run_make_fit():
"""Run the tool's main logic"""
args = parse_args()
- out_data, count, size = build_fit(args)
+ tmpdir = tempfile.mkdtemp(prefix='make_fit_')
+ try:
+ out_data, count, size = build_fit(args, tmpdir)
+ finally:
+ shutil.rmtree(tmpdir)
+
with open(args.output, 'wb') as outf:
outf.write(out_data)
--
2.43.0
base-commit: 846bd2225ec3cfa8be046655e02b9457ed41973e
branch: fita3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 5/5] kbuild: Allow adding modules into the FIT ramdisk
2025-09-22 22:48 [PATCH v3 1/5] scripts/make_fit: Speed up operation Simon Glass
` (2 preceding siblings ...)
2025-09-22 22:48 ` [PATCH v3 4/5] scripts/make_fit: Provide a way to add built modules Simon Glass
@ 2025-09-22 22:48 ` Simon Glass
2025-09-22 23:07 ` Randy Dunlap
2025-09-24 16:54 ` Nathan Chancellor
3 siblings, 2 replies; 10+ messages in thread
From: Simon Glass @ 2025-09-22 22:48 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Nicolas Schier, Tom Rini, Ahmad Fatoum, J . Neuschäfer,
Masahiro Yamada, Chen-Yu Tsai, Simon Glass, Ard Biesheuvel,
Han Shen, Josh Poimboeuf, Kees Cook, Nathan Chancellor,
Nicolas Schier, Rong Xu, linux-kbuild, linux-kernel
Support 'make image.fit FIT_MODULES=1' to put all the modules into a
ramdisk image within the FIT.
Signed-off-by: Simon Glass <sjg@chromium.org>
Suggested-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
(no changes since v1)
scripts/Makefile.lib | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 1d581ba5df66..2e880d9b4706 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -398,9 +398,15 @@ MAKE_FIT := $(srctree)/scripts/make_fit.py
# Use this to override the compression algorithm
FIT_COMPRESSION ?= gzip
+# Set this to 1 to include an initrd with all the kernel modules
+FIT_MODULES ?= 0
+ifeq ($(FIT_MODULES),1)
+EXTRA := -B $(objtree) -m
+endif
+
quiet_cmd_fit = FIT $@
cmd_fit = $(MAKE_FIT) -o $@ --arch $(UIMAGE_ARCH) --os linux \
- --name '$(UIMAGE_NAME)' \
+ --name '$(UIMAGE_NAME)' $(EXTRA) \
$(if $(findstring 1,$(KBUILD_VERBOSE)),-v) \
$(if $(FIT_DECOMPOSE_DTBS),--decompose-dtbs) \
--compress $(FIT_COMPRESSION) -k $< @$(word 2,$^)
--
2.43.0
base-commit: 846bd2225ec3cfa8be046655e02b9457ed41973e
branch: fita3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3 5/5] kbuild: Allow adding modules into the FIT ramdisk
2025-09-22 22:48 ` [PATCH v3 5/5] kbuild: Allow adding modules into the FIT ramdisk Simon Glass
@ 2025-09-22 23:07 ` Randy Dunlap
2025-09-23 11:41 ` Simon Glass
2025-09-24 16:54 ` Nathan Chancellor
1 sibling, 1 reply; 10+ messages in thread
From: Randy Dunlap @ 2025-09-22 23:07 UTC (permalink / raw)
To: Simon Glass, linux-arm-kernel
Cc: Nicolas Schier, Tom Rini, Ahmad Fatoum, J . Neuschäfer,
Masahiro Yamada, Chen-Yu Tsai, Ard Biesheuvel, Han Shen,
Josh Poimboeuf, Kees Cook, Nathan Chancellor, Nicolas Schier,
Rong Xu, linux-kbuild, linux-kernel
Hi,
On 9/22/25 3:48 PM, Simon Glass wrote:
> Support 'make image.fit FIT_MODULES=1' to put all the modules into a
> ramdisk image within the FIT.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> Suggested-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
Regarding $subject, a comment in scripts/make_fit.py says:
Note that this tool does not yet support adding a ramdisk / initrd.
Is the comment incorrect or are you changing that feature here?
Thanks.
>
> (no changes since v1)
>
> scripts/Makefile.lib | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
> index 1d581ba5df66..2e880d9b4706 100644
> --- a/scripts/Makefile.lib
> +++ b/scripts/Makefile.lib
> @@ -398,9 +398,15 @@ MAKE_FIT := $(srctree)/scripts/make_fit.py
> # Use this to override the compression algorithm
> FIT_COMPRESSION ?= gzip
>
> +# Set this to 1 to include an initrd with all the kernel modules
> +FIT_MODULES ?= 0
> +ifeq ($(FIT_MODULES),1)
> +EXTRA := -B $(objtree) -m
> +endif
> +
> quiet_cmd_fit = FIT $@
> cmd_fit = $(MAKE_FIT) -o $@ --arch $(UIMAGE_ARCH) --os linux \
> - --name '$(UIMAGE_NAME)' \
> + --name '$(UIMAGE_NAME)' $(EXTRA) \
> $(if $(findstring 1,$(KBUILD_VERBOSE)),-v) \
> $(if $(FIT_DECOMPOSE_DTBS),--decompose-dtbs) \
> --compress $(FIT_COMPRESSION) -k $< @$(word 2,$^)
--
~Randy
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 5/5] kbuild: Allow adding modules into the FIT ramdisk
2025-09-22 23:07 ` Randy Dunlap
@ 2025-09-23 11:41 ` Simon Glass
0 siblings, 0 replies; 10+ messages in thread
From: Simon Glass @ 2025-09-23 11:41 UTC (permalink / raw)
To: Randy Dunlap
Cc: linux-arm-kernel, Nicolas Schier, Tom Rini, Ahmad Fatoum,
J . Neuschäfer, Masahiro Yamada, Chen-Yu Tsai,
Ard Biesheuvel, Han Shen, Josh Poimboeuf, Kees Cook,
Nathan Chancellor, Nicolas Schier, Rong Xu, linux-kbuild,
linux-kernel
Hi Randy,
On Mon, 22 Sept 2025 at 17:08, Randy Dunlap <rdunlap@infradead.org> wrote:
>
> Hi,
>
> On 9/22/25 3:48 PM, Simon Glass wrote:
> > Support 'make image.fit FIT_MODULES=1' to put all the modules into a
> > ramdisk image within the FIT.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > Suggested-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> > ---
>
> Regarding $subject, a comment in scripts/make_fit.py says:
>
> Note that this tool does not yet support adding a ramdisk / initrd.
>
> Is the comment incorrect or are you changing that feature here?
I am changing it (in patch 2 of this series).
Regards,
Simon
>
> Thanks.
>
> >
> > (no changes since v1)
> >
> > scripts/Makefile.lib | 8 +++++++-
> > 1 file changed, 7 insertions(+), 1 deletion(-)
> >
> > diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
> > index 1d581ba5df66..2e880d9b4706 100644
> > --- a/scripts/Makefile.lib
> > +++ b/scripts/Makefile.lib
> > @@ -398,9 +398,15 @@ MAKE_FIT := $(srctree)/scripts/make_fit.py
> > # Use this to override the compression algorithm
> > FIT_COMPRESSION ?= gzip
> >
> > +# Set this to 1 to include an initrd with all the kernel modules
> > +FIT_MODULES ?= 0
> > +ifeq ($(FIT_MODULES),1)
> > +EXTRA := -B $(objtree) -m
> > +endif
> > +
> > quiet_cmd_fit = FIT $@
> > cmd_fit = $(MAKE_FIT) -o $@ --arch $(UIMAGE_ARCH) --os linux \
> > - --name '$(UIMAGE_NAME)' \
> > + --name '$(UIMAGE_NAME)' $(EXTRA) \
> > $(if $(findstring 1,$(KBUILD_VERBOSE)),-v) \
> > $(if $(FIT_DECOMPOSE_DTBS),--decompose-dtbs) \
> > --compress $(FIT_COMPRESSION) -k $< @$(word 2,$^)
>
> --
> ~Randy
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 5/5] kbuild: Allow adding modules into the FIT ramdisk
2025-09-22 22:48 ` [PATCH v3 5/5] kbuild: Allow adding modules into the FIT ramdisk Simon Glass
2025-09-22 23:07 ` Randy Dunlap
@ 2025-09-24 16:54 ` Nathan Chancellor
1 sibling, 0 replies; 10+ messages in thread
From: Nathan Chancellor @ 2025-09-24 16:54 UTC (permalink / raw)
To: Simon Glass
Cc: linux-arm-kernel, Nicolas Schier, Tom Rini, Ahmad Fatoum,
J . Neuschäfer, Masahiro Yamada, Chen-Yu Tsai,
Ard Biesheuvel, Han Shen, Josh Poimboeuf, Kees Cook,
Nicolas Schier, Rong Xu, linux-kbuild, linux-kernel
On Mon, Sep 22, 2025 at 04:48:32PM -0600, Simon Glass wrote:
> Support 'make image.fit FIT_MODULES=1' to put all the modules into a
> ramdisk image within the FIT.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> Suggested-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
Acked-by: Nathan Chancellor <nathan@kernel.org>
> scripts/Makefile.lib | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
> index 1d581ba5df66..2e880d9b4706 100644
> --- a/scripts/Makefile.lib
> +++ b/scripts/Makefile.lib
> @@ -398,9 +398,15 @@ MAKE_FIT := $(srctree)/scripts/make_fit.py
> # Use this to override the compression algorithm
> FIT_COMPRESSION ?= gzip
>
> +# Set this to 1 to include an initrd with all the kernel modules
> +FIT_MODULES ?= 0
> +ifeq ($(FIT_MODULES),1)
> +EXTRA := -B $(objtree) -m
Not that I can imagine it being a big issue, it would be nice to
potentially namespace this variable, like MAKE_FIT_EXTRA or
MAKE_FIT_FLAGS?
> +endif
> +
> quiet_cmd_fit = FIT $@
> cmd_fit = $(MAKE_FIT) -o $@ --arch $(UIMAGE_ARCH) --os linux \
> - --name '$(UIMAGE_NAME)' \
> + --name '$(UIMAGE_NAME)' $(EXTRA) \
> $(if $(findstring 1,$(KBUILD_VERBOSE)),-v) \
> $(if $(FIT_DECOMPOSE_DTBS),--decompose-dtbs) \
> --compress $(FIT_COMPRESSION) -k $< @$(word 2,$^)
> --
> 2.43.0
>
> base-commit: 846bd2225ec3cfa8be046655e02b9457ed41973e
> branch: fita3
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 4/5] scripts/make_fit: Provide a way to add built modules
2025-09-22 22:48 ` [PATCH v3 4/5] scripts/make_fit: Provide a way to add built modules Simon Glass
@ 2025-09-25 7:43 ` Ahmad Fatoum
2025-10-06 23:02 ` Simon Glass
0 siblings, 1 reply; 10+ messages in thread
From: Ahmad Fatoum @ 2025-09-25 7:43 UTC (permalink / raw)
To: Simon Glass, linux-arm-kernel
Cc: Nicolas Schier, Tom Rini, J . Neuschäfer, Masahiro Yamada,
Chen-Yu Tsai, linux-kernel, kernel@pengutronix.de
Hello Simon,
Thanks for looking into this!
On 9/23/25 12:48 AM, Simon Glass wrote:
> +def build_ramdisk(args, tmpdir):
> + """Build a cpio ramdisk containing kernel modules
> +
> + Similar to mkinitramfs, this creates a compressed cpio-archive containing
> + the kernel modules for the current kernel version.
> +
> + Args:
> + args (Namespace): Program arguments
> + tmpdir (str): Temporary directory to use for modules installation
> +
> + Returns:
> + tuple:
> + bytes: Compressed cpio data containing modules
> + int: total uncompressed size
> + """
> + suppress = None if args.verbose else subprocess.DEVNULL
> + # Use provided tmpdir or custom install path
> + if args.path:
> + mod_path = args.path
> + else:
> + mod_path = os.path.join(tmpdir, 'modules_install')
> + os.makedirs(mod_path, exist_ok=True)
> +
> + if args.verbose:
> + print(f'Installing modules to {mod_path}')
> +
> + cmd = ['make', '-s', '-j']
Executing `make image.fit FIT_MODULES=1` in a fresh build will result in
a python stack trace, because image.fit only has dependencies for the
kernel image and the device trees, but none for the modules.
Even with that added, I don't think it's a good idea to have make call a
script only for it to call make again.
Instead, there should probably be a modules.cpio.gz make target or
similar in its own right and image.fit should depend on it if
FIT_MODULES is set.
Thanks,
Ahmad
> +
> + # It seems that the only way to prevent a 'jobserver unavailable' warning
> + # is to remove it from the makeflags
> + env = os.environ.copy()
> + makeflags = env.get('MAKEFLAGS', '')
> + env['MAKEFLAGS'] = ' '.join(f for f in makeflags.split()
> + if not f.startswith('--jobserver-auth'))
> +
> + if args.build_dir:
> + cmd.append(f'O={args.build_dir}')
> + cmd.extend(['INSTALL_MOD_PATH=' + mod_path, 'modules_install'])
> + subprocess.check_call(cmd, cwd=os.getcwd(), stdout=suppress, env=env)
> +
> + # Find the modules directory that was created (e.g. due to dirty tree)
> + base_dir = os.path.join(mod_path, 'lib', 'modules')
> + if not os.path.exists(base_dir):
> + raise ValueError(f'Modules base directory {base_dir} not found')
> + dirs = [d for d in os.listdir(base_dir)
> + if os.path.isdir(os.path.join(base_dir, d))]
> + if not dirs:
> + raise ValueError(f'No module directories found in {base_dir}')
> + if len(dirs) > 1:
> + raise ValueError(f'Must have only one module directory in {base_dir}')
> +
> + # Create initramfs-style directory structure (usr/lib/modules instead of
> + # lib/modules) and move modules into it
> + outdir = os.path.join(tmpdir, 'initramfs')
> + new_dir = os.path.join(outdir, 'usr', 'lib', 'modules')
> + os.makedirs(new_dir, exist_ok=True)
> + shutil.move(os.path.join(base_dir, dirs[0]), os.path.join(new_dir, dirs[0]))
> +
> + if args.verbose:
> + print(f'Creating cpio archive from {outdir}')
> +
> + with tempfile.NamedTemporaryFile() as cpio_file:
> + # Change to initramfs directory and create cpio archive
> + with subprocess.Popen(['find', '.', '-print0'], cwd=outdir,
> + stdout=subprocess.PIPE) as find:
> + with subprocess.Popen(['cpio', '-o', '-0', '-H', 'newc'],
> + stdin=find.stdout, stdout=cpio_file,
> + stderr=suppress, cwd=outdir) as cpio:
> + find.stdout.close()
> + cpio.wait()
> + find.wait()
> +
> + if cpio.returncode != 0:
> + raise RuntimeError('Failed to create cpio archive')
> +
> + cpio_file.seek(0) # Reset to beginning for reading
> + return compress_data(cpio_file, args.compress), cpio_file.tell()
> +
> +
> def process_dtb(fname, args):
> """Process an input DTB, decomposing it if requested and is possible
>
> @@ -318,11 +414,12 @@ def _process_dtbs(args, fsw, entries, fdts):
> return seq, size
>
>
> -def build_fit(args):
> +def build_fit(args, tmpdir):
> """Build the FIT from the provided files and arguments
>
> Args:
> args (Namespace): Program arguments
> + tmpdir (str): Temporary directory for any temporary files
>
> Returns:
> tuple:
> @@ -344,20 +441,29 @@ def build_fit(args):
>
> # Handle the ramdisk if provided. Compression is not supported as it is
> # already compressed.
> + ramdisk_data = None
> if args.ramdisk:
> with open(args.ramdisk, 'rb') as inf:
> - data = inf.read()
> - size += len(data)
> - write_ramdisk(fsw, data, args)
> + ramdisk_data = inf.read()
> + size += len(ramdisk_data)
> + elif args.modules_ramdisk:
> + if args.verbose:
> + print('Building modules ramdisk...')
> + ramdisk_data, uncomp_size = build_ramdisk(args, tmpdir)
> + size += uncomp_size
> +
> + if ramdisk_data:
> + write_ramdisk(fsw, ramdisk_data, args)
>
> count, fdt_size = _process_dtbs(args, fsw, entries, fdts)
> size += fdt_size
>
> - finish_fit(fsw, entries, bool(args.ramdisk))
> + finish_fit(fsw, entries, has_ramdisk=bool(ramdisk_data))
>
> - # Include the kernel itself in the returned file count
> fdt = fsw.as_fdt()
> fdt.pack()
> +
> + # Count FDT files, kernel, plus ramdisk if present
> return fdt.as_bytearray(), count + 1 + bool(args.ramdisk), size
>
>
> @@ -365,7 +471,12 @@ def run_make_fit():
> """Run the tool's main logic"""
> args = parse_args()
>
> - out_data, count, size = build_fit(args)
> + tmpdir = tempfile.mkdtemp(prefix='make_fit_')
> + try:
> + out_data, count, size = build_fit(args, tmpdir)
> + finally:
> + shutil.rmtree(tmpdir)
> +
> with open(args.output, 'wb') as outf:
> outf.write(out_data)
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 4/5] scripts/make_fit: Provide a way to add built modules
2025-09-25 7:43 ` Ahmad Fatoum
@ 2025-10-06 23:02 ` Simon Glass
0 siblings, 0 replies; 10+ messages in thread
From: Simon Glass @ 2025-10-06 23:02 UTC (permalink / raw)
To: Ahmad Fatoum
Cc: linux-arm-kernel, Nicolas Schier, Tom Rini, J . Neuschäfer,
Masahiro Yamada, Chen-Yu Tsai, linux-kernel,
kernel@pengutronix.de
Hi Ahmad,
On Thu, 25 Sept 2025 at 01:43, Ahmad Fatoum <a.fatoum@pengutronix.de> wrote:
>
> Hello Simon,
>
> Thanks for looking into this!
>
> On 9/23/25 12:48 AM, Simon Glass wrote:
> > +def build_ramdisk(args, tmpdir):
> > + """Build a cpio ramdisk containing kernel modules
> > +
> > + Similar to mkinitramfs, this creates a compressed cpio-archive containing
> > + the kernel modules for the current kernel version.
> > +
> > + Args:
> > + args (Namespace): Program arguments
> > + tmpdir (str): Temporary directory to use for modules installation
> > +
> > + Returns:
> > + tuple:
> > + bytes: Compressed cpio data containing modules
> > + int: total uncompressed size
> > + """
> > + suppress = None if args.verbose else subprocess.DEVNULL
> > + # Use provided tmpdir or custom install path
> > + if args.path:
> > + mod_path = args.path
> > + else:
> > + mod_path = os.path.join(tmpdir, 'modules_install')
> > + os.makedirs(mod_path, exist_ok=True)
> > +
> > + if args.verbose:
> > + print(f'Installing modules to {mod_path}')
> > +
> > + cmd = ['make', '-s', '-j']
>
> Executing `make image.fit FIT_MODULES=1` in a fresh build will result in
> a python stack trace, because image.fit only has dependencies for the
> kernel image and the device trees, but none for the modules.
>
> Even with that added, I don't think it's a good idea to have make call a
> script only for it to call make again.
Yes I don't like that either.
>
> Instead, there should probably be a modules.cpio.gz make target or
> similar in its own right and image.fit should depend on it if
> FIT_MODULES is set.
That seems better. I'll give it a try.
>
> Thanks,
> Ahmad
>
> > +
> > + # It seems that the only way to prevent a 'jobserver unavailable' warning
> > + # is to remove it from the makeflags
> > + env = os.environ.copy()
> > + makeflags = env.get('MAKEFLAGS', '')
> > + env['MAKEFLAGS'] = ' '.join(f for f in makeflags.split()
> > + if not f.startswith('--jobserver-auth'))
> > +
> > + if args.build_dir:
> > + cmd.append(f'O={args.build_dir}')
> > + cmd.extend(['INSTALL_MOD_PATH=' + mod_path, 'modules_install'])
> > + subprocess.check_call(cmd, cwd=os.getcwd(), stdout=suppress, env=env)
> > +
> > + # Find the modules directory that was created (e.g. due to dirty tree)
> > + base_dir = os.path.join(mod_path, 'lib', 'modules')
> > + if not os.path.exists(base_dir):
> > + raise ValueError(f'Modules base directory {base_dir} not found')
> > + dirs = [d for d in os.listdir(base_dir)
> > + if os.path.isdir(os.path.join(base_dir, d))]
> > + if not dirs:
> > + raise ValueError(f'No module directories found in {base_dir}')
> > + if len(dirs) > 1:
> > + raise ValueError(f'Must have only one module directory in {base_dir}')
> > +
> > + # Create initramfs-style directory structure (usr/lib/modules instead of
> > + # lib/modules) and move modules into it
> > + outdir = os.path.join(tmpdir, 'initramfs')
> > + new_dir = os.path.join(outdir, 'usr', 'lib', 'modules')
> > + os.makedirs(new_dir, exist_ok=True)
> > + shutil.move(os.path.join(base_dir, dirs[0]), os.path.join(new_dir, dirs[0]))
> > +
> > + if args.verbose:
> > + print(f'Creating cpio archive from {outdir}')
> > +
> > + with tempfile.NamedTemporaryFile() as cpio_file:
> > + # Change to initramfs directory and create cpio archive
> > + with subprocess.Popen(['find', '.', '-print0'], cwd=outdir,
> > + stdout=subprocess.PIPE) as find:
> > + with subprocess.Popen(['cpio', '-o', '-0', '-H', 'newc'],
> > + stdin=find.stdout, stdout=cpio_file,
> > + stderr=suppress, cwd=outdir) as cpio:
> > + find.stdout.close()
> > + cpio.wait()
> > + find.wait()
> > +
> > + if cpio.returncode != 0:
> > + raise RuntimeError('Failed to create cpio archive')
> > +
> > + cpio_file.seek(0) # Reset to beginning for reading
> > + return compress_data(cpio_file, args.compress), cpio_file.tell()
> > +
> > +
> > def process_dtb(fname, args):
> > """Process an input DTB, decomposing it if requested and is possible
> >
> > @@ -318,11 +414,12 @@ def _process_dtbs(args, fsw, entries, fdts):
> > return seq, size
> >
> >
> > -def build_fit(args):
> > +def build_fit(args, tmpdir):
> > """Build the FIT from the provided files and arguments
> >
> > Args:
> > args (Namespace): Program arguments
> > + tmpdir (str): Temporary directory for any temporary files
> >
> > Returns:
> > tuple:
> > @@ -344,20 +441,29 @@ def build_fit(args):
> >
> > # Handle the ramdisk if provided. Compression is not supported as it is
> > # already compressed.
> > + ramdisk_data = None
> > if args.ramdisk:
> > with open(args.ramdisk, 'rb') as inf:
> > - data = inf.read()
> > - size += len(data)
> > - write_ramdisk(fsw, data, args)
> > + ramdisk_data = inf.read()
> > + size += len(ramdisk_data)
> > + elif args.modules_ramdisk:
> > + if args.verbose:
> > + print('Building modules ramdisk...')
> > + ramdisk_data, uncomp_size = build_ramdisk(args, tmpdir)
> > + size += uncomp_size
> > +
> > + if ramdisk_data:
> > + write_ramdisk(fsw, ramdisk_data, args)
> >
> > count, fdt_size = _process_dtbs(args, fsw, entries, fdts)
> > size += fdt_size
> >
> > - finish_fit(fsw, entries, bool(args.ramdisk))
> > + finish_fit(fsw, entries, has_ramdisk=bool(ramdisk_data))
> >
> > - # Include the kernel itself in the returned file count
> > fdt = fsw.as_fdt()
> > fdt.pack()
> > +
> > + # Count FDT files, kernel, plus ramdisk if present
> > return fdt.as_bytearray(), count + 1 + bool(args.ramdisk), size
> >
> >
> > @@ -365,7 +471,12 @@ def run_make_fit():
> > """Run the tool's main logic"""
> > args = parse_args()
> >
> > - out_data, count, size = build_fit(args)
> > + tmpdir = tempfile.mkdtemp(prefix='make_fit_')
> > + try:
> > + out_data, count, size = build_fit(args, tmpdir)
> > + finally:
> > + shutil.rmtree(tmpdir)
> > +
> > with open(args.output, 'wb') as outf:
> > outf.write(out_data)
> >
>
> --
> Pengutronix e.K. | |
> Steuerwalder Str. 21 | http://www.pengutronix.de/ |
> 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
> Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
>
Regards,
Simon
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-10-06 23:03 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-22 22:48 [PATCH v3 1/5] scripts/make_fit: Speed up operation Simon Glass
2025-09-22 22:48 ` [PATCH v3 2/5] scripts/make_fit: Support an initial ramdisk Simon Glass
2025-09-22 22:48 ` [PATCH v3 3/5] scripts/make_fit: Move dtb processing into a function Simon Glass
2025-09-22 22:48 ` [PATCH v3 4/5] scripts/make_fit: Provide a way to add built modules Simon Glass
2025-09-25 7:43 ` Ahmad Fatoum
2025-10-06 23:02 ` Simon Glass
2025-09-22 22:48 ` [PATCH v3 5/5] kbuild: Allow adding modules into the FIT ramdisk Simon Glass
2025-09-22 23:07 ` Randy Dunlap
2025-09-23 11:41 ` Simon Glass
2025-09-24 16:54 ` Nathan Chancellor
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).