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;
|
EFI_STATUS Status;
|
||||||
UINT32 LinuxImageSize;
|
UINT32 LinuxImageSize;
|
||||||
|
UINT32 InitrdImageBaseSize = 0;
|
||||||
UINT32 InitrdImageSize = 0;
|
UINT32 InitrdImageSize = 0;
|
||||||
UINT32 AtagSize;
|
UINT32 AtagSize;
|
||||||
EFI_PHYSICAL_ADDRESS AtagBase;
|
EFI_PHYSICAL_ADDRESS AtagBase;
|
||||||
EFI_PHYSICAL_ADDRESS LinuxImage;
|
EFI_PHYSICAL_ADDRESS LinuxImage;
|
||||||
EFI_PHYSICAL_ADDRESS InitrdImage;
|
EFI_PHYSICAL_ADDRESS InitrdImageBase = 0;
|
||||||
|
EFI_PHYSICAL_ADDRESS InitrdImage = 0;
|
||||||
|
|
||||||
PERF_START (NULL, "BDS", NULL, 0);
|
PERF_START (NULL, "BDS", NULL, 0);
|
||||||
|
|
||||||
|
@ -164,21 +166,24 @@ BdsBootLinuxAtag (
|
||||||
|
|
||||||
if (InitrdDevicePath) {
|
if (InitrdDevicePath) {
|
||||||
// Load the initrd near to the Linux kernel
|
// Load the initrd near to the Linux kernel
|
||||||
InitrdImage = LINUX_KERNEL_MAX_OFFSET;
|
InitrdImageBase = LINUX_KERNEL_MAX_OFFSET;
|
||||||
Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, &InitrdImageSize);
|
Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImageBase, &InitrdImageBaseSize);
|
||||||
if (Status == EFI_OUT_OF_RESOURCES) {
|
if (Status == EFI_OUT_OF_RESOURCES) {
|
||||||
Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize);
|
Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImageBase, &InitrdImageBaseSize);
|
||||||
}
|
}
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
Print (L"ERROR: Did not find initrd image.\n");
|
Print (L"ERROR: Did not find initrd image.\n");
|
||||||
return Status;
|
goto EXIT_FREE_LINUX;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the initrd is a uInitrd
|
// 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
|
// Skip the 64-byte image header
|
||||||
InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);
|
InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImageBase + 64);
|
||||||
InitrdImageSize -= 64;
|
InitrdImageSize = InitrdImageBaseSize - 64;
|
||||||
|
} else {
|
||||||
|
InitrdImage = InitrdImageBase;
|
||||||
|
InitrdImageSize = InitrdImageBaseSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,10 +195,20 @@ BdsBootLinuxAtag (
|
||||||
Status = PrepareAtagList (CommandLineArguments, InitrdImage, InitrdImageSize, &AtagBase, &AtagSize);
|
Status = PrepareAtagList (CommandLineArguments, InitrdImage, InitrdImageSize, &AtagBase, &AtagSize);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", 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));
|
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;
|
EFI_STATUS Status;
|
||||||
UINT32 LinuxImageSize;
|
UINT32 LinuxImageSize;
|
||||||
|
UINT32 InitrdImageBaseSize = 0;
|
||||||
UINT32 InitrdImageSize = 0;
|
UINT32 InitrdImageSize = 0;
|
||||||
UINT32 FdtBlobSize;
|
UINT32 FdtBlobSize;
|
||||||
EFI_PHYSICAL_ADDRESS FdtBlobBase;
|
EFI_PHYSICAL_ADDRESS FdtBlobBase;
|
||||||
EFI_PHYSICAL_ADDRESS LinuxImage;
|
EFI_PHYSICAL_ADDRESS LinuxImage;
|
||||||
EFI_PHYSICAL_ADDRESS InitrdImage;
|
EFI_PHYSICAL_ADDRESS InitrdImageBase = 0;
|
||||||
|
EFI_PHYSICAL_ADDRESS InitrdImage = 0;
|
||||||
|
|
||||||
PERF_START (NULL, "BDS", NULL, 0);
|
PERF_START (NULL, "BDS", NULL, 0);
|
||||||
|
|
||||||
|
@ -235,21 +252,24 @@ BdsBootLinuxFdt (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InitrdDevicePath) {
|
if (InitrdDevicePath) {
|
||||||
InitrdImage = LINUX_KERNEL_MAX_OFFSET;
|
InitrdImageBase = LINUX_KERNEL_MAX_OFFSET;
|
||||||
Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, &InitrdImageSize);
|
Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImageBase, &InitrdImageBaseSize);
|
||||||
if (Status == EFI_OUT_OF_RESOURCES) {
|
if (Status == EFI_OUT_OF_RESOURCES) {
|
||||||
Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize);
|
Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImageBase, &InitrdImageBaseSize);
|
||||||
}
|
}
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
Print (L"ERROR: Did not find initrd image.\n");
|
Print (L"ERROR: Did not find initrd image.\n");
|
||||||
return Status;
|
goto EXIT_FREE_LINUX;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the initrd is a uInitrd
|
// Check if the initrd is a uInitrd
|
||||||
if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {
|
if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {
|
||||||
// Skip the 64-byte image header
|
// Skip the 64-byte image header
|
||||||
InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);
|
InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImageBase + 64);
|
||||||
InitrdImageSize -= 64;
|
InitrdImageSize = InitrdImageBaseSize - 64;
|
||||||
|
} else {
|
||||||
|
InitrdImage = InitrdImageBase;
|
||||||
|
InitrdImageSize = InitrdImageBaseSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +278,7 @@ BdsBootLinuxFdt (
|
||||||
Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);
|
Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
Print (L"ERROR: Did not find Device Tree blob.\n");
|
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.
|
// 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);
|
Status = PrepareFdt (CommandLineArguments, InitrdImage, InitrdImageSize, &FdtBlobBase, &FdtBlobSize);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
Print(L"ERROR: Can not load kernel with FDT. Status=%r\n", 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);
|
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);
|
Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(NewFdtBlobSize), &NewFdtBlobBase);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
ASSERT_EFI_ERROR(Status);
|
ASSERT_EFI_ERROR(Status);
|
||||||
goto FAIL_NEW_FDT;
|
goto FAIL_ALLOCATE_NEW_FDT;
|
||||||
} else {
|
} 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));
|
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);
|
//DebugDumpFdt (fdt);
|
||||||
DEBUG_CODE_END();
|
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;
|
*FdtBlobBase = NewFdtBlobBase;
|
||||||
*FdtBlobSize = (UINTN)fdt_totalsize ((VOID*)(UINTN)(NewFdtBlobBase));
|
*FdtBlobSize = (UINTN)fdt_totalsize ((VOID*)(UINTN)(NewFdtBlobBase));
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
FAIL_NEW_FDT:
|
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 success even if we failed to update the FDT blob. The original one is still valid.
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue