Skip to content

Commit b031b90

Browse files
kernel tools: add build-dtb-image.sh for combined DTB FAT image generation
Introduce build-dtb-image.sh, a standalone tool to generate a FAT-formatted image containing a single combined DTB for Qualcomm-based ARM64 platforms. The script: - Consumes a manifest listing DTB filenames (one per line), supporting both absolute and DTB source–relative paths. - Normalizes and sanitizes the manifest into a temporary list, skipping blank and comment lines. - Validates that: - The manifest file exists and yields at least one DTB entry. - All referenced DTB files exist under the specified DTB source tree. - The requested FAT image size (-size) is a positive integer (MB). - Concatenates DTBs in manifest order into <DTB_SRC>/combined-dtb.dtb - Creates a FAT image of configurable size (default 7 MB), attaches it to a loop device, formats it, mounts it on a temporary directory, and copies the combined DTB into the root of the filesystem. - Installs an EXIT trap with a robust cleanup path that: - Preserves the original exit status. - Unmounts the temporary mountpoint only if mounted. - Detaches the loop device only if it was successfully created. - Removes all temporary files and directories. This provides a reproducible, automation-friendly way to package a curated DTB set into a single combined DTB and corresponding FAT image suitable for boot flows and CI pipelines. Signed-off-by: Bjordis Collaku <[email protected]>
1 parent b235d54 commit b031b90

File tree

1 file changed

+244
-0
lines changed

1 file changed

+244
-0
lines changed

kernel/scripts/build-dtb-image.sh

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
#!/usr/bin/env bash
2+
#
3+
# =============================================================================
4+
# build-dtb-image.sh
5+
#
6+
# Description:
7+
# Build a FAT-formatted image containing a single *combined* Device Tree
8+
# Blob (DTB) file for Qualcomm-based ARM64 platforms.
9+
#
10+
# This script:
11+
# 1. Reads a manifest file listing DTB filenames (one per line).
12+
# 2. Normalizes entries to absolute paths under the specified DTB source
13+
# directory (unless already absolute).
14+
# 3. Validates that all DTB files exist.
15+
# 4. Concatenates all DTBs (in manifest order) into a single combined
16+
# DTB file: <DTB_SRC>/combined-dtb.dtb
17+
# 5. Creates a FAT image of configurable size.
18+
# 6. Mounts the FAT image via a loop device and copies the combined DTB
19+
# into the image.
20+
#
21+
# Usage:
22+
# ./build-dtb-image.sh -dtb-src <path> -manifest <file> [-size <MB>] [-out <file>]
23+
#
24+
# Arguments:
25+
# -dtb-src Path to DTB source directory
26+
# e.g., arch/arm64/boot/dts/qcom
27+
#
28+
# -manifest Path to manifest file listing DTBs (one per line). Each line:
29+
# - may be relative to -dtb-src, OR
30+
# - an absolute path to a .dtb file.
31+
# Blank lines and lines starting with '#' are ignored.
32+
#
33+
# -size FAT image size in MB (integer > 0, default: 4)
34+
#
35+
# -out Output image filename (default: dtb.bin)
36+
#
37+
# Requirements / Assumptions:
38+
# - Linux host with:
39+
# * bash
40+
# * mkfs.vfat
41+
# * losetup
42+
# * mount / umount
43+
# * dd (with status=progress support is nice but not required)
44+
# - sudo access for:
45+
# * losetup
46+
# * mkfs.vfat
47+
# * mount / umount
48+
#
49+
# Notes:
50+
# - The combined DTB is written to: <DTB_SRC>/combined-dtb.dtb
51+
# - The resulting FAT image contains exactly one file: combined-dtb.dtb
52+
# in the root directory of the filesystem.
53+
# - The script installs a cleanup trap to:
54+
# * unmount the image,
55+
# * detach the loop device,
56+
# * delete temporary files and directories.
57+
#
58+
# =============================================================================
59+
60+
set -euo pipefail
61+
62+
# ----------------------------- Defaults --------------------------------------
63+
64+
DTB_BIN_SIZE=4 # Default FAT image size (MB)
65+
DTB_BIN="dtb.bin" # Default output image filename
66+
67+
DTB_SRC="" # DTB source directory (required)
68+
DTB_LIST="" # Manifest file (required)
69+
70+
SANLIST="" # Will hold the path to the sanitized DTB list
71+
MNT_DIR="" # Temporary mount directory
72+
LOOP_DEV="" # Loop device used for the FAT image
73+
74+
# ---------------------------- Helper Functions -------------------------------
75+
76+
usage() {
77+
cat <<EOF
78+
Usage: $0 -dtb-src <path> -manifest <file> [-size <MB>] [-out <file>]
79+
80+
-dtb-src Path to DTB source directory (e.g. arch/arm64/boot/dts/qcom)
81+
-manifest Path to manifest file listing DTBs (one per line)
82+
-size FAT image size in MB (default: 7)
83+
-out Output image filename (default: dtb.bin)
84+
EOF
85+
exit 1
86+
}
87+
88+
cleanup() {
89+
# Preserve the original exit status so we can exit with the right code
90+
local status=$?
91+
92+
# Ensure any buffered writes are flushed (best-effort)
93+
sync || true
94+
95+
# Unmount the mountpoint if it exists and is currently mounted
96+
if [[ -n "${MNT_DIR:-}" && -d "$MNT_DIR" ]]; then
97+
if mountpoint -q "$MNT_DIR"; then
98+
sudo umount "$MNT_DIR" || true
99+
fi
100+
# Try to remove the temporary directory (ignore failures)
101+
rmdir "$MNT_DIR" 2>/dev/null || true
102+
fi
103+
104+
# Detach loop device if it was created
105+
if [[ -n "${LOOP_DEV:-}" ]]; then
106+
sudo losetup -d "$LOOP_DEV" || true
107+
fi
108+
109+
# Remove temporary sanitized list
110+
if [[ -n "${SANLIST:-}" && -f "$SANLIST" ]]; then
111+
rm -f "$SANLIST"
112+
fi
113+
114+
exit "$status"
115+
}
116+
117+
# Install trap early to handle failures after we start creating resources.
118+
trap cleanup EXIT
119+
120+
# ------------------------------ Arg Parsing ----------------------------------
121+
122+
while [[ $# -gt 0 ]]; do
123+
case "$1" in
124+
-dtb-src)
125+
DTB_SRC="${2:-}"
126+
shift 2
127+
;;
128+
-manifest)
129+
DTB_LIST="${2:-}"
130+
shift 2
131+
;;
132+
-size)
133+
DTB_BIN_SIZE="${2:-}"
134+
shift 2
135+
;;
136+
-out)
137+
DTB_BIN="${2:-}"
138+
shift 2
139+
;;
140+
*)
141+
usage
142+
;;
143+
esac
144+
done
145+
146+
# ----------------------------- Validation ------------------------------------
147+
148+
# Require mandatory arguments
149+
if [[ -z "$DTB_SRC" || -z "$DTB_LIST" ]]; then
150+
echo "ERROR: -dtb-src and -manifest are required." >&2
151+
usage
152+
fi
153+
154+
# Validate manifest exists
155+
if [[ ! -f "$DTB_LIST" ]]; then
156+
echo "ERROR: Manifest file '$DTB_LIST' not found." >&2
157+
exit 1
158+
fi
159+
160+
# Validate DTB source directory
161+
if [[ ! -d "$DTB_SRC" ]]; then
162+
echo "ERROR: DTB source directory '$DTB_SRC' not found." >&2
163+
exit 1
164+
fi
165+
166+
# Validate image size is a positive integer
167+
if ! [[ "$DTB_BIN_SIZE" =~ ^[0-9]+$ ]] || (( DTB_BIN_SIZE <= 0 )); then
168+
echo "ERROR: -size must be a positive integer (MB), got '$DTB_BIN_SIZE'." >&2
169+
exit 1
170+
fi
171+
172+
# --------------------------- Sanitize Manifest -------------------------------
173+
174+
# Temporary file to hold the fully-qualified DTB paths
175+
SANLIST="$(mktemp -t dtb-list-XXXXXX)"
176+
177+
# Normalize manifest lines:
178+
# - Skip blank lines
179+
# - Skip comment lines starting with '#'
180+
# - If the entry is absolute, keep as-is
181+
# - Otherwise, prefix with DTB_SRC
182+
awk -v src="$DTB_SRC" '
183+
/^[[:space:]]*$/ {next} # skip blank lines
184+
/^[[:space:]]*#/ {next} # skip comments
185+
{
186+
if ($0 ~ /^\//) print $0;
187+
else print src "/" $0;
188+
}
189+
' "$DTB_LIST" > "$SANLIST"
190+
191+
# Ensure that the manifest produced at least one valid entry
192+
if [[ ! -s "$SANLIST" ]]; then
193+
echo "ERROR: Manifest '$DTB_LIST' has no valid DTB entries (non-comment, non-empty)." >&2
194+
exit 1
195+
fi
196+
197+
# Validate each DTB exists
198+
while IFS= read -r f; do
199+
if [[ ! -f "$f" ]]; then
200+
echo "ERROR: Missing DTB: $f" >&2
201+
exit 1
202+
fi
203+
done < "$SANLIST"
204+
205+
# -------------------------- Combine DTBs -------------------------------------
206+
207+
OUT="${DTB_SRC}/combined-dtb.dtb"
208+
rm -f "$OUT"
209+
210+
# Concatenate in the order specified by the sanitized manifest.
211+
# xargs -a is GNU-specific but acceptable for typical Linux build hosts.
212+
xargs -a "$SANLIST" -r cat > "$OUT"
213+
echo "[INFO] Combined DTBs into: $OUT"
214+
ls -lh "$OUT"
215+
216+
# -------------------------- Create FAT Image ---------------------------------
217+
218+
echo "[INFO] Creating FAT image '$DTB_BIN' (${DTB_BIN_SIZE} MB)..."
219+
dd if=/dev/zero of="$DTB_BIN" bs=1M count="$DTB_BIN_SIZE" status=progress
220+
221+
# Attach a loop device to the image
222+
LOOP_DEV="$(sudo losetup --show -fP "$DTB_BIN")"
223+
echo "[INFO] Using loop device: $LOOP_DEV"
224+
225+
# Create a temporary mount directory for this run
226+
MNT_DIR="$(mktemp -d -t dtb-mnt-XXXXXX)"
227+
228+
# Format the loop device with FAT
229+
echo "[INFO] Formatting $LOOP_DEV as FAT..."
230+
sudo mkfs.vfat "$LOOP_DEV" >/dev/null
231+
232+
# Mount the loop device
233+
echo "[INFO] Mounting $LOOP_DEV at $MNT_DIR..."
234+
sudo mount "$LOOP_DEV" "$MNT_DIR"
235+
236+
# ----------------------- Deploy Combined DTB ---------------------------------
237+
238+
sudo cp "$OUT" "$MNT_DIR/"
239+
echo "[INFO] Deployed combined DTB into FAT image."
240+
echo "[INFO] Files in image:"
241+
ls -lh "$MNT_DIR"
242+
243+
# Normal exit (cleanup will still run, but now everything should succeed).
244+
exit 0

0 commit comments

Comments
 (0)