summaryrefslogtreecommitdiffstats
path: root/ArmPlatformPkg/Bds/BdsHelper.c
diff options
context:
space:
mode:
Diffstat (limited to 'ArmPlatformPkg/Bds/BdsHelper.c')
-rw-r--r--ArmPlatformPkg/Bds/BdsHelper.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/ArmPlatformPkg/Bds/BdsHelper.c b/ArmPlatformPkg/Bds/BdsHelper.c
new file mode 100644
index 0000000000..2f0cb31d39
--- /dev/null
+++ b/ArmPlatformPkg/Bds/BdsHelper.c
@@ -0,0 +1,307 @@
+/** @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;
+}