ArmPlatformPkg: remove ARM BDS

This is no longer used, and does not belong in a reference code base,
so remove it.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
Reviewed-by: Ryan Harkin <ryan.harkin@linaro.org>
This commit is contained in:
Ard Biesheuvel 2016-10-25 18:12:45 +01:00
parent 90b10821cd
commit c133041fa6
8 changed files with 0 additions and 4129 deletions

View File

@ -1,561 +0,0 @@
/** @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 "BdsInternal.h"
#include <Library/PcdLib.h>
#include <Library/PerformanceLib.h>
#include <Protocol/Bds.h>
#include <Guid/EventGroup.h>
#define EFI_SET_TIMER_TO_SECOND 10000000
STATIC
EFI_STATUS
GetConsoleDevicePathFromVariable (
IN CHAR16* ConsoleVarName,
IN CHAR16* DefaultConsolePaths,
OUT EFI_DEVICE_PATH** DevicePaths
)
{
EFI_STATUS Status;
UINTN Size;
EFI_DEVICE_PATH_PROTOCOL* DevicePathInstances;
EFI_DEVICE_PATH_PROTOCOL* DevicePathInstance;
CHAR16* DevicePathStr;
CHAR16* NextDevicePathStr;
EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
Status = GetGlobalEnvironmentVariable (ConsoleVarName, NULL, NULL, (VOID**)&DevicePathInstances);
if (EFI_ERROR(Status)) {
// In case no default console device path has been defined we assume a driver handles the console (eg: SimpleTextInOutSerial)
if ((DefaultConsolePaths == NULL) || (DefaultConsolePaths[0] == L'\0')) {
*DevicePaths = NULL;
return EFI_SUCCESS;
}
Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
ASSERT_EFI_ERROR(Status);
DevicePathInstances = NULL;
// Extract the Device Path instances from the multi-device path string
while ((DefaultConsolePaths != NULL) && (DefaultConsolePaths[0] != L'\0')) {
NextDevicePathStr = StrStr (DefaultConsolePaths, L";");
if (NextDevicePathStr == NULL) {
DevicePathStr = DefaultConsolePaths;
DefaultConsolePaths = NULL;
} else {
DevicePathStr = (CHAR16*)AllocateCopyPool ((NextDevicePathStr - DefaultConsolePaths + 1) * sizeof(CHAR16), DefaultConsolePaths);
*(DevicePathStr + (NextDevicePathStr - DefaultConsolePaths)) = L'\0';
DefaultConsolePaths = NextDevicePathStr;
if (DefaultConsolePaths[0] == L';') {
DefaultConsolePaths++;
}
}
DevicePathInstance = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (DevicePathStr);
ASSERT(DevicePathInstance != NULL);
DevicePathInstances = AppendDevicePathInstance (DevicePathInstances, DevicePathInstance);
if (NextDevicePathStr != NULL) {
FreePool (DevicePathStr);
}
FreePool (DevicePathInstance);
}
// Set the environment variable with this device path multi-instances
Size = GetDevicePathSize (DevicePathInstances);
if (Size > 0) {
gRT->SetVariable (
ConsoleVarName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
Size,
DevicePathInstances
);
} else {
Status = EFI_INVALID_PARAMETER;
}
}
if (!EFI_ERROR(Status)) {
*DevicePaths = DevicePathInstances;
}
return Status;
}
STATIC
EFI_STATUS
InitializeConsolePipe (
IN EFI_DEVICE_PATH *ConsoleDevicePaths,
IN EFI_GUID *Protocol,
OUT EFI_HANDLE *Handle,
OUT VOID* *Interface
)
{
EFI_STATUS Status;
UINTN Size;
UINTN NoHandles;
EFI_HANDLE *Buffer;
EFI_DEVICE_PATH_PROTOCOL* DevicePath;
// Connect all the Device Path Consoles
while (ConsoleDevicePaths != NULL) {
DevicePath = GetNextDevicePathInstance (&ConsoleDevicePaths, &Size);
Status = BdsConnectDevicePath (DevicePath, Handle, NULL);
DEBUG_CODE_BEGIN();
if (EFI_ERROR(Status)) {
// We convert back to the text representation of the device Path
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
CHAR16* DevicePathTxt;
EFI_STATUS Status;
Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
if (!EFI_ERROR(Status)) {
DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (DevicePath, TRUE, TRUE);
DEBUG((EFI_D_ERROR,"Fail to start the console with the Device Path '%s'. (Error '%r')\n", DevicePathTxt, Status));
FreePool (DevicePathTxt);
}
}
DEBUG_CODE_END();
// If the console splitter driver is not supported by the platform then use the first Device Path
// instance for the console interface.
if (!EFI_ERROR(Status) && (*Interface == NULL)) {
Status = gBS->HandleProtocol (*Handle, Protocol, Interface);
}
}
// No Device Path has been defined for this console interface. We take the first protocol implementation
if (*Interface == NULL) {
Status = gBS->LocateHandleBuffer (ByProtocol, Protocol, NULL, &NoHandles, &Buffer);
if (EFI_ERROR (Status)) {
BdsConnectAllDrivers();
Status = gBS->LocateHandleBuffer (ByProtocol, Protocol, NULL, &NoHandles, &Buffer);
}
if (!EFI_ERROR(Status)) {
*Handle = Buffer[0];
Status = gBS->HandleProtocol (*Handle, Protocol, Interface);
ASSERT_EFI_ERROR(Status);
FreePool (Buffer);
}
} else {
Status = EFI_SUCCESS;
}
return Status;
}
EFI_STATUS
InitializeConsole (
VOID
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH* ConOutDevicePaths;
EFI_DEVICE_PATH* ConInDevicePaths;
EFI_DEVICE_PATH* ConErrDevicePaths;
// By getting the Console Device Paths from the environment variables before initializing the console pipe, we
// create the 3 environment variables (ConIn, ConOut, ConErr) that allows to initialize all the console interface
// of newly installed console drivers
Status = GetConsoleDevicePathFromVariable (L"ConOut", (CHAR16*)PcdGetPtr(PcdDefaultConOutPaths), &ConOutDevicePaths);
ASSERT_EFI_ERROR (Status);
Status = GetConsoleDevicePathFromVariable (L"ConIn", (CHAR16*)PcdGetPtr(PcdDefaultConInPaths), &ConInDevicePaths);
ASSERT_EFI_ERROR (Status);
Status = GetConsoleDevicePathFromVariable (L"ErrOut", (CHAR16*)PcdGetPtr(PcdDefaultConOutPaths), &ConErrDevicePaths);
ASSERT_EFI_ERROR (Status);
// Initialize the Consoles
Status = InitializeConsolePipe (ConOutDevicePaths, &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **)&gST->ConOut);
ASSERT_EFI_ERROR (Status);
Status = InitializeConsolePipe (ConInDevicePaths, &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **)&gST->ConIn);
ASSERT_EFI_ERROR (Status);
Status = InitializeConsolePipe (ConErrDevicePaths, &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **)&gST->StdErr);
if (EFI_ERROR(Status)) {
// In case of error, we reuse the console output for the error output
gST->StandardErrorHandle = gST->ConsoleOutHandle;
gST->StdErr = gST->ConOut;
}
// Free Memory allocated for reading the UEFI Variables
if (ConOutDevicePaths) {
FreePool (ConOutDevicePaths);
}
if (ConInDevicePaths) {
FreePool (ConInDevicePaths);
}
if (ConErrDevicePaths) {
FreePool (ConErrDevicePaths);
}
return EFI_SUCCESS;
}
EFI_STATUS
DefineDefaultBootEntries (
VOID
)
{
BDS_LOAD_OPTION* BdsLoadOption;
UINTN Size;
EFI_STATUS Status;
EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol;
EFI_DEVICE_PATH* BootDevicePath;
UINTN CmdLineSize;
UINTN CmdLineAsciiSize;
CHAR16* DefaultBootArgument;
CHAR8* AsciiDefaultBootArgument;
//
// If Boot Order does not exist then create a default entry
//
Size = 0;
Status = gRT->GetVariable (L"BootOrder", &gEfiGlobalVariableGuid, NULL, &Size, NULL);
if (Status == EFI_NOT_FOUND) {
if ((PcdGetPtr(PcdDefaultBootDevicePath) == NULL) || (StrLen ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath)) == 0)) {
return EFI_UNSUPPORTED;
}
Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
if (EFI_ERROR(Status)) {
// You must provide an implementation of DevicePathFromTextProtocol in your firmware (eg: DevicePathDxe)
DEBUG((EFI_D_ERROR,"Error: Bds requires DevicePathFromTextProtocol\n"));
return Status;
}
BootDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath));
DEBUG_CODE_BEGIN();
// We convert back to the text representation of the device Path to see if the initial text is correct
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
CHAR16* DevicePathTxt;
Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
ASSERT_EFI_ERROR(Status);
DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (BootDevicePath, TRUE, TRUE);
if (StrCmp ((CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath), DevicePathTxt) != 0) {
DEBUG ((EFI_D_ERROR, "Device Path given: '%s' Device Path expected: '%s'\n",
(CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath), DevicePathTxt));
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
}
FreePool (DevicePathTxt);
DEBUG_CODE_END();
// Create the entry is the Default values are correct
if (BootDevicePath != NULL) {
// We do not support NULL pointer
ASSERT (PcdGetPtr (PcdDefaultBootArgument) != NULL);
//
// Logic to handle ASCII or Unicode default parameters
//
if (*(CHAR8*)PcdGetPtr (PcdDefaultBootArgument) == '\0') {
CmdLineSize = 0;
CmdLineAsciiSize = 0;
DefaultBootArgument = NULL;
AsciiDefaultBootArgument = NULL;
} else if (IsUnicodeString ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument))) {
// The command line is a Unicode string
DefaultBootArgument = (CHAR16*)PcdGetPtr (PcdDefaultBootArgument);
CmdLineSize = StrSize (DefaultBootArgument);
// Initialize ASCII variables
CmdLineAsciiSize = CmdLineSize / 2;
AsciiDefaultBootArgument = AllocatePool (CmdLineAsciiSize);
if (AsciiDefaultBootArgument == NULL) {
return EFI_OUT_OF_RESOURCES;
}
UnicodeStrToAsciiStr ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument), AsciiDefaultBootArgument);
} else {
// The command line is a ASCII string
AsciiDefaultBootArgument = (CHAR8*)PcdGetPtr (PcdDefaultBootArgument);
CmdLineAsciiSize = AsciiStrSize (AsciiDefaultBootArgument);
// Initialize ASCII variables
CmdLineSize = CmdLineAsciiSize * 2;
DefaultBootArgument = AllocatePool (CmdLineSize);
if (DefaultBootArgument == NULL) {
return EFI_OUT_OF_RESOURCES;
}
AsciiStrToUnicodeStr (AsciiDefaultBootArgument, DefaultBootArgument);
}
BootOptionCreate (LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT,
(CHAR16*)PcdGetPtr (PcdDefaultBootDescription),
BootDevicePath,
(UINT8 *)DefaultBootArgument, // OptionalData
CmdLineSize, // OptionalDataSize
&BdsLoadOption
);
FreePool (BdsLoadOption);
if (DefaultBootArgument == (CHAR16*)PcdGetPtr (PcdDefaultBootArgument)) {
FreePool (AsciiDefaultBootArgument);
} else if (DefaultBootArgument != NULL) {
FreePool (DefaultBootArgument);
}
} else {
Status = EFI_UNSUPPORTED;
}
}
return Status;
}
EFI_STATUS
StartDefaultBootOnTimeout (
VOID
)
{
UINTN Size;
UINT16 Timeout;
UINT16 *TimeoutPtr;
EFI_EVENT WaitList[2];
UINTN WaitIndex;
UINT16 *BootOrder;
UINTN BootOrderSize;
UINTN Index;
CHAR16 BootVariableName[9];
EFI_STATUS Status;
EFI_INPUT_KEY Key;
Size = sizeof(UINT16);
Timeout = (UINT16)PcdGet16 (PcdPlatformBootTimeOut);
Status = GetGlobalEnvironmentVariable (L"Timeout", &Timeout, &Size, (VOID**)&TimeoutPtr);
if (!EFI_ERROR (Status)) {
Timeout = *TimeoutPtr;
FreePool (TimeoutPtr);
}
if (Timeout != 0xFFFF) {
if (Timeout > 0) {
// Create the waiting events (keystroke and 1sec timer)
gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &WaitList[0]);
gBS->SetTimer (WaitList[0], TimerPeriodic, EFI_SET_TIMER_TO_SECOND);
WaitList[1] = gST->ConIn->WaitForKey;
// Start the timer
WaitIndex = 0;
Print(L"The default boot selection will start in ");
while ((Timeout > 0) && (WaitIndex == 0)) {
Print(L"%3d seconds",Timeout);
gBS->WaitForEvent (2, WaitList, &WaitIndex);
if (WaitIndex == 0) {
Print(L"\b\b\b\b\b\b\b\b\b\b\b");
Timeout--;
}
}
// Discard key in the buffer
do {
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
} while(!EFI_ERROR(Status));
gBS->CloseEvent (WaitList[0]);
Print(L"\n\r");
}
// In case of Timeout we start the default boot selection
if (Timeout == 0) {
// Get the Boot Option Order from the environment variable (a default value should have been created)
GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOrder[Index]);
Status = BdsStartBootOption (BootVariableName);
if(!EFI_ERROR(Status)){
// Boot option returned successfully, hence don't need to start next boot option
break;
}
// In case of success, we should not return from this call.
}
FreePool (BootOrder);
}
}
return EFI_SUCCESS;
}
/**
An empty function to pass error checking of CreateEventEx ().
@param Event Event whose notification function is being invoked.
@param Context Pointer to the notification function's context,
which is implementation-dependent.
**/
VOID
EFIAPI
EmptyCallbackFunction (
IN EFI_EVENT Event,
IN VOID *Context
)
{
return;
}
/**
This function uses policy data from the platform to determine what operating
system or system utility should be loaded and invoked. This function call
also optionally make the use of user input to determine the operating system
or system utility to be loaded and invoked. When the DXE Core has dispatched
all the drivers on the dispatch queue, this function is called. This
function will attempt to connect the boot devices required to load and invoke
the selected operating system or system utility. During this process,
additional firmware volumes may be discovered that may contain addition DXE
drivers that can be dispatched by the DXE Core. If a boot device cannot be
fully connected, this function calls the DXE Service Dispatch() to allow the
DXE drivers from any newly discovered firmware volumes to be dispatched.
Then the boot device connection can be attempted again. If the same boot
device connection operation fails twice in a row, then that boot device has
failed, and should be skipped. This function should never return.
@param This The EFI_BDS_ARCH_PROTOCOL instance.
@return None.
**/
VOID
EFIAPI
BdsEntry (
IN EFI_BDS_ARCH_PROTOCOL *This
)
{
UINTN Size;
EFI_STATUS Status;
UINT16 *BootNext;
UINTN BootNextSize;
CHAR16 BootVariableName[9];
EFI_EVENT EndOfDxeEvent;
//
// Signal EndOfDxe PI Event
//
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
EmptyCallbackFunction,
NULL,
&gEfiEndOfDxeEventGroupGuid,
&EndOfDxeEvent
);
if (!EFI_ERROR (Status)) {
gBS->SignalEvent (EndOfDxeEvent);
}
PERF_END (NULL, "DXE", NULL, 0);
//
// Declare the Firmware Vendor
//
if (FixedPcdGetPtr(PcdFirmwareVendor) != NULL) {
Size = 0x100;
gST->FirmwareVendor = AllocateRuntimePool (Size);
ASSERT (gST->FirmwareVendor != NULL);
UnicodeSPrint (gST->FirmwareVendor, Size, L"%a EFI %a %a", PcdGetPtr(PcdFirmwareVendor), __DATE__, __TIME__);
}
//
// Fixup Table CRC after we updated Firmware Vendor
//
gST->Hdr.CRC32 = 0;
Status = gBS->CalculateCrc32 ((VOID*)gST, gST->Hdr.HeaderSize, &gST->Hdr.CRC32);
ASSERT_EFI_ERROR (Status);
// Now we need to setup the EFI System Table with information about the console devices.
InitializeConsole ();
// If BootNext environment variable is defined then we just load it !
BootNextSize = sizeof(UINT16);
Status = GetGlobalEnvironmentVariable (L"BootNext", NULL, &BootNextSize, (VOID**)&BootNext);
if (!EFI_ERROR(Status)) {
ASSERT(BootNextSize == sizeof(UINT16));
// Generate the requested Boot Entry variable name
UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", *BootNext);
// Set BootCurrent variable
gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
BootNextSize, BootNext);
FreePool (BootNext);
// Start the requested Boot Entry
Status = BdsStartBootOption (BootVariableName);
if (Status != EFI_NOT_FOUND) {
// BootNext has not been succeeded launched
if (EFI_ERROR(Status)) {
Print(L"Fail to start BootNext.\n");
}
// Delete the BootNext environment variable
gRT->SetVariable (L"BootNext", &gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0, NULL);
}
// Clear BootCurrent variable
gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0, NULL);
}
// If Boot Order does not exist then create a default entry
DefineDefaultBootEntries ();
//
// Update the CRC32 in the EFI System Table header
//
gST->Hdr.CRC32 = 0;
Status = gBS->CalculateCrc32 ((VOID*)gST, gST->Hdr.HeaderSize, &gST->Hdr.CRC32);
ASSERT_EFI_ERROR (Status);
// Timer before initiating the default boot selection
StartDefaultBootOnTimeout ();
// Start the Boot Menu
Status = BootMenuMain ();
ASSERT_EFI_ERROR (Status);
}
EFI_BDS_ARCH_PROTOCOL gBdsProtocol = {
BdsEntry,
};
EFI_STATUS
EFIAPI
BdsInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
Status = gBS->InstallMultipleProtocolInterfaces (
&ImageHandle,
&gEfiBdsArchProtocolGuid, &gBdsProtocol,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@ -1,90 +0,0 @@
#/** @file
#
# Component description file for Bds module
#
# Copyright (c) 2011-2015, ARM Ltd. All rights reserved.<BR>
#
# 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 = 0x00010005
BASE_NAME = ArmPlatformBds
FILE_GUID = 5a50aa81-c3ae-4608-a0e3-41a2e69baf94
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = BdsInitialize
[Sources]
Bds.c
BdsHelper.c
BootLinux.c
BootMenu.c
BootOption.c
BootOptionSupport.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
ArmPkg/ArmPkg.dec
ArmPlatformPkg/ArmPlatformPkg.dec
EmbeddedPkg/EmbeddedPkg.dec
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
[Guids]
gFdtTableGuid
[LibraryClasses]
BdsLib
UefiBootServicesTableLib
DxeServicesTableLib
UefiDriverEntryPoint
DebugLib
PerformanceLib
PrintLib
BaseLib
FdtLib
NetLib
[Guids]
gEfiEndOfDxeEventGroupGuid
gEfiFileSystemInfoGuid
gFdtVariableGuid
[Protocols]
gEfiBdsArchProtocolGuid
gEfiBlockIoProtocolGuid
gEfiSimpleTextInProtocolGuid
gEfiPxeBaseCodeProtocolGuid
gEfiSimpleNetworkProtocolGuid
gEfiDevicePathToTextProtocolGuid
gEfiFirmwareVolumeBlockProtocolGuid
gEfiFirmwareVolumeBlock2ProtocolGuid
gEfiDhcp4ServiceBindingProtocolGuid
gEfiMtftp4ServiceBindingProtocolGuid
[FeaturePcd]
gArmPlatformTokenSpaceGuid.PcdBdsLinuxSupport
[Pcd]
gArmPlatformTokenSpaceGuid.PcdFirmwareVendor
gArmPlatformTokenSpaceGuid.PcdDefaultBootDescription
gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath
gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths
gArmPlatformTokenSpaceGuid.PcdDefaultConOutPaths
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile
[Depex]
TRUE

View File

@ -1,465 +0,0 @@
/** @file
*
* Copyright (c) 2011 - 2014, 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/NetLib.h>
#include "BdsInternal.h"
EFI_STATUS
EditHIInputStr (
IN OUT CHAR16 *CmdLine,
IN UINTN MaxCmdLine
)
{
UINTN CmdLineIndex;
UINTN WaitIndex;
CHAR8 Char;
EFI_INPUT_KEY Key;
EFI_STATUS Status;
// The command line must be at least one character long
ASSERT (MaxCmdLine > 0);
// Ensure the last character of the buffer is the NULL character
CmdLine[MaxCmdLine - 1] = '\0';
Print (CmdLine);
// To prevent a buffer overflow, we only allow to enter (MaxCmdLine-1) characters
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"\r\n");
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 if (CmdLineIndex < (MaxCmdLine-1)) {
CmdLine[CmdLineIndex++] = Key.UnicodeChar;
Print (L"%c", Key.UnicodeChar);
}
}
return EFI_SUCCESS;
}
EFI_STATUS
GetHIInputStr (
IN OUT CHAR16 *CmdLine,
IN UINTN MaxCmdLine
)
{
EFI_STATUS Status;
// For a new input just passed an empty string
CmdLine[0] = L'\0';
Status = EditHIInputStr (CmdLine, MaxCmdLine);
return Status;
}
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);
if (!EFI_ERROR(Status)) {
UnicodeStrToAsciiStr (Str, CmdLine);
}
FreePool (Str);
return Status;
}
EFI_STATUS
GetHIInputAscii (
IN OUT CHAR8 *CmdLine,
IN UINTN MaxCmdLine
)
{
// For a new input just passed an empty string
CmdLine[0] = '\0';
return EditHIInputAscii (CmdLine,MaxCmdLine);
}
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;
}
/**
Get an IPv4 address
The function asks the user for an IPv4 address. If the input
string defines a valid IPv4 address, the four bytes of the
corresponding IPv4 address are extracted from the string and returned by
the function. As long as the user does not define a valid IP
address, he is asked for one. He can always escape by
pressing ESC.
@param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if
and only if the returned value
is equal to EFI_SUCCESS
@retval EFI_SUCCESS Input completed
@retval EFI_ABORTED Editing aborted by the user
@retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to
lack of resource
**/
EFI_STATUS
GetHIInputIP (
OUT EFI_IP_ADDRESS *OutIpAddr
)
{
EFI_STATUS Status;
CHAR16 CmdLine[48];
while (TRUE) {
CmdLine[0] = '\0';
Status = EditHIInputStr (CmdLine, 48);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
}
Status = NetLibStrToIp4 (CmdLine, &OutIpAddr->v4);
if (Status == EFI_INVALID_PARAMETER) {
Print (L"Invalid address\n");
} else {
return Status;
}
}
}
/**
Edit an IPv4 address
The function displays as a string following the "%d.%d.%d.%d" format the
IPv4 address that is passed in and asks the user to modify it. If the
resulting string defines a valid IPv4 address, the four bytes of the
corresponding IPv4 address are extracted from the string and returned by
the function. As long as the user does not define a valid IP
address, he is asked for one. He can always escape by
pressing ESC.
@param[in ] EFI_IP_ADDRESS InIpAddr Input IPv4 address
@param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if
and only if the returned value
is equal to EFI_SUCCESS
@retval EFI_SUCCESS Update completed
@retval EFI_ABORTED Editing aborted by the user
@retval EFI_INVALID_PARAMETER The string returned by the user is
mal-formated
@retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to
lack of resource
**/
EFI_STATUS
EditHIInputIP (
IN EFI_IP_ADDRESS *InIpAddr,
OUT EFI_IP_ADDRESS *OutIpAddr
)
{
EFI_STATUS Status;
CHAR16 CmdLine[48];
while (TRUE) {
UnicodeSPrint (
CmdLine, 48, L"%d.%d.%d.%d",
InIpAddr->v4.Addr[0], InIpAddr->v4.Addr[1],
InIpAddr->v4.Addr[2], InIpAddr->v4.Addr[3]
);
Status = EditHIInputStr (CmdLine, 48);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
}
Status = NetLibStrToIp4 (CmdLine, &OutIpAddr->v4);
if (Status == EFI_INVALID_PARAMETER) {
Print (L"Invalid address\n");
} else {
return Status;
}
}
}
EFI_STATUS
GetHIInputBoolean (
OUT BOOLEAN *Value
)
{
CHAR16 CmdBoolean[2];
EFI_STATUS Status;
while(1) {
Print (L"[y/n] ");
Status = GetHIInputStr (CmdBoolean, 2);
if (EFI_ERROR(Status)) {
return Status;
} else if ((CmdBoolean[0] == L'y') || (CmdBoolean[0] == L'Y')) {
if (Value) *Value = TRUE;
return EFI_SUCCESS;
} else if ((CmdBoolean[0] == L'n') || (CmdBoolean[0] == L'N')) {
if (Value) *Value = FALSE;
return EFI_SUCCESS;
}
}
}
// Return the last non end-type Device Path Node from a Device Path
EFI_DEVICE_PATH*
GetLastDevicePathNode (
IN EFI_DEVICE_PATH* DevicePath
)
{
EFI_DEVICE_PATH* PrevDevicePathNode;
PrevDevicePathNode = DevicePath;
while (!IsDevicePathEndType (DevicePath)) {
PrevDevicePathNode = DevicePath;
DevicePath = NextDevicePathNode (DevicePath);
}
return PrevDevicePathNode;
}
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;
}
EFI_STATUS
BdsStartBootOption (
IN CHAR16* BootOption
)
{
EFI_STATUS Status;
BDS_LOAD_OPTION *BdsLoadOption;
Status = BootOptionFromLoadOptionVariable (BootOption, &BdsLoadOption);
if (!EFI_ERROR(Status)) {
Status = BootOptionStart (BdsLoadOption);
FreePool (BdsLoadOption);
if (!EFI_ERROR(Status)) {
Status = EFI_SUCCESS;
} else {
Status = EFI_NOT_STARTED;
}
} else {
Status = EFI_NOT_FOUND;
}
return Status;
}
UINTN
GetUnalignedDevicePathSize (
IN EFI_DEVICE_PATH* DevicePath
)
{
UINTN Size;
EFI_DEVICE_PATH* AlignedDevicePath;
if ((UINTN)DevicePath & 0x1) {
AlignedDevicePath = DuplicateDevicePath (DevicePath);
Size = GetDevicePathSize (AlignedDevicePath);
FreePool (AlignedDevicePath);
} else {
Size = GetDevicePathSize (DevicePath);
}
return Size;
}
EFI_DEVICE_PATH*
GetAlignedDevicePath (
IN EFI_DEVICE_PATH* DevicePath
)
{
if ((UINTN)DevicePath & 0x1) {
return DuplicateDevicePath (DevicePath);
} else {
return DevicePath;
}
}
BOOLEAN
IsUnicodeString (
IN VOID* String
)
{
// We do not support NULL pointer
ASSERT (String != NULL);
if (*(CHAR16*)String < 0x100) {
//Note: We could get issue if the string is an empty Ascii string...
return TRUE;
} else {
return FALSE;
}
}
/*
* Try to detect if the given string is an ASCII or Unicode string
*
* There are actually few limitation to this function but it is mainly to give
* a user friendly output.
*
* Some limitations:
* - it only supports unicode string that use ASCII character (< 0x100)
* - single character ASCII strings are interpreted as Unicode string
* - string cannot be longer than BOOT_DEVICE_OPTION_MAX characters and
* thus (BOOT_DEVICE_OPTION_MAX*2) bytes for an Unicode string and
* BOOT_DEVICE_OPTION_MAX bytes for an ASCII string.
*
* @param String Buffer that might contain a Unicode or Ascii string
* @param IsUnicode If not NULL this boolean value returns if the string is an
* ASCII or Unicode string.
*/
BOOLEAN
IsPrintableString (
IN VOID* String,
OUT BOOLEAN *IsUnicode
)
{
BOOLEAN UnicodeDetected;
BOOLEAN IsPrintable;
UINTN Index;
CHAR16 Character;
// We do not support NULL pointer
ASSERT (String != NULL);
// Test empty string
if (*(CHAR16*)String == L'\0') {
if (IsUnicode) {
*IsUnicode = TRUE;
}
return TRUE;
} else if (*(CHAR16*)String == '\0') {
if (IsUnicode) {
*IsUnicode = FALSE;
}
return TRUE;
}
// Limitation: if the string is an ASCII single character string. This comparison
// will assume it is a Unicode string.
if (*(CHAR16*)String < 0x100) {
UnicodeDetected = TRUE;
} else {
UnicodeDetected = FALSE;
}
IsPrintable = FALSE;
for (Index = 0; Index < BOOT_DEVICE_OPTION_MAX; Index++) {
if (UnicodeDetected) {
Character = ((CHAR16*)String)[Index];
} else {
Character = ((CHAR8*)String)[Index];
}
if (Character == '\0') {
// End of the string
IsPrintable = TRUE;
break;
} else if ((Character < 0x20) || (Character > 0x7f)) {
// We only support the range of printable ASCII character
IsPrintable = FALSE;
break;
}
}
if (IsPrintable && IsUnicode) {
*IsUnicode = UnicodeDetected;
}
return IsPrintable;
}

View File

@ -1,277 +0,0 @@
/** @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.
*
**/
#ifndef _BDSINTERNAL_H_
#define _BDSINTERNAL_H_
#include <PiDxe.h>
#include <Library/BaseMemoryLib.h>
#include <Library/BdsLib.h>
#include <Library/DebugLib.h>
#include <Library/DevicePathLib.h>
#include <Library/UefiLib.h>
#include <Library/PrintLib.h>
#include <Library/PcdLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Protocol/DevicePathFromText.h>
#include <Protocol/DevicePathToText.h>
#include <Guid/GlobalVariable.h>
#include <Guid/Fdt.h>
#define BOOT_DEVICE_DESCRIPTION_MAX 100
#define BOOT_DEVICE_FILEPATH_MAX 100
#define BOOT_DEVICE_OPTION_MAX 300
#define BOOT_DEVICE_ADDRESS_MAX (sizeof(L"0x0000000000000000"))
#define UPDATE_BOOT_ENTRY L"Update entry: "
#define DELETE_BOOT_ENTRY L"Delete entry: "
#define MOVE_BOOT_ENTRY L"Move entry: "
typedef struct {
LIST_ENTRY Link;
BDS_LOAD_OPTION* BdsLoadOption;
} BDS_LOAD_OPTION_ENTRY;
typedef enum {
BDS_DEVICE_FILESYSTEM = 0,
BDS_DEVICE_MEMMAP,
BDS_DEVICE_PXE,
BDS_DEVICE_TFTP,
BDS_DEVICE_MAX
} BDS_SUPPORTED_DEVICE_TYPE;
typedef struct {
LIST_ENTRY Link;
CHAR16 Description[BOOT_DEVICE_DESCRIPTION_MAX];
EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;
struct _BDS_LOAD_OPTION_SUPPORT* Support;
} BDS_SUPPORTED_DEVICE;
#define SUPPORTED_BOOT_DEVICE_FROM_LINK(a) BASE_CR(a, BDS_SUPPORTED_DEVICE, Link)
typedef struct _BDS_LOAD_OPTION_SUPPORT {
BDS_SUPPORTED_DEVICE_TYPE Type;
EFI_STATUS (*ListDevices)(IN OUT LIST_ENTRY* BdsLoadOptionList);
BOOLEAN (*IsSupported)(IN EFI_DEVICE_PATH *DevicePath);
EFI_STATUS (*CreateDevicePathNode)(IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes);
EFI_STATUS (*UpdateDevicePathNode)(IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath);
/// Define if the boot menu should request if the file is a EFI binary or a Linux kernel
/// Example: PXE boot always deliver a UEFI application.
BOOLEAN RequestBootType;
} BDS_LOAD_OPTION_SUPPORT;
#define LOAD_OPTION_ENTRY_FROM_LINK(a) BASE_CR(a, BDS_LOAD_OPTION_ENTRY, Link)
#define LOAD_OPTION_FROM_LINK(a) ((BDS_LOAD_OPTION_ENTRY*)BASE_CR(a, BDS_LOAD_OPTION_ENTRY, Link))->BdsLoadOption
// GUID of the EFI Linux Loader
extern CONST EFI_GUID mLinuxLoaderAppGuid;
// Device path of the EFI Linux Loader in the Firmware Volume
extern EFI_DEVICE_PATH* mLinuxLoaderDevicePath;
EFI_STATUS
BootDeviceListSupportedInit (
IN OUT LIST_ENTRY *SupportedDeviceList
);
EFI_STATUS
BootDeviceListSupportedFree (
IN LIST_ENTRY *SupportedDeviceList,
IN BDS_SUPPORTED_DEVICE *Except
);
EFI_STATUS
BootDeviceGetDeviceSupport (
IN EFI_DEVICE_PATH *DevicePath,
OUT BDS_LOAD_OPTION_SUPPORT **DeviceSupport
);
EFI_STATUS
GetHIInputStr (
IN OUT CHAR16 *CmdLine,
IN UINTN MaxCmdLine
);
EFI_STATUS
EditHIInputStr (
IN OUT CHAR16 *CmdLine,
IN UINTN MaxCmdLine
);
EFI_STATUS
GetHIInputAscii (
IN OUT CHAR8 *CmdLine,
IN UINTN MaxCmdLine
);
EFI_STATUS
EditHIInputAscii (
IN OUT CHAR8 *CmdLine,
IN UINTN MaxCmdLine
);
EFI_STATUS
GetHIInputInteger (
IN OUT UINTN *Integer
);
EFI_STATUS
GetHIInputIP (
OUT EFI_IP_ADDRESS *Ip
);
EFI_STATUS
EditHIInputIP (
IN EFI_IP_ADDRESS *InIpAddr,
OUT EFI_IP_ADDRESS *OutIpAddr
);
EFI_STATUS
GetHIInputBoolean (
OUT BOOLEAN *Value
);
EFI_DEVICE_PATH*
GetLastDevicePathNode (
IN EFI_DEVICE_PATH* DevicePath
);
EFI_STATUS
BdsStartBootOption (
IN CHAR16* BootOption
);
UINTN
GetUnalignedDevicePathSize (
IN EFI_DEVICE_PATH* DevicePath
);
EFI_DEVICE_PATH*
GetAlignedDevicePath (
IN EFI_DEVICE_PATH* DevicePath
);
EFI_STATUS
GenerateDeviceDescriptionName (
IN EFI_HANDLE Handle,
IN OUT CHAR16* Description
);
EFI_STATUS
BootOptionList (
IN OUT LIST_ENTRY *BootOptionList
);
EFI_STATUS
BootOptionParseLoadOption (
IN EFI_LOAD_OPTION EfiLoadOption,
IN UINTN EfiLoadOptionSize,
OUT BDS_LOAD_OPTION **BdsLoadOption
);
EFI_STATUS
BootOptionStart (
IN BDS_LOAD_OPTION *BootOption
);
EFI_STATUS
BootOptionCreate (
IN UINT32 Attributes,
IN CHAR16* BootDescription,
IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,
IN UINT8* OptionalData,
IN UINTN OptionalDataSize,
OUT BDS_LOAD_OPTION** BdsLoadOption
);
EFI_STATUS
BootOptionUpdate (
IN BDS_LOAD_OPTION* BdsLoadOption,
IN UINT32 Attributes,
IN CHAR16* BootDescription,
IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,
IN UINT8* OptionalData,
IN UINTN OptionalDataSize
);
EFI_STATUS
BootOptionDelete (
IN BDS_LOAD_OPTION *BootOption
);
EFI_STATUS
BootMenuMain (
VOID
);
BOOLEAN
IsUnicodeString (
IN VOID* String
);
/*
* Try to detect if the given string is an ASCII or Unicode string
*
* There are actually few limitation to this function but it is mainly to give
* a user friendly output.
*
* Some limitations:
* - it only supports unicode string that use ASCII character (< 0x100)
* - single character ASCII strings are interpreted as Unicode string
* - string cannot be longer than 2 x BOOT_DEVICE_OPTION_MAX (600 bytes)
*
* @param String Buffer that might contain a Unicode or Ascii string
* @param IsUnicode If not NULL this boolean value returns if the string is an
* ASCII or Unicode string.
*/
BOOLEAN
IsPrintableString (
IN VOID* String,
OUT BOOLEAN *IsUnicode
);
/**
An empty function to pass error checking of CreateEventEx ().
@param Event Event whose notification function is being invoked.
@param Context Pointer to the notification function's context,
which is implementation-dependent.
**/
VOID
EFIAPI
EmptyCallbackFunction (
IN EFI_EVENT Event,
IN VOID *Context
);
/**
* This function check if the DevicePath defines an EFI binary
*
* This function is used when the BDS support Linux loader to
* detect if the binary is an EFI application or potentially a
* Linux kernel.
*/
EFI_STATUS
IsEfiBinary (
IN EFI_DEVICE_PATH* DevicePath,
OUT BOOLEAN *EfiBinary
);
#endif /* _BDSINTERNAL_H_ */

View File

@ -1,124 +0,0 @@
/** @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 "BdsInternal.h"
// This GUID is defined in the INGF file of ArmPkg/Application/LinuxLoader
CONST EFI_GUID mLinuxLoaderAppGuid = { 0x701f54f2, 0x0d70, 0x4b89, { 0xbc, 0x0a, 0xd9, 0xca, 0x25, 0x37, 0x90, 0x59 }};
// Device path of the EFI Linux Loader in the Firmware Volume
EFI_DEVICE_PATH* mLinuxLoaderDevicePath = NULL;
STATIC
BOOLEAN
HasFilePathEfiExtension (
IN CHAR16* FilePath
)
{
return (StrCmp (FilePath + (StrSize (FilePath) / sizeof (CHAR16)) - 5, L".EFI") == 0) ||
(StrCmp (FilePath + (StrSize (FilePath) / sizeof (CHAR16)) - 5, L".efi") == 0);
}
/**
* This function check if the DevicePath defines an EFI binary
*
* This function is used when the BDS support Linux loader to
* detect if the binary is an EFI application or potentially a
* Linux kernel.
*/
EFI_STATUS
IsEfiBinary (
IN EFI_DEVICE_PATH* DevicePath,
OUT BOOLEAN *EfiBinary
)
{
EFI_STATUS Status;
CHAR16* FileName;
EFI_DEVICE_PATH* PrevDevicePathNode;
EFI_DEVICE_PATH* DevicePathNode;
EFI_PHYSICAL_ADDRESS Image;
UINTN FileSize;
EFI_IMAGE_DOS_HEADER* DosHeader;
UINTN PeCoffHeaderOffset;
EFI_IMAGE_NT_HEADERS32* NtHeader;
ASSERT (EfiBinary != NULL);
//
// Check if the last node of the device path is a FilePath node
//
PrevDevicePathNode = NULL;
DevicePathNode = DevicePath;
while ((DevicePathNode != NULL) && !IsDevicePathEnd (DevicePathNode)) {
PrevDevicePathNode = DevicePathNode;
DevicePathNode = NextDevicePathNode (DevicePathNode);
}
if ((PrevDevicePathNode != NULL) &&
(PrevDevicePathNode->Type == MEDIA_DEVICE_PATH) &&
(PrevDevicePathNode->SubType == MEDIA_FILEPATH_DP))
{
FileName = ((FILEPATH_DEVICE_PATH*)PrevDevicePathNode)->PathName;
} else {
FileName = NULL;
}
if (FileName == NULL) {
Print (L"Is an EFI Application? ");
Status = GetHIInputBoolean (EfiBinary);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
}
} else if (HasFilePathEfiExtension (FileName)) {
*EfiBinary = TRUE;
} else {
// Check if the file exist
Status = BdsLoadImage (DevicePath, AllocateAnyPages, &Image, &FileSize);
if (!EFI_ERROR (Status)) {
DosHeader = (EFI_IMAGE_DOS_HEADER *)(UINTN) Image;
if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
//
// DOS image header is present,
// so read the PE header after the DOS image header.
//
PeCoffHeaderOffset = DosHeader->e_lfanew;
} else {
PeCoffHeaderOffset = 0;
}
//
// Check PE/COFF image.
//
NtHeader = (EFI_IMAGE_NT_HEADERS32 *)(UINTN) (Image + PeCoffHeaderOffset);
if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {
*EfiBinary = FALSE;
} else {
*EfiBinary = TRUE;
}
// Free memory
gBS->FreePages (Image, EFI_SIZE_TO_PAGES (FileSize));
} else {
// If we did not manage to open it then ask for the type
Print (L"Is an EFI Application? ");
Status = GetHIInputBoolean (EfiBinary);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
}
}
}
return EFI_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,316 +0,0 @@
/** @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 "BdsInternal.h"
EFI_STATUS
BootOptionStart (
IN BDS_LOAD_OPTION *BootOption
)
{
EFI_STATUS Status;
UINT16 LoadOptionIndexSize;
// Connect all the drivers if the EFI Application is not a EFI OS Loader
if ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_APP) {
BdsConnectAllDrivers ();
}
// Set BootCurrent variable
LoadOptionIndexSize = sizeof (UINT16);
gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
LoadOptionIndexSize, &(BootOption->LoadOptionIndex));
Status = BdsStartEfiApplication (gImageHandle, BootOption->FilePathList, BootOption->OptionalDataSize, BootOption->OptionalData);
// Clear BootCurrent variable
LoadOptionIndexSize = sizeof (UINT16);
gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0, NULL);
return Status;
}
EFI_STATUS
BootOptionList (
IN OUT LIST_ENTRY *BootOptionList
)
{
EFI_STATUS Status;
UINTN Index;
UINT16* BootOrder;
UINTN BootOrderSize;
BDS_LOAD_OPTION* BdsLoadOption;
BDS_LOAD_OPTION_ENTRY* BdsLoadOptionEntry;
InitializeListHead (BootOptionList);
// Get the Boot Option Order from the environment variable
Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
if (EFI_ERROR(Status)) {
return Status;
}
for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
Status = BootOptionFromLoadOptionIndex (BootOrder[Index], &BdsLoadOption);
if (!EFI_ERROR(Status)) {
BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool(sizeof(BDS_LOAD_OPTION_ENTRY));
BdsLoadOptionEntry->BdsLoadOption = BdsLoadOption;
InsertTailList (BootOptionList,&BdsLoadOptionEntry->Link);
}
}
FreePool (BootOrder);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
BootOptionSetFields (
IN BDS_LOAD_OPTION* BootOption,
IN UINT32 Attributes,
IN CHAR16* BootDescription,
IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,
IN UINT8* OptionalData,
IN UINTN OptionalDataSize
)
{
EFI_LOAD_OPTION *EfiLoadOption;
UINTN EfiLoadOptionSize;
UINTN BootDescriptionSize;
UINT16 FilePathListLength;
UINT8* EfiLoadOptionPtr;
// If we are overwriting an existent Boot Option then we have to free previously allocated memory
if (BootOption->LoadOption) {
FreePool (BootOption->LoadOption);
}
BootDescriptionSize = StrSize (BootDescription);
// Compute the size of the FilePath list
FilePathListLength = GetUnalignedDevicePathSize (DevicePath);
// Allocate the memory for the EFI Load Option
EfiLoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + BootDescriptionSize + FilePathListLength + OptionalDataSize;
EfiLoadOption = (EFI_LOAD_OPTION *)AllocatePool(EfiLoadOptionSize);
EfiLoadOptionPtr = (UINT8 *)EfiLoadOption;
//
// Populate the EFI Load Option and BDS Boot Option structures
//
// Attributes fields
BootOption->Attributes = Attributes;
*(UINT32*)EfiLoadOptionPtr = Attributes;
EfiLoadOptionPtr += sizeof(UINT32);
// FilePath List fields
BootOption->FilePathListLength = FilePathListLength;
*(UINT16*)EfiLoadOptionPtr = FilePathListLength;
EfiLoadOptionPtr += sizeof(UINT16);
// Boot description fields
BootOption->Description = (CHAR16*)EfiLoadOptionPtr;
CopyMem (EfiLoadOptionPtr, BootDescription, BootDescriptionSize);
EfiLoadOptionPtr += BootDescriptionSize;
// File path fields
BootOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)EfiLoadOptionPtr;
CopyMem (EfiLoadOptionPtr, DevicePath, FilePathListLength);
EfiLoadOptionPtr += FilePathListLength;
// Optional Data fields, Do unaligned writes
BootOption->OptionalData = EfiLoadOptionPtr;
if (OptionalData != NULL) {
CopyMem (BootOption->OptionalData, OptionalData, OptionalDataSize);
}
BootOption->OptionalDataSize = OptionalDataSize;
// If this function is called at the creation of the Boot Device entry (not at the update) the
// BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry
if (BootOption->LoadOptionSize == 0) {
BootOption->LoadOptionIndex = BootOptionAllocateBootIndex ();
}
// Fill the EFI Load option fields
BootOption->LoadOption = EfiLoadOption;
BootOption->LoadOptionSize = EfiLoadOptionSize;
return EFI_SUCCESS;
}
EFI_STATUS
BootOptionCreate (
IN UINT32 Attributes,
IN CHAR16* BootDescription,
IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,
IN UINT8* OptionalData,
IN UINTN OptionalDataSize,
OUT BDS_LOAD_OPTION** BdsLoadOption
)
{
EFI_STATUS Status;
BDS_LOAD_OPTION_ENTRY* BootOptionEntry;
BDS_LOAD_OPTION* BootOption;
CHAR16 BootVariableName[9];
UINT16* BootOrder;
UINTN BootOrderSize;
//
// Allocate and fill the memory for the BDS Load Option structure
//
BootOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof (BDS_LOAD_OPTION_ENTRY));
InitializeListHead (&BootOptionEntry->Link);
BootOptionEntry->BdsLoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));
BootOption = BootOptionEntry->BdsLoadOption;
BootOptionSetFields (BootOption, Attributes, BootDescription, DevicePath, OptionalData, OptionalDataSize);
//
// Set the related environment variables
//
// Create Boot#### environment variable
UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOption->LoadOptionIndex);
Status = gRT->SetVariable (
BootVariableName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
BootOption->LoadOptionSize,
BootOption->LoadOption
);
// Add the new Boot Index to the list
Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
if (!EFI_ERROR(Status)) {
BootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof(UINT16), BootOrder);
// Add the new index at the end
BootOrder[BootOrderSize / sizeof(UINT16)] = BootOption->LoadOptionIndex;
BootOrderSize += sizeof(UINT16);
} else {
// BootOrder does not exist. Create it
BootOrderSize = sizeof(UINT16);
BootOrder = &(BootOption->LoadOptionIndex);
}
// Update (or Create) the BootOrder environment variable
Status = gRT->SetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
BootOrderSize,
BootOrder
);
// We only free it if the UEFI Variable 'BootOrder' was already existing
if (BootOrderSize > sizeof(UINT16)) {
FreePool (BootOrder);
}
*BdsLoadOption = BootOption;
return Status;
}
EFI_STATUS
BootOptionUpdate (
IN BDS_LOAD_OPTION* BdsLoadOption,
IN UINT32 Attributes,
IN CHAR16* BootDescription,
IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,
IN UINT8* OptionalData,
IN UINTN OptionalDataSize
)
{
EFI_STATUS Status;
CHAR16 BootVariableName[9];
// Update the BDS Load Option structure
BootOptionSetFields (BdsLoadOption, Attributes, BootDescription, DevicePath, OptionalData, OptionalDataSize);
// Update the related environment variables
UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex);
Status = gRT->SetVariable (
BootVariableName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
BdsLoadOption->LoadOptionSize,
BdsLoadOption->LoadOption
);
return Status;
}
EFI_STATUS
BootOptionDelete (
IN BDS_LOAD_OPTION *BootOption
)
{
UINTN Index;
UINTN BootOrderSize;
UINT16* BootOrder;
UINTN BootOrderCount;
CHAR16 BootVariableName[9];
EFI_STATUS Status;
// Remove the entry from the BootOrder environment variable
Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
if (!EFI_ERROR(Status)) {
BootOrderCount = BootOrderSize / sizeof(UINT16);
// Find the index of the removed entry
for (Index = 0; Index < BootOrderCount; Index++) {
if (BootOrder[Index] == BootOption->LoadOptionIndex) {
// If it the last entry we do not need to rearrange the BootOrder list
if (Index + 1 != BootOrderCount) {
CopyMem (
&BootOrder[Index],
&BootOrder[Index + 1],
(BootOrderCount - (Index + 1)) * sizeof(UINT16)
);
}
break;
}
}
// Update the BootOrder environment variable
Status = gRT->SetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
BootOrderSize - sizeof(UINT16),
BootOrder
);
}
// Delete Boot#### environment variable
UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOption->LoadOptionIndex);
Status = gRT->SetVariable (
BootVariableName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0,
NULL
);
FreePool (BootOrder);
return Status;
}

File diff suppressed because it is too large Load Diff