diff options
Diffstat (limited to 'ArmPkg/Application')
-rw-r--r-- | ArmPkg/Application/LinuxLoader/LinuxAtagLoader.c | 103 | ||||
-rw-r--r-- | ArmPkg/Application/LinuxLoader/LinuxAtagLoader.inf | 40 | ||||
-rw-r--r-- | ArmPkg/Application/LinuxLoader/LinuxConfig.c | 355 | ||||
-rw-r--r-- | ArmPkg/Application/LinuxLoader/LinuxFdtLoader.c | 105 | ||||
-rw-r--r-- | ArmPkg/Application/LinuxLoader/LinuxFdtLoader.inf | 40 | ||||
-rw-r--r-- | ArmPkg/Application/LinuxLoader/LinuxInternal.h | 49 |
6 files changed, 692 insertions, 0 deletions
diff --git a/ArmPkg/Application/LinuxLoader/LinuxAtagLoader.c b/ArmPkg/Application/LinuxLoader/LinuxAtagLoader.c new file mode 100644 index 0000000000..50a4b474cf --- /dev/null +++ b/ArmPkg/Application/LinuxLoader/LinuxAtagLoader.c @@ -0,0 +1,103 @@ +/** @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* 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
+ DevicePathKernel = FileDevicePath (LoadedImage->DeviceHandle, LINUX_KERNEL_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 = BdsBootLinuxAtag (DevicePathKernel, InitrdDevicePath, OptionalDataArguments);
+
+ if ((UINTN)OptionalDataInitrd & 0x1) {
+ FreePool (Initrd);
+ }
+
+ FreePool (DevicePathKernel);
+ if (InitrdDevicePath) {
+ FreePool (InitrdDevicePath);
+ }
+ }
+
+ return Status;
+}
diff --git a/ArmPkg/Application/LinuxLoader/LinuxAtagLoader.inf b/ArmPkg/Application/LinuxLoader/LinuxAtagLoader.inf new file mode 100644 index 0000000000..d3edb533b9 --- /dev/null +++ b/ArmPkg/Application/LinuxLoader/LinuxAtagLoader.inf @@ -0,0 +1,40 @@ +#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = LinuxAtagLoader
+ FILE_GUID = a912f198-7f0e-4803-b908-b757b806ec83
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 0.1
+ ENTRY_POINT = UefiMain
+
+[Sources]
+ LinuxAtagLoader.c
+ LinuxConfig.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BdsLib
+ DxeServicesTableLib
+ UefiLib
+ UefiApplicationEntryPoint
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid
+
+ #TODO: RemoveMe
+ gEfiDevicePathToTextProtocolGuid
diff --git a/ArmPkg/Application/LinuxLoader/LinuxConfig.c b/ArmPkg/Application/LinuxLoader/LinuxConfig.c new file mode 100644 index 0000000000..88b8500725 --- /dev/null +++ b/ArmPkg/Application/LinuxLoader/LinuxConfig.c @@ -0,0 +1,355 @@ +/** @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" + +//TODO: RemoveMe +#include <Protocol/DevicePathToText.h> + +#define DEFAULT_BOOT_ENTRY_DESCRIPTION L"Linux" +#define MAX_STR_INPUT 300 +#define MAX_ASCII_INPUT 300 + +typedef enum { + LINUX_LOADER_NEW = 1, + LINUX_LOADER_UPDATE +} LINUX_LOADER_ACTION; + +STATIC +EFI_STATUS +EditHIInputStr ( + IN OUT CHAR16 *CmdLine, + IN UINTN MaxCmdLine + ) +{ + UINTN CmdLineIndex; + UINTN WaitIndex; + CHAR8 Char; + EFI_INPUT_KEY Key; + EFI_STATUS Status; + + Print (CmdLine); + + for (CmdLineIndex = StrLen (CmdLine); CmdLineIndex < MaxCmdLine; ) { + Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex); + ASSERT_EFI_ERROR (Status); + + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + ASSERT_EFI_ERROR (Status); + + // Unicode character is valid when Scancode is NUll + if (Key.ScanCode == SCAN_NULL) { + // Scan code is NUll, hence read Unicode character + Char = (CHAR8)Key.UnicodeChar; + } else { + Char = CHAR_NULL; + } + + if ((Char == CHAR_LINEFEED) || (Char == CHAR_CARRIAGE_RETURN) || (Char == 0x7f)) { + CmdLine[CmdLineIndex] = '\0'; + Print (L"\n\r"); + + return EFI_SUCCESS; + } else if ((Key.UnicodeChar == L'\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){ + if (CmdLineIndex != 0) { + CmdLineIndex--; + Print (L"\b \b"); + } + } else if ((Key.ScanCode == SCAN_ESC) || (Char == 0x1B) || (Char == 0x0)) { + return EFI_INVALID_PARAMETER; + } else { + CmdLine[CmdLineIndex++] = Key.UnicodeChar; + Print (L"%c", Key.UnicodeChar); + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EditHIInputAscii ( + IN OUT CHAR8 *CmdLine, + IN UINTN MaxCmdLine + ) +{ + CHAR16* Str; + EFI_STATUS Status; + + Str = (CHAR16*)AllocatePool (MaxCmdLine * sizeof(CHAR16)); + AsciiStrToUnicodeStr (CmdLine, Str); + + Status = EditHIInputStr (Str, MaxCmdLine); + + UnicodeStrToAsciiStr (Str, CmdLine); + FreePool (Str); + + return Status; +} + +STATIC +EFI_STATUS +GetHIInputInteger ( + OUT UINTN *Integer + ) +{ + CHAR16 CmdLine[255]; + EFI_STATUS Status; + + CmdLine[0] = '\0'; + Status = EditHIInputStr (CmdLine, 255); + if (!EFI_ERROR(Status)) { + *Integer = StrDecimalToUintn (CmdLine); + } + + return Status; +} + +#if 0 +EFI_STATUS +GenerateDeviceDescriptionName ( + IN EFI_HANDLE Handle, + IN OUT CHAR16* Description + ) +{ + EFI_STATUS Status; + EFI_COMPONENT_NAME_PROTOCOL* ComponentName2Protocol; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; + EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol; + CHAR16* DriverName; + CHAR16* DevicePathTxt; + EFI_DEVICE_PATH* DevicePathNode; + + ComponentName2Protocol = NULL; + Status = gBS->HandleProtocol (Handle, &gEfiComponentName2ProtocolGuid, (VOID **)&ComponentName2Protocol); + if (!EFI_ERROR(Status)) { + //TODO: Fixme. we must find the best langague + Status = ComponentName2Protocol->GetDriverName (ComponentName2Protocol,"en",&DriverName); + if (!EFI_ERROR(Status)) { + StrnCpy (Description,DriverName,BOOT_DEVICE_DESCRIPTION_MAX); + } + } + + if (EFI_ERROR(Status)) { + // Use the lastest non null entry of the Device path as a description + Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol); + if (EFI_ERROR(Status)) { + return Status; + } + + // Convert the last non end-type Device Path Node in text for the description + DevicePathNode = GetLastDevicePathNode (DevicePathProtocol); + Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); + ASSERT_EFI_ERROR(Status); + DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(DevicePathNode,TRUE,TRUE); + StrnCpy (Description, DevicePathTxt, BOOT_DEVICE_DESCRIPTION_MAX); + FreePool (DevicePathTxt); + } + + return EFI_SUCCESS; +} +#endif + +EFI_STATUS +LinuxLoaderConfig ( + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage + ) +{ + EFI_STATUS Status; + LINUX_LOADER_ACTION Choice; + UINTN BootOrderSize; + UINT16* BootOrder; + UINTN BootOrderCount; + UINTN Index; + CHAR16 Description[MAX_ASCII_INPUT]; + CHAR8 CmdLine[MAX_ASCII_INPUT]; + CHAR16 Initrd[MAX_STR_INPUT]; + UINT16 InitrdPathListLength; + UINT16 CmdLineLength; + BDS_LOAD_OPTION* BdsLoadOption; + BDS_LOAD_OPTION** SupportedBdsLoadOptions; + UINTN SupportedBdsLoadOptionCount; + LINUX_LOADER_OPTIONAL_DATA* LinuxOptionalData; + EFI_DEVICE_PATH* DevicePathRoot; + + SupportedBdsLoadOptions = NULL; + SupportedBdsLoadOptionCount = 0; + + do { + Print (L"[%d] Create new Linux Boot Entry\n",LINUX_LOADER_NEW); + Print (L"[%d] Update Linux Boot Entry\n",LINUX_LOADER_UPDATE); + + Print (L"Option: "); + Status = GetHIInputInteger (&Choice); + if (Status == EFI_INVALID_PARAMETER) { + Print (L"\n"); + return Status; + } else if ((Choice != LINUX_LOADER_NEW) && (Choice != LINUX_LOADER_UPDATE)) { + Print (L"Error: the option should be either '%d' or '%d'\n",LINUX_LOADER_NEW,LINUX_LOADER_UPDATE); + Status = EFI_INVALID_PARAMETER; + } + } while (EFI_ERROR(Status)); + + if (Choice == LINUX_LOADER_UPDATE) { + // If no compatible entry then we just create a new entry + Choice = LINUX_LOADER_NEW; + + // Scan the OptionalData of every entry for the correct signature + Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder); + if (!EFI_ERROR(Status)) { + BootOrderCount = BootOrderSize / sizeof(UINT16); + + // Allocate an array to handle maximum number of supported Boot Entry + SupportedBdsLoadOptions = (BDS_LOAD_OPTION**)AllocatePool(sizeof(BDS_LOAD_OPTION*) * BootOrderCount); + + SupportedBdsLoadOptionCount = 0; + + // Check if the signature is present in the list of the current Boot entries + for (Index = 0; Index < BootOrderCount; Index++) { + Status = BootOptionFromLoadOptionIndex (BootOrder[Index], &BdsLoadOption); + if (!EFI_ERROR(Status)) { + if ((BdsLoadOption->OptionalDataSize >= sizeof(UINT32)) && + (*(UINT32*)BdsLoadOption->OptionalData == LINUX_LOADER_SIGNATURE)) { + SupportedBdsLoadOptions[SupportedBdsLoadOptionCount++] = BdsLoadOption; + Choice = LINUX_LOADER_UPDATE; + } + } + } + } + } + + if (Choice == LINUX_LOADER_NEW) { + Description[0] = '\0'; + CmdLine[0] = '\0'; + Initrd[0] = '\0'; + + BdsLoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION)); + + DEBUG_CODE_BEGIN(); + CHAR16* DevicePathTxt; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; + + Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); + ASSERT_EFI_ERROR(Status); + DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (LoadedImage->FilePath, TRUE, TRUE); + + Print(L"EFI OS Loader: %s\n",DevicePathTxt); + + FreePool(DevicePathTxt); + DEBUG_CODE_END(); + + // + // Fill the known fields of BdsLoadOption + // + + BdsLoadOption->Attributes = LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT; + + // Get the full Device Path for this file + Status = gBS->HandleProtocol (LoadedImage->DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathRoot); + ASSERT_EFI_ERROR(Status); + + BdsLoadOption->FilePathList = AppendDevicePath (DevicePathRoot, LoadedImage->FilePath); + BdsLoadOption->FilePathListLength = GetDevicePathSize (BdsLoadOption->FilePathList); + } else { + if (SupportedBdsLoadOptionCount > 1) { + for (Index = 0; Index < SupportedBdsLoadOptionCount; Index++) { + Print (L"[%d] %s\n",Index + 1,SupportedBdsLoadOptions[Index]->Description); + } + + do { + Print (L"Update Boot Entry: "); + Status = GetHIInputInteger (&Choice); + if (Status == EFI_INVALID_PARAMETER) { + Print (L"\n"); + return Status; + } else if ((Choice < 1) && (Choice > SupportedBdsLoadOptionCount)) { + Print (L"Choose entry from 1 to %d\n",SupportedBdsLoadOptionCount); + Status = EFI_INVALID_PARAMETER; + } + } while (EFI_ERROR(Status)); + BdsLoadOption = SupportedBdsLoadOptions[Choice-1]; + } + StrnCpy (Description, BdsLoadOption->Description, MAX_STR_INPUT); + + LinuxOptionalData = (LINUX_LOADER_OPTIONAL_DATA*)BdsLoadOption->OptionalData; + if (LinuxOptionalData->CmdLineLength > 0) { + CopyMem (CmdLine, (CHAR8*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA), LinuxOptionalData->CmdLineLength); + } else { + CmdLine[0] = '\0'; + } + + if (LinuxOptionalData->InitrdPathListLength > 0) { + CopyMem (Initrd, (CHAR8*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA) + LinuxOptionalData->CmdLineLength, LinuxOptionalData->InitrdPathListLength); + } else { + Initrd[0] = L'\0'; + } + DEBUG((EFI_D_ERROR,"L\n")); + } + + // Description + Print (L"Description: "); + Status = EditHIInputStr (Description, MAX_STR_INPUT); + if (EFI_ERROR(Status)) { + return Status; + } + if (StrLen (Description) == 0) { + StrnCpy (Description, DEFAULT_BOOT_ENTRY_DESCRIPTION, MAX_STR_INPUT); + } + BdsLoadOption->Description = Description; + + // CmdLine + Print (L"Command Line: "); + Status = EditHIInputAscii (CmdLine, MAX_ASCII_INPUT); + if (EFI_ERROR(Status)) { + return Status; + } + + // Initrd + Print (L"Initrd name: "); + Status = EditHIInputStr (Initrd, MAX_STR_INPUT); + if (EFI_ERROR(Status)) { + return Status; + } + + CmdLineLength = AsciiStrLen (CmdLine); + if (CmdLineLength > 0) { + CmdLineLength += sizeof(CHAR8); + } + + InitrdPathListLength = StrLen (Initrd) * sizeof(CHAR16); + if (InitrdPathListLength > 0) { + InitrdPathListLength += sizeof(CHAR16); + } + + BdsLoadOption->OptionalDataSize = sizeof(LINUX_LOADER_OPTIONAL_DATA) + CmdLineLength + InitrdPathListLength; + + LinuxOptionalData = (LINUX_LOADER_OPTIONAL_DATA*)AllocatePool (BdsLoadOption->OptionalDataSize); + BdsLoadOption->OptionalData = LinuxOptionalData; + + LinuxOptionalData->Signature = LINUX_LOADER_SIGNATURE; + LinuxOptionalData->CmdLineLength = CmdLineLength; + LinuxOptionalData->InitrdPathListLength = InitrdPathListLength; + + if (CmdLineLength > 0) { + CopyMem (LinuxOptionalData + 1, CmdLine, CmdLineLength); + } + if (InitrdPathListLength > 0) { + CopyMem ((UINT8*)(LinuxOptionalData + 1) + CmdLineLength, Initrd, InitrdPathListLength); + } + + // Create or Update the boot entry + Status = BootOptionToLoadOptionVariable (BdsLoadOption); + + return Status; +} diff --git a/ArmPkg/Application/LinuxLoader/LinuxFdtLoader.c b/ArmPkg/Application/LinuxLoader/LinuxFdtLoader.c new file mode 100644 index 0000000000..2e222de51b --- /dev/null +++ b/ArmPkg/Application/LinuxLoader/LinuxFdtLoader.c @@ -0,0 +1,105 @@ +/** @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 blobl
+ 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;
+}
diff --git a/ArmPkg/Application/LinuxLoader/LinuxFdtLoader.inf b/ArmPkg/Application/LinuxLoader/LinuxFdtLoader.inf new file mode 100644 index 0000000000..76773af76b --- /dev/null +++ b/ArmPkg/Application/LinuxLoader/LinuxFdtLoader.inf @@ -0,0 +1,40 @@ +#/* @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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = LinuxFdtLoader
+ FILE_GUID = f536d559-459f-48fa-8bbc-43b554ecae8d
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 0.1
+ ENTRY_POINT = UefiMain
+
+[Sources]
+ LinuxFdtLoader.c
+ LinuxConfig.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BdsLib
+ DxeServicesTableLib
+ UefiLib
+ UefiApplicationEntryPoint
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid
+
+ #TODO: RemoveMe
+ gEfiDevicePathToTextProtocolGuid
diff --git a/ArmPkg/Application/LinuxLoader/LinuxInternal.h b/ArmPkg/Application/LinuxLoader/LinuxInternal.h new file mode 100644 index 0000000000..e486273520 --- /dev/null +++ b/ArmPkg/Application/LinuxLoader/LinuxInternal.h @@ -0,0 +1,49 @@ +/** @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. +* +**/ + +#ifndef __LOADER_INTERNAL_H +#define __LOADER_INTERNAL_H + +#include <Uefi.h> +#include <Library/BaseMemoryLib.h> +#include <Library/BdsLib.h> +#include <Library/DebugLib.h> +#include <Library/DevicePathLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + +#include <Protocol/LoadedImage.h> + +#define LINUX_KERNEL_NAME L"zImage" +#define FDT_NAME L"platform.dtb" + +#define LINUX_LOADER_SIGNATURE SIGNATURE_32('l', 'i', 'l', 'o') + +typedef struct { + UINT32 Signature; + UINT16 CmdLineLength; + UINT16 InitrdPathListLength; + + // These following fields have variable length: + //CHAR8* CmdLine; + //CHAR16* Initrd; +} LINUX_LOADER_OPTIONAL_DATA; + +EFI_STATUS +LinuxLoaderConfig ( + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage + ); + +#endif |