| /** @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; | |
| } |