mirror of https://github.com/acidanthera/audk.git
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.martin@arm.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14193 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
7e91decd13
commit
a90e327921
|
@ -146,11 +146,13 @@ BdsBootLinuxAtag (
|
|||
{
|
||||
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 @@ BdsBootLinuxAtag (
|
|||
|
||||
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 @@ BdsBootLinuxAtag (
|
|||
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 @@ BdsBootLinuxFdt (
|
|||
{
|
||||
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 @@ BdsBootLinuxFdt (
|
|||
}
|
||||
|
||||
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 @@ BdsBootLinuxFdt (
|
|||
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 @@ BdsBootLinuxFdt (
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -310,7 +310,7 @@ PrepareFdt (
|
|||
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 @@ PrepareFdt (
|
|||
//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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue