audk/ArmPlatformPkg/Bds/BdsHelper.c

308 lines
8.1 KiB
C

/** @file
*
* Copyright (c) 2011, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#include "BdsInternal.h"
EFI_STATUS
GetEnvironmentVariable (
IN CONST CHAR16* VariableName,
IN VOID* DefaultValue,
IN OUT UINTN* Size,
OUT VOID** Value
)
{
EFI_STATUS Status;
UINTN VariableSize;
// Try to get the variable size.
*Value = NULL;
VariableSize = 0;
Status = gRT->GetVariable ((CHAR16 *) VariableName, &gEfiGlobalVariableGuid, NULL, &VariableSize, *Value);
if (Status == EFI_NOT_FOUND) {
if ((DefaultValue != NULL) && (Size != NULL) && (*Size != 0)) {
// If the environment variable does not exist yet then set it with the default value
Status = gRT->SetVariable (
(CHAR16*)VariableName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
*Size,
DefaultValue
);
*Value = DefaultValue;
} else {
return EFI_NOT_FOUND;
}
} else if (Status == EFI_BUFFER_TOO_SMALL) {
// Get the environment variable value
*Value = AllocatePool (VariableSize);
if (*Value == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = gRT->GetVariable ((CHAR16 *)VariableName, &gEfiGlobalVariableGuid, NULL, &VariableSize, *Value);
if (EFI_ERROR (Status)) {
FreePool(*Value);
return EFI_INVALID_PARAMETER;
}
if (Size) {
*Size = VariableSize;
}
} else {
*Value = DefaultValue;
return Status;
}
return EFI_SUCCESS;
}
EFI_STATUS
EditHIInputAscii (
IN OUT CHAR8 *CmdLine,
IN UINTN MaxCmdLine
)
{
UINTN CmdLineIndex;
UINTN WaitIndex;
CHAR8 Char;
EFI_INPUT_KEY Key;
EFI_STATUS Status;
AsciiPrint (CmdLine);
for (CmdLineIndex = AsciiStrLen(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';
AsciiPrint ("\n\r");
return EFI_SUCCESS;
} else if ((Char == '\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){
if (CmdLineIndex != 0) {
CmdLineIndex--;
AsciiPrint ("\b \b");
}
} else if ((Key.ScanCode == SCAN_ESC) || (Char == 0x1B) || (Char == 0x0)) {
return EFI_INVALID_PARAMETER;
} else {
CmdLine[CmdLineIndex++] = Char;
AsciiPrint ("%c", Char);
}
}
return EFI_SUCCESS;
}
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
)
{
CHAR8 CmdLine[255];
EFI_STATUS Status;
CmdLine[0] = '\0';
Status = EditHIInputAscii (CmdLine,255);
if (!EFI_ERROR(Status)) {
*Integer = AsciiStrDecimalToUintn (CmdLine);
}
return Status;
}
EFI_STATUS
GetHIInputIP (
OUT EFI_IP_ADDRESS *Ip
)
{
CHAR8 CmdLine[255];
CHAR8 *Str;
EFI_STATUS Status;
CmdLine[0] = '\0';
Status = EditHIInputAscii (CmdLine,255);
if (!EFI_ERROR(Status)) {
Str = CmdLine;
Ip->v4.Addr[0] = (UINT8)AsciiStrDecimalToUintn (Str);
Str = AsciiStrStr (Str, ".");
if (Str == NULL) {
return EFI_INVALID_PARAMETER;
}
Ip->v4.Addr[1] = (UINT8)AsciiStrDecimalToUintn (++Str);
Str = AsciiStrStr (Str, ".");
if (Str == NULL) {
return EFI_INVALID_PARAMETER;
}
Ip->v4.Addr[2] = (UINT8)AsciiStrDecimalToUintn (++Str);
Str = AsciiStrStr (Str, ".");
if (Str == NULL) {
return EFI_INVALID_PARAMETER;
}
Ip->v4.Addr[3] = (UINT8)AsciiStrDecimalToUintn (++Str);
}
return Status;
}
EFI_STATUS
GetHIInputBoolean (
OUT BOOLEAN *Value
)
{
CHAR8 CmdBoolean[2];
EFI_STATUS Status;
while(1) {
Print (L"[y/n] ");
Status = GetHIInputAscii (CmdBoolean,2);
if (EFI_ERROR(Status)) {
return Status;
} else if ((CmdBoolean[0] == 'y') || (CmdBoolean[0] == 'Y')) {
if (Value) *Value = TRUE;
return EFI_SUCCESS;
} else if ((CmdBoolean[0] == 'n') || (CmdBoolean[0] == 'N')) {
if (Value) *Value = FALSE;
return EFI_SUCCESS;
}
}
}
BOOLEAN
HasFilePathEfiExtension (
IN CHAR16* FilePath
)
{
return (StrCmp (FilePath + (StrSize(FilePath)/sizeof(CHAR16)) - 5, L".efi") == 0);
}
// 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;
EFI_LOAD_OPTION EfiLoadOption;
UINTN EfiLoadOptionSize;
BDS_LOAD_OPTION *BdsLoadOption;
Status = GetEnvironmentVariable (BootOption, NULL, &EfiLoadOptionSize, (VOID**)&EfiLoadOption);
if (!EFI_ERROR(Status)) {
Status = BootOptionParseLoadOption (EfiLoadOption, EfiLoadOptionSize, &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;
}