From: Douglas Anderson <dianders@chromium.org>
To: Devicetree-compiler@vger.kernel.org,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Konrad Dybcio <konradybcio@kernel.org>
Cc: "Peter Griffin" <peter.griffin@linaro.org>,
"Saravana Kannan" <saravanak@kernel.org>,
Devicetree@vger.kernel.org, "Simon Glass" <sjg@chromium.org>,
"Chen-Yu Tsai" <wenst@chromium.org>,
"Julius Werner" <jwerner@chromium.org>,
"Brian Norris" <briannorris@chromium.org>,
linux-kernel@vger.kernel.org,
"Tudor Ambarus" <tudor.ambarus@linaro.org>,
"André Draszik" <andre.draszik@linaro.org>,
"David Gibson" <david@gibson.dropbear.id.au>,
"Douglas Anderson" <dianders@chromium.org>
Subject: [PATCH v3 13/15] fdtfactor: Add -S/--strip-local-fixups option
Date: Sun, 1 Nov 2026 14:01:20 -0800 [thread overview]
Message-ID: <20261101220224.1436242-14-dianders@chromium.org> (raw)
In-Reply-To: <20261101220224.1436242-1-dianders@chromium.org>
By default, `fdtfactor` preserves `/__local_fixups__` on `base.dtb` so
that when `fdt_overlay_apply()` merges a `.dtbo` overlay, the
reconstructed device tree retains full `/__local_fixups__` information
(for instance, if an OS kernel wants to know which property cells
contain phandles at runtime).
When `-L` was passed to `dtc` solely to help `fdtfactor` locate phandle
cells at build time and `/__local_fixups__` is not needed at runtime,
retaining `/__local_fixups__` in `base.dtb` wastes space.
Add `-S` / `--strip-local-fixups` to omit `/__local_fixups__` from
`base.dtb` (and therefore from the merged device trees produced by
`fdt_overlay_apply()`). On a set of 47 Qualcomm SC7180 Trogdor
Chromebook board DTBs, `fdtfactor` without `-S` reduces total
uncompressed size from 7.69 MB to 932 KB (88.2% savings), while
`fdtfactor -S` reduces it to 634 KB (91.8% savings, saving an additional
298 KB by omitting `/__local_fixups__` from `base.dtb`).
Add a test case in `tests/run_tests.sh` verifying that `fdtfactor -S`
followed by `fdtoverlay` reproduces DTBs compiled with `-@` (without
`-L`) via `dtbs_equal_unordered`.
Assisted-by: Gemini:gemini-pro-prerelease
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v3:
- Include both non--S (932 KB) and -S (634 KB) Trogdor size numbers in
the commit message to show the savings of -S itself (Simon Glass)
- Pass -S to the negative test verifying that inputs lacking
/__local_fixups__ are still rejected when -S is used, and move the
non--S rejection test to the base fdtfactor patch (Simon Glass)
Changes in v2:
- Split -S/--strip-local-fixups into a separate opt-in patch (David
Gibson)
README.md | 9 +++++++++
fdtfactor | 34 ++++++++++++++++++++++++++--------
tests/run_tests.sh | 18 ++++++++++++++++++
3 files changed, 53 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index 61fefc4424fe..bb6f041e1e78 100644
--- a/README.md
+++ b/README.md
@@ -139,6 +139,15 @@ Options:
* `-o`, `--outdir`: Output directory for generated `.dtbo` files and
`--output-base-dtb` (default: alongside each input `.dtb` for `.dtbo` files,
current directory for `--output-base-dtb`).
+* `-S`, `--strip-local-fixups`: Omit `/__local_fixups__` from the generated
+ `base.dtb` and final reconstructed device trees. By default, `fdtfactor`
+ preserves `/__local_fixups__` on `base.dtb` so that when `fdt_overlay_apply()`
+ merges a `.dtbo` overlay, the reconstructed device tree retains full
+ `/__local_fixups__` information (e.g., for an OS kernel that wants to
+ know which property cells contain phandles at runtime). When `-L` was
+ passed to `dtc` solely to help `fdtfactor` locate phandles at build time
+ and `/__local_fixups__` is not needed at runtime, passing `-S` strips it
+ from `base.dtb` to save space.
* `-s`, `--stats`: Print size savings summary.
### TODO
diff --git a/fdtfactor b/fdtfactor
index f6944e36a0f2..7442a2597399 100755
--- a/fdtfactor
+++ b/fdtfactor
@@ -442,7 +442,8 @@ def _build_base_tree(dtbs):
return base_root
-def _serialize_base_dtb(base_root, base_dtb_symbols, rsvmap, boot_cpuid_phys):
+def _serialize_base_dtb(base_root, base_dtb_symbols, rsvmap, boot_cpuid_phys,
+ strip_local_fixups=False):
"""Materialize phandles, `/__symbols__`, and `/__local_fixups__` and flatten.
Args:
@@ -451,6 +452,8 @@ def _serialize_base_dtb(base_root, base_dtb_symbols, rsvmap, boot_cpuid_phys):
base_dtb_symbols: Dict mapping common symbol labels to target paths.
rsvmap: Sequence of `(address, size)` memory reservation tuples.
boot_cpuid_phys: Physical boot CPU ID for the FDT header.
+ strip_local_fixups: If True, omit `/__local_fixups__` from the
+ generated `base.dtb`.
Returns:
Serialized `.dtb` `bytes` for the common base DTB.
@@ -485,11 +488,12 @@ def _serialize_base_dtb(base_root, base_dtb_symbols, rsvmap, boot_cpuid_phys):
for label, target_path in base_dtb_symbols.items():
sym_node.set_str(label, target_path or '/')
- # Create `/__local_fixups__` on the base DTB so `fdt_overlay_apply()`
- # updates it with the overlay's phandle fixups when merging.
- lf_root = out_root.create_path('/__local_fixups__')
- for path, prop_name, offs in lf_entries:
- lf_root.create_path(path).set_u32_list(prop_name, offs)
+ if not strip_local_fixups:
+ # Create `/__local_fixups__` on the base DTB so `fdt_overlay_apply()`
+ # updates it with the overlay's phandle fixups when merging.
+ lf_root = out_root.create_path('/__local_fixups__')
+ for path, prop_name, offs in lf_entries:
+ lf_root.create_path(path).set_u32_list(prop_name, offs)
fdt = out_root.flatten(mem_rsv=rsvmap, boot_cpuid_phys=boot_cpuid_phys)
return bytes(fdt.as_bytearray())
@@ -638,11 +642,13 @@ def _build_board_dtbo(dtb, base_root, base_dtb_symbols,
return bytes(dtbo_root.flatten().as_bytearray())
-def create_base_dtb_and_overlays(dtbs):
+def create_base_dtb_and_overlays(dtbs, strip_local_fixups=False):
"""Compute the base DTB and per-board DTBO blobs from parsed DTBs.
Args:
dtbs: Sequence of `ParsedDtb` instances (at least two).
+ strip_local_fixups: If True, omit `/__local_fixups__` from the
+ generated `base.dtb`.
Returns:
Tuple of `(base_dtb_blob, dtbo_blobs)` where `base_dtb_blob` is the
@@ -657,6 +663,7 @@ def create_base_dtb_and_overlays(dtbs):
base_dtb_blob = _serialize_base_dtb(
base_root, base_dtb_symbols,
dtbs[0].mem_rsv, dtbs[0].boot_cpuid_phys,
+ strip_local_fixups=strip_local_fixups,
)
dtbo_blobs = [
_build_board_dtbo(
@@ -719,6 +726,14 @@ def parse_args(argv=None):
'current directory for --output-base-dtb)'
),
)
+ parser.add_argument(
+ '-S', '--strip-local-fixups',
+ action='store_true',
+ help=(
+ 'Omit /__local_fixups__ from the generated base .dtb and '
+ 'reconstructed device trees'
+ ),
+ )
parser.add_argument(
'-s', '--stats',
action='store_true',
@@ -803,7 +818,10 @@ def factor_dtb_files(args):
seen_paths.add(abs_out)
dtbo_paths.append(out_path)
- base_dtb_blob, dtbo_blobs = create_base_dtb_and_overlays(dtbs)
+ base_dtb_blob, dtbo_blobs = create_base_dtb_and_overlays(
+ dtbs,
+ strip_local_fixups=args.strip_local_fixups,
+ )
if args.outdir:
os.makedirs(args.outdir, exist_ok=True)
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 166a662708a5..e5ac38dd2bab 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -1243,6 +1243,24 @@ fdtfactor_tests () {
done
run_wrap_error_test $PYTHON $FDTFACTOR -o fdtfactor_legacy.test.dir \
fdtfactor_board1.nolf.test.dtb fdtfactor_board2.test.dtb
+
+ # Strip local fixups (-S): verify that merged DTBs match DTBs compiled
+ # with -@ (without -L), and that inputs lacking /__local_fixups__ are
+ # still rejected even when -S is passed.
+ run_wrap_error_test $PYTHON $FDTFACTOR -S -o fdtfactor_strip.test.dir \
+ fdtfactor_board1.nolf.test.dtb fdtfactor_board2.test.dtb
+ rm -rf fdtfactor_strip.test.dir
+ run_wrap_test $PYTHON $FDTFACTOR -S --output-base-dtb base_strip.test.dtb \
+ -o fdtfactor_strip.test.dir \
+ fdtfactor_board1.test.dtb fdtfactor_board2.test.dtb \
+ fdtfactor_board3.test.dtb
+ for i in 1 2 3; do
+ run_wrap_test $FDTOVERLAY -i fdtfactor_strip.test.dir/base_strip.test.dtb \
+ -o fdtfactor_strip.test.dir/merged${i}.test.dtb \
+ fdtfactor_strip.test.dir/fdtfactor_board${i}.test.dtbo
+ run_test dtbs_equal_unordered fdtfactor_board${i}.nolf.test.dtb \
+ fdtfactor_strip.test.dir/merged${i}.test.dtb
+ done
}
while getopts "vt:me" ARG ; do
--
2.56.0.317.g454f8302e1-goog
next prev parent reply other threads:[~2026-11-01 22:04 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-01 22:01 [PATCH v3 00/15] fdtfactor: Introduce fdtfactor to auto-factor overlays Douglas Anderson
2026-11-01 22:01 ` [PATCH v3 01/15] libfdt: overlay: Fix out-of-bounds write on bad fixup offset Douglas Anderson
2026-11-02 4:29 ` David Gibson
2026-11-01 22:01 ` [PATCH v3 02/15] libfdt: overlay: Drop redundant *sep != ':' checks after memchr() Douglas Anderson
2026-11-02 4:30 ` David Gibson
2026-11-01 22:01 ` [PATCH v3 03/15] pylibfdt: Clarify iterator docstrings and test negative offsets Douglas Anderson
2026-11-02 4:32 ` David Gibson
2026-11-01 22:01 ` [PATCH v3 04/15] pylibfdt: Handle empty properties in as_str() and as_stringlist() Douglas Anderson
2026-11-02 4:33 ` David Gibson
2026-11-01 22:01 ` [PATCH v3 05/15] pylibfdt: Add Fdt.set_boot_cpuid_phys() Douglas Anderson
2026-11-02 4:34 ` David Gibson
2026-11-01 22:01 ` [PATCH v3 06/15] pylibfdt: Support copy.copy() and copy.deepcopy() on Property Douglas Anderson
2026-11-02 4:35 ` David Gibson
2026-11-01 22:01 ` [PATCH v3 07/15] devicetree: Add DeviceTree live tree representation Douglas Anderson
2026-11-01 22:01 ` [PATCH v3 08/15] libfdt: overlay: Factor out fixup and fragment path parsing helpers Douglas Anderson
2026-11-01 22:01 ` [PATCH v3 09/15] libfdt: overlay: Prepare fragment path helper for reuse Douglas Anderson
2026-11-01 22:01 ` [PATCH v3 10/15] libfdt: overlay: Make fdto const in overlay_apply_node() Douglas Anderson
2026-11-01 22:01 ` [PATCH v3 11/15] libfdt: overlay: Update base /__local_fixups__ on apply Douglas Anderson
2026-11-01 22:01 ` [PATCH v3 12/15] fdtfactor: Add tool to split DTBs into a base DTB and overlays Douglas Anderson
2026-11-01 22:01 ` Douglas Anderson [this message]
2026-11-01 22:01 ` [PATCH v3 14/15] fdtfactor: Support compressed DTB inputs and outputs Douglas Anderson
2026-11-01 22:01 ` [PATCH v3 15/15] fdtfactor: Add compiled FIT factoring support Douglas Anderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261101220224.1436242-14-dianders@chromium.org \
--to=dianders@chromium.org \
--cc=Devicetree-compiler@vger.kernel.org \
--cc=Devicetree@vger.kernel.org \
--cc=andre.draszik@linaro.org \
--cc=briannorris@chromium.org \
--cc=conor+dt@kernel.org \
--cc=david@gibson.dropbear.id.au \
--cc=jwerner@chromium.org \
--cc=konradybcio@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=peter.griffin@linaro.org \
--cc=robh@kernel.org \
--cc=saravanak@kernel.org \
--cc=sjg@chromium.org \
--cc=tudor.ambarus@linaro.org \
--cc=wenst@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®