Skip to content

Commit e053af0

Browse files
committed
Introduce jetsonCheckSpecCompatability pre-switch check
We can check whether the bup for a NixOS configuration matches the machine we're trying to deploy the NixOS system to. This aims to improve user experience: if the firmware doesn't support the expected board, the capsule update will fail and it's not clear why unless you inspect the serial logs. The check can be manually skipped by setting the SKIP_TEGRA_COMPAT_CHECK environment variable.
1 parent 4ebd078 commit e053af0

File tree

4 files changed

+96
-3
lines changed

4 files changed

+96
-3
lines changed

modules/flash-script.nix

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,14 @@ in
436436
inherit (pkgs.nvidia-jetpack) uefiCapsuleUpdate flashScript initrdFlashScript fuseScript signedFirmware;
437437
};
438438

439+
system.preSwitchChecks.jetsonCheckSpecCompatability = "${lib.getExe (pkgs.writeShellApplication {
440+
name = "ota-check-tegra-compatability-spec";
441+
text = ''
442+
[ -n "$SKIP_TEGRA_COMPAT_CHECK" ] && exit 0
443+
exec ${lib.getExe' pkgs.nvidia-jetpack.otaUtils "ota-check-compat"} ${pkgs.nvidia-jetpack.bupSpecs}
444+
'';
445+
})}";
446+
439447
hardware.nvidia-jetpack.flashScriptOverrides.flashArgs = lib.mkAfter (
440448
lib.optional (cfg.firmware.secureBoot.pkcFile != null) "-u ${cfg.firmware.secureBoot.pkcFile}" ++
441449
lib.optional (cfg.firmware.secureBoot.sbkFile != null) "-v ${cfg.firmware.secureBoot.sbkFile}" ++

overlay-with-config.nix

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ final: prev: (
150150
# TODO: Remove preSignCommands when we switch to using signedFirmware directly
151151
flashCommands = ''
152152
${cfg.firmware.secureBoot.preSignCommands final.buildPackages}
153+
touch nix-multispec
153154
'' + lib.concatMapStringsSep "\n"
154155
(v: with v;
155156
(lib.concatStringsSep " " [
@@ -168,10 +169,17 @@ final: prev: (
168169
"--bup"
169170
"--multi-spec"
170171
(builtins.toString cfg.flashScriptOverrides.flashArgs)
171-
]))
172+
]) + ''
173+
174+
find bootloader/multi_signed -maxdepth 1 -type d -name ${boardid}\* -printf "%f\n" >> nix-multispec
175+
'')
172176
cfg.firmware.variants;
173177
}) + ''
174178
mkdir -p $out
179+
# it's likely that the nix-multispec has duplicate entries because
180+
# boardid is the same across the different variants.
181+
# sort -u to remove the duplicates.
182+
sort -u nix-multispec > $out/nix-multispec
175183
cp -r bootloader/payloads_*/* $out/
176184
'');
177185

@@ -196,6 +204,8 @@ final: prev: (
196204
${finalJetpack.socType}
197205
'');
198206

207+
bupSpecs = prev.runCommand "${config.networking.hostName}-specs" {} "cp ${finalJetpack.bup}/nix-multispec $out";
208+
199209
signedFirmware = final.runCommand "signed-${hostName}-${finalJetpack.l4tMajorMinorPatchVersion}"
200210
{ inherit (cfg.firmware.secureBoot) requiredSystemFeatures; }
201211
(finalJetpack.mkFlashScript final.pkgsBuildBuild.nvidia-jetpack.flash-tools {

pkgs/ota-utils/default.nix

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{ lib, stdenvNoCC, bash, util-linux, e2fsprogs, tegra-eeprom-tool, efiSysMountPoint ? "/boot", expectedBiosVersion ? "Unknown" }:
1+
{ lib, stdenvNoCC, bash, coreutils, util-linux, e2fsprogs, tegra-eeprom-tool, efiSysMountPoint ? "/boot", expectedBiosVersion ? "Unknown" }:
22

33
stdenvNoCC.mkDerivation {
44
name = "ota-utils";
@@ -21,8 +21,9 @@ stdenvNoCC.mkDerivation {
2121
cp ${./ota-apply-capsule-update.sh} $out/bin/ota-apply-capsule-update
2222
cp ${./ota-check-firmware.sh} $out/bin/ota-check-firmware
2323
cp ${./ota-abort-capsule-update.sh} $out/bin/ota-abort-capsule-update
24+
cp ${./ota-check-compat.sh} $out/bin/ota-check-compat
2425
cp ${./ota_helpers.func} $out/share/ota_helpers.func
25-
chmod +x $out/bin/ota-setup-efivars $out/bin/ota-apply-capsule-update $out/bin/ota-check-firmware $out/bin/ota-abort-capsule-update
26+
chmod +x $out/bin/ota-setup-efivars $out/bin/ota-apply-capsule-update $out/bin/ota-check-firmware $out/bin/ota-abort-capsule-update $out/bin/ota-check-compat
2627
2728
for path in $out/bin/ota-apply-capsule-update $out/share/ota_helpers.func $out/bin/ota-abort-capsule-update; do
2829
substituteInPlace "$path" --subst-var efiSysMountPoint
@@ -34,6 +35,8 @@ stdenvNoCC.mkDerivation {
3435
sed -i '2a export PATH=${lib.makeBinPath [ util-linux e2fsprogs tegra-eeprom-tool ]}:$PATH' $out/bin/$fname
3536
done
3637
38+
sed -i '2a PATH=${lib.makeBinPath [ coreutils util-linux ]}:$PATH' $out/bin/ota-check-compat
39+
3740
substituteInPlace $out/bin/ota-check-firmware \
3841
--replace "@expectedBiosVersion@" "${expectedBiosVersion}"
3942

pkgs/ota-utils/ota-check-compat.sh

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/env bash
2+
3+
SPECS="$1"
4+
5+
# See FwPackageCheckTnSpec() in edk2-nvidia/Silicon/NVIDIA/Library/FwPackageLib
6+
checkspec() {
7+
local expected="$1"
8+
local actual="$2"
9+
10+
# Return 1 (no match) if either argument is empty
11+
if [[ -z "$expected" || -z "$actual" ]]; then
12+
return 1
13+
fi
14+
15+
# Split the strings into tokens using '-' as delimiter
16+
IFS='-' read -ra tokensExpected <<< "$expected"
17+
IFS='-' read -ra tokensActual <<< "$actual"
18+
19+
# If the token counts differ, it's a mismatch
20+
if [[ "${#tokensExpected[@]}" -ne "${#tokensActual[@]}" ]]; then
21+
return 1
22+
fi
23+
24+
# Iterate over each token index
25+
for i in "${!tokensExpected[@]}"; do
26+
local token1="${tokensExpected[i]}"
27+
local token2="${tokensActual[i]}"
28+
29+
# If either token is empty, ignore and continue to next token
30+
if [[ -z "$token1" || -z "$token2" ]]; then
31+
continue
32+
fi
33+
34+
# If the tokens do not match, return 1 indicating no match
35+
if [[ "$token1" != "$token2" ]]; then
36+
return 1
37+
fi
38+
done
39+
40+
# All tokens match (ignoring empty tokens), return 0 for success
41+
return 0
42+
}
43+
44+
extractboardname() {
45+
local spec="$1"
46+
47+
# per flash.sh, spec="${BOARDID}-${FAB}-${BOARDSKU}-${BOARDREV}-${fuselevel_s}-${hwchiprev}-${ext_target_board}-";
48+
# and we want ext_target_board. ext_target_board has "-" in it, which makes processing this a little more annoying
49+
cut -d- -f7- <<< "$spec" | rev | cut -d- -f2- | rev
50+
}
51+
52+
# cut -c 4- to remove the leading attributes from the efi variable
53+
# See the warning at: https://docs.kernel.org/filesystems/efivarfs.html
54+
PLATFORM_SPEC="$(cut -c 4- </sys/firmware/efi/efivars/TegraPlatformSpec-781e084c-a330-417c-b678-38e696380cb9 | tr -d '\0')"
55+
COMPAT_SPEC="$(cut -c 4- </sys/firmware/efi/efivars/TegraPlatformCompatSpec-781e084c-a330-417c-b678-38e696380cb9 | tr -d '\0')"
56+
57+
NIXOS_BOARDS=""
58+
59+
while read spec ; do
60+
if checkspec "$PLATFORM_SPEC" "$spec" || checkspec "$COMPAT_SPEC" "$spec"; then
61+
exit 0
62+
fi
63+
NIXOS_BOARDS+="$(extractboardname "$spec")"$'\n'
64+
done < "$SPECS"
65+
66+
MACHINE_BOARDS="$( (extractboardname "$PLATFORM_SPEC" ; extractboardname "$COMPAT_SPEC") | sort -u | tr '\n' ' ' )"
67+
NIXOS_BOARDS="$( echo "$NIXOS_BOARDS" | sort -u | tr '\n' ' ' )"
68+
69+
echo "This machine is not compatible with the platform specs for this NixOS system!"
70+
echo "This machine is a: ${MACHINE_BOARDS}"
71+
echo "This NixOS system supports: ${NIXOS_BOARDS}"
72+
exit 1

0 commit comments

Comments
 (0)