]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPkg/BdsLib: Free the memory when Linux fails to start
authoroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 12 Mar 2013 01:02:44 +0000 (01:02 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 12 Mar 2013 01:02:44 +0000 (01:02 +0000)
Not freeing the memory prevents Linux to be started again.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.martin@arm.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14193 6f19259b-4bc3-4df7-8a09-765794883524

ArmPkg/Library/BdsLib/Arm/BdsLinuxLoader.c
ArmPkg/Library/BdsLib/BdsLinuxFdt.c

index e3249e130775d7f0fe4282651e2a14b5b3d514e5..0c4d9f6b08a5dee88d76adce10828da98eeba65e 100644 (file)
@@ -146,11 +146,13 @@ BdsBootLinuxAtag (
 {\r
   EFI_STATUS            Status;\r
   UINT32                LinuxImageSize;\r
+  UINT32                InitrdImageBaseSize = 0;\r
   UINT32                InitrdImageSize = 0;\r
   UINT32                AtagSize;\r
   EFI_PHYSICAL_ADDRESS  AtagBase;\r
   EFI_PHYSICAL_ADDRESS  LinuxImage;\r
-  EFI_PHYSICAL_ADDRESS  InitrdImage;\r
+  EFI_PHYSICAL_ADDRESS  InitrdImageBase = 0;\r
+  EFI_PHYSICAL_ADDRESS  InitrdImage = 0;\r
 \r
   PERF_START (NULL, "BDS", NULL, 0);\r
 \r
@@ -164,21 +166,24 @@ BdsBootLinuxAtag (
 \r
   if (InitrdDevicePath) {\r
     // Load the initrd near to the Linux kernel\r
-    InitrdImage = LINUX_KERNEL_MAX_OFFSET;\r
-    Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, &InitrdImageSize);\r
+    InitrdImageBase = LINUX_KERNEL_MAX_OFFSET;\r
+    Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImageBase, &InitrdImageBaseSize);\r
     if (Status == EFI_OUT_OF_RESOURCES) {\r
-      Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize);\r
+      Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImageBase, &InitrdImageBaseSize);\r
     }\r
     if (EFI_ERROR(Status)) {\r
       Print (L"ERROR: Did not find initrd image.\n");\r
-      return Status;\r
+      goto EXIT_FREE_LINUX;\r
     }\r
     \r
     // Check if the initrd is a uInitrd\r
-    if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {\r
+    if (*(UINT32*)((UINTN)InitrdImageBase) == LINUX_UIMAGE_SIGNATURE) {\r
       // Skip the 64-byte image header\r
-      InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);\r
-      InitrdImageSize -= 64;\r
+      InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImageBase + 64);\r
+      InitrdImageSize = InitrdImageBaseSize - 64;\r
+    } else {\r
+      InitrdImage = InitrdImageBase;\r
+      InitrdImageSize = InitrdImageBaseSize;\r
     }\r
   }\r
 \r
@@ -190,10 +195,20 @@ BdsBootLinuxAtag (
   Status = PrepareAtagList (CommandLineArguments, InitrdImage, InitrdImageSize, &AtagBase, &AtagSize);\r
   if (EFI_ERROR(Status)) {\r
     Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", Status);\r
-    return Status;\r
+    goto EXIT_FREE_INITRD;\r
   }\r
 \r
   return StartLinux (LinuxImage, LinuxImageSize, AtagBase, AtagSize, PcdGet32(PcdArmMachineType));\r
+\r
+EXIT_FREE_INITRD:\r
+  if (InitrdDevicePath) {\r
+    gBS->FreePages (InitrdImageBase, EFI_SIZE_TO_PAGES (InitrdImageBaseSize));\r
+  }\r
+\r
+EXIT_FREE_LINUX:\r
+  gBS->FreePages (LinuxImage, EFI_SIZE_TO_PAGES (LinuxImageSize));\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -218,11 +233,13 @@ BdsBootLinuxFdt (
 {\r
   EFI_STATUS            Status;\r
   UINT32                LinuxImageSize;\r
+  UINT32                InitrdImageBaseSize = 0;\r
   UINT32                InitrdImageSize = 0;\r
   UINT32                FdtBlobSize;\r
   EFI_PHYSICAL_ADDRESS  FdtBlobBase;\r
   EFI_PHYSICAL_ADDRESS  LinuxImage;\r
-  EFI_PHYSICAL_ADDRESS  InitrdImage;\r
+  EFI_PHYSICAL_ADDRESS  InitrdImageBase = 0;\r
+  EFI_PHYSICAL_ADDRESS  InitrdImage = 0;\r
 \r
   PERF_START (NULL, "BDS", NULL, 0);\r
 \r
@@ -235,21 +252,24 @@ BdsBootLinuxFdt (
   }\r
 \r
   if (InitrdDevicePath) {\r
-    InitrdImage = LINUX_KERNEL_MAX_OFFSET;\r
-    Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, &InitrdImageSize);\r
+    InitrdImageBase = LINUX_KERNEL_MAX_OFFSET;\r
+    Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImageBase, &InitrdImageBaseSize);\r
     if (Status == EFI_OUT_OF_RESOURCES) {\r
-      Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize);\r
+      Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImageBase, &InitrdImageBaseSize);\r
     }\r
     if (EFI_ERROR(Status)) {\r
       Print (L"ERROR: Did not find initrd image.\n");\r
-      return Status;\r
+      goto EXIT_FREE_LINUX;\r
     }\r
 \r
     // Check if the initrd is a uInitrd\r
     if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {\r
       // Skip the 64-byte image header\r
-      InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);\r
-      InitrdImageSize -= 64;\r
+      InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImageBase + 64);\r
+      InitrdImageSize = InitrdImageBaseSize - 64;\r
+    } else {\r
+      InitrdImage = InitrdImageBase;\r
+      InitrdImageSize = InitrdImageBaseSize;\r
     }\r
   }\r
 \r
@@ -258,7 +278,7 @@ BdsBootLinuxFdt (
   Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);\r
   if (EFI_ERROR(Status)) {\r
     Print (L"ERROR: Did not find Device Tree blob.\n");\r
-    return Status;\r
+    goto EXIT_FREE_INITRD;\r
   }\r
 \r
   // Update the Fdt with the Initrd information. The FDT will increase in size.\r
@@ -266,9 +286,22 @@ BdsBootLinuxFdt (
   Status = PrepareFdt (CommandLineArguments, InitrdImage, InitrdImageSize, &FdtBlobBase, &FdtBlobSize);\r
   if (EFI_ERROR(Status)) {\r
     Print(L"ERROR: Can not load kernel with FDT. Status=%r\n", Status);\r
-    return Status;\r
+    goto EXIT_FREE_FDT;\r
   }\r
 \r
   return StartLinux (LinuxImage, LinuxImageSize, FdtBlobBase, FdtBlobSize, ARM_FDT_MACHINE_TYPE);\r
+\r
+EXIT_FREE_FDT:\r
+  gBS->FreePages (FdtBlobBase, EFI_SIZE_TO_PAGES (FdtBlobSize));\r
+\r
+EXIT_FREE_INITRD:\r
+  if (InitrdDevicePath) {\r
+    gBS->FreePages (InitrdImageBase, EFI_SIZE_TO_PAGES (InitrdImageBaseSize));\r
+  }\r
+\r
+EXIT_FREE_LINUX:\r
+  gBS->FreePages (LinuxImage, EFI_SIZE_TO_PAGES (LinuxImageSize));\r
+\r
+  return Status;\r
 }\r
 \r
index 1baa23716246cee65dbf73befb0e83aa4711d685..b5dd2371363fa1659e9158a3a17d55716952f2ea 100644 (file)
@@ -310,7 +310,7 @@ PrepareFdt (
     Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(NewFdtBlobSize), &NewFdtBlobBase);\r
     if (EFI_ERROR(Status)) {\r
       ASSERT_EFI_ERROR(Status);\r
-      goto FAIL_NEW_FDT;\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
@@ -515,12 +515,18 @@ PrepareFdt (
     //DebugDumpFdt (fdt);\r
   DEBUG_CODE_END();\r
 \r
+  // 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
   *FdtBlobBase = NewFdtBlobBase;\r
   *FdtBlobSize = (UINTN)fdt_totalsize ((VOID*)(UINTN)(NewFdtBlobBase));\r
   return EFI_SUCCESS;\r
 \r
 FAIL_NEW_FDT:\r
-  *FdtBlobSize = OriginalFdtSize;\r
+  gBS->FreePages (NewFdtBlobBase, EFI_SIZE_TO_PAGES (NewFdtBlobSize));\r
+\r
+FAIL_ALLOCATE_NEW_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 EFI_SUCCESS;\r
 }\r