mirror of https://github.com/acidanthera/audk.git
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:
parent
90b10821cd
commit
c133041fa6
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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
|
@ -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
Loading…
Reference in New Issue