Skip to content

Commit 972e5e2

Browse files
Yury-MonZonalchark
authored andcommitted
flipper-bls.sh: shared BLS boot-entry library
Sourced helpers for the per-profile scheme, where the entry-token <NN>-flipperos-<subvol> is both the /boot/<token>/ dir and the <token>-<version>.conf name (U-Boot's filename sort gives the menu band). make_token, stage_kernel_reflink, emit_entry, remove_entries, remove_root_entries, clone_slot, discover_devicetreedir, flipper_write_entry. The ospack recipe overlays overlays/usr/lib to /usr/lib so the library ships.
1 parent c62f7a2 commit 972e5e2

2 files changed

Lines changed: 337 additions & 0 deletions

File tree

debian-rk3576-ospack.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ actions:
198198
source: overlays/usr/local
199199
destination: /usr/local
200200

201+
- action: overlay
202+
description: Overlay our usr/lib helpers
203+
source: overlays/usr/lib
204+
destination: /usr/lib
205+
201206
- action: overlay
202207
description: Overlay our usr/share files
203208
source: overlays/usr/share

overlays/usr/lib/flipper-bls.sh

Lines changed: 332 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,332 @@
1+
#!/bin/sh
2+
# SPDX-License-Identifier: LGPL-2.1-or-later
3+
#
4+
# flipper-bls.sh - shared library for Flipper One BLS boot-entry generation.
5+
#
6+
# SOURCED, never executed. Defines the helpers used by the kernel-install plugin
7+
# (90-loaderentry.install) and the btrfs snapshot tooling (create_profile/rename_profile).
8+
# Functions read globals lazily (at call time), so callers set what they need first.
9+
# The kernel/initrd staging and devicetree(dir) handling are derived from systemd's
10+
# 90-loaderentry.install (LGPL-2.1-or-later).
11+
12+
VENDOR=rockchip
13+
TITLE_MAX="${FLIPPER_TITLE_MAX:-26}"
14+
15+
log() { [ "${KERNEL_INSTALL_VERBOSE:-0}" -gt 0 ] && echo "flipper-bls: $*" >&2; return 0; }
16+
die() { echo "flipper-bls: $*" >&2; exit 1; }
17+
trim() { printf '%s' "$1" | sed 's/^ *//; s/ *$//'; }
18+
# copy a file into the entry dir as root:root 0644
19+
stage_file() { install -m 0644 -o root -g root "$1" "$2" || die "could not copy '$1'"; }
20+
21+
# absolute path under BOOT_ROOT -> path as it must appear inside a BLS entry (relative to the
22+
# boot partition; identical to the absolute path while /boot is on the rootfs). On Flipper One
23+
# BOOT_MNT=/ (/boot is a subvol on the root partition, never a separate boot partition).
24+
boot_rel() { if [ "${BOOT_MNT:-/}" = "/" ]; then printf '%s\n' "$1"; else printf '%s\n' "${1#"${BOOT_MNT}"}"; fi; }
25+
26+
has_config() { [ -f "$KCONFIG" ] && grep -q "^CONFIG_$1=[ym]" "$KCONFIG"; }
27+
28+
# Last rootflags=subvol= value in a cmdline/options string (empty if none).
29+
subvol_of() { printf '%s' "$1" | tr ' ' '\n' | sed -n 's/^rootflags=subvol=//p' | tail -n1; }
30+
31+
# BLS sort-key from os-release (IMAGE_ID, else ID); empty if no os-release.
32+
os_sort_key() { [ -r /etc/os-release ] && ( . /etc/os-release; printf '%s' "${IMAGE_ID:-$ID}" ) || :; }
33+
34+
# Set DTB_DIR + DTB_DIRS (primary dir + modules fallback) for the current $KERNEL_VERSION.
35+
set_dtb_dirs() { DTB_DIR="/usr/lib/linux-image-$KERNEL_VERSION"; DTB_DIRS="$DTB_DIR /usr/lib/modules/$KERNEL_VERSION/dtb"; }
36+
37+
# Kernel entry-token for a root: <NN>-flipperos-<subvol sans @>, carrying the menu band + root id.
38+
# Empty NN -> plain flipperos-<name> (sorts above the numbered bands, like an unmappable root).
39+
make_token() { # $1 = NN (may be empty) $2 = subvol
40+
_n="$(printf '%s' "$2" | tr -d '@')"
41+
[ -n "$1" ] && printf '%s-flipperos-%s' "$1" "$_n" || printf 'flipperos-%s' "$_n"
42+
}
43+
44+
# Reflink the shared /boot kernel + initrd for $KERNEL_VERSION into this $ENTRY_TOKEN's staging
45+
# dir (/boot/$ENTRY_TOKEN/$KERNEL_VERSION); btrfs shares the extents, so per-root dirs are ~free.
46+
# Sets KERNEL_ENTRY + INITRD_ENTRIES. For paths the kernel-install plugin does not stage itself
47+
# (the build fan-out and the clone tooling).
48+
stage_kernel_reflink() {
49+
_sd="/boot/$ENTRY_TOKEN/$KERNEL_VERSION"
50+
mkdir -p "$_sd" || die "cannot create $_sd"
51+
cp -a --reflink=auto "/boot/vmlinuz-$KERNEL_VERSION" "$_sd/linux" || die "no /boot/vmlinuz-$KERNEL_VERSION"
52+
KERNEL_ENTRY="$(boot_rel "$_sd/linux")"
53+
INITRD_ENTRIES=""
54+
if [ -e "/boot/initrd.img-$KERNEL_VERSION" ]; then
55+
cp -a --reflink=auto "/boot/initrd.img-$KERNEL_VERSION" "$_sd/initrd.img-$KERNEL_VERSION"
56+
INITRD_ENTRIES="$(boot_rel "$_sd/initrd.img-$KERNEL_VERSION")"
57+
fi
58+
}
59+
60+
# U-Boot reads the btrfs TOP LEVEL (subvolid 5), so in-entry devicetreedir/overlay paths need the
61+
# entry's own root subvol prefixed (/@<subvol>/usr/lib/...), taken from its rootflags=subvol=.
62+
# Set FDT_SUBVOL_PREFIX to override (e.g. "" if the root isn't a subvol).
63+
fdt_prefix() { # $1 = options string -> "/<rootflags-subvol>" (or $FDT_SUBVOL_PREFIX if set)
64+
if [ "${FDT_SUBVOL_PREFIX+x}" = x ]; then printf '%s' "$FDT_SUBVOL_PREFIX"; return 0; fi
65+
_sv=$(subvol_of "$1")
66+
[ -n "$_sv" ] && printf '/%s' "$_sv"
67+
return 0
68+
}
69+
70+
# btrfs subvol of the currently-booted root (e.g. @Desktop); empty if not a subvol.
71+
current_subvol() { findmnt -nro FSROOT / 2>/dev/null | sed 's,^/,,'; }
72+
73+
# Remove loader entries whose options select SUBVOL and whose version == VERSION. Content-based
74+
# (token/filename-agnostic), so it leaves every other root's entries untouched. Uses $ENTRIES.
75+
remove_entries() { # $1 = subvol $2 = version
76+
[ -n "$1" ] && [ -n "$2" ] || return 0
77+
for _c in "${ENTRIES:-/boot/loader/entries}"/*.conf; do
78+
[ -f "$_c" ] || continue
79+
[ "$(awk '$1=="version"{print $2; exit}' "$_c")" = "$2" ] || continue
80+
_es="$(awk '$1=="options"{for(i=2;i<=NF;i++) if($i ~ /^rootflags=subvol=/) s=$i}
81+
END{sub(/^rootflags=subvol=/,"",s); print s}' "$_c")"
82+
[ "$_es" = "$1" ] && rm -f "$_c"
83+
done
84+
return 0 # a non-matching last entry must not fail the loop under set -e
85+
}
86+
87+
# Tear down a whole root: remove EVERY entry that selects SUBVOL (all versions) and each one's
88+
# /boot/<token>/ staging tree. The staging dir is derived from the entry's own 'linux' line, so it
89+
# works no matter how the token was computed. For delete_profile/rename_profile (whole-profile ops).
90+
# Uses $ENTRIES. Prints what it removes to stderr.
91+
remove_root_entries() { # $1 = subvol
92+
[ -n "$1" ] || return 0
93+
for _c in "${ENTRIES:-/boot/loader/entries}"/*.conf; do
94+
[ -f "$_c" ] || continue
95+
_es="$(awk '$1=="options"{for(i=2;i<=NF;i++) if($i ~ /^rootflags=subvol=/) s=$i}
96+
END{sub(/^rootflags=subvol=/,"",s); print s}' "$_c")"
97+
[ "$_es" = "$1" ] || continue
98+
_lx="$(awk '$1=="linux"{print $2; exit}' "$_c")"
99+
rm -f "$_c"; echo "removed boot entry $_c" >&2
100+
case "$_lx" in /boot/*/*/linux)
101+
_td="${_lx%/*/linux}"; [ "$_td" != /boot ] && rm -rf "$_td" ;;
102+
esac
103+
done
104+
return 0
105+
}
106+
107+
# Base menu slot (900,800,700,... by flipper-profiles position) for the profile $1 belongs to.
108+
# $1 is a btrfs-PARENT name. It anchors on an ACTUAL profile: the exact name (@Desktop) or its
109+
# golden base / snapshot (@Desktop_stock, @Desktop_<stamp>: profile name followed by '_'). A
110+
# hyphen-suffixed clone (@Desktop-2) must NOT match here, so origin_base_depth can walk THROUGH
111+
# it to count clone depth. Empty if none. Steps of 100 leave room for ~99 variants per band.
112+
profile_base_nn() {
113+
_want="$1"; _pf="${PROFILES:-/etc/kernel/flipper-profiles}"; [ -f "$_pf" ] || return 0
114+
_j=0
115+
while IFS='|' read -r _t _s _e _g _d _l; do
116+
_t="$(echo "$_t" | tr -d '[:space:]')"; case "$_t" in ''|\#*) continue ;; esac
117+
_sv="$(subvol_of "$_e" | tr -d '[:space:]')"
118+
[ -n "$_sv" ] && case "$_want" in "$_sv"|"$_sv"_*) printf '%03d' "$((900 - _j * 100))"; return 0 ;; esac
119+
_j=$((_j + 1))
120+
done <"$_pf"
121+
return 0
122+
}
123+
124+
# Origin-profile base slot AND clone depth for a derived root. Clone/snapshot names are arbitrary
125+
# and can chain (a snapshot of a snapshot), so instead of matching the name we WALK the btrfs
126+
# parent_uuid chain up from the subvol at $1, counting hops, until an ancestor is a listed profile
127+
# or its golden base (profile_base_nn). Prints "BASE DEPTH" (e.g. "900 2" = desktop, grandparent);
128+
# depth is the hop count (1 = direct clone, 2 = clone of a clone, ...). Empty if none maps or no
129+
# btrfs. One `subvolume list` covers the whole fs (ancestors need not be mounted).
130+
origin_base_depth() { # $1 = mounted path (default /)
131+
command -v btrfs >/dev/null 2>&1 || return 0
132+
_mp="${1:-/}"
133+
_cur="$(btrfs subvolume show "$_mp" 2>/dev/null | sed -n 's/.*[Pp]arent UUID:[[:space:]]*//p' | head -n1)"
134+
[ -n "$_cur" ] && [ "$_cur" != "-" ] || return 0
135+
# fs-wide table: one row "uuid parent_uuid name" per subvolume
136+
_tbl="$(btrfs subvolume list -qu "$_mp" 2>/dev/null | awk '{ u="-"; p="-"; for(i=1;i<NF;i++){ if($i=="uuid")u=$(i+1); else if($i=="parent_uuid")p=$(i+1) } print u, p, $NF }')"
137+
_seen=" "; _depth=0
138+
while [ -n "$_cur" ] && [ "$_cur" != "-" ]; do
139+
case "$_seen" in *" $_cur "*) break ;; esac # cycle guard
140+
_seen="$_seen$_cur "
141+
_row="$(printf '%s\n' "$_tbl" | awk -v u="$_cur" '$1==u{print $2, $3; exit}')"
142+
[ -n "$_row" ] || break
143+
_depth=$((_depth + 1))
144+
_pn="${_row#* }"; _pn="${_pn##*/}" # this ancestor's name (basename)
145+
_bn="$(profile_base_nn "$_pn")"
146+
[ -n "$_bn" ] && { printf '%s %s' "$_bn" "$_depth"; return 0; }
147+
_cur="${_row%% *}" # follow parent_uuid to the grandparent
148+
done
149+
return 0
150+
}
151+
152+
# Clone menu slot for a derived root: origin base + clone-depth (direct clone -> base+1,
153+
# clone of a clone -> base+2, ...), so clones sit just above the profile (whose factory and
154+
# in-profile-install entries share the base slot). $1 = mounted path; $2 = optional origin hint
155+
# (the name it was restored FROM). Prefers the parent-chain walk (true depth); if that yields
156+
# nothing (e.g. parent_uuid left dangling by a move/receive) it falls back to the hint as a direct
157+
# clone (depth 1 -> base+1). Prints a 3-digit NN, or empty if unresolved.
158+
clone_slot() { # $1 = mounted path (default /); $2 = origin hint (optional)
159+
_cs_bd="$(origin_base_depth "${1:-/}")"
160+
if [ -n "$_cs_bd" ]; then
161+
printf '%03d' "$(( ${_cs_bd%% *} + ${_cs_bd#* } ))"; return 0
162+
fi
163+
if [ -n "${2:-}" ]; then
164+
_cs_b="$(profile_base_nn "${2##*/}")"
165+
[ -n "$_cs_b" ] && printf '%03d' "$(( _cs_b + 1 ))"
166+
fi
167+
return 0
168+
}
169+
170+
# Menu titles must fit the small screen: cap total at TITLE_MAX by trimming the (long) version
171+
# while keeping the suffix intact. (Filenames + the 'version' field keep the full version.)
172+
make_title() {
173+
_suf="$1"
174+
_avail=$(( TITLE_MAX - ${#_suf} - 1 ))
175+
if [ "$_avail" -ge 1 ]; then
176+
printf '%s %s' "$(printf '%s' "$KERNEL_VERSION" | cut -c"1-$_avail")" "$_suf"
177+
else
178+
printf '%s' "$_suf" | cut -c"1-$TITLE_MAX"
179+
fi
180+
}
181+
182+
# write_entry FILE TITLE OPTIONS FDTOVERLAYS
183+
write_entry() {
184+
_f="$1"; _title="$2"; _opts="$3"; _fdtov="$4"
185+
# devicetreedir is prefixed with THIS entry's root subvol (U-Boot reads subvolid 5)
186+
_dtdir=""; [ -n "$DEVICETREEDIR_REL" ] && _dtdir="$(fdt_prefix "$_opts")$DEVICETREEDIR_REL"
187+
{
188+
echo "# Boot Loader Specification type#1 entry (Flipper One)"
189+
echo "title $_title"
190+
echo "version $KERNEL_VERSION"
191+
[ -n "$MACHINE_ID" ] && [ "$ENTRY_TOKEN" = "$MACHINE_ID" ] && echo "machine-id $MACHINE_ID"
192+
[ -n "$SORT_KEY" ] && echo "sort-key $SORT_KEY"
193+
[ -n "$_opts" ] && echo "options $_opts"
194+
echo "linux $KERNEL_ENTRY"
195+
[ -n "$DEVICETREE_ENTRY" ] && echo "devicetree $DEVICETREE_ENTRY"
196+
[ -n "$_dtdir" ] && echo "devicetreedir $_dtdir"
197+
[ -n "$_fdtov" ] && echo "devicetree-overlay $_fdtov"
198+
for _ird in $INITRD_ENTRIES; do echo "initrd $_ird"; done
199+
} >"$_f"
200+
return 0 # don't let a trailing empty conditional's status abort `set -e`
201+
}
202+
203+
# Echo the space-separated paths of the named DT overlays (flat, next to the DTBs).
204+
# Returns non-zero with no output if any one is missing.
205+
overlay_paths() { # $1 = subvol prefix (e.g. /@Desktop); remaining args = overlay names
206+
_pfx="$1"; shift
207+
_paths=""
208+
for _n in "$@"; do
209+
[ -f "$OVERLAY_DIR/$_n.dtbo" ] || return 1 # check the real on-disk path
210+
_paths="$_paths${_paths:+ }$_pfx$OVERLAY_DIR/$_n.dtbo"
211+
done
212+
printf '%s' "$_paths"
213+
}
214+
215+
# Set BASE_OPTS from CONF_ROOT/cmdline (root=UUID + policy) + this kernel's console layout.
216+
# FIQ kernel -> console=ttyFIQ0 ; mainline -> console=ttyS0 + ttyS4 + fbcon=map:1.
217+
compute_base_opts() {
218+
if [ -f "$CONF_ROOT/cmdline" ]; then
219+
BASE_OPTS="$(grep -Gv '^\s*#' "$CONF_ROOT/cmdline" | tr -s '[:space:]' ' ')"
220+
elif [ -f /usr/lib/kernel/cmdline ]; then
221+
BASE_OPTS="$(grep -Gv '^\s*#' /usr/lib/kernel/cmdline | tr -s '[:space:]' ' ')"
222+
else
223+
BASE_OPTS=""
224+
fi
225+
BASE_OPTS="$(trim "$BASE_OPTS")"
226+
# Pin systemd.machine_id= only when entries are named after the machine-id (no-op otherwise).
227+
if [ -n "$MACHINE_ID" ] && [ "$ENTRY_TOKEN" = "$MACHINE_ID" ] && ! echo "$BASE_OPTS" | grep -q "systemd.machine_id="; then
228+
BASE_OPTS="$BASE_OPTS systemd.machine_id=$MACHINE_ID"
229+
fi
230+
if has_config FIQ_DEBUGGER_CONSOLE; then
231+
BASE_OPTS="$(echo " $BASE_OPTS " | sed 's/ console=ttyS0,1500000n8 / /g')"
232+
BASE_OPTS="$(trim "$BASE_OPTS") console=ttyFIQ0,1500000n8"
233+
else
234+
BASE_OPTS="$(echo " $BASE_OPTS " | sed 's/ console=ttyS0,1500000n8 / /g')"
235+
BASE_OPTS="$(trim "$BASE_OPTS") console=ttyS0,1500000n8"
236+
BASE_OPTS="$(echo " $BASE_OPTS " | sed 's/ console=ttyS4,1500000n8 / /g')"
237+
BASE_OPTS="$(trim "$BASE_OPTS") console=ttyS4,1500000n8"
238+
BASE_OPTS="$(echo " $BASE_OPTS " | sed 's/ console=ttyFIQ0,1500000n8 / /g')"
239+
BASE_OPTS="$(trim "$BASE_OPTS") fbcon=map:1"
240+
fi
241+
}
242+
243+
# Set DEVICETREEDIR_REL + OVERLAY_DIR for $KERNEL_VERSION (needs DTB_DIR/DTB_DIRS set). Opt-in via a
244+
# /etc/kernel/devicetreedir boolean, only when no single 'devicetree' is configured. Always the
245+
# kernel's own installed DTB dir (first existing of DTB_DIRS), never inspected or borrowed; if it
246+
# ships none, no devicetreedir is written and U-Boot falls back to its control FDT.
247+
discover_devicetreedir() {
248+
DEVICETREEDIR_SRC=""; DEVICETREEDIR_REL=""
249+
if [ -z "${DEVICETREE:-}" ] && [ -f "$CONF_ROOT/devicetreedir" ]; then
250+
_v=""; read -r _v <"$CONF_ROOT/devicetreedir" || :
251+
case "$_v" in
252+
1|[Yy]|[Yy][Ee][Ss]|[Tt]|[Tt][Rr][Uu][Ee]|[Oo][Nn])
253+
for p in $DTB_DIRS; do
254+
[ -d "$p" ] && { DEVICETREEDIR_SRC="$p"; break; }
255+
done
256+
if [ -n "$DEVICETREEDIR_SRC" ]; then
257+
DEVICETREEDIR_REL="$(boot_rel "$DEVICETREEDIR_SRC")" # /usr/lib/...; prefixed per entry
258+
else
259+
log "$KERNEL_VERSION ships no DTB dir; omitting devicetreedir (U-Boot control FDT)"
260+
fi
261+
;;
262+
esac
263+
fi
264+
# DT overlays sit flat next to the .dtb files (upstream layout), in the same vendor dir.
265+
OVERLAY_DIR="${DEVICETREEDIR_SRC:-$DTB_DIR}/$VENDOR"
266+
}
267+
268+
# emit_entry SUF EXTRA GATE DTBOS -> write one BLS entry for the current $ENTRY_TOKEN.
269+
# The filename is $ENTRY_TOKEN-$KERNEL_VERSION.conf. The token is <NN>-flipperos-<subvol>, so it
270+
# LEADS with the 3-digit menu band and U-Boot's bls (filename sort, descending) orders entries by
271+
# band then version. EXTRA carries this entry's rootflags=subvol=; BASE_OPTS has none, so there is
272+
# exactly one per entry. Honours gate (skip if a CONFIG_ symbol is missing) + overlays.
273+
emit_entry() {
274+
_suf="$1"; _extra="$2"; _gate="$3"; _dtbos="$4"
275+
276+
# gate may list several config symbols; all must be present in this kernel.
277+
for _g in $_gate; do
278+
has_config "$_g" || { log "skip $ENTRY_TOKEN (CONFIG_$_g not set for $KERNEL_VERSION)"; return 0; }
279+
done
280+
281+
_opts="$BASE_OPTS"
282+
[ -n "$_extra" ] && _opts="$_opts $_extra"
283+
_fn="$ENTRIES/$ENTRY_TOKEN-$KERNEL_VERSION.conf"
284+
285+
if [ -z "$_dtbos" ]; then
286+
write_entry "$_fn" "$(make_title "$_suf")" "$_opts" ""
287+
return 0
288+
fi
289+
290+
# A leading '!' on the overlay list = required (skip the entry if the overlays are
291+
# absent); otherwise optional (the entry is still written, sans overlay).
292+
_required=0
293+
case "$_dtbos" in '!'*) _required=1; _dtbos="$(trim "${_dtbos#\!}")" ;; esac
294+
295+
_paths="$(overlay_paths "$(fdt_prefix "$_opts")" $_dtbos)" || _paths=""
296+
if [ -z "$_paths" ] && [ "$_required" = 1 ]; then
297+
log "skip $ENTRY_TOKEN (overlays not found for $KERNEL_VERSION)"
298+
return 0
299+
fi
300+
write_entry "$_fn" "$(make_title "$_suf")" "$_opts" "$_paths"
301+
}
302+
303+
# flipper_write_entry <subvol> <mounted-path> [<origin-hint>]: write a BLS entry for an EXISTING
304+
# writable top-level subvol (a restored snapshot/clone). Token = <NN>-flipperos-<name>, NN from
305+
# clone_slot (origin base + depth; the origin hint is the dangling-parent fallback). Reflinks
306+
# the shared /boot kernel into the root's own /boot/<token>/ dir. Sourced by create_profile /
307+
# rename_profile. Returns non-zero (no exit) on a recoverable problem.
308+
flipper_write_entry() {
309+
_name="$1"; _snap="$2"; _origin="${3:-}"
310+
{ [ -n "$_name" ] && [ -d "$_snap" ]; } || { echo "flipper-bls: usage: flipper_write_entry <name> <mounted-path>" >&2; return 1; }
311+
ENTRIES="${ENTRIES:-/boot/loader/entries}"
312+
CONF_ROOT="${KERNEL_INSTALL_CONF_ROOT:-/etc/kernel}"
313+
MACHINE_ID=""; DEVICETREE=""; DEVICETREE_ENTRY=""
314+
# version from the target's OWN tree, so modules + dtbs are self-consistent
315+
KERNEL_VERSION="$(ls -1d "$_snap"/usr/lib/linux-image-* 2>/dev/null | sed 's,.*/linux-image-,,' | sort -V | tail -n1)"
316+
[ -n "$KERNEL_VERSION" ] || { echo "flipper-bls: no /usr/lib/linux-image-* inside $_name" >&2; return 1; }
317+
[ -e "/boot/vmlinuz-$KERNEL_VERSION" ] || { echo "flipper-bls: kernel not in /boot: vmlinuz-$KERNEL_VERSION" >&2; return 1; }
318+
KCONFIG="/boot/config-$KERNEL_VERSION"
319+
set_dtb_dirs
320+
SORT_KEY="$(os_sort_key)"
321+
ENTRY_TOKEN="$(make_token "$(clone_slot "$_snap" "$_origin")" "$_name")"
322+
mkdir -p "$ENTRIES" || { echo "flipper-bls: cannot create $ENTRIES" >&2; return 1; }
323+
compute_base_opts
324+
stage_kernel_reflink
325+
# devicetreedir is the target root's OWN kernel dir (KERNEL_VERSION came from it, so it exists).
326+
DEVICETREEDIR_REL="/usr/lib/linux-image-$KERNEL_VERSION"
327+
OVERLAY_DIR="$DTB_DIR/$VENDOR"
328+
# pin the root's own entry-token so a later runtime apt install in it lands in the same band
329+
mkdir -p "$_snap/etc/kernel" && printf '%s\n' "$ENTRY_TOKEN" > "$_snap/etc/kernel/entry-token"
330+
emit_entry "$(printf '%s' "$_name" | tr -d '@')" "rootflags=subvol=$_name" "" ""
331+
echo "flipper-bls: wrote entry for $_name (kernel $KERNEL_VERSION, token $ENTRY_TOKEN)"
332+
}

0 commit comments

Comments
 (0)