Revision: 14193
          http://edk2.svn.sourceforge.net/edk2/?rev=14193&view=rev
Author:   oliviermartin
Date:     2013-03-12 01:02:44 +0000 (Tue, 12 Mar 2013)
Log Message:
-----------
ArmPkg/BdsLib: Free the memory when Linux fails to start

Not freeing the memory prevents Linux to be started again.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.mar...@arm.com>

Modified Paths:
--------------
    trunk/edk2/ArmPkg/Library/BdsLib/Arm/BdsLinuxLoader.c
    trunk/edk2/ArmPkg/Library/BdsLib/BdsLinuxFdt.c

Modified: trunk/edk2/ArmPkg/Library/BdsLib/Arm/BdsLinuxLoader.c
===================================================================
--- trunk/edk2/ArmPkg/Library/BdsLib/Arm/BdsLinuxLoader.c       2013-03-12 
01:01:55 UTC (rev 14192)
+++ trunk/edk2/ArmPkg/Library/BdsLib/Arm/BdsLinuxLoader.c       2013-03-12 
01:02:44 UTC (rev 14193)
@@ -146,11 +146,13 @@
 {
   EFI_STATUS            Status;
   UINT32                LinuxImageSize;
+  UINT32                InitrdImageBaseSize = 0;
   UINT32                InitrdImageSize = 0;
   UINT32                AtagSize;
   EFI_PHYSICAL_ADDRESS  AtagBase;
   EFI_PHYSICAL_ADDRESS  LinuxImage;
-  EFI_PHYSICAL_ADDRESS  InitrdImage;
+  EFI_PHYSICAL_ADDRESS  InitrdImageBase = 0;
+  EFI_PHYSICAL_ADDRESS  InitrdImage = 0;
 
   PERF_START (NULL, "BDS", NULL, 0);
 
@@ -164,21 +166,24 @@
 
   if (InitrdDevicePath) {
     // Load the initrd near to the Linux kernel
-    InitrdImage = LINUX_KERNEL_MAX_OFFSET;
-    Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, 
&InitrdImageSize);
+    InitrdImageBase = LINUX_KERNEL_MAX_OFFSET;
+    Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, 
&InitrdImageBase, &InitrdImageBaseSize);
     if (Status == EFI_OUT_OF_RESOURCES) {
-      Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, 
&InitrdImageSize);
+      Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, 
&InitrdImageBase, &InitrdImageBaseSize);
     }
     if (EFI_ERROR(Status)) {
       Print (L"ERROR: Did not find initrd image.\n");
-      return Status;
+      goto EXIT_FREE_LINUX;
     }
     
     // Check if the initrd is a uInitrd
-    if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {
+    if (*(UINT32*)((UINTN)InitrdImageBase) == LINUX_UIMAGE_SIGNATURE) {
       // Skip the 64-byte image header
-      InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);
-      InitrdImageSize -= 64;
+      InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImageBase + 64);
+      InitrdImageSize = InitrdImageBaseSize - 64;
+    } else {
+      InitrdImage = InitrdImageBase;
+      InitrdImageSize = InitrdImageBaseSize;
     }
   }
 
@@ -190,10 +195,20 @@
   Status = PrepareAtagList (CommandLineArguments, InitrdImage, 
InitrdImageSize, &AtagBase, &AtagSize);
   if (EFI_ERROR(Status)) {
     Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", Status);
-    return Status;
+    goto EXIT_FREE_INITRD;
   }
 
   return StartLinux (LinuxImage, LinuxImageSize, AtagBase, AtagSize, 
PcdGet32(PcdArmMachineType));
+
+EXIT_FREE_INITRD:
+  if (InitrdDevicePath) {
+    gBS->FreePages (InitrdImageBase, EFI_SIZE_TO_PAGES (InitrdImageBaseSize));
+  }
+
+EXIT_FREE_LINUX:
+  gBS->FreePages (LinuxImage, EFI_SIZE_TO_PAGES (LinuxImageSize));
+
+  return Status;
 }
 
 /**
@@ -218,11 +233,13 @@
 {
   EFI_STATUS            Status;
   UINT32                LinuxImageSize;
+  UINT32                InitrdImageBaseSize = 0;
   UINT32                InitrdImageSize = 0;
   UINT32                FdtBlobSize;
   EFI_PHYSICAL_ADDRESS  FdtBlobBase;
   EFI_PHYSICAL_ADDRESS  LinuxImage;
-  EFI_PHYSICAL_ADDRESS  InitrdImage;
+  EFI_PHYSICAL_ADDRESS  InitrdImageBase = 0;
+  EFI_PHYSICAL_ADDRESS  InitrdImage = 0;
 
   PERF_START (NULL, "BDS", NULL, 0);
 
@@ -235,21 +252,24 @@
   }
 
   if (InitrdDevicePath) {
-    InitrdImage = LINUX_KERNEL_MAX_OFFSET;
-    Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, 
&InitrdImageSize);
+    InitrdImageBase = LINUX_KERNEL_MAX_OFFSET;
+    Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, 
&InitrdImageBase, &InitrdImageBaseSize);
     if (Status == EFI_OUT_OF_RESOURCES) {
-      Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, 
&InitrdImageSize);
+      Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, 
&InitrdImageBase, &InitrdImageBaseSize);
     }
     if (EFI_ERROR(Status)) {
       Print (L"ERROR: Did not find initrd image.\n");
-      return Status;
+      goto EXIT_FREE_LINUX;
     }
 
     // Check if the initrd is a uInitrd
     if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {
       // Skip the 64-byte image header
-      InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);
-      InitrdImageSize -= 64;
+      InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImageBase + 64);
+      InitrdImageSize = InitrdImageBaseSize - 64;
+    } else {
+      InitrdImage = InitrdImageBase;
+      InitrdImageSize = InitrdImageBaseSize;
     }
   }
 
@@ -258,7 +278,7 @@
   Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, 
&FdtBlobSize);
   if (EFI_ERROR(Status)) {
     Print (L"ERROR: Did not find Device Tree blob.\n");
-    return Status;
+    goto EXIT_FREE_INITRD;
   }
 
   // Update the Fdt with the Initrd information. The FDT will increase in size.
@@ -266,9 +286,22 @@
   Status = PrepareFdt (CommandLineArguments, InitrdImage, InitrdImageSize, 
&FdtBlobBase, &FdtBlobSize);
   if (EFI_ERROR(Status)) {
     Print(L"ERROR: Can not load kernel with FDT. Status=%r\n", Status);
-    return Status;
+    goto EXIT_FREE_FDT;
   }
 
   return StartLinux (LinuxImage, LinuxImageSize, FdtBlobBase, FdtBlobSize, 
ARM_FDT_MACHINE_TYPE);
+
+EXIT_FREE_FDT:
+  gBS->FreePages (FdtBlobBase, EFI_SIZE_TO_PAGES (FdtBlobSize));
+
+EXIT_FREE_INITRD:
+  if (InitrdDevicePath) {
+    gBS->FreePages (InitrdImageBase, EFI_SIZE_TO_PAGES (InitrdImageBaseSize));
+  }
+
+EXIT_FREE_LINUX:
+  gBS->FreePages (LinuxImage, EFI_SIZE_TO_PAGES (LinuxImageSize));
+
+  return Status;
 }
 

Modified: trunk/edk2/ArmPkg/Library/BdsLib/BdsLinuxFdt.c
===================================================================
--- trunk/edk2/ArmPkg/Library/BdsLib/BdsLinuxFdt.c      2013-03-12 01:01:55 UTC 
(rev 14192)
+++ trunk/edk2/ArmPkg/Library/BdsLib/BdsLinuxFdt.c      2013-03-12 01:02:44 UTC 
(rev 14193)
@@ -310,7 +310,7 @@
     Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, 
EFI_SIZE_TO_PAGES(NewFdtBlobSize), &NewFdtBlobBase);
     if (EFI_ERROR(Status)) {
       ASSERT_EFI_ERROR(Status);
-      goto FAIL_NEW_FDT;
+      goto FAIL_ALLOCATE_NEW_FDT;
     } else {
       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));
     }
@@ -515,12 +515,18 @@
     //DebugDumpFdt (fdt);
   DEBUG_CODE_END();
 
+  // If we succeeded to generate the new Device Tree then free the old Device 
Tree
+  gBS->FreePages (*FdtBlobBase, EFI_SIZE_TO_PAGES (*FdtBlobSize));
+
   *FdtBlobBase = NewFdtBlobBase;
   *FdtBlobSize = (UINTN)fdt_totalsize ((VOID*)(UINTN)(NewFdtBlobBase));
   return EFI_SUCCESS;
 
 FAIL_NEW_FDT:
-  *FdtBlobSize = OriginalFdtSize;
+  gBS->FreePages (NewFdtBlobBase, EFI_SIZE_TO_PAGES (NewFdtBlobSize));
+
+FAIL_ALLOCATE_NEW_FDT:
+  *FdtBlobSize = (UINTN)fdt_totalsize ((VOID*)(UINTN)(*FdtBlobBase));
   // Return success even if we failed to update the FDT blob. The original one 
is still valid.
   return EFI_SUCCESS;
 }

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester  
Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the  
endpoint security space. For insight on selecting the right partner to 
tackle endpoint security challenges, access the full report. 
http://p.sf.net/sfu/symantec-dev2dev
_______________________________________________
edk2-commits mailing list
edk2-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to