summaryrefslogtreecommitdiff
path: root/ArmPkg/Application/LinuxLoader/LinuxLoader.c
diff options
context:
space:
mode:
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 0000000000..70b960b66f
--- /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;
+}