diff --git a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-Add-hup-and-rollback-support-agx-orin-32-5-2.patch b/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-Add-hup-and-rollback-support-agx-orin-32-5-2.patch deleted file mode 100644 index cea6470b..00000000 --- a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-Add-hup-and-rollback-support-agx-orin-32-5-2.patch +++ /dev/null @@ -1,587 +0,0 @@ - - -L4TLauncher is loaded by the UEFI firmware from -the resin-boot partition. The launcher's name -is BOOTAARCH64.efi. - -With this patch, the Nvidia bootloader parses resinos_uEnv.txt, -extra_uEnv.txt and bootcount.env in order to load the -extlinux.conf and the selected dtb from the current active -rootfs. - -The A/B rootfs switch logic implemented in this change -is the same as the one that exists in balenaOS u-boot and is -compatible with the dtb selection mechanism implemented in the -Supervisor for the rest of the boards that use u-boot. - -Upstream-status: Inappropriate [configuration] -Signed-off-by: Alexandru Costache - -Index: edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.c -=================================================================== ---- edk2-tegra.orig/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.c -+++ edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.c -@@ -986,6 +986,145 @@ CheckCommandString ( - return EFI_NOT_FOUND; - } - -+STATIC -+EFI_STATUS -+EFIAPI -+CheckDtbExists ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ IN CONST CHAR16 *BalenaOSRootFs, -+ IN CONST CHAR16 *DtbPath -+ ) -+{ -+ EFI_STATUS Status; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ EFI_HANDLE RootFsHandle; -+ -+ if (NULL == BalenaOSRootFs || NULL == DtbPath) { -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ Status = FindPartitionInfo (DeviceHandle, BalenaOSRootFs, BootChain, NULL, &RootFsHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Unable to find partition info\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (RootFsHandle, DtbPath); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open dtb file. Reason: %r\r\n", __FUNCTION__, Status); -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ return Status; -+} -+ -+STATIC -+EFI_STATUS -+EFIAPI -+ProcessExtrauEnv ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ IN CONST CHAR16 *BalenaOSRootFs, -+ OUT CHAR16 **CustomFdtName -+) -+{ -+ EFI_STATUS Status; -+ EFI_HANDLE BootPartHandle; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR16 *FileLine = NULL; -+ CHAR16 *DtbName = NULL; -+ BOOLEAN Ascii; -+ CHAR16 *LineCopy = AllocateZeroPool(MAX_DTB_PATH_LEN); -+ UINT64 len; -+ -+ // Set default dtb as fail-safe -+ *CustomFdtName = AllocateZeroPool(MAX_DTB_PATH_LEN); -+ UnicodeSPrint (*CustomFdtName, MAX_DTB_PATH_LEN, L"boot\\%s\0", DEFAULT_AGX_ORIN_DTB_NAME); -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Unable to find boot partition\r\n", __FUNCTION__); -+ return Status; -+ } -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_EXTRA_UENV_FILE); -+ -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path to extra_uEnv.txt\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open file extra_uEnv.txt: %r\r\n", __FUNCTION__, Status); -+ return Status; -+ } -+ -+ while (!FileHandleEof (FileHandle)) { -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ FileLine = FileHandleReturnLine (FileHandle, &Ascii); -+ -+ if (NULL == FileLine) { -+ break; -+ } -+ -+ UnicodeSPrint (LineCopy, MAX_DTB_PATH_LEN, L"%s\0", FileLine); -+ Print(L"Processing entry: %s\n", LineCopy); -+ -+ len = StrLen(LineCopy); -+ -+ if (len < 21 /* dtb name should have at least 1 character + extension */) { -+ ErrorPrint(L"DTB name is too short. Using default dtb.\n"); -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ DtbName = StrStr(LineCopy, L"custom_fdt_file="); -+ -+ if (NULL != DtbName) { -+ DtbName += StrLen(L"custom_fdt_file="); -+ UnicodeSPrint(*CustomFdtName, MAX_DTB_PATH_LEN, L"boot\\%s\0", DtbName); -+ Print(L"Selected dtb name is %s:\n", CustomFdtName); -+ Status = CheckDtbExists(DeviceHandle, BootChain, BalenaOSRootFs, *CustomFdtName); -+ -+ if (EFI_ERROR(Status)) { -+ ErrorPrint(L"Selected dtb not found! Using the default DTB for this device type\n"); -+ UnicodeSPrint(*CustomFdtName, MAX_DTB_PATH_LEN, L"boot\\%s\0", DEFAULT_AGX_ORIN_DTB_NAME); -+ return Status; -+ } -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ } -+ -+ return EFI_SUCCESS; -+} -+ - /** - Process the extlinux.conf file - -@@ -1003,6 +1142,7 @@ EFIAPI - ProcessExtLinuxConfig ( - IN EFI_HANDLE DeviceHandle, - IN UINT32 BootChain, -+ IN CONST CHAR16 *BalenaOSRootFs, - OUT EXTLINUX_BOOT_CONFIG *BootConfig, - OUT EFI_HANDLE *RootFsHandle - ) -@@ -1015,8 +1155,11 @@ ProcessExtLinuxConfig ( - CHAR16 *Timeout = NULL; - CHAR16 *CbootArg = NULL; - CHAR16 *PostCbootArg = NULL; -+ CONST CHAR16 *RootL = L"root=LABEL="; - BOOLEAN Ascii; - UINTN Index; -+ CHAR16 *UpdatedCmdline = NULL; -+ UINTN argsSize; - - ZeroMem (BootConfig, sizeof (EXTLINUX_BOOT_CONFIG)); - -@@ -1024,12 +1167,8 @@ ProcessExtLinuxConfig ( - return EFI_INVALID_PARAMETER; - } - -- Status = FindPartitionInfo (DeviceHandle, ROOTFS_BASE_NAME, BootChain, NULL, RootFsHandle); -- if (EFI_ERROR (Status)) { -- ErrorPrint (L"%a: Unable to find partition info\r\n", __FUNCTION__); -- return Status; -- } -- -+ /* Load extlinux.conf from the selected BalenaOS root filesystem */ -+ Status = FindPartitionInfo (DeviceHandle, BalenaOSRootFs, BootChain, NULL, RootFsHandle); - Status = OpenAndReadFileToBuffer ( - *RootFsHandle, - EXTLINUX_CONF_PATH, -@@ -1101,10 +1240,40 @@ ProcessExtLinuxConfig ( - - Status = CheckCommandString (CleanLine, EXTLINUX_KEY_FDT, &BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); - if (!EFI_ERROR (Status)) { -+ /* extlinux.conf contains a "FDT default" entry */ -+ if (0 == StrnCmp(BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath, EXTLINUX_GENERIC_FDT, StrLen (EXTLINUX_GENERIC_FDT))) { -+ if (NULL != BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath) { -+ FreePool(BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); -+ /* Check if a device-tree name is set in extra_uEnv.txt */ -+ CHAR16 *ExtrauEnvDtb = NULL; -+ Status = ProcessExtrauEnv(DeviceHandle, BootChain, BalenaOSRootFs, &ExtrauEnvDtb); -+ -+ if (!EFI_ERROR(Status)) { -+ Print(L"Using default device-tree\n"); -+ } -+ BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath = ExtrauEnvDtb; -+ Print(L"Kernel device-tree after parsing extra_uEnv.txt is %s\n", BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); -+ } -+ } else { -+ Print(L"Kernel device-tree is %s\n", BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); -+ } - continue; - } - - Status = CheckCommandString (CleanLine, EXTLINUX_KEY_APPEND, &BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); -+ argsSize = StrSize (BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); -+ UpdatedCmdline = AllocateZeroPool (argsSize + StrSize(RootL) + StrSize(BalenaOSRootFs) + 2); -+ if (NULL == UpdatedCmdline) { -+ ErrorPrint (L"%a: Failed to allocate memory for updated cmdline %d\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ /* Append root label to cmdline that has been read from the extlinux.conf read from the active rootfs */ -+ UnicodeSPrint (UpdatedCmdline, StrSize(RootL) + StrSize(BalenaOSRootFs) + argsSize, L"%s %s%s\0", BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs, RootL, BalenaOSRootFs); -+ if (NULL != BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs) { -+ FreePool(BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); -+ } -+ BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs = UpdatedCmdline; - if (!EFI_ERROR (Status)) { - CbootArg = StrStr (BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs, EXTLINUX_CBOOT_ARG); - if (CbootArg != NULL) { -@@ -1315,12 +1484,12 @@ ExtLinuxBoot ( - - // Reload fdt if needed - Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, &AcpiBase); -- if (EFI_ERROR (Status) && (BootOption->DtbPath != NULL)) { -+ if (BootOption->DtbPath != NULL) { - Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &OldFdtBase); - if (EFI_ERROR (Status)) { - OldFdtBase = NULL; - } -- -+ ErrorPrint (L"%a: OpenedAndReadFileToBuffer %s (%r)\r\n", __FUNCTION__, BootOption->DtbPath, Status); - Status = OpenAndReadFileToBuffer ( - DeviceHandle, - BootOption->DtbPath, -@@ -1972,6 +2141,220 @@ Exit: - return Status; - } - -+STATIC -+EFI_STATUS -+EFIAPI -+WriteBootCountFile ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ IN UINT32 BootCountValue -+) -+{ -+ EFI_STATUS Status; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR8 BootCountContent[11]; -+ UINTN BootCountFileSize; -+ EFI_HANDLE BootPartHandle; -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Unable to find partition resin-boot\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_BOOTCOUNT_FILE_PATH); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path bootcount.env\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open file bootcount.env: %r\r\n", __FUNCTION__, Status); -+ return Status; -+ } -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to set file size to 0\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ BootCountFileSize = AsciiSPrint (BootCountContent, 12, "bootcount=%d\0", BootCountValue); -+ Status = FileHandleWrite (FileHandle, &BootCountFileSize, BootCountContent); -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to write bootcount file contents\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+ -+STATIC -+EFI_STATUS -+EFIAPI -+ProcessBootCountValue ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ OUT UINTN *BootCountValue -+) -+{ -+ EFI_STATUS Status; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_HANDLE BootPartHandle; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR16 *FileLine = NULL; -+ CHAR16 *CleanLine; -+ BOOLEAN Ascii; -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Could not find partition resin-boot\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_BOOTCOUNT_FILE_PATH); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path for bootcount.env\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ if (EFI_ERROR (Status)) { -+ *BootCountValue = 1; -+ Status = WriteBootCountFile (DeviceHandle, BootChain, *BootCountValue); -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to write bootcount file contents\r\n", __FUNCTION__); -+ return Status; -+ } else { -+ Print(L"Initialized boot count to 1\r\n"); -+ } -+ } else { -+ while (!FileHandleEof (FileHandle)) { -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ FileLine = FileHandleReturnLine (FileHandle, &Ascii); -+ if (NULL == FileLine) { -+ break; -+ } -+ -+ CleanLine = CleanExtLinuxLine (FileLine); -+ if (*CleanLine != CHAR_NULL) { -+ if (StrStr(CleanLine, L"bootcount=")) { -+ *BootCountValue = StrDecimalToUintn(CleanLine + 10); -+ Print(L"%a: BootCount is %d : %s\r\n", __FUNCTION__, *BootCountValue); -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ } -+ -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ Status = WriteBootCountFile (DeviceHandle, BootChain, ++(*BootCountValue)); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to write bootcount file value %d\r\n", __FUNCTION__, *BootCountValue); -+ } -+ -+ return Status; -+ } -+ } -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+ -+STATIC -+EFI_STATUS -+EFIAPI -+ProcessResinOSuEnv ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ OUT UINTN *RootPart, -+ OUT UINTN *UpgradeAvailable -+) -+{ -+ EFI_STATUS Status; -+ EFI_HANDLE BootPartHandle; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR16 *FileLine = NULL; -+ CHAR16 *CleanLine; -+ BOOLEAN Ascii; -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Could not find partition Balena boot partition\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_BOOT_CONF_PATH); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create path for resinOS_uEnvt.xt\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open resinOS_uEnv.txt: %r\r\n", __FUNCTION__, Status); -+ return Status; -+ } -+ -+ while (!FileHandleEof (FileHandle)) { -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ FileLine = FileHandleReturnLine (FileHandle, &Ascii); -+ if (NULL == FileLine) { -+ break; -+ } -+ -+ CleanLine = CleanExtLinuxLine (FileLine); -+ if (*CleanLine != CHAR_NULL) { -+ if (StrStr(CleanLine, L"resin_root_part=")) { -+ *RootPart = StrDecimalToUintn(CleanLine + 16); -+ Print(L"RootPart is %d\r\n", *RootPart); -+ } else if (StrStr(CleanLine, L"upgrade_available=")) { -+ *UpgradeAvailable = StrDecimalToUintn(CleanLine + 18); -+ Print(L"UpgradeAvailable is %d\r\n", *UpgradeAvailable); -+ } -+ } -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ return EFI_SUCCESS; -+} -+ - /** - This is the declaration of an EFI image entry point. This entry point is - the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including -@@ -2001,7 +2384,10 @@ L4TLauncher ( - EXTLINUX_BOOT_CONFIG ExtLinuxConfig; - UINTN ExtLinuxBootOption; - UINTN Index; -- -+ CHAR16 *BalenaOSRootFs = NULL; -+ UINTN UpgradeAvailable = 0; -+ UINTN BootCountValue = 0; -+ UINTN RootFsIndex = BALENA_ROOTFS_INDEX_A; - Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage); - if (EFI_ERROR (Status)) { - ErrorPrint (L"%a: Unable to locate loaded image: %r\r\n", __FUNCTION__, Status); -@@ -2014,6 +2400,9 @@ L4TLauncher ( - return Status; - } - -+ ErrorPrint(L"BalenaOS: Set BootMode to NVIDIA_L4T_BOOTMODE_DIRECT\r\r\n"); -+ BootParams.BootMode = NVIDIA_L4T_BOOTMODE_DIRECT; -+ - if (BootParams.BootMode == NVIDIA_L4T_BOOTMODE_GRUB) { - ErrorPrint (L"%a: Attempting GRUB Boot\r\n", __FUNCTION__); - do { -@@ -2057,11 +2446,41 @@ L4TLauncher ( - } - - if (BootParams.BootMode == NVIDIA_L4T_BOOTMODE_DIRECT) { -- ErrorPrint (L"%a: Attempting Direct Boot\r\n", __FUNCTION__); -+ Print (L"%a: Attempt Direct Boot\r\n", __FUNCTION__); - do { -- Status = ProcessExtLinuxConfig (LoadedImage->DeviceHandle, BootParams.BootChain, &ExtLinuxConfig, &RootFsDeviceHandle); -+ Status = ProcessResinOSuEnv (LoadedImage->DeviceHandle, BootParams.BootChain, &RootFsIndex, &UpgradeAvailable); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint(L"resinOS_uEnv.txt does not exist\n"); -+ } -+ -+ Print(L"Current resin_root_part=%d - upgrade_available=%d\r\n", RootFsIndex, UpgradeAvailable); -+ if (1 == UpgradeAvailable) { -+ Status = ProcessBootCountValue (LoadedImage->DeviceHandle, BootParams.BootChain, &BootCountValue); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint(L"%a: Error while processing bootcount value\r\n", __FUNCTION__); -+ } -+ Print (L"%a: BootCountValue is %d\r\n", __FUNCTION__, BootCountValue); -+ } -+ -+ /* If boot limit is reached while upgrade_available=1, switch partitions */ -+ if (BALENA_OS_BC_LIM <= BootCountValue) { -+ if (BALENA_ROOTFS_INDEX_B == RootFsIndex) { -+ RootFsIndex = BALENA_ROOTFS_INDEX_A; -+ } else { -+ RootFsIndex = BALENA_ROOTFS_INDEX_B; -+ } -+ ErrorPrint(L"%a: Reached bootcount limit, will switch partitions... New index is %d\r\n", __FUNCTION__, RootFsIndex); -+ } -+ -+ if (BALENA_ROOTFS_INDEX_B == RootFsIndex) { -+ BalenaOSRootFs = BALENA_ROOTFS_BASE_NAME_B; -+ } else { -+ BalenaOSRootFs = BALENA_ROOTFS_BASE_NAME_A; -+ } -+ -+ Status = ProcessExtLinuxConfig (LoadedImage->DeviceHandle, BootParams.BootChain, BalenaOSRootFs, &ExtLinuxConfig, &RootFsDeviceHandle); - if (EFI_ERROR (Status)) { -- ErrorPrint (L"%a: Unable to process extlinux config: %r\r\n", __FUNCTION__, Status); -+ ErrorPrint (L"%a: ProcessExtLinuxConfig failed on partition %s: %r\r\n", __FUNCTION__, BalenaOSRootFs, Status); - BootParams.BootMode = NVIDIA_L4T_BOOTMODE_BOOTIMG; - break; - } -Index: edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.h -=================================================================== ---- edk2-tegra.orig/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.h -+++ edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.h -@@ -31,11 +31,21 @@ - #define BOOT_OS_VARIABLE_NAME L"BootChainOsCurrent" - - #define ROOTFS_BASE_NAME L"APP" -+#define BALENA_ROOTFS_BASE_NAME_A L"resin-rootA" -+#define BALENA_ROOTFS_BASE_NAME_B L"resin-rootB" -+#define BALENA_BOOT_PARTITION L"resin-boot" -+#define BALENA_BOOT_CONF_PATH L"resinOS_uEnv.txt" -+#define BALENA_BOOTCOUNT_FILE_PATH L"bootcount.env" -+#define MAX_RESINOS_UENV_SIZE 256 -+#define BALENA_ROOTFS_INDEX_A 7 -+#define BALENA_ROOTFS_INDEX_B 8 -+#define BALENA_OS_BC_LIM 3 -+#define BALENA_EXTRA_UENV_FILE L"extra_uEnv.txt" - #define BOOTIMG_BASE_NAME L"kernel" - #define BOOTIMG_DTB_BASE_NAME L"kernel-dtb" - #define RECOVERY_BASE_NAME L"recovery" - #define RECOVERY_DTB_BASE_NAME L"recovery-dtb" -- -+#define DEFAULT_AGX_ORIN_DTB_NAME L"tegra234-p3701-0000-p3737-0000.dtb" - #define EXTLINUX_KEY_TIMEOUT L"TIMEOUT" - #define EXTLINUX_KEY_DEFAULT L"DEFAULT" - #define EXTLINUX_KEY_MENU_TITLE L"MENU TITLE" -@@ -45,9 +55,10 @@ - #define EXTLINUX_KEY_INITRD L"INITRD" - #define EXTLINUX_KEY_FDT L"FDT" - #define EXTLINUX_KEY_APPEND L"APPEND" -- -+#define EXTLINUX_GENERIC_FDT L"default" - #define EXTLINUX_CBOOT_ARG L"${cbootargs}" - -+#define MAX_DTB_PATH_LEN 512 * 2 - #define MAX_EXTLINUX_OPTIONS 10 - - typedef struct { diff --git a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-Add-hup-and-rollback-support-agx-xavier-35-4-1.patch b/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-Add-hup-and-rollback-support-agx-xavier-35-4-1.patch index ef88ac86..a6785d59 100644 --- a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-Add-hup-and-rollback-support-agx-xavier-35-4-1.patch +++ b/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-Add-hup-and-rollback-support-agx-xavier-35-4-1.patch @@ -230,7 +230,7 @@ Index: edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher + argsSize = StrSize (BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); + UpdatedCmdline = AllocateZeroPool (argsSize + StrSize(RootL) + StrSize(BalenaOSRootFs) + 2); + if (NULL == UpdatedCmdline) { -+ ErrorPrint (L"%a: Failed to allocate memory for updated cmdline %d\r\n", __FUNCTION__); ++ ErrorPrint (L"%a: Failed to allocate memory for updated cmdline\r\n", __FUNCTION__); + return EFI_OUT_OF_RESOURCES; + } + diff --git a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-Add-hup-and-rollback-support-orin-nano-35-3-1.patch b/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-Add-hup-and-rollback-support-orin-nano-35-3-1.patch deleted file mode 100644 index 6ddbad6f..00000000 --- a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-Add-hup-and-rollback-support-orin-nano-35-3-1.patch +++ /dev/null @@ -1,587 +0,0 @@ - - -L4TLauncher is loaded by the UEFI firmware from -the resin-boot partition. The launcher's name -is BOOTAARCH64.efi. - -With this patch, the Nvidia bootloader parses resinos_uEnv.txt, -extra_uEnv.txt and bootcount.env in order to load the -extlinux.conf and the selected dtb from the current active -rootfs. - -The A/B rootfs switch logic implemented in this change -is the same as the one that exists in balenaOS u-boot and is -compatible with the dtb selection mechanism implemented in the -Supervisor for the rest of the boards that use u-boot. - -Upstream-status: Inappropriate [configuration] -Signed-off-by: Alexandru Costache - -Index: edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.c -=================================================================== ---- edk2-tegra.orig/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.c -+++ edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.c -@@ -986,6 +986,145 @@ CheckCommandString ( - return EFI_NOT_FOUND; - } - -+STATIC -+EFI_STATUS -+EFIAPI -+CheckDtbExists ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ IN CONST CHAR16 *BalenaOSRootFs, -+ IN CONST CHAR16 *DtbPath -+ ) -+{ -+ EFI_STATUS Status; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ EFI_HANDLE RootFsHandle; -+ -+ if (NULL == BalenaOSRootFs || NULL == DtbPath) { -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ Status = FindPartitionInfo (DeviceHandle, BalenaOSRootFs, BootChain, NULL, &RootFsHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Unable to find partition info\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (RootFsHandle, DtbPath); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open dtb file. Reason: %r\r\n", __FUNCTION__, Status); -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ return Status; -+} -+ -+STATIC -+EFI_STATUS -+EFIAPI -+ProcessExtrauEnv ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ IN CONST CHAR16 *BalenaOSRootFs, -+ OUT CHAR16 **CustomFdtName -+) -+{ -+ EFI_STATUS Status; -+ EFI_HANDLE BootPartHandle; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR16 *FileLine = NULL; -+ CHAR16 *DtbName = NULL; -+ BOOLEAN Ascii; -+ CHAR16 *LineCopy = AllocateZeroPool(MAX_DTB_PATH_LEN); -+ UINT64 len; -+ -+ // Set default dtb as fail-safe -+ *CustomFdtName = AllocateZeroPool(MAX_DTB_PATH_LEN); -+ UnicodeSPrint (*CustomFdtName, MAX_DTB_PATH_LEN, L"boot\\%s\0", DEFAULT_ORIN_NANO_DTB_NAME); -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Unable to find boot partition\r\n", __FUNCTION__); -+ return Status; -+ } -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_EXTRA_UENV_FILE); -+ -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path to extra_uEnv.txt\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open file extra_uEnv.txt: %r\r\n", __FUNCTION__, Status); -+ return Status; -+ } -+ -+ while (!FileHandleEof (FileHandle)) { -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ FileLine = FileHandleReturnLine (FileHandle, &Ascii); -+ -+ if (NULL == FileLine) { -+ break; -+ } -+ -+ UnicodeSPrint (LineCopy, MAX_DTB_PATH_LEN, L"%s\0", FileLine); -+ Print(L"Processing entry: %s\n", LineCopy); -+ -+ len = StrLen(LineCopy); -+ -+ if (len < 21 /* dtb name should have at least 1 character + extension */) { -+ ErrorPrint(L"DTB name is too short. Using default dtb.\n"); -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ DtbName = StrStr(LineCopy, L"custom_fdt_file="); -+ -+ if (NULL != DtbName) { -+ DtbName += StrLen(L"custom_fdt_file="); -+ UnicodeSPrint(*CustomFdtName, MAX_DTB_PATH_LEN, L"boot\\%s\0", DtbName); -+ Print(L"Selected dtb name is %s:\n", CustomFdtName); -+ Status = CheckDtbExists(DeviceHandle, BootChain, BalenaOSRootFs, *CustomFdtName); -+ -+ if (EFI_ERROR(Status)) { -+ ErrorPrint(L"Selected dtb not found! Using the default DTB for this device type\n"); -+ UnicodeSPrint(*CustomFdtName, MAX_DTB_PATH_LEN, L"boot\\%s\0", DEFAULT_ORIN_NANO_DTB_NAME); -+ return Status; -+ } -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ } -+ -+ return EFI_SUCCESS; -+} -+ - /** - Process the extlinux.conf file - -@@ -1003,6 +1142,7 @@ EFIAPI - ProcessExtLinuxConfig ( - IN EFI_HANDLE DeviceHandle, - IN UINT32 BootChain, -+ IN CONST CHAR16 *BalenaOSRootFs, - OUT EXTLINUX_BOOT_CONFIG *BootConfig, - OUT EFI_HANDLE *RootFsHandle - ) -@@ -1015,8 +1155,11 @@ ProcessExtLinuxConfig ( - CHAR16 *Timeout = NULL; - CHAR16 *CbootArg = NULL; - CHAR16 *PostCbootArg = NULL; -+ CONST CHAR16 *RootL = L"root=LABEL="; - BOOLEAN Ascii; - UINTN Index; -+ CHAR16 *UpdatedCmdline = NULL; -+ UINTN argsSize; - - ZeroMem (BootConfig, sizeof (EXTLINUX_BOOT_CONFIG)); - -@@ -1024,12 +1167,8 @@ ProcessExtLinuxConfig ( - return EFI_INVALID_PARAMETER; - } - -- Status = FindPartitionInfo (DeviceHandle, ROOTFS_BASE_NAME, BootChain, NULL, RootFsHandle); -- if (EFI_ERROR (Status)) { -- ErrorPrint (L"%a: Unable to find partition info\r\n", __FUNCTION__); -- return Status; -- } -- -+ /* Load extlinux.conf from the selected BalenaOS root filesystem */ -+ Status = FindPartitionInfo (DeviceHandle, BalenaOSRootFs, BootChain, NULL, RootFsHandle); - Status = OpenAndReadFileToBuffer ( - *RootFsHandle, - EXTLINUX_CONF_PATH, -@@ -1101,10 +1240,40 @@ ProcessExtLinuxConfig ( - - Status = CheckCommandString (CleanLine, EXTLINUX_KEY_FDT, &BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); - if (!EFI_ERROR (Status)) { -+ /* extlinux.conf contains a "FDT default" entry */ -+ if (0 == StrnCmp(BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath, EXTLINUX_GENERIC_FDT, StrLen (EXTLINUX_GENERIC_FDT))) { -+ if (NULL != BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath) { -+ FreePool(BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); -+ /* Check if a device-tree name is set in extra_uEnv.txt */ -+ CHAR16 *ExtrauEnvDtb = NULL; -+ Status = ProcessExtrauEnv(DeviceHandle, BootChain, BalenaOSRootFs, &ExtrauEnvDtb); -+ -+ if (!EFI_ERROR(Status)) { -+ Print(L"Using default device-tree\n"); -+ } -+ BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath = ExtrauEnvDtb; -+ Print(L"Kernel device-tree after parsing extra_uEnv.txt is %s\n", BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); -+ } -+ } else { -+ Print(L"Kernel device-tree is %s\n", BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); -+ } - continue; - } - - Status = CheckCommandString (CleanLine, EXTLINUX_KEY_APPEND, &BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); -+ argsSize = StrSize (BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); -+ UpdatedCmdline = AllocateZeroPool (argsSize + StrSize(RootL) + StrSize(BalenaOSRootFs) + 2); -+ if (NULL == UpdatedCmdline) { -+ ErrorPrint (L"%a: Failed to allocate memory for updated cmdline %d\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ /* Append root label to cmdline that has been read from the extlinux.conf read from the active rootfs */ -+ UnicodeSPrint (UpdatedCmdline, StrSize(RootL) + StrSize(BalenaOSRootFs) + argsSize, L"%s %s%s\0", BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs, RootL, BalenaOSRootFs); -+ if (NULL != BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs) { -+ FreePool(BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); -+ } -+ BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs = UpdatedCmdline; - if (!EFI_ERROR (Status)) { - CbootArg = StrStr (BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs, EXTLINUX_CBOOT_ARG); - if (CbootArg != NULL) { -@@ -1315,12 +1484,12 @@ ExtLinuxBoot ( - - // Reload fdt if needed - Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, &AcpiBase); -- if (EFI_ERROR (Status) && (BootOption->DtbPath != NULL)) { -+ if (BootOption->DtbPath != NULL) { - Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &OldFdtBase); - if (EFI_ERROR (Status)) { - OldFdtBase = NULL; - } -- -+ ErrorPrint (L"%a: OpenedAndReadFileToBuffer %s (%r)\r\n", __FUNCTION__, BootOption->DtbPath, Status); - Status = OpenAndReadFileToBuffer ( - DeviceHandle, - BootOption->DtbPath, -@@ -1972,6 +2141,220 @@ Exit: - return Status; - } - -+STATIC -+EFI_STATUS -+EFIAPI -+WriteBootCountFile ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ IN UINT32 BootCountValue -+) -+{ -+ EFI_STATUS Status; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR8 BootCountContent[11]; -+ UINTN BootCountFileSize; -+ EFI_HANDLE BootPartHandle; -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Unable to find partition resin-boot\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_BOOTCOUNT_FILE_PATH); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path bootcount.env\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open file bootcount.env: %r\r\n", __FUNCTION__, Status); -+ return Status; -+ } -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to set file size to 0\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ BootCountFileSize = AsciiSPrint (BootCountContent, 12, "bootcount=%d\0", BootCountValue); -+ Status = FileHandleWrite (FileHandle, &BootCountFileSize, BootCountContent); -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to write bootcount file contents\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+ -+STATIC -+EFI_STATUS -+EFIAPI -+ProcessBootCountValue ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ OUT UINTN *BootCountValue -+) -+{ -+ EFI_STATUS Status; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_HANDLE BootPartHandle; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR16 *FileLine = NULL; -+ CHAR16 *CleanLine; -+ BOOLEAN Ascii; -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Could not find partition resin-boot\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_BOOTCOUNT_FILE_PATH); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path for bootcount.env\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ if (EFI_ERROR (Status)) { -+ *BootCountValue = 1; -+ Status = WriteBootCountFile (DeviceHandle, BootChain, *BootCountValue); -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to write bootcount file contents\r\n", __FUNCTION__); -+ return Status; -+ } else { -+ Print(L"Initialized boot count to 1\r\n"); -+ } -+ } else { -+ while (!FileHandleEof (FileHandle)) { -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ FileLine = FileHandleReturnLine (FileHandle, &Ascii); -+ if (NULL == FileLine) { -+ break; -+ } -+ -+ CleanLine = CleanExtLinuxLine (FileLine); -+ if (*CleanLine != CHAR_NULL) { -+ if (StrStr(CleanLine, L"bootcount=")) { -+ *BootCountValue = StrDecimalToUintn(CleanLine + 10); -+ Print(L"%a: BootCount is %d : %s\r\n", __FUNCTION__, *BootCountValue); -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ } -+ -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ Status = WriteBootCountFile (DeviceHandle, BootChain, ++(*BootCountValue)); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to write bootcount file value %d\r\n", __FUNCTION__, *BootCountValue); -+ } -+ -+ return Status; -+ } -+ } -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+ -+STATIC -+EFI_STATUS -+EFIAPI -+ProcessResinOSuEnv ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ OUT UINTN *RootPart, -+ OUT UINTN *UpgradeAvailable -+) -+{ -+ EFI_STATUS Status; -+ EFI_HANDLE BootPartHandle; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR16 *FileLine = NULL; -+ CHAR16 *CleanLine; -+ BOOLEAN Ascii; -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Could not find partition Balena boot partition\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_BOOT_CONF_PATH); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create path for resinOS_uEnvt.xt\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open resinOS_uEnv.txt: %r\r\n", __FUNCTION__, Status); -+ return Status; -+ } -+ -+ while (!FileHandleEof (FileHandle)) { -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ FileLine = FileHandleReturnLine (FileHandle, &Ascii); -+ if (NULL == FileLine) { -+ break; -+ } -+ -+ CleanLine = CleanExtLinuxLine (FileLine); -+ if (*CleanLine != CHAR_NULL) { -+ if (StrStr(CleanLine, L"resin_root_part=")) { -+ *RootPart = StrHexToUintn(CleanLine + 16); -+ Print(L"RootPart is %d\r\n", *RootPart); -+ } else if (StrStr(CleanLine, L"upgrade_available=")) { -+ *UpgradeAvailable = StrDecimalToUintn(CleanLine + 18); -+ Print(L"UpgradeAvailable is %d\r\n", *UpgradeAvailable); -+ } -+ } -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ return EFI_SUCCESS; -+} -+ - /** - This is the declaration of an EFI image entry point. This entry point is - the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including -@@ -2001,7 +2384,10 @@ L4TLauncher ( - EXTLINUX_BOOT_CONFIG ExtLinuxConfig; - UINTN ExtLinuxBootOption; - UINTN Index; -- -+ CHAR16 *BalenaOSRootFs = NULL; -+ UINTN UpgradeAvailable = 0; -+ UINTN BootCountValue = 0; -+ UINTN RootFsIndex = BALENA_ROOTFS_INDEX_A; - Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage); - if (EFI_ERROR (Status)) { - ErrorPrint (L"%a: Unable to locate loaded image: %r\r\n", __FUNCTION__, Status); -@@ -2014,6 +2400,9 @@ L4TLauncher ( - return Status; - } - -+ ErrorPrint(L"BalenaOS: Set BootMode to NVIDIA_L4T_BOOTMODE_DIRECT\r\r\n"); -+ BootParams.BootMode = NVIDIA_L4T_BOOTMODE_DIRECT; -+ - if (BootParams.BootMode == NVIDIA_L4T_BOOTMODE_GRUB) { - ErrorPrint (L"%a: Attempting GRUB Boot\r\n", __FUNCTION__); - do { -@@ -2057,11 +2446,41 @@ L4TLauncher ( - } - - if (BootParams.BootMode == NVIDIA_L4T_BOOTMODE_DIRECT) { -- ErrorPrint (L"%a: Attempting Direct Boot\r\n", __FUNCTION__); -+ Print (L"%a: Attempt Direct Boot\r\n", __FUNCTION__); - do { -- Status = ProcessExtLinuxConfig (LoadedImage->DeviceHandle, BootParams.BootChain, &ExtLinuxConfig, &RootFsDeviceHandle); -+ Status = ProcessResinOSuEnv (LoadedImage->DeviceHandle, BootParams.BootChain, &RootFsIndex, &UpgradeAvailable); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint(L"resinOS_uEnv.txt does not exist\n"); -+ } -+ -+ Print(L"Current resin_root_part=%d - upgrade_available=%d\r\n", RootFsIndex, UpgradeAvailable); -+ if (1 == UpgradeAvailable) { -+ Status = ProcessBootCountValue (LoadedImage->DeviceHandle, BootParams.BootChain, &BootCountValue); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint(L"%a: Error while processing bootcount value\r\n", __FUNCTION__); -+ } -+ Print (L"%a: BootCountValue is %d\r\n", __FUNCTION__, BootCountValue); -+ } -+ -+ /* If boot limit is reached while upgrade_available=1, switch partitions */ -+ if (BALENA_OS_BC_LIM <= BootCountValue) { -+ if (BALENA_ROOTFS_INDEX_B == RootFsIndex) { -+ RootFsIndex = BALENA_ROOTFS_INDEX_A; -+ } else { -+ RootFsIndex = BALENA_ROOTFS_INDEX_B; -+ } -+ ErrorPrint(L"%a: Reached bootcount limit, will switch partitions... New index is %d\r\n", __FUNCTION__, RootFsIndex); -+ } -+ -+ if (BALENA_ROOTFS_INDEX_B == RootFsIndex) { -+ BalenaOSRootFs = BALENA_ROOTFS_BASE_NAME_B; -+ } else { -+ BalenaOSRootFs = BALENA_ROOTFS_BASE_NAME_A; -+ } -+ -+ Status = ProcessExtLinuxConfig (LoadedImage->DeviceHandle, BootParams.BootChain, BalenaOSRootFs, &ExtLinuxConfig, &RootFsDeviceHandle); - if (EFI_ERROR (Status)) { -- ErrorPrint (L"%a: Unable to process extlinux config: %r\r\n", __FUNCTION__, Status); -+ ErrorPrint (L"%a: ProcessExtLinuxConfig failed on partition %s: %r\r\n", __FUNCTION__, BalenaOSRootFs, Status); - BootParams.BootMode = NVIDIA_L4T_BOOTMODE_BOOTIMG; - break; - } -Index: edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.h -=================================================================== ---- edk2-tegra.orig/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.h -+++ edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.h -@@ -31,11 +31,21 @@ - #define BOOT_OS_VARIABLE_NAME L"BootChainOsCurrent" - - #define ROOTFS_BASE_NAME L"APP" -+#define BALENA_ROOTFS_BASE_NAME_A L"resin-rootA" -+#define BALENA_ROOTFS_BASE_NAME_B L"resin-rootB" -+#define BALENA_BOOT_PARTITION L"resin-boot" -+#define BALENA_BOOT_CONF_PATH L"resinOS_uEnv.txt" -+#define BALENA_BOOTCOUNT_FILE_PATH L"bootcount.env" -+#define MAX_RESINOS_UENV_SIZE 256 -+#define BALENA_ROOTFS_INDEX_A 15 -+#define BALENA_ROOTFS_INDEX_B 16 -+#define BALENA_OS_BC_LIM 3 -+#define BALENA_EXTRA_UENV_FILE L"extra_uEnv.txt" - #define BOOTIMG_BASE_NAME L"kernel" - #define BOOTIMG_DTB_BASE_NAME L"kernel-dtb" - #define RECOVERY_BASE_NAME L"recovery" - #define RECOVERY_DTB_BASE_NAME L"recovery-dtb" -- -+#define DEFAULT_ORIN_NANO_DTB_NAME L"tegra234-p3767-0003-p3768-0000-a0.dtb" - #define EXTLINUX_KEY_TIMEOUT L"TIMEOUT" - #define EXTLINUX_KEY_DEFAULT L"DEFAULT" - #define EXTLINUX_KEY_MENU_TITLE L"MENU TITLE" -@@ -45,9 +55,10 @@ - #define EXTLINUX_KEY_INITRD L"INITRD" - #define EXTLINUX_KEY_FDT L"FDT" - #define EXTLINUX_KEY_APPEND L"APPEND" -- -+#define EXTLINUX_GENERIC_FDT L"default" - #define EXTLINUX_CBOOT_ARG L"${cbootargs}" - -+#define MAX_DTB_PATH_LEN 512 * 2 - #define MAX_EXTLINUX_OPTIONS 10 - - typedef struct { diff --git a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-L4TLauncher-hup-rollback-support-jetson-xavier-nx-devkit-emmc.patch b/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-L4TLauncher-hup-rollback-support-jetson-xavier-nx-devkit-emmc.patch index b83ca260..08278494 100644 --- a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-L4TLauncher-hup-rollback-support-jetson-xavier-nx-devkit-emmc.patch +++ b/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-L4TLauncher-hup-rollback-support-jetson-xavier-nx-devkit-emmc.patch @@ -230,7 +230,7 @@ Index: edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher + argsSize = StrSize (BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); + UpdatedCmdline = AllocateZeroPool (argsSize + StrSize(RootL) + StrSize(BalenaOSRootFs) + 2); + if (NULL == UpdatedCmdline) { -+ ErrorPrint (L"%a: Failed to allocate memory for updated cmdline %d\r\n", __FUNCTION__); ++ ErrorPrint (L"%a: Failed to allocate memory for updated cmdline\r\n", __FUNCTION__); + return EFI_OUT_OF_RESOURCES; + } + diff --git a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-L4TLauncher-hup-rollback-support-orin-nx-seed-j4012.patch b/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-L4TLauncher-hup-rollback-support-orin-nx-seed-j4012.patch deleted file mode 100644 index 0b26f4c6..00000000 --- a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-L4TLauncher-hup-rollback-support-orin-nx-seed-j4012.patch +++ /dev/null @@ -1,587 +0,0 @@ - - -L4TLauncher is loaded by the UEFI firmware from -the resin-boot partition. The launcher's name -is BOOTAARCH64.efi. - -With this patch, the Nvidia bootloader parses resinos_uEnv.txt, -extra_uEnv.txt and bootcount.env in order to load the -extlinux.conf and the selected dtb from the current active -rootfs. - -The A/B rootfs switch logic implemented in this change -is the same as the one that exists in balenaOS u-boot and is -compatible with the dtb selection mechanism implemented in the -Supervisor for the rest of the boards that use u-boot. - -Upstream-status: Inappropriate [configuration] -Signed-off-by: Alexandru Costache - -Index: edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.c -=================================================================== ---- edk2-tegra.orig/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.c -+++ edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.c -@@ -986,6 +986,145 @@ CheckCommandString ( - return EFI_NOT_FOUND; - } - -+STATIC -+EFI_STATUS -+EFIAPI -+CheckDtbExists ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ IN CONST CHAR16 *BalenaOSRootFs, -+ IN CONST CHAR16 *DtbPath -+ ) -+{ -+ EFI_STATUS Status; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ EFI_HANDLE RootFsHandle; -+ -+ if (NULL == BalenaOSRootFs || NULL == DtbPath) { -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ Status = FindPartitionInfo (DeviceHandle, BalenaOSRootFs, BootChain, NULL, &RootFsHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Unable to find partition info\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (RootFsHandle, DtbPath); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open dtb file. Reason: %r\r\n", __FUNCTION__, Status); -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ return Status; -+} -+ -+STATIC -+EFI_STATUS -+EFIAPI -+ProcessExtrauEnv ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ IN CONST CHAR16 *BalenaOSRootFs, -+ OUT CHAR16 **CustomFdtName -+) -+{ -+ EFI_STATUS Status; -+ EFI_HANDLE BootPartHandle; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR16 *FileLine = NULL; -+ CHAR16 *DtbName = NULL; -+ BOOLEAN Ascii; -+ CHAR16 *LineCopy = AllocateZeroPool(MAX_DTB_PATH_LEN); -+ UINT64 len; -+ -+ // Set default dtb as fail-safe -+ *CustomFdtName = AllocateZeroPool(MAX_DTB_PATH_LEN); -+ UnicodeSPrint (*CustomFdtName, MAX_DTB_PATH_LEN, L"boot\\%s\0", DEFAULT_ORIN_NX_DVK_DTB_NAME); -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Unable to find boot partition\r\n", __FUNCTION__); -+ return Status; -+ } -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_EXTRA_UENV_FILE); -+ -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path to extra_uEnv.txt\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open file extra_uEnv.txt: %r\r\n", __FUNCTION__, Status); -+ return Status; -+ } -+ -+ while (!FileHandleEof (FileHandle)) { -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ FileLine = FileHandleReturnLine (FileHandle, &Ascii); -+ -+ if (NULL == FileLine) { -+ break; -+ } -+ -+ UnicodeSPrint (LineCopy, MAX_DTB_PATH_LEN, L"%s\0", FileLine); -+ Print(L"Processing entry: %s\n", LineCopy); -+ -+ len = StrLen(LineCopy); -+ -+ if (len < 21 /* dtb name should have at least 1 character + extension */) { -+ ErrorPrint(L"DTB name is too short. Using default dtb.\n"); -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ DtbName = StrStr(LineCopy, L"custom_fdt_file="); -+ -+ if (NULL != DtbName) { -+ DtbName += StrLen(L"custom_fdt_file="); -+ UnicodeSPrint(*CustomFdtName, MAX_DTB_PATH_LEN, L"boot\\%s\0", DtbName); -+ Print(L"Selected dtb name is %s:\n", CustomFdtName); -+ Status = CheckDtbExists(DeviceHandle, BootChain, BalenaOSRootFs, *CustomFdtName); -+ -+ if (EFI_ERROR(Status)) { -+ ErrorPrint(L"Selected dtb not found! Using the default DTB for this device type\n"); -+ UnicodeSPrint(*CustomFdtName, MAX_DTB_PATH_LEN, L"boot\\%s\0", DEFAULT_ORIN_NX_DVK_DTB_NAME); -+ return Status; -+ } -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ } -+ -+ return EFI_SUCCESS; -+} -+ - /** - Process the extlinux.conf file - -@@ -1003,6 +1142,7 @@ EFIAPI - ProcessExtLinuxConfig ( - IN EFI_HANDLE DeviceHandle, - IN UINT32 BootChain, -+ IN CONST CHAR16 *BalenaOSRootFs, - OUT EXTLINUX_BOOT_CONFIG *BootConfig, - OUT EFI_HANDLE *RootFsHandle - ) -@@ -1015,8 +1155,11 @@ ProcessExtLinuxConfig ( - CHAR16 *Timeout = NULL; - CHAR16 *CbootArg = NULL; - CHAR16 *PostCbootArg = NULL; -+ CONST CHAR16 *RootL = L"root=LABEL="; - BOOLEAN Ascii; - UINTN Index; -+ CHAR16 *UpdatedCmdline = NULL; -+ UINTN argsSize; - - ZeroMem (BootConfig, sizeof (EXTLINUX_BOOT_CONFIG)); - -@@ -1024,12 +1167,8 @@ ProcessExtLinuxConfig ( - return EFI_INVALID_PARAMETER; - } - -- Status = FindPartitionInfo (DeviceHandle, ROOTFS_BASE_NAME, BootChain, NULL, RootFsHandle); -- if (EFI_ERROR (Status)) { -- ErrorPrint (L"%a: Unable to find partition info\r\n", __FUNCTION__); -- return Status; -- } -- -+ /* Load extlinux.conf from the selected BalenaOS root filesystem */ -+ Status = FindPartitionInfo (DeviceHandle, BalenaOSRootFs, BootChain, NULL, RootFsHandle); - Status = OpenAndReadFileToBuffer ( - *RootFsHandle, - EXTLINUX_CONF_PATH, -@@ -1101,10 +1240,40 @@ ProcessExtLinuxConfig ( - - Status = CheckCommandString (CleanLine, EXTLINUX_KEY_FDT, &BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); - if (!EFI_ERROR (Status)) { -+ /* extlinux.conf contains a "FDT default" entry */ -+ if (0 == StrnCmp(BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath, EXTLINUX_GENERIC_FDT, StrLen (EXTLINUX_GENERIC_FDT))) { -+ if (NULL != BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath) { -+ FreePool(BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); -+ /* Check if a device-tree name is set in extra_uEnv.txt */ -+ CHAR16 *ExtrauEnvDtb = NULL; -+ Status = ProcessExtrauEnv(DeviceHandle, BootChain, BalenaOSRootFs, &ExtrauEnvDtb); -+ -+ if (!EFI_ERROR(Status)) { -+ Print(L"Using default device-tree\n"); -+ } -+ BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath = ExtrauEnvDtb; -+ Print(L"Kernel device-tree after parsing extra_uEnv.txt is %s\n", BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); -+ } -+ } else { -+ Print(L"Kernel device-tree is %s\n", BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); -+ } - continue; - } - - Status = CheckCommandString (CleanLine, EXTLINUX_KEY_APPEND, &BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); -+ argsSize = StrSize (BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); -+ UpdatedCmdline = AllocateZeroPool (argsSize + StrSize(RootL) + StrSize(BalenaOSRootFs) + 2); -+ if (NULL == UpdatedCmdline) { -+ ErrorPrint (L"%a: Failed to allocate memory for updated cmdline %d\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ /* Append root label to cmdline that has been read from the extlinux.conf read from the active rootfs */ -+ UnicodeSPrint (UpdatedCmdline, StrSize(RootL) + StrSize(BalenaOSRootFs) + argsSize, L"%s %s%s\0", BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs, RootL, BalenaOSRootFs); -+ if (NULL != BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs) { -+ FreePool(BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); -+ } -+ BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs = UpdatedCmdline; - if (!EFI_ERROR (Status)) { - CbootArg = StrStr (BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs, EXTLINUX_CBOOT_ARG); - if (CbootArg != NULL) { -@@ -1315,12 +1484,12 @@ ExtLinuxBoot ( - - // Reload fdt if needed - Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, &AcpiBase); -- if (EFI_ERROR (Status) && (BootOption->DtbPath != NULL)) { -+ if (BootOption->DtbPath != NULL) { - Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &OldFdtBase); - if (EFI_ERROR (Status)) { - OldFdtBase = NULL; - } -- -+ ErrorPrint (L"%a: OpenedAndReadFileToBuffer %s (%r)\r\n", __FUNCTION__, BootOption->DtbPath, Status); - Status = OpenAndReadFileToBuffer ( - DeviceHandle, - BootOption->DtbPath, -@@ -1972,6 +2141,220 @@ Exit: - return Status; - } - -+STATIC -+EFI_STATUS -+EFIAPI -+WriteBootCountFile ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ IN UINT32 BootCountValue -+) -+{ -+ EFI_STATUS Status; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR8 BootCountContent[11]; -+ UINTN BootCountFileSize; -+ EFI_HANDLE BootPartHandle; -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Unable to find partition resin-boot\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_BOOTCOUNT_FILE_PATH); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path bootcount.env\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open file bootcount.env: %r\r\n", __FUNCTION__, Status); -+ return Status; -+ } -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to set file size to 0\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ BootCountFileSize = AsciiSPrint (BootCountContent, 12, "bootcount=%d\0", BootCountValue); -+ Status = FileHandleWrite (FileHandle, &BootCountFileSize, BootCountContent); -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to write bootcount file contents\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+ -+STATIC -+EFI_STATUS -+EFIAPI -+ProcessBootCountValue ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ OUT UINTN *BootCountValue -+) -+{ -+ EFI_STATUS Status; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_HANDLE BootPartHandle; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR16 *FileLine = NULL; -+ CHAR16 *CleanLine; -+ BOOLEAN Ascii; -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Could not find partition resin-boot\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_BOOTCOUNT_FILE_PATH); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path for bootcount.env\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ if (EFI_ERROR (Status)) { -+ *BootCountValue = 1; -+ Status = WriteBootCountFile (DeviceHandle, BootChain, *BootCountValue); -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to write bootcount file contents\r\n", __FUNCTION__); -+ return Status; -+ } else { -+ Print(L"Initialized boot count to 1\r\n"); -+ } -+ } else { -+ while (!FileHandleEof (FileHandle)) { -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ FileLine = FileHandleReturnLine (FileHandle, &Ascii); -+ if (NULL == FileLine) { -+ break; -+ } -+ -+ CleanLine = CleanExtLinuxLine (FileLine); -+ if (*CleanLine != CHAR_NULL) { -+ if (StrStr(CleanLine, L"bootcount=")) { -+ *BootCountValue = StrDecimalToUintn(CleanLine + 10); -+ Print(L"%a: BootCount is %d : %s\r\n", __FUNCTION__, *BootCountValue); -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ } -+ -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ Status = WriteBootCountFile (DeviceHandle, BootChain, ++(*BootCountValue)); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to write bootcount file value %d\r\n", __FUNCTION__, *BootCountValue); -+ } -+ -+ return Status; -+ } -+ } -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+ -+STATIC -+EFI_STATUS -+EFIAPI -+ProcessResinOSuEnv ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ OUT UINTN *RootPart, -+ OUT UINTN *UpgradeAvailable -+) -+{ -+ EFI_STATUS Status; -+ EFI_HANDLE BootPartHandle; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR16 *FileLine = NULL; -+ CHAR16 *CleanLine; -+ BOOLEAN Ascii; -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Could not find partition Balena boot partition\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_BOOT_CONF_PATH); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create path for resinOS_uEnvt.xt\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open resinOS_uEnv.txt: %r\r\n", __FUNCTION__, Status); -+ return Status; -+ } -+ -+ while (!FileHandleEof (FileHandle)) { -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ FileLine = FileHandleReturnLine (FileHandle, &Ascii); -+ if (NULL == FileLine) { -+ break; -+ } -+ -+ CleanLine = CleanExtLinuxLine (FileLine); -+ if (*CleanLine != CHAR_NULL) { -+ if (StrStr(CleanLine, L"resin_root_part=")) { -+ *RootPart = StrHexToUintn(CleanLine + 16); -+ Print(L"RootPart is %d\r\n", *RootPart); -+ } else if (StrStr(CleanLine, L"upgrade_available=")) { -+ *UpgradeAvailable = StrDecimalToUintn(CleanLine + 18); -+ Print(L"UpgradeAvailable is %d\r\n", *UpgradeAvailable); -+ } -+ } -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ return EFI_SUCCESS; -+} -+ - /** - This is the declaration of an EFI image entry point. This entry point is - the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including -@@ -2001,7 +2384,10 @@ L4TLauncher ( - EXTLINUX_BOOT_CONFIG ExtLinuxConfig; - UINTN ExtLinuxBootOption; - UINTN Index; -- -+ CHAR16 *BalenaOSRootFs = NULL; -+ UINTN UpgradeAvailable = 0; -+ UINTN BootCountValue = 0; -+ UINTN RootFsIndex = BALENA_ROOTFS_INDEX_A; - Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage); - if (EFI_ERROR (Status)) { - ErrorPrint (L"%a: Unable to locate loaded image: %r\r\n", __FUNCTION__, Status); -@@ -2014,6 +2400,9 @@ L4TLauncher ( - return Status; - } - -+ ErrorPrint(L"BalenaOS: Set BootMode to NVIDIA_L4T_BOOTMODE_DIRECT\r\r\n"); -+ BootParams.BootMode = NVIDIA_L4T_BOOTMODE_DIRECT; -+ - if (BootParams.BootMode == NVIDIA_L4T_BOOTMODE_GRUB) { - ErrorPrint (L"%a: Attempting GRUB Boot\r\n", __FUNCTION__); - do { -@@ -2057,11 +2446,41 @@ L4TLauncher ( - } - - if (BootParams.BootMode == NVIDIA_L4T_BOOTMODE_DIRECT) { -- ErrorPrint (L"%a: Attempting Direct Boot\r\n", __FUNCTION__); -+ Print (L"%a: Attempt Direct Boot\r\n", __FUNCTION__); - do { -- Status = ProcessExtLinuxConfig (LoadedImage->DeviceHandle, BootParams.BootChain, &ExtLinuxConfig, &RootFsDeviceHandle); -+ Status = ProcessResinOSuEnv (LoadedImage->DeviceHandle, BootParams.BootChain, &RootFsIndex, &UpgradeAvailable); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint(L"resinOS_uEnv.txt does not exist\n"); -+ } -+ -+ Print(L"Current resin_root_part=%d - upgrade_available=%d\r\n", RootFsIndex, UpgradeAvailable); -+ if (1 == UpgradeAvailable) { -+ Status = ProcessBootCountValue (LoadedImage->DeviceHandle, BootParams.BootChain, &BootCountValue); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint(L"%a: Error while processing bootcount value\r\n", __FUNCTION__); -+ } -+ Print (L"%a: BootCountValue is %d\r\n", __FUNCTION__, BootCountValue); -+ } -+ -+ /* If boot limit is reached while upgrade_available=1, switch partitions */ -+ if (BALENA_OS_BC_LIM <= BootCountValue) { -+ if (BALENA_ROOTFS_INDEX_B == RootFsIndex) { -+ RootFsIndex = BALENA_ROOTFS_INDEX_A; -+ } else { -+ RootFsIndex = BALENA_ROOTFS_INDEX_B; -+ } -+ ErrorPrint(L"%a: Reached bootcount limit, will switch partitions... New index is %d\r\n", __FUNCTION__, RootFsIndex); -+ } -+ -+ if (BALENA_ROOTFS_INDEX_B == RootFsIndex) { -+ BalenaOSRootFs = BALENA_ROOTFS_BASE_NAME_B; -+ } else { -+ BalenaOSRootFs = BALENA_ROOTFS_BASE_NAME_A; -+ } -+ -+ Status = ProcessExtLinuxConfig (LoadedImage->DeviceHandle, BootParams.BootChain, BalenaOSRootFs, &ExtLinuxConfig, &RootFsDeviceHandle); - if (EFI_ERROR (Status)) { -- ErrorPrint (L"%a: Unable to process extlinux config: %r\r\n", __FUNCTION__, Status); -+ ErrorPrint (L"%a: ProcessExtLinuxConfig failed on partition %s: %r\r\n", __FUNCTION__, BalenaOSRootFs, Status); - BootParams.BootMode = NVIDIA_L4T_BOOTMODE_BOOTIMG; - break; - } -Index: edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.h -=================================================================== ---- edk2-tegra.orig/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.h -+++ edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.h -@@ -31,11 +31,21 @@ - #define BOOT_OS_VARIABLE_NAME L"BootChainOsCurrent" - - #define ROOTFS_BASE_NAME L"APP" -+#define BALENA_ROOTFS_BASE_NAME_A L"resin-rootA" -+#define BALENA_ROOTFS_BASE_NAME_B L"resin-rootB" -+#define BALENA_BOOT_PARTITION L"resin-boot" -+#define BALENA_BOOT_CONF_PATH L"resinOS_uEnv.txt" -+#define BALENA_BOOTCOUNT_FILE_PATH L"bootcount.env" -+#define MAX_RESINOS_UENV_SIZE 256 -+#define BALENA_ROOTFS_INDEX_A 15 -+#define BALENA_ROOTFS_INDEX_B 16 -+#define BALENA_OS_BC_LIM 3 -+#define BALENA_EXTRA_UENV_FILE L"extra_uEnv.txt" - #define BOOTIMG_BASE_NAME L"kernel" - #define BOOTIMG_DTB_BASE_NAME L"kernel-dtb" - #define RECOVERY_BASE_NAME L"recovery" - #define RECOVERY_DTB_BASE_NAME L"recovery-dtb" -- -+#define DEFAULT_ORIN_NX_DVK_DTB_NAME L"tegra234-p3767-0000-p3509-a02.dtb" - #define EXTLINUX_KEY_TIMEOUT L"TIMEOUT" - #define EXTLINUX_KEY_DEFAULT L"DEFAULT" - #define EXTLINUX_KEY_MENU_TITLE L"MENU TITLE" -@@ -45,9 +55,10 @@ - #define EXTLINUX_KEY_INITRD L"INITRD" - #define EXTLINUX_KEY_FDT L"FDT" - #define EXTLINUX_KEY_APPEND L"APPEND" -- -+#define EXTLINUX_GENERIC_FDT L"default" - #define EXTLINUX_CBOOT_ARG L"${cbootargs}" - -+#define MAX_DTB_PATH_LEN 512 * 2 - #define MAX_EXTLINUX_OPTIONS 10 - - typedef struct { diff --git a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-L4TLauncher-hup-rollback-support-orin-nx.patch b/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-L4TLauncher-hup-rollback-support-orin-nx.patch deleted file mode 100644 index 4a6d9f15..00000000 --- a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra/0005-L4TLauncher-hup-rollback-support-orin-nx.patch +++ /dev/null @@ -1,587 +0,0 @@ - - -L4TLauncher is loaded by the UEFI firmware from -the resin-boot partition. The launcher's name -is BOOTAARCH64.efi. - -With this patch, the Nvidia bootloader parses resinos_uEnv.txt, -extra_uEnv.txt and bootcount.env in order to load the -extlinux.conf and the selected dtb from the current active -rootfs. - -The A/B rootfs switch logic implemented in this change -is the same as the one that exists in balenaOS u-boot and is -compatible with the dtb selection mechanism implemented in the -Supervisor for the rest of the boards that use u-boot. - -Upstream-status: Inappropriate [configuration] -Signed-off-by: Alexandru Costache - -Index: edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.c -=================================================================== ---- edk2-tegra.orig/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.c -+++ edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.c -@@ -986,6 +986,145 @@ CheckCommandString ( - return EFI_NOT_FOUND; - } - -+STATIC -+EFI_STATUS -+EFIAPI -+CheckDtbExists ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ IN CONST CHAR16 *BalenaOSRootFs, -+ IN CONST CHAR16 *DtbPath -+ ) -+{ -+ EFI_STATUS Status; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ EFI_HANDLE RootFsHandle; -+ -+ if (NULL == BalenaOSRootFs || NULL == DtbPath) { -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ Status = FindPartitionInfo (DeviceHandle, BalenaOSRootFs, BootChain, NULL, &RootFsHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Unable to find partition info\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (RootFsHandle, DtbPath); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open dtb file. Reason: %r\r\n", __FUNCTION__, Status); -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ return Status; -+} -+ -+STATIC -+EFI_STATUS -+EFIAPI -+ProcessExtrauEnv ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ IN CONST CHAR16 *BalenaOSRootFs, -+ OUT CHAR16 **CustomFdtName -+) -+{ -+ EFI_STATUS Status; -+ EFI_HANDLE BootPartHandle; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR16 *FileLine = NULL; -+ CHAR16 *DtbName = NULL; -+ BOOLEAN Ascii; -+ CHAR16 *LineCopy = AllocateZeroPool(MAX_DTB_PATH_LEN); -+ UINT64 len; -+ -+ // Set default dtb as fail-safe -+ *CustomFdtName = AllocateZeroPool(MAX_DTB_PATH_LEN); -+ UnicodeSPrint (*CustomFdtName, MAX_DTB_PATH_LEN, L"boot\\%s\0", DEFAULT_ORIN_NX_DVK_DTB_NAME); -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Unable to find boot partition\r\n", __FUNCTION__); -+ return Status; -+ } -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_EXTRA_UENV_FILE); -+ -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path to extra_uEnv.txt\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open file extra_uEnv.txt: %r\r\n", __FUNCTION__, Status); -+ return Status; -+ } -+ -+ while (!FileHandleEof (FileHandle)) { -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ FileLine = FileHandleReturnLine (FileHandle, &Ascii); -+ -+ if (NULL == FileLine) { -+ break; -+ } -+ -+ UnicodeSPrint (LineCopy, MAX_DTB_PATH_LEN, L"%s\0", FileLine); -+ Print(L"Processing entry: %s\n", LineCopy); -+ -+ len = StrLen(LineCopy); -+ -+ if (len < 21 /* dtb name should have at least 1 character + extension */) { -+ ErrorPrint(L"DTB name is too short. Using default dtb.\n"); -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ DtbName = StrStr(LineCopy, L"custom_fdt_file="); -+ -+ if (NULL != DtbName) { -+ DtbName += StrLen(L"custom_fdt_file="); -+ UnicodeSPrint(*CustomFdtName, MAX_DTB_PATH_LEN, L"boot\\%s\0", DtbName); -+ Print(L"Selected dtb name is %s:\n", CustomFdtName); -+ Status = CheckDtbExists(DeviceHandle, BootChain, BalenaOSRootFs, *CustomFdtName); -+ -+ if (EFI_ERROR(Status)) { -+ ErrorPrint(L"Selected dtb not found! Using the default DTB for this device type\n"); -+ UnicodeSPrint(*CustomFdtName, MAX_DTB_PATH_LEN, L"boot\\%s\0", DEFAULT_ORIN_NX_DVK_DTB_NAME); -+ return Status; -+ } -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ } -+ -+ return EFI_SUCCESS; -+} -+ - /** - Process the extlinux.conf file - -@@ -1003,6 +1142,7 @@ EFIAPI - ProcessExtLinuxConfig ( - IN EFI_HANDLE DeviceHandle, - IN UINT32 BootChain, -+ IN CONST CHAR16 *BalenaOSRootFs, - OUT EXTLINUX_BOOT_CONFIG *BootConfig, - OUT EFI_HANDLE *RootFsHandle - ) -@@ -1015,8 +1155,11 @@ ProcessExtLinuxConfig ( - CHAR16 *Timeout = NULL; - CHAR16 *CbootArg = NULL; - CHAR16 *PostCbootArg = NULL; -+ CONST CHAR16 *RootL = L"root=LABEL="; - BOOLEAN Ascii; - UINTN Index; -+ CHAR16 *UpdatedCmdline = NULL; -+ UINTN argsSize; - - ZeroMem (BootConfig, sizeof (EXTLINUX_BOOT_CONFIG)); - -@@ -1024,12 +1167,8 @@ ProcessExtLinuxConfig ( - return EFI_INVALID_PARAMETER; - } - -- Status = FindPartitionInfo (DeviceHandle, ROOTFS_BASE_NAME, BootChain, NULL, RootFsHandle); -- if (EFI_ERROR (Status)) { -- ErrorPrint (L"%a: Unable to find partition info\r\n", __FUNCTION__); -- return Status; -- } -- -+ /* Load extlinux.conf from the selected BalenaOS root filesystem */ -+ Status = FindPartitionInfo (DeviceHandle, BalenaOSRootFs, BootChain, NULL, RootFsHandle); - Status = OpenAndReadFileToBuffer ( - *RootFsHandle, - EXTLINUX_CONF_PATH, -@@ -1101,10 +1240,40 @@ ProcessExtLinuxConfig ( - - Status = CheckCommandString (CleanLine, EXTLINUX_KEY_FDT, &BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); - if (!EFI_ERROR (Status)) { -+ /* extlinux.conf contains a "FDT default" entry */ -+ if (0 == StrnCmp(BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath, EXTLINUX_GENERIC_FDT, StrLen (EXTLINUX_GENERIC_FDT))) { -+ if (NULL != BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath) { -+ FreePool(BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); -+ /* Check if a device-tree name is set in extra_uEnv.txt */ -+ CHAR16 *ExtrauEnvDtb = NULL; -+ Status = ProcessExtrauEnv(DeviceHandle, BootChain, BalenaOSRootFs, &ExtrauEnvDtb); -+ -+ if (!EFI_ERROR(Status)) { -+ Print(L"Using default device-tree\n"); -+ } -+ BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath = ExtrauEnvDtb; -+ Print(L"Kernel device-tree after parsing extra_uEnv.txt is %s\n", BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); -+ } -+ } else { -+ Print(L"Kernel device-tree is %s\n", BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].DtbPath); -+ } - continue; - } - - Status = CheckCommandString (CleanLine, EXTLINUX_KEY_APPEND, &BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); -+ argsSize = StrSize (BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); -+ UpdatedCmdline = AllocateZeroPool (argsSize + StrSize(RootL) + StrSize(BalenaOSRootFs) + 2); -+ if (NULL == UpdatedCmdline) { -+ ErrorPrint (L"%a: Failed to allocate memory for updated cmdline %d\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ /* Append root label to cmdline that has been read from the extlinux.conf read from the active rootfs */ -+ UnicodeSPrint (UpdatedCmdline, StrSize(RootL) + StrSize(BalenaOSRootFs) + argsSize, L"%s %s%s\0", BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs, RootL, BalenaOSRootFs); -+ if (NULL != BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs) { -+ FreePool(BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs); -+ } -+ BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs = UpdatedCmdline; - if (!EFI_ERROR (Status)) { - CbootArg = StrStr (BootConfig->BootOptions[BootConfig->NumberOfBootOptions-1].BootArgs, EXTLINUX_CBOOT_ARG); - if (CbootArg != NULL) { -@@ -1315,12 +1484,12 @@ ExtLinuxBoot ( - - // Reload fdt if needed - Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, &AcpiBase); -- if (EFI_ERROR (Status) && (BootOption->DtbPath != NULL)) { -+ if (BootOption->DtbPath != NULL) { - Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &OldFdtBase); - if (EFI_ERROR (Status)) { - OldFdtBase = NULL; - } -- -+ ErrorPrint (L"%a: OpenedAndReadFileToBuffer %s (%r)\r\n", __FUNCTION__, BootOption->DtbPath, Status); - Status = OpenAndReadFileToBuffer ( - DeviceHandle, - BootOption->DtbPath, -@@ -1972,6 +2141,220 @@ Exit: - return Status; - } - -+STATIC -+EFI_STATUS -+EFIAPI -+WriteBootCountFile ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ IN UINT32 BootCountValue -+) -+{ -+ EFI_STATUS Status; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR8 BootCountContent[11]; -+ UINTN BootCountFileSize; -+ EFI_HANDLE BootPartHandle; -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Unable to find partition resin-boot\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_BOOTCOUNT_FILE_PATH); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path bootcount.env\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open file bootcount.env: %r\r\n", __FUNCTION__, Status); -+ return Status; -+ } -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to set file size to 0\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ BootCountFileSize = AsciiSPrint (BootCountContent, 12, "bootcount=%d\0", BootCountValue); -+ Status = FileHandleWrite (FileHandle, &BootCountFileSize, BootCountContent); -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to write bootcount file contents\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+ -+STATIC -+EFI_STATUS -+EFIAPI -+ProcessBootCountValue ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ OUT UINTN *BootCountValue -+) -+{ -+ EFI_STATUS Status; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_HANDLE BootPartHandle; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR16 *FileLine = NULL; -+ CHAR16 *CleanLine; -+ BOOLEAN Ascii; -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Could not find partition resin-boot\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_BOOTCOUNT_FILE_PATH); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create file device path for bootcount.env\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ if (EFI_ERROR (Status)) { -+ *BootCountValue = 1; -+ Status = WriteBootCountFile (DeviceHandle, BootChain, *BootCountValue); -+ -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to write bootcount file contents\r\n", __FUNCTION__); -+ return Status; -+ } else { -+ Print(L"Initialized boot count to 1\r\n"); -+ } -+ } else { -+ while (!FileHandleEof (FileHandle)) { -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ FileLine = FileHandleReturnLine (FileHandle, &Ascii); -+ if (NULL == FileLine) { -+ break; -+ } -+ -+ CleanLine = CleanExtLinuxLine (FileLine); -+ if (*CleanLine != CHAR_NULL) { -+ if (StrStr(CleanLine, L"bootcount=")) { -+ *BootCountValue = StrDecimalToUintn(CleanLine + 10); -+ Print(L"%a: BootCount is %d : %s\r\n", __FUNCTION__, *BootCountValue); -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ } -+ -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ Status = WriteBootCountFile (DeviceHandle, BootChain, ++(*BootCountValue)); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to write bootcount file value %d\r\n", __FUNCTION__, *BootCountValue); -+ } -+ -+ return Status; -+ } -+ } -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+ -+STATIC -+EFI_STATUS -+EFIAPI -+ProcessResinOSuEnv ( -+ IN EFI_HANDLE DeviceHandle, -+ IN UINT32 BootChain, -+ OUT UINTN *RootPart, -+ OUT UINTN *UpgradeAvailable -+) -+{ -+ EFI_STATUS Status; -+ EFI_HANDLE BootPartHandle; -+ EFI_DEVICE_PATH *FullDevicePath; -+ EFI_DEVICE_PATH *TmpFullDevicePath; -+ EFI_FILE_HANDLE FileHandle = NULL; -+ CHAR16 *FileLine = NULL; -+ CHAR16 *CleanLine; -+ BOOLEAN Ascii; -+ -+ Status = FindPartitionInfo (DeviceHandle, BALENA_BOOT_PARTITION, BootChain, NULL, &BootPartHandle); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Could not find partition Balena boot partition\r\n", __FUNCTION__); -+ return Status; -+ } -+ -+ FullDevicePath = FileDevicePath (BootPartHandle, BALENA_BOOT_CONF_PATH); -+ if (NULL == FullDevicePath) { -+ ErrorPrint (L"%a: Failed to create path for resinOS_uEnvt.xt\r\n", __FUNCTION__); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ TmpFullDevicePath = FullDevicePath; -+ Status = EfiOpenFileByDevicePath (&TmpFullDevicePath, &FileHandle, EFI_FILE_MODE_READ, 0); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint (L"%a: Failed to open resinOS_uEnv.txt: %r\r\n", __FUNCTION__, Status); -+ return Status; -+ } -+ -+ while (!FileHandleEof (FileHandle)) { -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ FileLine = FileHandleReturnLine (FileHandle, &Ascii); -+ if (NULL == FileLine) { -+ break; -+ } -+ -+ CleanLine = CleanExtLinuxLine (FileLine); -+ if (*CleanLine != CHAR_NULL) { -+ if (StrStr(CleanLine, L"resin_root_part=")) { -+ *RootPart = StrDecimalToUintn(CleanLine + 16); -+ Print(L"RootPart is %d\r\n", *RootPart); -+ } else if (StrStr(CleanLine, L"upgrade_available=")) { -+ *UpgradeAvailable = StrDecimalToUintn(CleanLine + 18); -+ Print(L"UpgradeAvailable is %d\r\n", *UpgradeAvailable); -+ } -+ } -+ } -+ -+ if (FileHandle != NULL) { -+ FileHandleClose (FileHandle); -+ } -+ -+ if (FileLine != NULL) { -+ FreePool (FileLine); -+ FileLine = NULL; -+ } -+ -+ return EFI_SUCCESS; -+} -+ - /** - This is the declaration of an EFI image entry point. This entry point is - the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including -@@ -2001,7 +2384,10 @@ L4TLauncher ( - EXTLINUX_BOOT_CONFIG ExtLinuxConfig; - UINTN ExtLinuxBootOption; - UINTN Index; -- -+ CHAR16 *BalenaOSRootFs = NULL; -+ UINTN UpgradeAvailable = 0; -+ UINTN BootCountValue = 0; -+ UINTN RootFsIndex = BALENA_ROOTFS_INDEX_A; - Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage); - if (EFI_ERROR (Status)) { - ErrorPrint (L"%a: Unable to locate loaded image: %r\r\n", __FUNCTION__, Status); -@@ -2014,6 +2400,9 @@ L4TLauncher ( - return Status; - } - -+ ErrorPrint(L"BalenaOS: Set BootMode to NVIDIA_L4T_BOOTMODE_DIRECT\r\r\n"); -+ BootParams.BootMode = NVIDIA_L4T_BOOTMODE_DIRECT; -+ - if (BootParams.BootMode == NVIDIA_L4T_BOOTMODE_GRUB) { - ErrorPrint (L"%a: Attempting GRUB Boot\r\n", __FUNCTION__); - do { -@@ -2057,11 +2446,41 @@ L4TLauncher ( - } - - if (BootParams.BootMode == NVIDIA_L4T_BOOTMODE_DIRECT) { -- ErrorPrint (L"%a: Attempting Direct Boot\r\n", __FUNCTION__); -+ Print (L"%a: Attempt Direct Boot\r\n", __FUNCTION__); - do { -- Status = ProcessExtLinuxConfig (LoadedImage->DeviceHandle, BootParams.BootChain, &ExtLinuxConfig, &RootFsDeviceHandle); -+ Status = ProcessResinOSuEnv (LoadedImage->DeviceHandle, BootParams.BootChain, &RootFsIndex, &UpgradeAvailable); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint(L"resinOS_uEnv.txt does not exist\n"); -+ } -+ -+ Print(L"Current resin_root_part=%d - upgrade_available=%d\r\n", RootFsIndex, UpgradeAvailable); -+ if (1 == UpgradeAvailable) { -+ Status = ProcessBootCountValue (LoadedImage->DeviceHandle, BootParams.BootChain, &BootCountValue); -+ if (EFI_ERROR (Status)) { -+ ErrorPrint(L"%a: Error while processing bootcount value\r\n", __FUNCTION__); -+ } -+ Print (L"%a: BootCountValue is %d\r\n", __FUNCTION__, BootCountValue); -+ } -+ -+ /* If boot limit is reached while upgrade_available=1, switch partitions */ -+ if (BALENA_OS_BC_LIM <= BootCountValue) { -+ if (BALENA_ROOTFS_INDEX_B == RootFsIndex) { -+ RootFsIndex = BALENA_ROOTFS_INDEX_A; -+ } else { -+ RootFsIndex = BALENA_ROOTFS_INDEX_B; -+ } -+ ErrorPrint(L"%a: Reached bootcount limit, will switch partitions... New index is %d\r\n", __FUNCTION__, RootFsIndex); -+ } -+ -+ if (BALENA_ROOTFS_INDEX_B == RootFsIndex) { -+ BalenaOSRootFs = BALENA_ROOTFS_BASE_NAME_B; -+ } else { -+ BalenaOSRootFs = BALENA_ROOTFS_BASE_NAME_A; -+ } -+ -+ Status = ProcessExtLinuxConfig (LoadedImage->DeviceHandle, BootParams.BootChain, BalenaOSRootFs, &ExtLinuxConfig, &RootFsDeviceHandle); - if (EFI_ERROR (Status)) { -- ErrorPrint (L"%a: Unable to process extlinux config: %r\r\n", __FUNCTION__, Status); -+ ErrorPrint (L"%a: ProcessExtLinuxConfig failed on partition %s: %r\r\n", __FUNCTION__, BalenaOSRootFs, Status); - BootParams.BootMode = NVIDIA_L4T_BOOTMODE_BOOTIMG; - break; - } -Index: edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.h -=================================================================== ---- edk2-tegra.orig/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.h -+++ edk2-tegra/edk2-nvidia/Silicon/NVIDIA/Application/L4TLauncher/L4TLauncher.h -@@ -31,11 +31,21 @@ - #define BOOT_OS_VARIABLE_NAME L"BootChainOsCurrent" - - #define ROOTFS_BASE_NAME L"APP" -+#define BALENA_ROOTFS_BASE_NAME_A L"resin-rootA" -+#define BALENA_ROOTFS_BASE_NAME_B L"resin-rootB" -+#define BALENA_BOOT_PARTITION L"resin-boot" -+#define BALENA_BOOT_CONF_PATH L"resinOS_uEnv.txt" -+#define BALENA_BOOTCOUNT_FILE_PATH L"bootcount.env" -+#define MAX_RESINOS_UENV_SIZE 256 -+#define BALENA_ROOTFS_INDEX_A 7 -+#define BALENA_ROOTFS_INDEX_B 8 -+#define BALENA_OS_BC_LIM 3 -+#define BALENA_EXTRA_UENV_FILE L"extra_uEnv.txt" - #define BOOTIMG_BASE_NAME L"kernel" - #define BOOTIMG_DTB_BASE_NAME L"kernel-dtb" - #define RECOVERY_BASE_NAME L"recovery" - #define RECOVERY_DTB_BASE_NAME L"recovery-dtb" -- -+#define DEFAULT_ORIN_NX_DVK_DTB_NAME L"tegra234-p3767-0000-p3509-a02.dtb" - #define EXTLINUX_KEY_TIMEOUT L"TIMEOUT" - #define EXTLINUX_KEY_DEFAULT L"DEFAULT" - #define EXTLINUX_KEY_MENU_TITLE L"MENU TITLE" -@@ -45,9 +55,10 @@ - #define EXTLINUX_KEY_INITRD L"INITRD" - #define EXTLINUX_KEY_FDT L"FDT" - #define EXTLINUX_KEY_APPEND L"APPEND" -- -+#define EXTLINUX_GENERIC_FDT L"default" - #define EXTLINUX_CBOOT_ARG L"${cbootargs}" - -+#define MAX_DTB_PATH_LEN 512 * 2 - #define MAX_EXTLINUX_OPTIONS 10 - - typedef struct { diff --git a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra_35.4.1.bbappend b/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra_35.4.1.bbappend index 68ebda7f..59dd6fd2 100644 --- a/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra_35.4.1.bbappend +++ b/layers/meta-balena-jetson/recipes-bsp/uefi/edk2-firmware-tegra_35.4.1.bbappend @@ -5,28 +5,6 @@ SRC_URI:append = " \ file://0006-boot.patch;patchdir=.. \ " -SRC_URI:append:jetson-agx-orin-devkit = " \ - file://0005-Add-hup-and-rollback-support-agx-orin-32-5-2.patch;patchdir=.. \ -" - -SRC_URI:append:jetson-orin-nx-xavier-nx-devkit = " \ - file://0005-L4TLauncher-hup-rollback-support-orin-nx.patch;patchdir=.. \ - file://set_boot_order.patch;patchdir=.. \ -" - -SRC_URI:append:jetson-orin-nano-devkit-nvme = " \ - file://0005-Add-hup-and-rollback-support-orin-nano-35-3-1.patch;patchdir=.. \ - file://set_boot_order.patch;patchdir=.. \ -" - -SRC_URI:remove:jetson-orin-nx-seeed-j4012 = " \ - file://0005-L4TLauncher-hup-rollback-support-orin-nx.patch;patchdir=.. \ -" - -SRC_URI:append:jetson-orin-nx-seeed-j4012 = " \ - file://0005-L4TLauncher-hup-rollback-support-orin-nx-seed-j4012.patch;patchdir=.. \ -" - do_deploy:append() { mkdir -p ${DEPLOYDIR}/bootfiles/EFI/BOOT/ cp ${WORKDIR}/build/images/BOOTAA64.efi ${DEPLOYDIR}/bootfiles/EFI/BOOT/BOOTAA64.efi