Skip to content

Commit 90510a7

Browse files
committed
Refactor uefi-firmware
This splits out uefi-firmware into multiple derivations to allow for easier overriding of individual components. This will eventually allow for the removal of nixos options that override these components, as overlays are now easier to use.
1 parent d8d927b commit 90510a7

8 files changed

+283
-279
lines changed

UPGRADE_CHECKLIST.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
### Updating
22
- [ ] Update `l4tVersion`, `jetpackVersion`, and `cudaVersion` in overlay.nix
3-
- [ ] Update branch/revision/sha256s in:
3+
- [ ] Update branch/revision/hashes in:
44
- [ ] `overlay.nix`
55
- [ ] `kernel/default.nix`
6-
- [ ] `pkgs/uefi-firmware/default.nix`
7-
- [ ] Grep for "sha256 = ", see if there is anything else not covered
6+
- [ ] `pkgs/uefi-firmware/edk2-nvidia.nix`
7+
- [ ] `pkgs/uefi-firmware/jetson-edk2-uefi.nix`
8+
- [ ] `grep -r -e "hash = " -e "sha256 = "` to see if there is anything else not covered
89
- [ ] Update the kernel version in `kernel/default.nix` if it chaged.
910
- [ ] Run `debs-update.py` and `gitrepos-update.py` under `sourceinfo` to generate new sourceinfo json files
1011
- [ ] Compare files from `unpackedDebs` before and after

device-pkgs/flash-script.nix

+5-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# be used by the bootloader(s) and passed to the kernel.
1010
dtbsDir ? null
1111
, # Optional package containing uefi_jetson.efi to replace prebuilt version
12-
uefi-firmware ? null
12+
uefiFirmware ? null
1313
, # Optional package containing tos.img to replace prebuilt version
1414
tosImage ? null
1515
, # Optional EKS file containing encrypted keyblob
@@ -44,15 +44,15 @@
4444
4545
${lib.optionalString (partitionTemplate != null) "cp ${partitionTemplate} flash.xml"}
4646
${lib.optionalString (dtbsDir != null) "cp -r ${dtbsDir}/. kernel/dtb/"}
47-
${lib.optionalString (uefi-firmware != null) ''
48-
cp ${uefi-firmware}/uefi_jetson.bin bootloader/uefi_jetson.bin
47+
${lib.optionalString (uefiFirmware != null) ''
48+
cp ${uefiFirmware}/uefi_jetson.bin bootloader/uefi_jetson.bin
4949
5050
# For normal NixOS usage, we'd probably use systemd-boot or GRUB instead,
5151
# but lets replace the upstream L4TLauncher EFI payload anyway
52-
cp ${uefi-firmware}/L4TLauncher.efi bootloader/BOOTAA64.efi
52+
cp ${uefiFirmware}/L4TLauncher.efi bootloader/BOOTAA64.efi
5353
5454
# Replace additional dtbos
55-
cp ${uefi-firmware}/dtbs/*.dtbo kernel/dtb/
55+
cp ${uefiFirmware}/dtbs/*.dtbo kernel/dtb/
5656
''}
5757
${lib.optionalString (tosImage != null) ''
5858
cp ${tosImage}/tos.img bootloader/tos-optee_${socType}.img

modules/flash-script.nix

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{ config, pkgs, lib, utils, ... }:
1+
{ options, config, pkgs, lib, utils, ... }:
22

33
# Convenience package that allows you to set options for the flash script using the NixOS module system.
44
# You could do the overrides yourself if you'd prefer.

overlay-with-config.nix

+10-5
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,19 @@ final: prev: (
3838
inherit (config.boot.loader.efi) efiSysMountPoint;
3939
};
4040

41-
uefi-firmware = prevJetpack.uefi-firmware.override ({
41+
edk2NvidiaSrc = (prevJetpack.edk2NvidiaSrc.override {
42+
errorLevelInfo = cfg.firmware.uefi.errorLevelInfo;
4243
bootLogo = cfg.firmware.uefi.logo;
44+
}).overrideAttrs (old: {
45+
patches = (old.patches or [ ]) ++ cfg.firmware.uefi.edk2NvidiaPatches;
46+
});
47+
48+
jetsonEdk2Uefi = (prevJetpack.jetsonEdk2Uefi.override ({
4349
debugMode = cfg.firmware.uefi.debugMode;
44-
errorLevelInfo = cfg.firmware.uefi.errorLevelInfo;
45-
edk2NvidiaPatches = cfg.firmware.uefi.edk2NvidiaPatches;
46-
edk2UefiPatches = cfg.firmware.uefi.edk2UefiPatches;
4750
} // lib.optionalAttrs cfg.firmware.uefi.capsuleAuthentication.enable {
4851
inherit (cfg.firmware.uefi.capsuleAuthentication) trustedPublicCertPemFile;
52+
})).overrideAttrs (old: {
53+
patches = (old.patches or [ ]) ++ cfg.firmware.uefi.edk2UefiPatches;
4954
});
5055

5156
flash-tools = prevJetpack.flash-tools.overrideAttrs ({ patches ? [ ], postPatch ? "", ... }: {
@@ -112,7 +117,7 @@ final: prev: (
112117
inherit lib flash-tools;
113118
inherit (cfg.firmware) eksFile;
114119
inherit (cfg.flashScriptOverrides) flashArgs partitionTemplate preFlashCommands postFlashCommands;
115-
inherit (finalJetpack) tosImage socType uefi-firmware;
120+
inherit (finalJetpack) tosImage socType uefiFirmware;
116121

117122
additionalDtbOverlays = args.additionalDtbOverlays or cfg.flashScriptOverrides.additionalDtbOverlays;
118123
dtbsDir = config.hardware.deviceTree.package;

overlay.nix

+3-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ in
5959
self.gitRepos
6060
);
6161

62-
inherit (prev.callPackages ./pkgs/uefi-firmware { inherit (self) l4tVersion; })
63-
edk2-jetson uefi-firmware;
62+
edk2NvidiaSrc = self.callPackage ./pkgs/uefi-firmware/edk2-nvidia-src.nix { };
63+
jetsonEdk2Uefi = self.callPackage ./pkgs/uefi-firmware/jetson-edk2-uefi.nix { };
64+
uefiFirmware = self.callPackage ./pkgs/uefi-firmware/default.nix { };
6465

6566
inherit (prev.callPackages ./pkgs/optee {
6667
# Nvidia's recommended toolchain is gcc9:

pkgs/uefi-firmware/default.nix

+23-263
Original file line numberDiff line numberDiff line change
@@ -1,269 +1,29 @@
1-
{ lib
2-
, stdenv
3-
, buildPackages
4-
, fetchFromGitHub
5-
, fetchurl
6-
, fetchpatch
7-
, fetchpatch2
8-
, runCommand
9-
, edk2
10-
, acpica-tools
11-
, dtc
1+
{ runCommand
122
, python3
13-
, bc
14-
, imagemagick
15-
, unixtools
16-
, libuuid
17-
, applyPatches
183
, nukeReferences
194
, l4tVersion
20-
, # Optional path to a boot logo that will be converted and cropped into the format required
21-
bootLogo ? null
22-
, # Patches to apply to edk2-nvidia source tree
23-
edk2NvidiaPatches ? [ ]
24-
, # Patches to apply to edk2 source tree
25-
edk2UefiPatches ? [ ]
26-
, debugMode ? false
27-
, errorLevelInfo ? debugMode
28-
, # Enables a bunch more info messages
29-
30-
# The root certificate (in PEM format) for authenticating capsule updates. By
31-
# default, EDK2 authenticates using a test keypair commited upstream.
32-
trustedPublicCertPemFile ? null
5+
, edk2NvidiaSrc
6+
, jetsonEdk2Uefi
337
}:
348

35-
let
36-
# TODO: Move this generation out of uefi-firmware.nix, because this .nix
37-
# file is callPackage'd using an aarch64 version of nixpkgs, and we don't
38-
# want to have to recompilie imagemagick
39-
bootLogoVariants = runCommand "uefi-bootlogo" { nativeBuildInputs = [ buildPackages.buildPackages.imagemagick ]; } ''
40-
mkdir -p $out
41-
convert ${bootLogo} -resize 1920x1080 -gravity Center -extent 1920x1080 -format bmp -define bmp:format=bmp3 $out/logo1080.bmp
42-
convert ${bootLogo} -resize 1280x720 -gravity Center -extent 1280x720 -format bmp -define bmp:format=bmp3 $out/logo720.bmp
43-
convert ${bootLogo} -resize 640x480 -gravity Center -extent 640x480 -format bmp -define bmp:format=bmp3 $out/logo480.bmp
44-
'';
45-
46-
###
47-
48-
# See: https://github.com/NVIDIA/edk2-edkrepo-manifest/blob/main/edk2-nvidia/Jetson/NVIDIAJetsonManifest.xml
49-
edk2-src = applyPatches {
50-
src = fetchFromGitHub {
51-
owner = "NVIDIA";
52-
repo = "edk2";
53-
rev = "r${l4tVersion}-edk2-stable202208";
54-
fetchSubmodules = true;
55-
sha256 = "sha256-w+rZq7Wjni62MJds6QmqpLod+zSFZ/qAN7kRDOit+jo=";
56-
};
57-
patches = [
58-
# Fix GCC 14 compile issue.
59-
# PR: https://github.com/tianocore/edk2/pull/5781
60-
(fetchpatch {
61-
url = "https://github.com/NVIDIA/edk2/commit/57a890fd03356350a1b7a2a0064c8118f44e9958.patch";
62-
hash = "sha256-on+yJOlH9B2cD1CS9b8Pmg99pzrlrZT6/n4qPHAbDcA=";
63-
})
64-
];
65-
};
66-
67-
edk2-platforms = fetchFromGitHub {
68-
owner = "NVIDIA";
69-
repo = "edk2-platforms";
70-
rev = "r${l4tVersion}-upstream-20220830";
71-
sha256 = "sha256-PjAJEbbswOLYupMg/xEqkAOJuAC8SxNsQlb9YBswRfo=";
72-
};
73-
74-
edk2-non-osi = fetchFromGitHub {
75-
owner = "NVIDIA";
76-
repo = "edk2-non-osi";
77-
rev = "r${l4tVersion}-upstream-20220830";
78-
sha256 = "sha256-EPtI63jYhEIo4uVTH3lUt9NC/lK5vPVacUAc5qgmz9M=";
79-
};
80-
81-
edk2-nvidia = applyPatches {
82-
src = fetchFromGitHub {
83-
owner = "NVIDIA";
84-
repo = "edk2-nvidia";
85-
rev = "c101ba515b2737fb78d8929c2852f5c8f9607330"; # Latest on r${l4tVersion}-updates branch as of 2024-01-15
86-
sha256 = "sha256-Ofj1FS1wLTLf6rCCPbB841SSBM3wjW4tdUJD6cY0ixE=";
87-
};
88-
patches = edk2NvidiaPatches ++ [
89-
# Fix Eqos driver to use correct TX clock name
90-
# PR: https://github.com/NVIDIA/edk2-nvidia/pull/76
91-
(fetchpatch {
92-
url = "https://github.com/NVIDIA/edk2-nvidia/commit/26f50dc3f0f041d20352d1656851c77f43c7238e.patch";
93-
hash = "sha256-cc+eGLFHZ6JQQix1VWe/UOkGunAzPb8jM9SXa9ScIn8=";
94-
})
95-
96-
./capsule-authentication.patch
97-
98-
# Have UEFI use the device tree compiled into the firmware, instead of
99-
# using one from the kernel-dtb partition.
100-
# See: https://github.com/anduril/jetpack-nixos/pull/18
101-
./edk2-uefi-dtb.patch
102-
103-
# Include patches to fix "Assertion 3" mentioned here:
104-
# https://forums.developer.nvidia.com/t/assertion-issue-in-uefi-during-boot/315628
105-
# From this PR: https://github.com/NVIDIA/edk2-nvidia/pull/110
106-
# It is unclear if it does (as of 2025-01-03), but hopefully this also
107-
# resolves the critical issue mentioned here:
108-
# https://forums.developer.nvidia.com/t/possible-uefi-memory-leak-and-partition-full/308540
109-
./fix-bug-in-block-erase-logic.patch
110-
./fix-variant-read-records-per-erase-block-and-fix-leak.patch
111-
];
112-
postPatch = lib.optionalString errorLevelInfo ''
113-
sed -i 's#PcdDebugPrintErrorLevel|.*#PcdDebugPrintErrorLevel|0x8000004F#' Platform/NVIDIA/NVIDIA.common.dsc.inc
114-
'' + lib.optionalString (bootLogo != null) ''
115-
cp ${bootLogoVariants}/logo1080.bmp Silicon/NVIDIA/Assets/nvidiagray1080.bmp
116-
cp ${bootLogoVariants}/logo720.bmp Silicon/NVIDIA/Assets/nvidiagray720.bmp
117-
cp ${bootLogoVariants}/logo480.bmp Silicon/NVIDIA/Assets/nvidiagray480.bmp
118-
'';
119-
};
120-
121-
edk2-nvidia-non-osi = fetchFromGitHub {
122-
owner = "NVIDIA";
123-
repo = "edk2-nvidia-non-osi";
124-
rev = "r${l4tVersion}";
125-
sha256 = "sha256-Fg8s9Fjwt5IzrGdJ7TKI3AjZLh/wHN8oyvi5Xw+Jg+k=";
126-
};
127-
128-
edk2-jetson = edk2.overrideAttrs (prev: {
129-
# Upstream nixpkgs patch to use nixpkgs OpenSSL
130-
# See https://github.com/NixOS/nixpkgs/blob/44733514b72e732bd49f5511bd0203dea9b9a434/pkgs/development/compilers/edk2/default.nix#L57
131-
src = runCommand "edk2-unvendored-src" { } ''
132-
cp --no-preserve=mode -r ${edk2-src} $out
133-
rm -rf $out/CryptoPkg/Library/OpensslLib/openssl
134-
mkdir -p $out/CryptoPkg/Library/OpensslLib/openssl
135-
tar --strip-components=1 -xf ${buildPackages.openssl.src} -C $out/CryptoPkg/Library/OpensslLib/openssl
136-
chmod -R +w $out/
137-
# Fix missing INT64_MAX include that edk2 explicitly does not provide
138-
# via it's own <stdint.h>. Let's pull in openssl's definition instead:
139-
sed -i $out/CryptoPkg/Library/OpensslLib/openssl/crypto/property/property_parse.c \
140-
-e '1i #include "internal/numbers.h"'
141-
'';
142-
143-
depsBuildBuild = prev.depsBuildBuild ++ [ libuuid ];
144-
});
145-
146-
pythonEnv = buildPackages.python3.withPackages (ps: [ ps.tkinter ]);
147-
targetArch =
148-
if stdenv.isi686 then
149-
"IA32"
150-
else if stdenv.isx86_64 then
151-
"X64"
152-
else if stdenv.isAarch64 then
153-
"AARCH64"
154-
else
155-
throw "Unsupported architecture";
156-
157-
buildType =
158-
if stdenv.isDarwin then
159-
"CLANGPDB"
160-
else
161-
"GCC5";
162-
163-
buildTarget = if debugMode then "DEBUG" else "RELEASE";
164-
165-
jetson-edk2-uefi =
166-
# TODO: edk2.mkDerivation doesn't have a way to override the edk version used!
167-
# Make it not via passthru ?
168-
stdenv.mkDerivation (finalAttrs: {
169-
pname = "jetson-edk2-uefi";
170-
version = l4tVersion;
171-
172-
# Initialize the build dir with the build tools from edk2
173-
src = edk2-src;
174-
175-
depsBuildBuild = [ buildPackages.stdenv.cc ];
176-
nativeBuildInputs = [ bc pythonEnv acpica-tools dtc unixtools.whereis ];
177-
strictDeps = true;
178-
179-
NIX_CFLAGS_COMPILE = [
180-
"-Wno-error=format-security" # TODO: Fix underlying issue
181-
182-
# Workaround for ../Silicon/NVIDIA/Drivers/EqosDeviceDxe/nvethernetrm/osi/core/osi_hal.c:1428: undefined reference to `__aarch64_ldadd4_sync'
183-
"-mno-outline-atomics"
184-
];
185-
186-
${"GCC5_${targetArch}_PREFIX"} = stdenv.cc.targetPrefix;
187-
188-
# From edk2-nvidia/Silicon/NVIDIA/edk2nv/stuart/settings.py
189-
PACKAGES_PATH = lib.concatStringsSep ":" [
190-
"${edk2-src}/BaseTools" # TODO: Is this needed?
191-
finalAttrs.src
192-
edk2-platforms
193-
edk2-non-osi
194-
edk2-nvidia
195-
edk2-nvidia-non-osi
196-
"${edk2-platforms}/Features/Intel/OutOfBandManagement"
197-
];
198-
199-
enableParallelBuilding = true;
200-
201-
prePatch = ''
202-
rm -rf BaseTools
203-
cp -r ${edk2-jetson}/BaseTools BaseTools
204-
chmod -R u+w BaseTools
205-
'';
206-
207-
patches = edk2UefiPatches;
208-
209-
configurePhase = ''
210-
runHook preConfigure
211-
export WORKSPACE="$PWD"
212-
source ./edksetup.sh BaseTools
213-
214-
${lib.optionalString (trustedPublicCertPemFile != null) ''
215-
echo Using ${trustedPublicCertPemFile} as public certificate for capsule verification
216-
${lib.getExe buildPackages.openssl} x509 -outform DER -in ${trustedPublicCertPemFile} -out PublicCapsuleKey.cer
217-
python3 BaseTools/Scripts/BinToPcd.py -p gEfiSecurityPkgTokenSpaceGuid.PcdPkcs7CertBuffer -i PublicCapsuleKey.cer -o PublicCapsuleKey.cer.gEfiSecurityPkgTokenSpaceGuid.PcdPkcs7CertBuffer.inc
218-
python3 BaseTools/Scripts/BinToPcd.py -x -p gFmpDevicePkgTokenSpaceGuid.PcdFmpDevicePkcs7CertBufferXdr -i PublicCapsuleKey.cer -o PublicCapsuleKey.cer.gFmpDevicePkgTokenSpaceGuid.PcdFmpDevicePkcs7CertBufferXdr.inc
219-
''}
220-
221-
runHook postConfigure
222-
'';
223-
224-
buildPhase = ''
225-
runHook preBuild
226-
227-
# The BUILDID_STRING and BUILD_DATE_TIME are used
228-
# just by nvidia, not generic edk2
229-
build -a ${targetArch} -b ${buildTarget} -t ${buildType} -p Platform/NVIDIA/Jetson/Jetson.dsc -n $NIX_BUILD_CORES \
230-
-D BUILDID_STRING=${l4tVersion} \
231-
-D BUILD_DATE_TIME="$(date --utc --iso-8601=seconds --date=@$SOURCE_DATE_EPOCH)" \
232-
${lib.optionalString (trustedPublicCertPemFile != null) "-D CUSTOM_CAPSULE_CERT"} \
233-
$buildFlags
234-
235-
runHook postBuild
236-
'';
237-
238-
installPhase = ''
239-
runHook preInstall
240-
mv -v Build/*/* $out
241-
runHook postInstall
242-
'';
243-
});
244-
245-
uefi-firmware = runCommand "uefi-firmware-${l4tVersion}"
246-
{
247-
nativeBuildInputs = [ python3 nukeReferences ];
248-
} ''
249-
mkdir -p $out
250-
python3 ${edk2-nvidia}/Silicon/NVIDIA/Tools/FormatUefiBinary.py \
251-
${jetson-edk2-uefi}/FV/UEFI_NS.Fv \
252-
$out/uefi_jetson.bin
253-
254-
python3 ${edk2-nvidia}/Silicon/NVIDIA/Tools/FormatUefiBinary.py \
255-
${jetson-edk2-uefi}/AARCH64/L4TLauncher.efi \
256-
$out/L4TLauncher.efi
257-
258-
mkdir -p $out/dtbs
259-
for filename in ${jetson-edk2-uefi}/AARCH64/Silicon/NVIDIA/Tegra/DeviceTree/DeviceTree/OUTPUT/*.dtb; do
260-
cp $filename $out/dtbs/$(basename "$filename" ".dtb").dtbo
261-
done
262-
263-
# Get rid of any string references to source(s)
264-
nuke-refs $out/uefi_jetson.bin
265-
'';
266-
in
9+
runCommand "uefi-firmware-${l4tVersion}"
26710
{
268-
inherit edk2-jetson uefi-firmware;
269-
}
11+
nativeBuildInputs = [ python3 nukeReferences ];
12+
} ''
13+
mkdir -p $out
14+
python3 ${edk2NvidiaSrc}/Silicon/NVIDIA/Tools/FormatUefiBinary.py \
15+
${jetsonEdk2Uefi}/FV/UEFI_NS.Fv \
16+
$out/uefi_jetson.bin
17+
18+
python3 ${edk2NvidiaSrc}/Silicon/NVIDIA/Tools/FormatUefiBinary.py \
19+
${jetsonEdk2Uefi}/AARCH64/L4TLauncher.efi \
20+
$out/L4TLauncher.efi
21+
22+
mkdir -p $out/dtbs
23+
for filename in ${jetsonEdk2Uefi}/AARCH64/Silicon/NVIDIA/Tegra/DeviceTree/DeviceTree/OUTPUT/*.dtb; do
24+
cp $filename $out/dtbs/$(basename "$filename" ".dtb").dtbo
25+
done
26+
27+
# Get rid of any string references to source(s)
28+
nuke-refs $out/uefi_jetson.bin
29+
''

0 commit comments

Comments
 (0)