mirror of https://github.com/acidanthera/audk.git
ArmPkg/Application/LinuxLoader: Create a Linux Loader EFI application
There are two variants of the Linux Loader EFI application: - the ATAG version 'LinuxAtagLoader.inf': expect to start an ATAG 'zImage' in the same directory as the EFI application - the FDT version 'LinuxFdtLoader.inf': load the FDT blob 'platform.dtb' and the FDT 'zImage' from the same directory as the EFI application. When these applications are started without any argument, a menu appears to the user to create/update a boot entry. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12410 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
d9325c8e4f
commit
75e4db2d3b
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue