[UEFI] 插入网卡后 UEFI 启动顺序变成网卡优先启动,无法从nvme启动

我的L4TConfiguration配置中 DefaultBootPriority 字段并没有配置http启动,默认情况下,但是插入网卡后再开机,UEFI自动将网卡设置为优先启动,导致无法直接从nvme启动。
L4TConfiguration 中的启动顺序被UEFI强制刷新了,请问如何解决?

L4TConfiguration.dts当前配置:

/ {
	overlay-name = "L4T Configuration Settings";

	fragment@0 {
		target-path = "/";
		board_config {
			sw-modules = "uefi";
		};

		__overlay__ {
			firmware {
				uefi {
					variables {
						gNVIDIAPublicVariableGuid {
							QuickBootEnabled {
								data = [00];
								non-volatile;
							};
							NewDeviceHierarchy {
								data = [01];
								runtime;
								non-volatile;
							};
							RootfsRetryCountMax {
								data = [03 00 00 00];
								runtime;
								locked;
							};
							RootfsRedundancyLevel {
								data = [00 00 00 00];
								runtime;
								locked;
							};
							AutoUpdateBrBct {
								data = [01 00 00 00];
								non-volatile;
							};
							L4TDefaultBootMode {
								data = [01 00 00 00];
								runtime;
								non-volatile;
							};
							ExposeRtRtcService {
								data = [00];
								runtime;
								non-volatile;
							};
						};

						gNVIDIATokenSpaceGuid {
							DefaultBootPriority {
								data = "nvme";
								locked;
							};
						};
					};
				};
			};
		};
	};
};

我阅读了以下帖子

但是这个方法只是禁用掉网卡启动,合理的做法应该是插拔网卡时,将网卡启动从启动顺序列表的底部插入,而不是顶部插入, 根据 edk2-nvidia 的源码,RestoreBootOrder 函数总是会将新增设备从顶部插入启动列表,正常的逻辑应该是从底部插入,因为新增网卡并不一定具备根文件系统。

按照 以上帖子修改代码后,只少了pxe启动项目,但仍然出现httpv4和httpv6启动项,无法解决问题

改动点如下:

diff --git a/NetworkPkg/NetworkPkg.dec b/NetworkPkg/NetworkPkg.dec
index 7c4289b77b..8e858fcee6 100644
--- a/NetworkPkg/NetworkPkg.dec
+++ b/NetworkPkg/NetworkPkg.dec
@@ -162,12 +162,12 @@
   ## IPv4 PXE support
   # 0x01 = PXE Enabled
   # 0x00 = PXE Disabled
-  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01|UINT8|0x10000009
+  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x00|UINT8|0x10000009^M
 
   ## IPv6 PXE support
   # 0x01 = PXE Enabled
   # 0x00 = PXE Disabled
-  gEfiNetworkPkgTokenSpaceGuid.PcdIPv6PXESupport|0x01|UINT8|0x1000000a
+  gEfiNetworkPkgTokenSpaceGuid.PcdIPv6PXESupport|0x00|UINT8|0x1000000a^M
 
   ## The Timeout value of HTTP IO.
   # @Prompt The Timeout value of HTTP Io. Default value is 5000.

Or, Linux_for_Tegra/tools/kernel_flash/README_initrd_flash.txt

sudo ADDITIONAL_DTB_OVERLAY_OPT=“BootOrderNvme.dtbo” ./l4t_initrd_flash.sh --external-device nvme0n1p1
[ -c ./tools/kernel_flash/flash_l4t_t264_nvme.xml ] --showlogs jetson-agx-thor-devkit internal

  • (Optional) Declare ADDITIONAL_DTB_OVERLAY_OPT= where can be BootOrderNvme.dtbo.
    This allows UEFI to prioritize booting from NVMe SSD. can also be BootOrderUsb.dtbo, which
    allows UEFI to prioritize booting from the USB storage drive

dtc -I dtb -O dts -o boot.dts ../kernel/dtb/BootOrderNvme.dtbo

/dts-v1/;

/ {
        overlay-name = "UEFI Boot order nvme default";

        fragment@0 {
                target-path = "/";

                board_config {
                        sw-modules = "uefi";
                };

                __overlay__ {

                        firmware {

                                uefi {

                                        variables {

                                                gNVIDIATokenSpaceGuid {

                                                        DefaultBootPriority {
                                                                data = "nvme";
                                                                locked;
                                                        };
                                                };
                                        };
                                };
                        };
                };
        };
};

I have tried this method, but ADDITIONAL_DTB_OVERLAY_OPT cannot solve this issue. The root cause of the issue is that when UEFI detects a change in the boot device (insertion of a network card), it will force the newly added network card to be inserted at the top of the boot order.

Upon reading UEFI code, it can be observed that the priority of refreshing the boot sequence list for hot-plugged devices is higher than that of BootOrderNvme.dtbo.

This might help resolve the problem in addition to BootOrderNvme

Run efibootmgr to get your nvme device name. Then change the two " MATCH=Samsung PSSD " below to your value.

sudo tee /usr/sbin/set-bootnext-ssd.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

MATCH="${MATCH:-Samsung PSSD}"

bootnum="$(
  /usr/bin/efibootmgr \
    | grep "$MATCH" \
    | sed -n 's/^Boot\([0-9A-Fa-f]\{4\}\).*/\1/p' \
    | head -n1
)"

if [ -z "$bootnum" ]; then
  echo "set-bootnext: no EFI boot entry matched: $MATCH" >&2
  exit 1
fi

#echo "set-bootnext: setting BootNext=Boot$bootnum (match: $MATCH)"
exec /usr/bin/efibootmgr -n "$bootnum" >/dev/null
EOF

sudo chmod 0755 /usr/sbin/set-bootnext-ssd.sh

sudo tee /etc/systemd/system/set-bootnext-ssd.service >/dev/null <<'EOF'
[Unit]
Description=Set UEFI BootNext to SSD EFI entry
ConditionPathExists=/sys/firmware/efi
After=local-fs.target

[Service]
Type=oneshot
Environment=MATCH=Samsung PSSD
ExecStart=/usr/sbin/set-bootnext-samsung-pssd.sh

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable set-bootnext-samsung-pssd.service
sudo systemctl start set-bootnext-samsung-pssd.service


Based on this paragraph of the UEFI Specification:

“The BootNext variable is a single UINT16 that defines the Boot#### option that is to be tried first on the next boot. After the BootNext boot option is tried the normal BootOrder list is used. To prevent loops, the boot manager deletes this variable before transferring control to the preselected boot option.”

感谢您的回复。但是以上脚本解决办法已经和具体的nvme型号耦合了,如果我们更换了nvme型号,就必须修改脚本,重新发布软件,因此无法产品化使用。

Run efibootmgr and reply with the Boot000? line with the nvme drive you are using and I’ll modify script if you want.

Currently, I can only temporarily configure CONFIG_NETWORKING=n to disable the network function to circumvent this issue, but this solution is not thorough. If I insert a USB mobile hard drive next time, it may also cause the boot sequence to be disrupted. I still believe that we should consider how to solve this problem from the perspective of UEFI software design. Other methods only address the symptoms and not the root cause.

I’ll see if there’s anything helpful here tomorrow.

https://github.com/NVIDIA/edk2-nvidia

I think if you were to change 0x01 to 0x00 in this file it would cause uefi to add new devices to bottom of list. Then configure and build edk2-nvidia.

nvidia-uefi/edk2-nvidia/Silicon/NVIDIA/NVIDIA.dec


#Option to add new boot device at top or bottom of list
  gNVIDIATokenSpaceGuid.PcdNewDeviceHierarchy|0x00|UINT8|0x00000068

Config and then build edk2-nvidia:

cd nvidia-uefi
edk2-nvidia/Platform/NVIDIA/Tegra/build.sh --init-defconfig edk2-nvidia/Platform/NVIDIA/Tegra/DefConfigs/t26x_general.defconfig
cp nvidia-uefi/images/uefi_t26x_general_RELEASE.bin Linux_for_Tegra/bootloader/uefi_t26x_general.bin

Then flash Thor to confirm.



Here’s the built as configured uefi_t26x_general_RELEASE.bin and other files from the image directory that you could test if so inclined. You may want to read Linux_for_Tegra/bootloader/uefi_bins/README_uefi.txt which discusses smaller uefi*.bin that decrease boot time in production; which you can build with edk2-nvidia.

cp bootloader/uefi_bins/uefi_t26x_general.bin bootloader/uefi_bins/uefi_t26x_general.bin.bak
cp uefi_t26x_general_RELEASE.bin bootloader/uefi_bins/uefi_t26x_general.bin

sudo ADDITIONAL_DTB_OVERLAY_OPT="BootOrderNvme.dtbo" ./l4t_initrd_flash.sh jetson-agx-thor-devkit internal

nvidia-uefi-images.tar.gz.txt (6.0 MB)


After i modify PcdNewDeviceHierarchy to 0x00, issue still occur.

Do you need to keep http/uefi boot ?

This can be set to FALSE
Platform/NVIDIA/NVIDIA.common.dsc.inc
gEfiNetworkPkgTokenSpaceGuid.PcdAllowHttpConnections|FALSE

This worked in Jetson AGX Orin. edk2-nvidia removed PcdIPv?PXESupport from Thor.

## IPv4 PXE support
# 0x01 = PXE Enabled
# 0x00 = PXE Disabled
gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x00|UINT8|0x10000009
## IPv6 PXE support
# 0x01 = PXE Enabled
# 0x00 = PXE Disabled
gEfiNetworkPkgTokenSpaceGuid.PcdIPv6PXESupport|0x00|UINT8|0x1000000a

Main edk2 repo still has this and I’ll look tomorrow night to see if edk2-nvidia calls it.

https://github.com/tianocore/edk2/NetworkPkg/NetworkDynamicPcds.dsc.inc
!if $(NETWORK_ENABLE) == TRUE
  #
  # IPv4 and IPv6 PXE Boot support.
  #
  !if $(NETWORK_PXE_BOOT_ENABLE) == TRUE
    gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01
    gEfiNetworkPkgTokenSpaceGuid.PcdIPv6PXESupport|0x01
  !endif

  #
  # IPv4 and IPv6 HTTP Boot support.
  #
  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4HttpSupport|TRUE
  gEfiNetworkPkgTokenSpaceGuid.PcdIPv6HttpSupport|TRUE
!endif

I think following may help.

To remove UEFI HTTPv4, UEFI HTTPv6 try following.

Edit nvidia-uefi/edk2/NetworkPkg/NetworkDefines.dsc.inc
change TRUE to FALSE / or from command line flag.

# These flags can be defined before the !include line, or changed on the command
# line to enable or disable related feature support.
#   -D FLAG=VALUE
DEFINE NETWORK_HTTP_BOOT_ENABLE       = FALSE

And edit and change y to n in
nvidia-uefi/nvidia-config/t26x_general/config.dsc.inc:CONFIG_NETWORKING_HTTP=n


To remove UEFI PXEv4, UEFI PXEv6 try following.

Edit nvidia-uefi/edk2/NetworkPkg/NetworkPkg.dec
change 0x01 to 0x00

## IPv4 PXE support
  # 0x01 = PXE Enabled
  # 0x00 = PXE Disabled
  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x00|UINT8|0x10000009

  ## IPv6 PXE support
  # 0x01 = PXE Enabled
  # 0x00 = PXE Disabled
  gEfiNetworkPkgTokenSpaceGuid.PcdIPv6PXESupport|0x00|UINT8|0x1000000a

You may want to make same change in these files unless you know what is the top file, if it is not NetworkPkg.dec.

~/nvidia-uefi/edk2$ grep -ir "gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01" .
./NetworkPkg/NetworkPkg.dec:  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01|UINT8|0x10000009
./OvmfPkg/OvmfPkgX64.dsc:  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01
./OvmfPkg/OvmfPkgIa32.dsc:  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01
./OvmfPkg/CloudHv/CloudHvX64.dsc:  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01
./OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc:  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01
./OvmfPkg/Microvm/MicrovmX64.dsc:  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01
./OvmfPkg/OvmfPkgIa32X64.dsc:  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01
./ArmVirtPkg/ArmVirtQemu.dsc:  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01
./ArmVirtPkg/ArmVirtQemuKernel.dsc:  gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01

我上面已经提到过,如果只是通过禁用网络来规避网络启动的问题,不需要这么麻烦,只需要配置t26x_general.defconfig 添加CONFIG_NETWORKING=n 配置即可,这个已经验证过了。但问题在于这个方法治标不治本,如果插入的不是网卡设备,而是USB硬盘设备, 难道又得禁用USB?

1 Like

I’m fairly certain that PcdNewDeviceHierarchy|0x00 would control the option shown in the attached picture and that if you were to thereafter plug a new usb drive into Thor it would go to the bottom.
You can look at your Thor settings in uefi-bios at a subsequent boot of Thor.

#Option to add new boot device at top or bottom of list
  gNVIDIATokenSpaceGuid.PcdNewDeviceHierarchy|0x00|UINT8|0x00000068

https://github.com/NVIDIA/edk2-nvidia/blob/main/Silicon/NVIDIA/NVIDIA.dec
nvidia-uefi/edk2-nvidia/Silicon/NVIDIA/NVIDIA.dec

我修改NVIDIA.dec 的 PcdNewDeviceHierarchy 值为0x00之后,bios 仍然默认为 Top ,而不是Bottom。

If this file does not have a later timestamp than the updated bootloader/uefi_t26x_general.bin.

ls -al Linux_for_Tegra/unified_flash/out/bsp_images/flash_workspace/flash-images/uefi_t26x_general_with_dtb_aligned_blob_w_bin_sigheader.bin.encrypt

In order to have flash generate updated files to include the modified uefi_t26x_general.bin you may need to :

mv out out_old
mv unified_flash/output unified_flash/output_old

Even if i remove out directory, boot order still is top, don’t change.