blob: 07d0ea7b4120e735d61fb47b47c862dba77d9576 [file] [log] [blame]
/** @file
*
* Copyright (c) 2011, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#include "LinuxInternal.h"
#include <Library/PrintLib.h>
#include <Library/UefiApplicationEntryPoint.h>
/**
The user Entry Point for Application. The user code starts with this function
as the real entry point for the application.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The entry point is executed successfully.
@retval other Some error occurs when executing this entry point.
**/
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
LINUX_LOADER_OPTIONAL_DATA* LinuxOptionalData;
EFI_DEVICE_PATH* DevicePathKernel;
EFI_DEVICE_PATH* DevicePathFdt;
EFI_DEVICE_PATH* InitrdDevicePath;
CHAR16* OptionalDataInitrd;
CHAR8* OptionalDataArguments;
CHAR16* Initrd;
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage);
ASSERT_EFI_ERROR (Status);
if (LoadedImage->LoadOptionsSize == 0) {
Status = LinuxLoaderConfig (LoadedImage);
} else {
// Ensure the signature is correct
LinuxOptionalData = (LINUX_LOADER_OPTIONAL_DATA*)LoadedImage->LoadOptions;
if (LinuxOptionalData->Signature != LINUX_LOADER_SIGNATURE) {
return EFI_UNSUPPORTED;
}
// Generate the File Path Node for the Linux Kernel & Device Tree blob
DevicePathKernel = FileDevicePath (LoadedImage->DeviceHandle, LINUX_KERNEL_NAME);
DevicePathFdt = FileDevicePath (LoadedImage->DeviceHandle, FDT_NAME);
if (LinuxOptionalData->CmdLineLength > 0) {
OptionalDataArguments = (CHAR8*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA);
} else {
OptionalDataArguments = NULL;
}
if (LinuxOptionalData->InitrdPathListLength > 0) {
if (OptionalDataArguments != NULL) {
OptionalDataInitrd = (CHAR16*)(OptionalDataArguments + LinuxOptionalData->CmdLineLength);
} else {
OptionalDataInitrd = (CHAR16*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA);
}
// If pointer not aligned
if ((UINTN)OptionalDataInitrd & 0x1) {
Initrd = (CHAR16*)AllocateCopyPool (LinuxOptionalData->InitrdPathListLength, OptionalDataInitrd);
} else {
Initrd = OptionalDataInitrd;
}
InitrdDevicePath = FileDevicePath (LoadedImage->DeviceHandle, Initrd);
} else {
OptionalDataInitrd = NULL;
InitrdDevicePath = NULL;
Initrd = NULL;
}
// Load and Start the Linux Kernel (we should never return)
Status = BdsBootLinuxFdt (DevicePathKernel, InitrdDevicePath, OptionalDataArguments, DevicePathFdt);
if ((UINTN)OptionalDataInitrd & 0x1) {
FreePool (Initrd);
}
FreePool (DevicePathKernel);
if (InitrdDevicePath) {
FreePool (InitrdDevicePath);
}
}
return Status;
}