]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/BdsLib/BdsLinuxFdt.c
ArmPlatformPkg: Add the LinuxLoader.efi EFI application
[mirror_edk2.git] / ArmPkg / Library / BdsLib / BdsLinuxFdt.c
index b6d08944abd08b3b03802ad97a0fbaf4ca3b9f42..e3795527f2d3d0a738d10095f4a30cd59b6a8c4e 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 *\r
-*  Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
+*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
 *\r
 *  This program and the accompanying materials\r
 *  are licensed and made available under the terms and conditions of the BSD License\r
@@ -16,8 +16,6 @@
 #include <Library/PcdLib.h>\r
 #include <libfdt.h>\r
 \r
-#include <IndustryStandard/ArmSmc.h>\r
-\r
 #include "BdsInternal.h"\r
 #include "BdsLinuxLoader.h"\r
 \r
 #define PALIGN(p, a)    ((void *)(ALIGN((unsigned long)(p), (a))))\r
 #define GET_CELL(p)     (p += 4, *((const UINT32 *)(p-4)))\r
 \r
+STATIC\r
+UINTN\r
+cpu_to_fdtn (UINTN x) {\r
+  if (sizeof (UINTN) == sizeof (UINT32)) {\r
+    return cpu_to_fdt32 (x);\r
+  } else {\r
+    return cpu_to_fdt64 (x);\r
+  }\r
+}\r
+\r
+typedef struct {\r
+  UINTN   Base;\r
+  UINTN   Size;\r
+} FdtRegion;\r
+\r
+\r
 STATIC\r
 UINTN\r
 IsPrintableString (\r
@@ -191,17 +205,86 @@ IsLinuxReservedRegion (
   case EfiUnusableMemory:\r
   case EfiACPIReclaimMemory:\r
   case EfiACPIMemoryNVS:\r
+  case EfiReservedMemoryType:\r
     return TRUE;\r
   default:\r
     return FALSE;\r
   }\r
 }\r
 \r
+/**\r
+** Relocate the FDT blob to a more appropriate location for the Linux kernel.\r
+** This function will allocate memory for the relocated FDT blob.\r
+**\r
+** @retval EFI_SUCCESS on success.\r
+** @retval EFI_OUT_OF_RESOURCES or EFI_INVALID_PARAMETER on failure.\r
+*/\r
+STATIC\r
+EFI_STATUS\r
+RelocateFdt (\r
+  EFI_PHYSICAL_ADDRESS   OriginalFdt,\r
+  UINTN                  OriginalFdtSize,\r
+  EFI_PHYSICAL_ADDRESS   *RelocatedFdt,\r
+  UINTN                  *RelocatedFdtSize,\r
+  EFI_PHYSICAL_ADDRESS   *RelocatedFdtAlloc\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  INTN                  Error;\r
+  UINT64                FdtAlignment;\r
+\r
+  *RelocatedFdtSize = OriginalFdtSize + FDT_ADDITIONAL_ENTRIES_SIZE;\r
+\r
+  // If FDT load address needs to be aligned, allocate more space.\r
+  FdtAlignment = PcdGet32 (PcdArmLinuxFdtAlignment);\r
+  if (FdtAlignment != 0) {\r
+    *RelocatedFdtSize += FdtAlignment;\r
+  }\r
+\r
+  // Try below a watermark address.\r
+  Status = EFI_NOT_FOUND;\r
+  if (PcdGet32 (PcdArmLinuxFdtMaxOffset) != 0) {\r
+    *RelocatedFdt = LINUX_FDT_MAX_OFFSET;\r
+    Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData,\r
+                    EFI_SIZE_TO_PAGES (*RelocatedFdtSize), RelocatedFdt);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_WARN, "Warning: Failed to load FDT below address 0x%lX (%r). Will try again at a random address anywhere.\n", *RelocatedFdt, Status));\r
+    }\r
+  }\r
+\r
+  // Try anywhere there is available space.\r
+  if (EFI_ERROR (Status)) {\r
+    Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData,\r
+                    EFI_SIZE_TO_PAGES (*RelocatedFdtSize), RelocatedFdt);\r
+    if (EFI_ERROR (Status)) {\r
+      ASSERT_EFI_ERROR (Status);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    } else {\r
+      DEBUG ((EFI_D_WARN, "WARNING: Loaded FDT at random address 0x%lX.\nWARNING: There is a risk of accidental overwriting by other code/data.\n", *RelocatedFdt));\r
+    }\r
+  }\r
+\r
+  *RelocatedFdtAlloc = *RelocatedFdt;\r
+  if (FdtAlignment != 0) {\r
+    *RelocatedFdt = ALIGN (*RelocatedFdt, FdtAlignment);\r
+  }\r
+\r
+  // Load the Original FDT tree into the new region\r
+  Error = fdt_open_into ((VOID*)(UINTN) OriginalFdt,\r
+            (VOID*)(UINTN)(*RelocatedFdt), *RelocatedFdtSize);\r
+  if (Error) {\r
+    DEBUG ((EFI_D_ERROR, "fdt_open_into(): %a\n", fdt_strerror (Error)));\r
+    gBS->FreePages (*RelocatedFdtAlloc, EFI_SIZE_TO_PAGES (*RelocatedFdtSize));\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  DEBUG_CODE_BEGIN();\r
+    //DebugDumpFdt (fdt);\r
+  DEBUG_CODE_END();\r
+\r
+  return EFI_SUCCESS;\r
+}\r
 \r
-typedef struct {\r
-  UINTN   Base;\r
-  UINTN   Size;\r
-} FdtRegion;\r
 \r
 EFI_STATUS\r
 PrepareFdt (\r
@@ -214,12 +297,13 @@ PrepareFdt (
 {\r
   EFI_STATUS            Status;\r
   EFI_PHYSICAL_ADDRESS  NewFdtBlobBase;\r
+  EFI_PHYSICAL_ADDRESS  NewFdtBlobAllocation;\r
   UINTN                 NewFdtBlobSize;\r
   VOID*                 fdt;\r
   INTN                  err;\r
   INTN                  node;\r
   INTN                  cpu_node;\r
-  INT                 lenp;\r
+  INT32                 lenp;\r
   CONST VOID*           BootArg;\r
   CONST VOID*           Method;\r
   EFI_PHYSICAL_ADDRESS  InitrdImageStart;\r
@@ -237,40 +321,16 @@ PrepareFdt (
   UINT64                CpuReleaseAddr;\r
   UINTN                 MemoryMapSize;\r
   EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
+  EFI_MEMORY_DESCRIPTOR *MemoryMapPtr;\r
   UINTN                 MapKey;\r
   UINTN                 DescriptorSize;\r
   UINT32                DescriptorVersion;\r
   UINTN                 Pages;\r
-  BOOLEAN               PsciSmcSupported;\r
-  UINTN                 Rx;\r
   UINTN                 OriginalFdtSize;\r
   BOOLEAN               CpusNodeExist;\r
+  UINTN                 CoreMpId;\r
 \r
-  //\r
-  // Ensure the Power State Coordination Interface (PSCI) SMCs are there if supported\r
-  //\r
-  PsciSmcSupported = FALSE;\r
-  if (FeaturePcdGet (PcdArmPsciSupport) == TRUE) {\r
-    // Check the SMC response to the Presence SMC\r
-    Rx   = ARM_SMC_ID_PRESENCE;\r
-    ArmCallSmc (&Rx);\r
-    if (Rx == 1) {\r
-      // Check the SMC UID\r
-      Rx   = ARM_SMC_ID_UID;\r
-      ArmCallSmc (&Rx);\r
-      if (Rx == ARM_TRUSTZONE_UID_4LETTERID) {\r
-        Rx   = ARM_SMC_ID_UID + 1;\r
-        ArmCallSmc (&Rx);\r
-        if (Rx == ARM_TRUSTZONE_ARM_UID) {\r
-          PsciSmcSupported = TRUE;\r
-        }\r
-      }\r
-      if (PsciSmcSupported == FALSE) {\r
-        DEBUG((EFI_D_ERROR,"Warning: The Power State Coordination Interface (PSCI) is not supported"\r
-                           "by your platform Trusted Firmware.\n"));\r
-      }\r
-    }\r
-  }\r
+  NewFdtBlobAllocation = 0;\r
 \r
   //\r
   // Sanity checks on the original FDT blob.\r
@@ -291,52 +351,24 @@ PrepareFdt (
   }\r
 \r
   //\r
-  // Allocate memory for the new FDT\r
+  // Relocate the FDT to its final location.\r
   //\r
-  NewFdtBlobSize = OriginalFdtSize + FDT_ADDITIONAL_ENTRIES_SIZE;\r
-\r
-  // Try below a watermark address\r
-  Status = EFI_NOT_FOUND;\r
-  if (PcdGet32(PcdArmLinuxFdtMaxOffset) != 0) {\r
-    NewFdtBlobBase = LINUX_FDT_MAX_OFFSET;\r
-    Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, EFI_SIZE_TO_PAGES(NewFdtBlobSize), &NewFdtBlobBase);\r
-    if (EFI_ERROR(Status)) {\r
-      DEBUG ((EFI_D_WARN, "Warning: Failed to load FDT below address 0x%lX (%r). Will try again at a random address anywhere.\n", NewFdtBlobBase, Status));\r
-    }\r
-  }\r
-\r
-  // Try anywhere there is available space\r
-  if (EFI_ERROR(Status)) {\r
-    Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(NewFdtBlobSize), &NewFdtBlobBase);\r
-    if (EFI_ERROR(Status)) {\r
-      ASSERT_EFI_ERROR(Status);\r
-      goto FAIL_ALLOCATE_NEW_FDT;\r
-    } else {\r
-      DEBUG ((EFI_D_WARN, "WARNING: Loaded FDT at random address 0x%lX.\nWARNING: There is a risk of accidental overwriting by other code/data.\n", NewFdtBlobBase));\r
-    }\r
+  Status = RelocateFdt (*FdtBlobBase, OriginalFdtSize,\r
+             &NewFdtBlobBase, &NewFdtBlobSize, &NewFdtBlobAllocation);\r
+  if (EFI_ERROR (Status)) {\r
+    goto FAIL_RELOCATE_FDT;\r
   }\r
 \r
-  // Load the Original FDT tree into the new region\r
   fdt = (VOID*)(UINTN)NewFdtBlobBase;\r
-  err = fdt_open_into((VOID*)(UINTN)(*FdtBlobBase), fdt, NewFdtBlobSize);\r
-  if (err) {\r
-    DEBUG((EFI_D_ERROR, "fdt_open_into(): %a\n", fdt_strerror(err)));\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto FAIL_NEW_FDT;\r
-  }\r
 \r
-  DEBUG_CODE_BEGIN();\r
-    //DebugDumpFdt (fdt);\r
-  DEBUG_CODE_END();\r
-\r
-  node = fdt_subnode_offset(fdt, 0, "chosen");\r
+  node = fdt_subnode_offset (fdt, 0, "chosen");\r
   if (node < 0) {\r
     // The 'chosen' node does not exist, create it\r
     node = fdt_add_subnode(fdt, 0, "chosen");\r
     if (node < 0) {\r
       DEBUG((EFI_D_ERROR,"Error on finding 'chosen' node\n"));\r
       Status = EFI_INVALID_PARAMETER;\r
-      goto FAIL_NEW_FDT;\r
+      goto FAIL_COMPLETE_FDT;\r
     }\r
   }\r
 \r
@@ -387,13 +419,8 @@ PrepareFdt (
       GetSystemMemoryResources (&ResourceList);\r
       Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)ResourceList.ForwardLink;\r
 \r
-      if (sizeof(UINTN) == sizeof(UINT32)) {\r
-        Region.Base = cpu_to_fdt32((UINTN)Resource->PhysicalStart);\r
-        Region.Size = cpu_to_fdt32((UINTN)Resource->ResourceLength);\r
-      } else {\r
-        Region.Base = cpu_to_fdt64((UINTN)Resource->PhysicalStart);\r
-        Region.Size = cpu_to_fdt64((UINTN)Resource->ResourceLength);\r
-      }\r
+      Region.Base = cpu_to_fdtn ((UINTN)Resource->PhysicalStart);\r
+      Region.Size = cpu_to_fdtn ((UINTN)Resource->ResourceLength);\r
 \r
       err = fdt_setprop(fdt, node, "reg", &Region, sizeof(Region));\r
       if (err) {\r
@@ -411,29 +438,41 @@ PrepareFdt (
   MemoryMapSize = 0;\r
   Status = gBS->GetMemoryMap (&MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion);\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    // The UEFI specification advises to allocate more memory for the MemoryMap buffer between successive\r
+    // calls to GetMemoryMap(), since allocation of the new buffer may potentially increase memory map size.\r
     Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;\r
     MemoryMap = AllocatePages (Pages);\r
+    if (MemoryMap == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto FAIL_COMPLETE_FDT;\r
+    }\r
     Status = gBS->GetMemoryMap (&MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion);\r
   }\r
 \r
   // Go through the list and add the reserved region to the Device Tree\r
   if (!EFI_ERROR(Status)) {\r
-    for (Index = 0; Index < (MemoryMapSize / sizeof(EFI_MEMORY_DESCRIPTOR)); Index++) {\r
-      if (IsLinuxReservedRegion ((EFI_MEMORY_TYPE)MemoryMap[Index].Type)) {\r
-        DEBUG((DEBUG_VERBOSE, "Reserved region of type %d [0x%X, 0x%X]\n",\r
-            MemoryMap[Index].Type,\r
-            (UINTN)MemoryMap[Index].PhysicalStart,\r
-            (UINTN)(MemoryMap[Index].PhysicalStart + MemoryMap[Index].NumberOfPages * EFI_PAGE_SIZE)));\r
-        err = fdt_add_mem_rsv(fdt, MemoryMap[Index].PhysicalStart, MemoryMap[Index].NumberOfPages * EFI_PAGE_SIZE);\r
+    MemoryMapPtr = MemoryMap;\r
+    for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) {\r
+      if (IsLinuxReservedRegion ((EFI_MEMORY_TYPE)MemoryMapPtr->Type)) {\r
+        DEBUG((DEBUG_VERBOSE, "Reserved region of type %d [0x%lX, 0x%lX]\n",\r
+            MemoryMapPtr->Type,\r
+            (UINTN)MemoryMapPtr->PhysicalStart,\r
+            (UINTN)(MemoryMapPtr->PhysicalStart + MemoryMapPtr->NumberOfPages * EFI_PAGE_SIZE)));\r
+        err = fdt_add_mem_rsv(fdt, MemoryMapPtr->PhysicalStart, MemoryMapPtr->NumberOfPages * EFI_PAGE_SIZE);\r
         if (err != 0) {\r
           Print(L"Warning: Fail to add 'memreserve' (err:%d)\n", err);\r
         }\r
       }\r
+      MemoryMapPtr = (EFI_MEMORY_DESCRIPTOR*)((UINTN)MemoryMapPtr + DescriptorSize);\r
     }\r
   }\r
 \r
   //\r
-  // Setup Arm Mpcore Info if it is a multi-core or multi-cluster platforms\r
+  // Setup Arm Mpcore Info if it is a multi-core or multi-cluster platforms.\r
+  //\r
+  // For 'cpus' and 'cpu' device tree nodes bindings, refer to this file\r
+  // in the kernel documentation:\r
+  // Documentation/devicetree/bindings/arm/cpus.txt\r
   //\r
   for (Index=0; Index < gST->NumberOfTableEntries; Index++) {\r
     // Check for correct GUID type\r
@@ -447,7 +486,7 @@ PrepareFdt (
         // Create the /cpus node\r
         node = fdt_add_subnode(fdt, 0, "cpus");\r
         fdt_setprop_string(fdt, node, "name", "cpus");\r
-        fdt_setprop_cell(fdt, node, "#address-cells", 1);\r
+        fdt_setprop_cell (fdt, node, "#address-cells", sizeof (UINTN) / 4);\r
         fdt_setprop_cell(fdt, node, "#size-cells", 0);\r
         CpusNodeExist = FALSE;\r
       } else {\r
@@ -459,36 +498,48 @@ PrepareFdt (
       ArmCoreInfoTable = ArmProcessorTable->ArmCpus;\r
 \r
       for (Index = 0; Index < ArmProcessorTable->NumberOfEntries; Index++) {\r
-        AsciiSPrint (Name, 10, "cpu@%d", Index);\r
+        CoreMpId = (UINTN) GET_MPID (ArmCoreInfoTable[Index].ClusterId,\r
+                             ArmCoreInfoTable[Index].CoreId);\r
+        AsciiSPrint (Name, 10, "cpu@%x", CoreMpId);\r
 \r
-        // If the 'cpus' node did not exist then creates the 'cpu' nodes. In case 'cpus' node\r
-        // is provided in the original FDT then we do not add any 'cpu' node.\r
+        // If the 'cpus' node did not exist then create all the 'cpu' nodes.\r
+        // In case 'cpus' node is provided in the original FDT then we do not add\r
+        // any 'cpu' node.\r
         if (!CpusNodeExist) {\r
-          cpu_node = fdt_add_subnode(fdt, node, Name);\r
-          fdt_setprop_string(fdt, cpu_node, "device-type", "cpu");\r
-          fdt_setprop(fdt, cpu_node, "reg", &Index, sizeof(Index));\r
+          cpu_node = fdt_add_subnode (fdt, node, Name);\r
+          if (cpu_node < 0) {\r
+            DEBUG ((EFI_D_ERROR, "Error on creating '%s' node\n", Name));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto FAIL_COMPLETE_FDT;\r
+          }\r
+\r
+          fdt_setprop_string (fdt, cpu_node, "device_type", "cpu");\r
+\r
+          CoreMpId = cpu_to_fdtn (CoreMpId);\r
+          fdt_setprop (fdt, cpu_node, "reg", &CoreMpId, sizeof (CoreMpId));\r
         } else {\r
           cpu_node = fdt_subnode_offset(fdt, node, Name);\r
         }\r
 \r
-        // If Power State Coordination Interface (PSCI) is not supported then it is expected the secondary\r
-        // cores are spinning waiting for the Operating System to release them\r
-        if ((PsciSmcSupported == FALSE) && (cpu_node >= 0)) {\r
-          // We as the bootloader are responsible for either creating or updating\r
-          // these entries. Do not trust the entries in the DT. We only know about\r
-          // 'spin-table' type. Do not try to update other types if defined.\r
-          Method = fdt_getprop(fdt, cpu_node, "enable-method", &lenp);\r
-          if ( (Method == NULL) || (!AsciiStrCmp((CHAR8 *)Method, "spin-table")) ) {\r
-            fdt_setprop_string(fdt, cpu_node, "enable-method", "spin-table");\r
-            CpuReleaseAddr = cpu_to_fdt64(ArmCoreInfoTable[Index].MailboxSetAddress);\r
-            fdt_setprop(fdt, cpu_node, "cpu-release-addr", &CpuReleaseAddr, sizeof(CpuReleaseAddr));\r
-\r
-            // If it is not the primary core than the cpu should be disabled\r
-            if (((ArmCoreInfoTable[Index].ClusterId != ClusterId) || (ArmCoreInfoTable[Index].CoreId != CoreId))) {\r
-              fdt_setprop_string(fdt, cpu_node, "status", "disabled");\r
+        if (cpu_node >= 0) {\r
+          Method = fdt_getprop (fdt, cpu_node, "enable-method", &lenp);\r
+          // We only care when 'enable-method' == 'spin-table'. If the enable-method is not defined\r
+          // or defined as 'psci' then we ignore its properties.\r
+          if ((Method != NULL) && (AsciiStrCmp ((CHAR8 *)Method, "spin-table") == 0)) {\r
+            // There are two cases;\r
+            //  - UEFI firmware parked the secondary cores and/or UEFI firmware is aware of the CPU\r
+            //    release addresses (PcdArmLinuxSpinTable == TRUE)\r
+            //  - the parking of the secondary cores has been managed before starting UEFI and/or UEFI\r
+            //    does not anything about the CPU release addresses - in this case we do nothing\r
+            if (FeaturePcdGet (PcdArmLinuxSpinTable)) {\r
+              CpuReleaseAddr = cpu_to_fdt64 (ArmCoreInfoTable[Index].MailboxSetAddress);\r
+              fdt_setprop (fdt, cpu_node, "cpu-release-addr", &CpuReleaseAddr, sizeof(CpuReleaseAddr));\r
+\r
+              // If it is not the primary core than the cpu should be disabled\r
+              if (((ArmCoreInfoTable[Index].ClusterId != ClusterId) || (ArmCoreInfoTable[Index].CoreId != CoreId))) {\r
+                fdt_setprop_string(fdt, cpu_node, "status", "disabled");\r
+              }\r
             }\r
-          } else {\r
-            Print(L"Warning: Unsupported enable-method type for CPU[%d] : %a\n", Index, (CHAR8 *)Method);\r
           }\r
         }\r
       }\r
@@ -496,28 +547,6 @@ PrepareFdt (
     }\r
   }\r
 \r
-  // If the Power State Coordination Interface is supported then we signal it in the Device Tree\r
-  if (PsciSmcSupported == TRUE) {\r
-    // Before to create it we check if the node is not already defined in the Device Tree\r
-    node = fdt_subnode_offset(fdt, 0, "psci");\r
-    if (node < 0) {\r
-      // The 'psci' node does not exist, create it\r
-      node = fdt_add_subnode(fdt, 0, "psci");\r
-      if (node < 0) {\r
-        DEBUG((EFI_D_ERROR,"Error on creating 'psci' node\n"));\r
-        Status = EFI_INVALID_PARAMETER;\r
-        goto FAIL_NEW_FDT;\r
-      } else {\r
-        fdt_setprop_string(fdt, node, "compatible", "arm,psci");\r
-        fdt_setprop_string(fdt, node, "method", "smc");\r
-        fdt_setprop_cell(fdt, node, "cpu_suspend", ARM_SMC_ARM_CPU_SUSPEND);\r
-        fdt_setprop_cell(fdt, node, "cpu_off", ARM_SMC_ARM_CPU_OFF);\r
-        fdt_setprop_cell(fdt, node, "cpu_on", ARM_SMC_ARM_CPU_ON);\r
-        fdt_setprop_cell(fdt, node, "cpu_migrate", ARM_SMC_ARM_MIGRATE);\r
-      }\r
-    }\r
-  }\r
-\r
   DEBUG_CODE_BEGIN();\r
     //DebugDumpFdt (fdt);\r
   DEBUG_CODE_END();\r
@@ -525,17 +554,19 @@ PrepareFdt (
   // If we succeeded to generate the new Device Tree then free the old Device Tree\r
   gBS->FreePages (*FdtBlobBase, EFI_SIZE_TO_PAGES (*FdtBlobSize));\r
 \r
+  // Update the real size of the Device Tree\r
+  fdt_pack ((VOID*)(UINTN)(NewFdtBlobBase));\r
+\r
   *FdtBlobBase = NewFdtBlobBase;\r
   *FdtBlobSize = (UINTN)fdt_totalsize ((VOID*)(UINTN)(NewFdtBlobBase));\r
   return EFI_SUCCESS;\r
 \r
-FAIL_NEW_FDT:\r
-  gBS->FreePages (NewFdtBlobBase, EFI_SIZE_TO_PAGES (NewFdtBlobSize));\r
+FAIL_COMPLETE_FDT:\r
+  gBS->FreePages (NewFdtBlobAllocation, EFI_SIZE_TO_PAGES (NewFdtBlobSize));\r
 \r
-FAIL_ALLOCATE_NEW_FDT:\r
+FAIL_RELOCATE_FDT:\r
   *FdtBlobSize = (UINTN)fdt_totalsize ((VOID*)(UINTN)(*FdtBlobBase));\r
-  // Return success even if we failed to update the FDT blob. The original one is still valid.\r
+  // Return success even if we failed to update the FDT blob.\r
+  // The original one is still valid.\r
   return EFI_SUCCESS;\r
 }\r
-\r
-\r