summaryrefslogtreecommitdiff
path: root/ArmPkg/Application/LinuxLoader/LinuxLoader.c
diff options
context:
space:
mode:
authorRonald Cron <Ronald.Cron@arm.com>2015-07-06 16:49:40 +0000
committeroliviermartin <oliviermartin@Edk2>2015-07-06 16:49:40 +0000
commit23b01c83b28a7cb8f7eea7af679aecd39f782f1e (patch)
treeddc89c89e93ab7a73b71b8375aa74f7333194811 /ArmPkg/Application/LinuxLoader/LinuxLoader.c
parente6c51eaf023449825aacad4ea87757e60a3f1665 (diff)
ArmPkg/Application: Add new EFI application to boot Linux
This new application support ATAG and FDT Linux kernel. It uses the Device Tree from the EFI Configuration Table to boot FDT aware Linux kernel. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ronald Cron <Ronald.Cron@arm.com> Reviewed-by: Olivier Martin <Olivier.Martin@arm.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17828 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ArmPkg/Application/LinuxLoader/LinuxLoader.c')
-rw-r--r--ArmPkg/Application/LinuxLoader/LinuxLoader.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/ArmPkg/Application/LinuxLoader/LinuxLoader.c b/ArmPkg/Application/LinuxLoader/LinuxLoader.c
new file mode 100644
index 000000000..70b960b66
--- /dev/null
+++ b/ArmPkg/Application/LinuxLoader/LinuxLoader.c
@@ -0,0 +1,246 @@
+/** @file
+*
+* Copyright (c) 2011-2015, 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 <Library/UefiApplicationEntryPoint.h>
+#include <Library/BaseMemoryLib.h>
+
+#include <Protocol/DevicePathFromText.h>
+
+#include "LinuxLoader.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 was executed successfully.
+ @retval EFI_NOT_FOUND Protocol not found.
+ @retval EFI_NOT_FOUND Path to the Linux kernel not found.
+ @retval EFI_ABORTED The initialisation of the Shell Library failed.
+ @retval EFI_INVALID_PARAMETER At least one parameter is not valid or there is a
+ conflict between two parameters.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+
+**/
+EFI_STATUS
+EFIAPI
+LinuxLoaderEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
+ EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters;
+ CHAR16 *KernelPath;
+ CHAR16 *FdtPath;
+ CHAR16 *InitrdPath;
+ CHAR16 *KernelTextDevicePath;
+ CHAR16 *FdtTextDevicePath;
+ CHAR16 *InitrdTextDevicePath;
+ CHAR16 *LinuxCommandLine;
+ UINTN AtagMachineType;
+ EFI_DEVICE_PATH *KernelDevicePath;
+ EFI_DEVICE_PATH *FdtDevicePath;
+ EFI_DEVICE_PATH *InitrdDevicePath;
+ CHAR8 *AsciiLinuxCommandLine;
+ LIST_ENTRY ResourceList;
+ LIST_ENTRY *ResourceLink;
+ SYSTEM_MEMORY_RESOURCE *Resource;
+ EFI_PHYSICAL_ADDRESS SystemMemoryBase;
+
+ Status = gBS->LocateProtocol (
+ &gEfiDevicePathFromTextProtocolGuid,
+ NULL,
+ (VOID **)&EfiDevicePathFromTextProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Register the strings for the user interface in the HII Database.
+ // This shows the way to the multi-language support, even if
+ // only the English language is actually supported. The strings to register
+ // are stored in the "LinuxLoaderStrings[]" array. This array is
+ // built by the building process from the "*.uni" file associated to
+ // the present application (cf. LinuxLoader.inf). Examine the Build
+ // folder of the application and you will find the array defined in the
+ // LinuxLoaderStrDefs.h file.
+ //
+ mLinuxLoaderHiiHandle = HiiAddPackages (
+ &mLinuxLoaderHiiGuid,
+ ImageHandle,
+ LinuxLoaderStrings,
+ NULL
+ );
+ if (mLinuxLoaderHiiHandle == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = gBS->HandleProtocol (
+ ImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID**)&ShellParameters
+ );
+
+ KernelDevicePath = NULL;
+ FdtDevicePath = NULL;
+ InitrdDevicePath = NULL;
+ AsciiLinuxCommandLine = NULL;
+
+ //
+ // Call the proper function to handle the command line
+ // depending on whether the application has been called
+ // from the Shell or not.
+ //
+
+ if (!EFI_ERROR (Status)) {
+ KernelTextDevicePath = NULL;
+ FdtTextDevicePath = NULL;
+ InitrdTextDevicePath = NULL;
+
+ Status = ProcessShellParameters (
+ &KernelPath, &FdtPath, &InitrdPath, &LinuxCommandLine, &AtagMachineType
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ KernelDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (KernelPath);
+ if (KernelDevicePath != NULL) {
+ FreePool (KernelPath);
+ } else {
+ KernelTextDevicePath = KernelPath;
+ }
+
+ if (FdtPath != NULL) {
+ FdtDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (FdtPath);
+ if (FdtDevicePath != NULL) {
+ FreePool (FdtPath);
+ } else {
+ FdtTextDevicePath = FdtPath;
+ }
+ }
+
+ if (InitrdPath != NULL) {
+ InitrdDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (InitrdPath);
+ if (InitrdDevicePath != NULL) {
+ FreePool (InitrdPath);
+ } else {
+ InitrdTextDevicePath = InitrdPath;
+ }
+ }
+
+ } else {
+ Status = ProcessAppCommandLine (
+ &KernelTextDevicePath, &FdtTextDevicePath,
+ &InitrdTextDevicePath, &LinuxCommandLine, &AtagMachineType
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ }
+
+ Status = EFI_INVALID_PARAMETER;
+ if (KernelTextDevicePath != NULL) {
+ KernelDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (
+ KernelTextDevicePath
+ );
+ if (KernelDevicePath == NULL) {
+ goto Error;
+ }
+ }
+ if (FdtTextDevicePath != NULL) {
+ FdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (
+ FdtTextDevicePath
+ );
+ if (FdtDevicePath == NULL) {
+ goto Error;
+ }
+ }
+ if (InitrdTextDevicePath != NULL) {
+ InitrdDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (
+ InitrdTextDevicePath
+ );
+ if (InitrdDevicePath == NULL) {
+ goto Error;
+ }
+ }
+
+ if (LinuxCommandLine != NULL) {
+ AsciiLinuxCommandLine = AllocatePool ((StrLen (LinuxCommandLine) + 1) * sizeof (CHAR8));
+ if (AsciiLinuxCommandLine == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ UnicodeStrToAsciiStr (LinuxCommandLine, AsciiLinuxCommandLine);
+ }
+
+ //
+ // Find Base of System Memory - we keep the lowest physical address
+ //
+ SystemMemoryBase = ~0;
+ GetSystemMemoryResources (&ResourceList);
+ ResourceLink = ResourceList.ForwardLink;
+ while (ResourceLink != NULL && ResourceLink != &ResourceList) {
+ Resource = (SYSTEM_MEMORY_RESOURCE*)ResourceLink;
+ if (Resource->PhysicalStart < SystemMemoryBase) {
+ SystemMemoryBase = Resource->PhysicalStart;
+ }
+ ResourceLink = ResourceLink->ForwardLink;
+ }
+
+ if (AtagMachineType != ARM_FDT_MACHINE_TYPE) {
+ Status = BootLinuxAtag (SystemMemoryBase, KernelDevicePath, InitrdDevicePath, AsciiLinuxCommandLine, AtagMachineType);
+ } else {
+ Status = BootLinuxFdt (SystemMemoryBase, KernelDevicePath, InitrdDevicePath, FdtDevicePath, AsciiLinuxCommandLine);
+ }
+
+Error:
+ if (KernelTextDevicePath != NULL) {
+ FreePool (KernelTextDevicePath);
+ }
+ if (FdtTextDevicePath != NULL) {
+ FreePool (FdtTextDevicePath);
+ }
+ if (InitrdTextDevicePath != NULL) {
+ FreePool (InitrdTextDevicePath);
+ }
+ if (LinuxCommandLine != NULL) {
+ FreePool (LinuxCommandLine);
+ }
+ if (KernelDevicePath != NULL) {
+ FreePool (KernelDevicePath);
+ }
+ if (FdtDevicePath != NULL) {
+ FreePool (FdtDevicePath);
+ }
+ if (InitrdDevicePath != NULL) {
+ FreePool (InitrdDevicePath);
+ }
+ if (AsciiLinuxCommandLine != NULL) {
+ FreePool (AsciiLinuxCommandLine);
+ }
+
+ if (EFI_ERROR (Status)) {
+ PrintHii (NULL, STRING_TOKEN (STR_ERROR), Status);
+ }
+
+ HiiRemovePackages (mLinuxLoaderHiiHandle);
+
+ return Status;
+}