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