+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011-2015, ARM Limited. All rights reserved.\r
-*\r
-* This program and the accompanying materials\r
-* are licensed and made available under the terms and conditions of the BSD License\r
-* which accompanies this distribution. The full text of the license may be found at\r
-* http://opensource.org/licenses/bsd-license.php\r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-\r
-#include "BdsInternal.h"\r
-\r
-#include <Library/PcdLib.h>\r
-#include <Library/PerformanceLib.h>\r
-\r
-#include <Protocol/Bds.h>\r
-\r
-#include <Guid/EventGroup.h>\r
-\r
-#define EFI_SET_TIMER_TO_SECOND 10000000\r
-\r
-STATIC\r
-EFI_STATUS\r
-GetConsoleDevicePathFromVariable (\r
- IN CHAR16* ConsoleVarName,\r
- IN CHAR16* DefaultConsolePaths,\r
- OUT EFI_DEVICE_PATH** DevicePaths\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Size;\r
- EFI_DEVICE_PATH_PROTOCOL* DevicePathInstances;\r
- EFI_DEVICE_PATH_PROTOCOL* DevicePathInstance;\r
- CHAR16* DevicePathStr;\r
- CHAR16* NextDevicePathStr;\r
- EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;\r
-\r
- Status = GetGlobalEnvironmentVariable (ConsoleVarName, NULL, NULL, (VOID**)&DevicePathInstances);\r
- if (EFI_ERROR(Status)) {\r
- // In case no default console device path has been defined we assume a driver handles the console (eg: SimpleTextInOutSerial)\r
- if ((DefaultConsolePaths == NULL) || (DefaultConsolePaths[0] == L'\0')) {\r
- *DevicePaths = NULL;\r
- return EFI_SUCCESS;\r
- }\r
-\r
- Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);\r
- ASSERT_EFI_ERROR(Status);\r
-\r
- DevicePathInstances = NULL;\r
-\r
- // Extract the Device Path instances from the multi-device path string\r
- while ((DefaultConsolePaths != NULL) && (DefaultConsolePaths[0] != L'\0')) {\r
- NextDevicePathStr = StrStr (DefaultConsolePaths, L";");\r
- if (NextDevicePathStr == NULL) {\r
- DevicePathStr = DefaultConsolePaths;\r
- DefaultConsolePaths = NULL;\r
- } else {\r
- DevicePathStr = (CHAR16*)AllocateCopyPool ((NextDevicePathStr - DefaultConsolePaths + 1) * sizeof(CHAR16), DefaultConsolePaths);\r
- *(DevicePathStr + (NextDevicePathStr - DefaultConsolePaths)) = L'\0';\r
- DefaultConsolePaths = NextDevicePathStr;\r
- if (DefaultConsolePaths[0] == L';') {\r
- DefaultConsolePaths++;\r
- }\r
- }\r
-\r
- DevicePathInstance = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (DevicePathStr);\r
- ASSERT(DevicePathInstance != NULL);\r
- DevicePathInstances = AppendDevicePathInstance (DevicePathInstances, DevicePathInstance);\r
-\r
- if (NextDevicePathStr != NULL) {\r
- FreePool (DevicePathStr);\r
- }\r
- FreePool (DevicePathInstance);\r
- }\r
-\r
- // Set the environment variable with this device path multi-instances\r
- Size = GetDevicePathSize (DevicePathInstances);\r
- if (Size > 0) {\r
- gRT->SetVariable (\r
- ConsoleVarName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- Size,\r
- DevicePathInstances\r
- );\r
- } else {\r
- Status = EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- if (!EFI_ERROR(Status)) {\r
- *DevicePaths = DevicePathInstances;\r
- }\r
- return Status;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-InitializeConsolePipe (\r
- IN EFI_DEVICE_PATH *ConsoleDevicePaths,\r
- IN EFI_GUID *Protocol,\r
- OUT EFI_HANDLE *Handle,\r
- OUT VOID* *Interface\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Size;\r
- UINTN NoHandles;\r
- EFI_HANDLE *Buffer;\r
- EFI_DEVICE_PATH_PROTOCOL* DevicePath;\r
-\r
- // Connect all the Device Path Consoles\r
- while (ConsoleDevicePaths != NULL) {\r
- DevicePath = GetNextDevicePathInstance (&ConsoleDevicePaths, &Size);\r
-\r
- Status = BdsConnectDevicePath (DevicePath, Handle, NULL);\r
- DEBUG_CODE_BEGIN();\r
- if (EFI_ERROR(Status)) {\r
- // We convert back to the text representation of the device Path\r
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
- CHAR16* DevicePathTxt;\r
- EFI_STATUS Status;\r
-\r
- Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
- if (!EFI_ERROR(Status)) {\r
- DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (DevicePath, TRUE, TRUE);\r
-\r
- DEBUG((EFI_D_ERROR,"Fail to start the console with the Device Path '%s'. (Error '%r')\n", DevicePathTxt, Status));\r
-\r
- FreePool (DevicePathTxt);\r
- }\r
- }\r
- DEBUG_CODE_END();\r
-\r
- // If the console splitter driver is not supported by the platform then use the first Device Path\r
- // instance for the console interface.\r
- if (!EFI_ERROR(Status) && (*Interface == NULL)) {\r
- Status = gBS->HandleProtocol (*Handle, Protocol, Interface);\r
- }\r
- }\r
-\r
- // No Device Path has been defined for this console interface. We take the first protocol implementation\r
- if (*Interface == NULL) {\r
- Status = gBS->LocateHandleBuffer (ByProtocol, Protocol, NULL, &NoHandles, &Buffer);\r
- if (EFI_ERROR (Status)) {\r
- BdsConnectAllDrivers();\r
- Status = gBS->LocateHandleBuffer (ByProtocol, Protocol, NULL, &NoHandles, &Buffer);\r
- }\r
-\r
- if (!EFI_ERROR(Status)) {\r
- *Handle = Buffer[0];\r
- Status = gBS->HandleProtocol (*Handle, Protocol, Interface);\r
- ASSERT_EFI_ERROR(Status);\r
- FreePool (Buffer);\r
- }\r
- } else {\r
- Status = EFI_SUCCESS;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-InitializeConsole (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH* ConOutDevicePaths;\r
- EFI_DEVICE_PATH* ConInDevicePaths;\r
- EFI_DEVICE_PATH* ConErrDevicePaths;\r
-\r
- // By getting the Console Device Paths from the environment variables before initializing the console pipe, we\r
- // create the 3 environment variables (ConIn, ConOut, ConErr) that allows to initialize all the console interface\r
- // of newly installed console drivers\r
- Status = GetConsoleDevicePathFromVariable (L"ConOut", (CHAR16*)PcdGetPtr(PcdDefaultConOutPaths), &ConOutDevicePaths);\r
- ASSERT_EFI_ERROR (Status);\r
- Status = GetConsoleDevicePathFromVariable (L"ConIn", (CHAR16*)PcdGetPtr(PcdDefaultConInPaths), &ConInDevicePaths);\r
- ASSERT_EFI_ERROR (Status);\r
- Status = GetConsoleDevicePathFromVariable (L"ErrOut", (CHAR16*)PcdGetPtr(PcdDefaultConOutPaths), &ConErrDevicePaths);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- // Initialize the Consoles\r
- Status = InitializeConsolePipe (ConOutDevicePaths, &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **)&gST->ConOut);\r
- ASSERT_EFI_ERROR (Status);\r
- Status = InitializeConsolePipe (ConInDevicePaths, &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **)&gST->ConIn);\r
- ASSERT_EFI_ERROR (Status);\r
- Status = InitializeConsolePipe (ConErrDevicePaths, &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **)&gST->StdErr);\r
- if (EFI_ERROR(Status)) {\r
- // In case of error, we reuse the console output for the error output\r
- gST->StandardErrorHandle = gST->ConsoleOutHandle;\r
- gST->StdErr = gST->ConOut;\r
- }\r
-\r
- // Free Memory allocated for reading the UEFI Variables\r
- if (ConOutDevicePaths) {\r
- FreePool (ConOutDevicePaths);\r
- }\r
- if (ConInDevicePaths) {\r
- FreePool (ConInDevicePaths);\r
- }\r
- if (ConErrDevicePaths) {\r
- FreePool (ConErrDevicePaths);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-DefineDefaultBootEntries (\r
- VOID\r
- )\r
-{\r
- BDS_LOAD_OPTION* BdsLoadOption;\r
- UINTN Size;\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol;\r
- EFI_DEVICE_PATH* BootDevicePath;\r
- UINTN CmdLineSize;\r
- UINTN CmdLineAsciiSize;\r
- CHAR16* DefaultBootArgument;\r
- CHAR8* AsciiDefaultBootArgument;\r
-\r
- //\r
- // If Boot Order does not exist then create a default entry\r
- //\r
- Size = 0;\r
- Status = gRT->GetVariable (L"BootOrder", &gEfiGlobalVariableGuid, NULL, &Size, NULL);\r
- if (Status == EFI_NOT_FOUND) {\r
- if ((PcdGetPtr(PcdDefaultBootDevicePath) == NULL) || (StrLen ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath)) == 0)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);\r
- if (EFI_ERROR(Status)) {\r
- // You must provide an implementation of DevicePathFromTextProtocol in your firmware (eg: DevicePathDxe)\r
- DEBUG((EFI_D_ERROR,"Error: Bds requires DevicePathFromTextProtocol\n"));\r
- return Status;\r
- }\r
- BootDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath));\r
-\r
- DEBUG_CODE_BEGIN();\r
- // We convert back to the text representation of the device Path to see if the initial text is correct\r
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
- CHAR16* DevicePathTxt;\r
-\r
- Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
- ASSERT_EFI_ERROR(Status);\r
- DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (BootDevicePath, TRUE, TRUE);\r
-\r
- if (StrCmp ((CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath), DevicePathTxt) != 0) {\r
- DEBUG ((EFI_D_ERROR, "Device Path given: '%s' Device Path expected: '%s'\n",\r
- (CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath), DevicePathTxt));\r
- ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);\r
- }\r
-\r
- FreePool (DevicePathTxt);\r
- DEBUG_CODE_END();\r
-\r
- // Create the entry is the Default values are correct\r
- if (BootDevicePath != NULL) {\r
- // We do not support NULL pointer\r
- ASSERT (PcdGetPtr (PcdDefaultBootArgument) != NULL);\r
-\r
- //\r
- // Logic to handle ASCII or Unicode default parameters\r
- //\r
- if (*(CHAR8*)PcdGetPtr (PcdDefaultBootArgument) == '\0') {\r
- CmdLineSize = 0;\r
- CmdLineAsciiSize = 0;\r
- DefaultBootArgument = NULL;\r
- AsciiDefaultBootArgument = NULL;\r
- } else if (IsUnicodeString ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument))) {\r
- // The command line is a Unicode string\r
- DefaultBootArgument = (CHAR16*)PcdGetPtr (PcdDefaultBootArgument);\r
- CmdLineSize = StrSize (DefaultBootArgument);\r
-\r
- // Initialize ASCII variables\r
- CmdLineAsciiSize = CmdLineSize / 2;\r
- AsciiDefaultBootArgument = AllocatePool (CmdLineAsciiSize);\r
- if (AsciiDefaultBootArgument == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- UnicodeStrToAsciiStr ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument), AsciiDefaultBootArgument);\r
- } else {\r
- // The command line is a ASCII string\r
- AsciiDefaultBootArgument = (CHAR8*)PcdGetPtr (PcdDefaultBootArgument);\r
- CmdLineAsciiSize = AsciiStrSize (AsciiDefaultBootArgument);\r
-\r
- // Initialize ASCII variables\r
- CmdLineSize = CmdLineAsciiSize * 2;\r
- DefaultBootArgument = AllocatePool (CmdLineSize);\r
- if (DefaultBootArgument == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- AsciiStrToUnicodeStr (AsciiDefaultBootArgument, DefaultBootArgument);\r
- }\r
-\r
- BootOptionCreate (LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT,\r
- (CHAR16*)PcdGetPtr (PcdDefaultBootDescription),\r
- BootDevicePath,\r
- (UINT8 *)DefaultBootArgument, // OptionalData\r
- CmdLineSize, // OptionalDataSize\r
- &BdsLoadOption\r
- );\r
- FreePool (BdsLoadOption);\r
-\r
- if (DefaultBootArgument == (CHAR16*)PcdGetPtr (PcdDefaultBootArgument)) {\r
- FreePool (AsciiDefaultBootArgument);\r
- } else if (DefaultBootArgument != NULL) {\r
- FreePool (DefaultBootArgument);\r
- }\r
- } else {\r
- Status = EFI_UNSUPPORTED;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-StartDefaultBootOnTimeout (\r
- VOID\r
- )\r
-{\r
- UINTN Size;\r
- UINT16 Timeout;\r
- UINT16 *TimeoutPtr;\r
- EFI_EVENT WaitList[2];\r
- UINTN WaitIndex;\r
- UINT16 *BootOrder;\r
- UINTN BootOrderSize;\r
- UINTN Index;\r
- CHAR16 BootVariableName[9];\r
- EFI_STATUS Status;\r
- EFI_INPUT_KEY Key;\r
-\r
- Size = sizeof(UINT16);\r
- Timeout = (UINT16)PcdGet16 (PcdPlatformBootTimeOut);\r
- Status = GetGlobalEnvironmentVariable (L"Timeout", &Timeout, &Size, (VOID**)&TimeoutPtr);\r
- if (!EFI_ERROR (Status)) {\r
- Timeout = *TimeoutPtr;\r
- FreePool (TimeoutPtr);\r
- }\r
-\r
- if (Timeout != 0xFFFF) {\r
- if (Timeout > 0) {\r
- // Create the waiting events (keystroke and 1sec timer)\r
- gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &WaitList[0]);\r
- gBS->SetTimer (WaitList[0], TimerPeriodic, EFI_SET_TIMER_TO_SECOND);\r
- WaitList[1] = gST->ConIn->WaitForKey;\r
-\r
- // Start the timer\r
- WaitIndex = 0;\r
- Print(L"The default boot selection will start in ");\r
- while ((Timeout > 0) && (WaitIndex == 0)) {\r
- Print(L"%3d seconds",Timeout);\r
- gBS->WaitForEvent (2, WaitList, &WaitIndex);\r
- if (WaitIndex == 0) {\r
- Print(L"\b\b\b\b\b\b\b\b\b\b\b");\r
- Timeout--;\r
- }\r
- }\r
- // Discard key in the buffer\r
- do {\r
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
- } while(!EFI_ERROR(Status));\r
- gBS->CloseEvent (WaitList[0]);\r
- Print(L"\n\r");\r
- }\r
-\r
- // In case of Timeout we start the default boot selection\r
- if (Timeout == 0) {\r
- // Get the Boot Option Order from the environment variable (a default value should have been created)\r
- GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
-\r
- for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
- UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOrder[Index]);\r
- Status = BdsStartBootOption (BootVariableName);\r
- if(!EFI_ERROR(Status)){\r
- // Boot option returned successfully, hence don't need to start next boot option\r
- break;\r
- }\r
- // In case of success, we should not return from this call.\r
- }\r
- FreePool (BootOrder);\r
- }\r
- }\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- An empty function to pass error checking of CreateEventEx ().\r
-\r
- @param Event Event whose notification function is being invoked.\r
- @param Context Pointer to the notification function's context,\r
- which is implementation-dependent.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-EmptyCallbackFunction (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- return;\r
-}\r
-\r
-/**\r
- This function uses policy data from the platform to determine what operating\r
- system or system utility should be loaded and invoked. This function call\r
- also optionally make the use of user input to determine the operating system\r
- or system utility to be loaded and invoked. When the DXE Core has dispatched\r
- all the drivers on the dispatch queue, this function is called. This\r
- function will attempt to connect the boot devices required to load and invoke\r
- the selected operating system or system utility. During this process,\r
- additional firmware volumes may be discovered that may contain addition DXE\r
- drivers that can be dispatched by the DXE Core. If a boot device cannot be\r
- fully connected, this function calls the DXE Service Dispatch() to allow the\r
- DXE drivers from any newly discovered firmware volumes to be dispatched.\r
- Then the boot device connection can be attempted again. If the same boot\r
- device connection operation fails twice in a row, then that boot device has\r
- failed, and should be skipped. This function should never return.\r
-\r
- @param This The EFI_BDS_ARCH_PROTOCOL instance.\r
-\r
- @return None.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-BdsEntry (\r
- IN EFI_BDS_ARCH_PROTOCOL *This\r
- )\r
-{\r
- UINTN Size;\r
- EFI_STATUS Status;\r
- UINT16 *BootNext;\r
- UINTN BootNextSize;\r
- CHAR16 BootVariableName[9];\r
- EFI_EVENT EndOfDxeEvent;\r
-\r
- //\r
- // Signal EndOfDxe PI Event\r
- //\r
- Status = gBS->CreateEventEx (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- EmptyCallbackFunction,\r
- NULL,\r
- &gEfiEndOfDxeEventGroupGuid,\r
- &EndOfDxeEvent\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- gBS->SignalEvent (EndOfDxeEvent);\r
- }\r
-\r
- PERF_END (NULL, "DXE", NULL, 0);\r
-\r
- //\r
- // Declare the Firmware Vendor\r
- //\r
- if (FixedPcdGetPtr(PcdFirmwareVendor) != NULL) {\r
- Size = 0x100;\r
- gST->FirmwareVendor = AllocateRuntimePool (Size);\r
- ASSERT (gST->FirmwareVendor != NULL);\r
- UnicodeSPrint (gST->FirmwareVendor, Size, L"%a EFI %a %a", PcdGetPtr(PcdFirmwareVendor), __DATE__, __TIME__);\r
- }\r
-\r
- //\r
- // Fixup Table CRC after we updated Firmware Vendor\r
- //\r
- gST->Hdr.CRC32 = 0;\r
- Status = gBS->CalculateCrc32 ((VOID*)gST, gST->Hdr.HeaderSize, &gST->Hdr.CRC32);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- // Now we need to setup the EFI System Table with information about the console devices.\r
- InitializeConsole ();\r
-\r
- // If BootNext environment variable is defined then we just load it !\r
- BootNextSize = sizeof(UINT16);\r
- Status = GetGlobalEnvironmentVariable (L"BootNext", NULL, &BootNextSize, (VOID**)&BootNext);\r
- if (!EFI_ERROR(Status)) {\r
- ASSERT(BootNextSize == sizeof(UINT16));\r
-\r
- // Generate the requested Boot Entry variable name\r
- UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", *BootNext);\r
-\r
- // Set BootCurrent variable\r
- gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- BootNextSize, BootNext);\r
-\r
- FreePool (BootNext);\r
-\r
- // Start the requested Boot Entry\r
- Status = BdsStartBootOption (BootVariableName);\r
- if (Status != EFI_NOT_FOUND) {\r
- // BootNext has not been succeeded launched\r
- if (EFI_ERROR(Status)) {\r
- Print(L"Fail to start BootNext.\n");\r
- }\r
-\r
- // Delete the BootNext environment variable\r
- gRT->SetVariable (L"BootNext", &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- 0, NULL);\r
- }\r
-\r
- // Clear BootCurrent variable\r
- gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- 0, NULL);\r
- }\r
-\r
- // If Boot Order does not exist then create a default entry\r
- DefineDefaultBootEntries ();\r
-\r
- //\r
- // Update the CRC32 in the EFI System Table header\r
- //\r
- gST->Hdr.CRC32 = 0;\r
- Status = gBS->CalculateCrc32 ((VOID*)gST, gST->Hdr.HeaderSize, &gST->Hdr.CRC32);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- // Timer before initiating the default boot selection\r
- StartDefaultBootOnTimeout ();\r
-\r
- // Start the Boot Menu\r
- Status = BootMenuMain ();\r
- ASSERT_EFI_ERROR (Status);\r
-\r
-}\r
-\r
-EFI_BDS_ARCH_PROTOCOL gBdsProtocol = {\r
- BdsEntry,\r
-};\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-BdsInitialize (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &ImageHandle,\r
- &gEfiBdsArchProtocolGuid, &gBdsProtocol,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-#/** @file\r
-#\r
-# Component description file for Bds module\r
-#\r
-# Copyright (c) 2011-2015, ARM Ltd. All rights reserved.<BR>\r
-#\r
-# This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this distribution. The full text of the license may be found at\r
-# http://opensource.org/licenses/bsd-license.php\r
-#\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#\r
-#**/\r
-\r
-\r
-[Defines]\r
- INF_VERSION = 0x00010005\r
- BASE_NAME = ArmPlatformBds\r
- FILE_GUID = 5a50aa81-c3ae-4608-a0e3-41a2e69baf94\r
- MODULE_TYPE = DXE_DRIVER\r
- VERSION_STRING = 1.0\r
-\r
- ENTRY_POINT = BdsInitialize\r
-\r
-[Sources]\r
- Bds.c\r
- BdsHelper.c\r
- BootLinux.c\r
- BootMenu.c\r
- BootOption.c\r
- BootOptionSupport.c\r
-\r
-[Packages]\r
- MdePkg/MdePkg.dec\r
- MdeModulePkg/MdeModulePkg.dec\r
- ArmPkg/ArmPkg.dec\r
- ArmPlatformPkg/ArmPlatformPkg.dec\r
- EmbeddedPkg/EmbeddedPkg.dec\r
- IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
-\r
-[Guids]\r
- gFdtTableGuid\r
-\r
-[LibraryClasses]\r
- BdsLib\r
- UefiBootServicesTableLib\r
- DxeServicesTableLib\r
- UefiDriverEntryPoint\r
- DebugLib\r
- PerformanceLib\r
- PrintLib\r
- BaseLib\r
- FdtLib\r
- NetLib\r
-\r
-[Guids]\r
- gEfiEndOfDxeEventGroupGuid\r
- gEfiFileSystemInfoGuid\r
- gFdtVariableGuid\r
-\r
-[Protocols]\r
- gEfiBdsArchProtocolGuid\r
- gEfiBlockIoProtocolGuid\r
- gEfiSimpleTextInProtocolGuid\r
- gEfiPxeBaseCodeProtocolGuid\r
- gEfiSimpleNetworkProtocolGuid\r
- gEfiDevicePathToTextProtocolGuid\r
- gEfiFirmwareVolumeBlockProtocolGuid\r
- gEfiFirmwareVolumeBlock2ProtocolGuid\r
- gEfiDhcp4ServiceBindingProtocolGuid\r
- gEfiMtftp4ServiceBindingProtocolGuid\r
-\r
-[FeaturePcd]\r
- gArmPlatformTokenSpaceGuid.PcdBdsLinuxSupport\r
-\r
-[Pcd]\r
- gArmPlatformTokenSpaceGuid.PcdFirmwareVendor\r
- gArmPlatformTokenSpaceGuid.PcdDefaultBootDescription\r
- gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath\r
- gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument\r
- gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut\r
- gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths\r
- gArmPlatformTokenSpaceGuid.PcdDefaultConOutPaths\r
-\r
- gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile\r
-\r
-[Depex]\r
- TRUE\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.\r
-*\r
-* This program and the accompanying materials\r
-* are licensed and made available under the terms and conditions of the BSD License\r
-* which accompanies this distribution. The full text of the license may be found at\r
-* http://opensource.org/licenses/bsd-license.php\r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-\r
-#include <Library/NetLib.h>\r
-#include "BdsInternal.h"\r
-\r
-EFI_STATUS\r
-EditHIInputStr (\r
- IN OUT CHAR16 *CmdLine,\r
- IN UINTN MaxCmdLine\r
- )\r
-{\r
- UINTN CmdLineIndex;\r
- UINTN WaitIndex;\r
- CHAR8 Char;\r
- EFI_INPUT_KEY Key;\r
- EFI_STATUS Status;\r
-\r
- // The command line must be at least one character long\r
- ASSERT (MaxCmdLine > 0);\r
-\r
- // Ensure the last character of the buffer is the NULL character\r
- CmdLine[MaxCmdLine - 1] = '\0';\r
-\r
- Print (CmdLine);\r
-\r
- // To prevent a buffer overflow, we only allow to enter (MaxCmdLine-1) characters\r
- for (CmdLineIndex = StrLen (CmdLine); CmdLineIndex < MaxCmdLine; ) {\r
- Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- // Unicode character is valid when Scancode is NUll\r
- if (Key.ScanCode == SCAN_NULL) {\r
- // Scan code is NUll, hence read Unicode character\r
- Char = (CHAR8)Key.UnicodeChar;\r
- } else {\r
- Char = CHAR_NULL;\r
- }\r
-\r
- if ((Char == CHAR_LINEFEED) || (Char == CHAR_CARRIAGE_RETURN) || (Char == 0x7f)) {\r
- CmdLine[CmdLineIndex] = '\0';\r
- Print (L"\r\n");\r
-\r
- return EFI_SUCCESS;\r
- } else if ((Key.UnicodeChar == L'\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){\r
- if (CmdLineIndex != 0) {\r
- CmdLineIndex--;\r
- Print (L"\b \b");\r
- }\r
- } else if ((Key.ScanCode == SCAN_ESC) || (Char == 0x1B) || (Char == 0x0)) {\r
- return EFI_INVALID_PARAMETER;\r
- } else if (CmdLineIndex < (MaxCmdLine-1)) {\r
- CmdLine[CmdLineIndex++] = Key.UnicodeChar;\r
- Print (L"%c", Key.UnicodeChar);\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-GetHIInputStr (\r
- IN OUT CHAR16 *CmdLine,\r
- IN UINTN MaxCmdLine\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- // For a new input just passed an empty string\r
- CmdLine[0] = L'\0';\r
-\r
- Status = EditHIInputStr (CmdLine, MaxCmdLine);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EditHIInputAscii (\r
- IN OUT CHAR8 *CmdLine,\r
- IN UINTN MaxCmdLine\r
- )\r
-{\r
- CHAR16* Str;\r
- EFI_STATUS Status;\r
-\r
- Str = (CHAR16*)AllocatePool (MaxCmdLine * sizeof(CHAR16));\r
- AsciiStrToUnicodeStr (CmdLine, Str);\r
-\r
- Status = EditHIInputStr (Str, MaxCmdLine);\r
- if (!EFI_ERROR(Status)) {\r
- UnicodeStrToAsciiStr (Str, CmdLine);\r
- }\r
- FreePool (Str);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-GetHIInputAscii (\r
- IN OUT CHAR8 *CmdLine,\r
- IN UINTN MaxCmdLine\r
- )\r
-{\r
- // For a new input just passed an empty string\r
- CmdLine[0] = '\0';\r
-\r
- return EditHIInputAscii (CmdLine,MaxCmdLine);\r
-}\r
-\r
-EFI_STATUS\r
-GetHIInputInteger (\r
- OUT UINTN *Integer\r
- )\r
-{\r
- CHAR16 CmdLine[255];\r
- EFI_STATUS Status;\r
-\r
- CmdLine[0] = '\0';\r
- Status = EditHIInputStr (CmdLine, 255);\r
- if (!EFI_ERROR(Status)) {\r
- *Integer = StrDecimalToUintn (CmdLine);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Get an IPv4 address\r
-\r
- The function asks the user for an IPv4 address. If the input\r
- string defines a valid IPv4 address, the four bytes of the\r
- corresponding IPv4 address are extracted from the string and returned by\r
- the function. As long as the user does not define a valid IP\r
- address, he is asked for one. He can always escape by\r
- pressing ESC.\r
-\r
- @param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if\r
- and only if the returned value\r
- is equal to EFI_SUCCESS\r
-\r
- @retval EFI_SUCCESS Input completed\r
- @retval EFI_ABORTED Editing aborted by the user\r
- @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to\r
- lack of resource\r
-**/\r
-EFI_STATUS\r
-GetHIInputIP (\r
- OUT EFI_IP_ADDRESS *OutIpAddr\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 CmdLine[48];\r
-\r
- while (TRUE) {\r
- CmdLine[0] = '\0';\r
- Status = EditHIInputStr (CmdLine, 48);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- Status = NetLibStrToIp4 (CmdLine, &OutIpAddr->v4);\r
- if (Status == EFI_INVALID_PARAMETER) {\r
- Print (L"Invalid address\n");\r
- } else {\r
- return Status;\r
- }\r
- }\r
-}\r
-\r
-/**\r
- Edit an IPv4 address\r
-\r
- The function displays as a string following the "%d.%d.%d.%d" format the\r
- IPv4 address that is passed in and asks the user to modify it. If the\r
- resulting string defines a valid IPv4 address, the four bytes of the\r
- corresponding IPv4 address are extracted from the string and returned by\r
- the function. As long as the user does not define a valid IP\r
- address, he is asked for one. He can always escape by\r
- pressing ESC.\r
-\r
- @param[in ] EFI_IP_ADDRESS InIpAddr Input IPv4 address\r
- @param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if\r
- and only if the returned value\r
- is equal to EFI_SUCCESS\r
-\r
- @retval EFI_SUCCESS Update completed\r
- @retval EFI_ABORTED Editing aborted by the user\r
- @retval EFI_INVALID_PARAMETER The string returned by the user is\r
- mal-formated\r
- @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to\r
- lack of resource\r
-**/\r
-EFI_STATUS\r
-EditHIInputIP (\r
- IN EFI_IP_ADDRESS *InIpAddr,\r
- OUT EFI_IP_ADDRESS *OutIpAddr\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 CmdLine[48];\r
-\r
- while (TRUE) {\r
- UnicodeSPrint (\r
- CmdLine, 48, L"%d.%d.%d.%d",\r
- InIpAddr->v4.Addr[0], InIpAddr->v4.Addr[1],\r
- InIpAddr->v4.Addr[2], InIpAddr->v4.Addr[3]\r
- );\r
-\r
- Status = EditHIInputStr (CmdLine, 48);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_ABORTED;\r
- }\r
- Status = NetLibStrToIp4 (CmdLine, &OutIpAddr->v4);\r
- if (Status == EFI_INVALID_PARAMETER) {\r
- Print (L"Invalid address\n");\r
- } else {\r
- return Status;\r
- }\r
- }\r
-}\r
-\r
-EFI_STATUS\r
-GetHIInputBoolean (\r
- OUT BOOLEAN *Value\r
- )\r
-{\r
- CHAR16 CmdBoolean[2];\r
- EFI_STATUS Status;\r
-\r
- while(1) {\r
- Print (L"[y/n] ");\r
- Status = GetHIInputStr (CmdBoolean, 2);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- } else if ((CmdBoolean[0] == L'y') || (CmdBoolean[0] == L'Y')) {\r
- if (Value) *Value = TRUE;\r
- return EFI_SUCCESS;\r
- } else if ((CmdBoolean[0] == L'n') || (CmdBoolean[0] == L'N')) {\r
- if (Value) *Value = FALSE;\r
- return EFI_SUCCESS;\r
- }\r
- }\r
-}\r
-\r
-// Return the last non end-type Device Path Node from a Device Path\r
-EFI_DEVICE_PATH*\r
-GetLastDevicePathNode (\r
- IN EFI_DEVICE_PATH* DevicePath\r
- )\r
-{\r
- EFI_DEVICE_PATH* PrevDevicePathNode;\r
-\r
- PrevDevicePathNode = DevicePath;\r
- while (!IsDevicePathEndType (DevicePath)) {\r
- PrevDevicePathNode = DevicePath;\r
- DevicePath = NextDevicePathNode (DevicePath);\r
- }\r
-\r
- return PrevDevicePathNode;\r
-}\r
-\r
-EFI_STATUS\r
-GenerateDeviceDescriptionName (\r
- IN EFI_HANDLE Handle,\r
- IN OUT CHAR16* Description\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_COMPONENT_NAME_PROTOCOL* ComponentName2Protocol;\r
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
- EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
- CHAR16* DriverName;\r
- CHAR16* DevicePathTxt;\r
- EFI_DEVICE_PATH* DevicePathNode;\r
-\r
- ComponentName2Protocol = NULL;\r
- Status = gBS->HandleProtocol (Handle, &gEfiComponentName2ProtocolGuid, (VOID **)&ComponentName2Protocol);\r
- if (!EFI_ERROR(Status)) {\r
- //TODO: Fixme. we must find the best langague\r
- Status = ComponentName2Protocol->GetDriverName (ComponentName2Protocol,"en",&DriverName);\r
- if (!EFI_ERROR(Status)) {\r
- StrnCpy (Description, DriverName, BOOT_DEVICE_DESCRIPTION_MAX);\r
- }\r
- }\r
-\r
- if (EFI_ERROR(Status)) {\r
- // Use the lastest non null entry of the Device path as a description\r
- Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- // Convert the last non end-type Device Path Node in text for the description\r
- DevicePathNode = GetLastDevicePathNode (DevicePathProtocol);\r
- Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
- ASSERT_EFI_ERROR(Status);\r
- DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (DevicePathNode, TRUE, TRUE);\r
- StrnCpy (Description, DevicePathTxt, BOOT_DEVICE_DESCRIPTION_MAX);\r
- FreePool (DevicePathTxt);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-BdsStartBootOption (\r
- IN CHAR16* BootOption\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BDS_LOAD_OPTION *BdsLoadOption;\r
-\r
- Status = BootOptionFromLoadOptionVariable (BootOption, &BdsLoadOption);\r
- if (!EFI_ERROR(Status)) {\r
- Status = BootOptionStart (BdsLoadOption);\r
- FreePool (BdsLoadOption);\r
-\r
- if (!EFI_ERROR(Status)) {\r
- Status = EFI_SUCCESS;\r
- } else {\r
- Status = EFI_NOT_STARTED;\r
- }\r
- } else {\r
- Status = EFI_NOT_FOUND;\r
- }\r
- return Status;\r
-}\r
-\r
-UINTN\r
-GetUnalignedDevicePathSize (\r
- IN EFI_DEVICE_PATH* DevicePath\r
- )\r
-{\r
- UINTN Size;\r
- EFI_DEVICE_PATH* AlignedDevicePath;\r
-\r
- if ((UINTN)DevicePath & 0x1) {\r
- AlignedDevicePath = DuplicateDevicePath (DevicePath);\r
- Size = GetDevicePathSize (AlignedDevicePath);\r
- FreePool (AlignedDevicePath);\r
- } else {\r
- Size = GetDevicePathSize (DevicePath);\r
- }\r
- return Size;\r
-}\r
-\r
-EFI_DEVICE_PATH*\r
-GetAlignedDevicePath (\r
- IN EFI_DEVICE_PATH* DevicePath\r
- )\r
-{\r
- if ((UINTN)DevicePath & 0x1) {\r
- return DuplicateDevicePath (DevicePath);\r
- } else {\r
- return DevicePath;\r
- }\r
-}\r
-\r
-BOOLEAN\r
-IsUnicodeString (\r
- IN VOID* String\r
- )\r
-{\r
- // We do not support NULL pointer\r
- ASSERT (String != NULL);\r
-\r
- if (*(CHAR16*)String < 0x100) {\r
- //Note: We could get issue if the string is an empty Ascii string...\r
- return TRUE;\r
- } else {\r
- return FALSE;\r
- }\r
-}\r
-\r
-/*\r
- * Try to detect if the given string is an ASCII or Unicode string\r
- *\r
- * There are actually few limitation to this function but it is mainly to give\r
- * a user friendly output.\r
- *\r
- * Some limitations:\r
- * - it only supports unicode string that use ASCII character (< 0x100)\r
- * - single character ASCII strings are interpreted as Unicode string\r
- * - string cannot be longer than BOOT_DEVICE_OPTION_MAX characters and\r
- * thus (BOOT_DEVICE_OPTION_MAX*2) bytes for an Unicode string and\r
- * BOOT_DEVICE_OPTION_MAX bytes for an ASCII string.\r
- *\r
- * @param String Buffer that might contain a Unicode or Ascii string\r
- * @param IsUnicode If not NULL this boolean value returns if the string is an\r
- * ASCII or Unicode string.\r
- */\r
-BOOLEAN\r
-IsPrintableString (\r
- IN VOID* String,\r
- OUT BOOLEAN *IsUnicode\r
- )\r
-{\r
- BOOLEAN UnicodeDetected;\r
- BOOLEAN IsPrintable;\r
- UINTN Index;\r
- CHAR16 Character;\r
-\r
- // We do not support NULL pointer\r
- ASSERT (String != NULL);\r
-\r
- // Test empty string\r
- if (*(CHAR16*)String == L'\0') {\r
- if (IsUnicode) {\r
- *IsUnicode = TRUE;\r
- }\r
- return TRUE;\r
- } else if (*(CHAR16*)String == '\0') {\r
- if (IsUnicode) {\r
- *IsUnicode = FALSE;\r
- }\r
- return TRUE;\r
- }\r
-\r
- // Limitation: if the string is an ASCII single character string. This comparison\r
- // will assume it is a Unicode string.\r
- if (*(CHAR16*)String < 0x100) {\r
- UnicodeDetected = TRUE;\r
- } else {\r
- UnicodeDetected = FALSE;\r
- }\r
-\r
- IsPrintable = FALSE;\r
- for (Index = 0; Index < BOOT_DEVICE_OPTION_MAX; Index++) {\r
- if (UnicodeDetected) {\r
- Character = ((CHAR16*)String)[Index];\r
- } else {\r
- Character = ((CHAR8*)String)[Index];\r
- }\r
-\r
- if (Character == '\0') {\r
- // End of the string\r
- IsPrintable = TRUE;\r
- break;\r
- } else if ((Character < 0x20) || (Character > 0x7f)) {\r
- // We only support the range of printable ASCII character\r
- IsPrintable = FALSE;\r
- break;\r
- }\r
- }\r
-\r
- if (IsPrintable && IsUnicode) {\r
- *IsUnicode = UnicodeDetected;\r
- }\r
-\r
- return IsPrintable;\r
-}\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011-2015, ARM Limited. All rights reserved.\r
-*\r
-* This program and the accompanying materials\r
-* are licensed and made available under the terms and conditions of the BSD License\r
-* which accompanies this distribution. The full text of the license may be found at\r
-* http://opensource.org/licenses/bsd-license.php\r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-\r
-#ifndef _BDSINTERNAL_H_\r
-#define _BDSINTERNAL_H_\r
-\r
-#include <PiDxe.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/BdsLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/PrintLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-\r
-#include <Protocol/DevicePathFromText.h>\r
-#include <Protocol/DevicePathToText.h>\r
-\r
-#include <Guid/GlobalVariable.h>\r
-#include <Guid/Fdt.h>\r
-\r
-#define BOOT_DEVICE_DESCRIPTION_MAX 100\r
-#define BOOT_DEVICE_FILEPATH_MAX 100\r
-#define BOOT_DEVICE_OPTION_MAX 300\r
-#define BOOT_DEVICE_ADDRESS_MAX (sizeof(L"0x0000000000000000"))\r
-\r
-#define UPDATE_BOOT_ENTRY L"Update entry: "\r
-#define DELETE_BOOT_ENTRY L"Delete entry: "\r
-#define MOVE_BOOT_ENTRY L"Move entry: "\r
-\r
-typedef struct {\r
- LIST_ENTRY Link;\r
- BDS_LOAD_OPTION* BdsLoadOption;\r
-} BDS_LOAD_OPTION_ENTRY;\r
-\r
-typedef enum {\r
- BDS_DEVICE_FILESYSTEM = 0,\r
- BDS_DEVICE_MEMMAP,\r
- BDS_DEVICE_PXE,\r
- BDS_DEVICE_TFTP,\r
- BDS_DEVICE_MAX\r
-} BDS_SUPPORTED_DEVICE_TYPE;\r
-\r
-typedef struct {\r
- LIST_ENTRY Link;\r
- CHAR16 Description[BOOT_DEVICE_DESCRIPTION_MAX];\r
- EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
- struct _BDS_LOAD_OPTION_SUPPORT* Support;\r
-} BDS_SUPPORTED_DEVICE;\r
-\r
-#define SUPPORTED_BOOT_DEVICE_FROM_LINK(a) BASE_CR(a, BDS_SUPPORTED_DEVICE, Link)\r
-\r
-typedef struct _BDS_LOAD_OPTION_SUPPORT {\r
- BDS_SUPPORTED_DEVICE_TYPE Type;\r
- EFI_STATUS (*ListDevices)(IN OUT LIST_ENTRY* BdsLoadOptionList);\r
- BOOLEAN (*IsSupported)(IN EFI_DEVICE_PATH *DevicePath);\r
- EFI_STATUS (*CreateDevicePathNode)(IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes);\r
- EFI_STATUS (*UpdateDevicePathNode)(IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath);\r
-\r
- /// Define if the boot menu should request if the file is a EFI binary or a Linux kernel\r
- /// Example: PXE boot always deliver a UEFI application.\r
- BOOLEAN RequestBootType;\r
-} BDS_LOAD_OPTION_SUPPORT;\r
-\r
-#define LOAD_OPTION_ENTRY_FROM_LINK(a) BASE_CR(a, BDS_LOAD_OPTION_ENTRY, Link)\r
-#define LOAD_OPTION_FROM_LINK(a) ((BDS_LOAD_OPTION_ENTRY*)BASE_CR(a, BDS_LOAD_OPTION_ENTRY, Link))->BdsLoadOption\r
-\r
-// GUID of the EFI Linux Loader\r
-extern CONST EFI_GUID mLinuxLoaderAppGuid;\r
-\r
-// Device path of the EFI Linux Loader in the Firmware Volume\r
-extern EFI_DEVICE_PATH* mLinuxLoaderDevicePath;\r
-\r
-EFI_STATUS\r
-BootDeviceListSupportedInit (\r
- IN OUT LIST_ENTRY *SupportedDeviceList\r
- );\r
-\r
-EFI_STATUS\r
-BootDeviceListSupportedFree (\r
- IN LIST_ENTRY *SupportedDeviceList,\r
- IN BDS_SUPPORTED_DEVICE *Except\r
- );\r
-\r
-EFI_STATUS\r
-BootDeviceGetDeviceSupport (\r
- IN EFI_DEVICE_PATH *DevicePath,\r
- OUT BDS_LOAD_OPTION_SUPPORT **DeviceSupport\r
- );\r
-\r
-EFI_STATUS\r
-GetHIInputStr (\r
- IN OUT CHAR16 *CmdLine,\r
- IN UINTN MaxCmdLine\r
- );\r
-\r
-EFI_STATUS\r
-EditHIInputStr (\r
- IN OUT CHAR16 *CmdLine,\r
- IN UINTN MaxCmdLine\r
- );\r
-\r
-EFI_STATUS\r
-GetHIInputAscii (\r
- IN OUT CHAR8 *CmdLine,\r
- IN UINTN MaxCmdLine\r
- );\r
-\r
-EFI_STATUS\r
-EditHIInputAscii (\r
- IN OUT CHAR8 *CmdLine,\r
- IN UINTN MaxCmdLine\r
- );\r
-\r
-EFI_STATUS\r
-GetHIInputInteger (\r
- IN OUT UINTN *Integer\r
- );\r
-\r
-EFI_STATUS\r
-GetHIInputIP (\r
- OUT EFI_IP_ADDRESS *Ip\r
- );\r
-\r
-EFI_STATUS\r
-EditHIInputIP (\r
- IN EFI_IP_ADDRESS *InIpAddr,\r
- OUT EFI_IP_ADDRESS *OutIpAddr\r
- );\r
-\r
-EFI_STATUS\r
-GetHIInputBoolean (\r
- OUT BOOLEAN *Value\r
- );\r
-\r
-EFI_DEVICE_PATH*\r
-GetLastDevicePathNode (\r
- IN EFI_DEVICE_PATH* DevicePath\r
- );\r
-\r
-EFI_STATUS\r
-BdsStartBootOption (\r
- IN CHAR16* BootOption\r
- );\r
-\r
-UINTN\r
-GetUnalignedDevicePathSize (\r
- IN EFI_DEVICE_PATH* DevicePath\r
- );\r
-\r
-EFI_DEVICE_PATH*\r
-GetAlignedDevicePath (\r
- IN EFI_DEVICE_PATH* DevicePath\r
- );\r
-\r
-EFI_STATUS\r
-GenerateDeviceDescriptionName (\r
- IN EFI_HANDLE Handle,\r
- IN OUT CHAR16* Description\r
- );\r
-\r
-EFI_STATUS\r
-BootOptionList (\r
- IN OUT LIST_ENTRY *BootOptionList\r
- );\r
-\r
-EFI_STATUS\r
-BootOptionParseLoadOption (\r
- IN EFI_LOAD_OPTION EfiLoadOption,\r
- IN UINTN EfiLoadOptionSize,\r
- OUT BDS_LOAD_OPTION **BdsLoadOption\r
- );\r
-\r
-EFI_STATUS\r
-BootOptionStart (\r
- IN BDS_LOAD_OPTION *BootOption\r
- );\r
-\r
-EFI_STATUS\r
-BootOptionCreate (\r
- IN UINT32 Attributes,\r
- IN CHAR16* BootDescription,\r
- IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,\r
- IN UINT8* OptionalData,\r
- IN UINTN OptionalDataSize,\r
- OUT BDS_LOAD_OPTION** BdsLoadOption\r
- );\r
-\r
-EFI_STATUS\r
-BootOptionUpdate (\r
- IN BDS_LOAD_OPTION* BdsLoadOption,\r
- IN UINT32 Attributes,\r
- IN CHAR16* BootDescription,\r
- IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,\r
- IN UINT8* OptionalData,\r
- IN UINTN OptionalDataSize\r
- );\r
-\r
-EFI_STATUS\r
-BootOptionDelete (\r
- IN BDS_LOAD_OPTION *BootOption\r
- );\r
-\r
-EFI_STATUS\r
-BootMenuMain (\r
- VOID\r
- );\r
-\r
-BOOLEAN\r
-IsUnicodeString (\r
- IN VOID* String\r
- );\r
-\r
-/*\r
- * Try to detect if the given string is an ASCII or Unicode string\r
- *\r
- * There are actually few limitation to this function but it is mainly to give\r
- * a user friendly output.\r
- *\r
- * Some limitations:\r
- * - it only supports unicode string that use ASCII character (< 0x100)\r
- * - single character ASCII strings are interpreted as Unicode string\r
- * - string cannot be longer than 2 x BOOT_DEVICE_OPTION_MAX (600 bytes)\r
- *\r
- * @param String Buffer that might contain a Unicode or Ascii string\r
- * @param IsUnicode If not NULL this boolean value returns if the string is an\r
- * ASCII or Unicode string.\r
- */\r
-BOOLEAN\r
-IsPrintableString (\r
- IN VOID* String,\r
- OUT BOOLEAN *IsUnicode\r
- );\r
-\r
-/**\r
- An empty function to pass error checking of CreateEventEx ().\r
-\r
- @param Event Event whose notification function is being invoked.\r
- @param Context Pointer to the notification function's context,\r
- which is implementation-dependent.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-EmptyCallbackFunction (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- );\r
-\r
-/**\r
- * This function check if the DevicePath defines an EFI binary\r
- *\r
- * This function is used when the BDS support Linux loader to\r
- * detect if the binary is an EFI application or potentially a\r
- * Linux kernel.\r
- */\r
-EFI_STATUS\r
-IsEfiBinary (\r
- IN EFI_DEVICE_PATH* DevicePath,\r
- OUT BOOLEAN *EfiBinary\r
- );\r
-\r
-#endif /* _BDSINTERNAL_H_ */\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011 - 2015, ARM Limited. All rights reserved.\r
-*\r
-* This program and the accompanying materials\r
-* are licensed and made available under the terms and conditions of the BSD License\r
-* which accompanies this distribution. The full text of the license may be found at\r
-* http://opensource.org/licenses/bsd-license.php\r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-\r
-#include "BdsInternal.h"\r
-\r
-// This GUID is defined in the INGF file of ArmPkg/Application/LinuxLoader\r
-CONST EFI_GUID mLinuxLoaderAppGuid = { 0x701f54f2, 0x0d70, 0x4b89, { 0xbc, 0x0a, 0xd9, 0xca, 0x25, 0x37, 0x90, 0x59 }};\r
-\r
-// Device path of the EFI Linux Loader in the Firmware Volume\r
-EFI_DEVICE_PATH* mLinuxLoaderDevicePath = NULL;\r
-\r
-STATIC\r
-BOOLEAN\r
-HasFilePathEfiExtension (\r
- IN CHAR16* FilePath\r
- )\r
-{\r
- return (StrCmp (FilePath + (StrSize (FilePath) / sizeof (CHAR16)) - 5, L".EFI") == 0) ||\r
- (StrCmp (FilePath + (StrSize (FilePath) / sizeof (CHAR16)) - 5, L".efi") == 0);\r
-}\r
-\r
-/**\r
- * This function check if the DevicePath defines an EFI binary\r
- *\r
- * This function is used when the BDS support Linux loader to\r
- * detect if the binary is an EFI application or potentially a\r
- * Linux kernel.\r
- */\r
-EFI_STATUS\r
-IsEfiBinary (\r
- IN EFI_DEVICE_PATH* DevicePath,\r
- OUT BOOLEAN *EfiBinary\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CHAR16* FileName;\r
- EFI_DEVICE_PATH* PrevDevicePathNode;\r
- EFI_DEVICE_PATH* DevicePathNode;\r
- EFI_PHYSICAL_ADDRESS Image;\r
- UINTN FileSize;\r
- EFI_IMAGE_DOS_HEADER* DosHeader;\r
- UINTN PeCoffHeaderOffset;\r
- EFI_IMAGE_NT_HEADERS32* NtHeader;\r
-\r
- ASSERT (EfiBinary != NULL);\r
-\r
- //\r
- // Check if the last node of the device path is a FilePath node\r
- //\r
- PrevDevicePathNode = NULL;\r
- DevicePathNode = DevicePath;\r
- while ((DevicePathNode != NULL) && !IsDevicePathEnd (DevicePathNode)) {\r
- PrevDevicePathNode = DevicePathNode;\r
- DevicePathNode = NextDevicePathNode (DevicePathNode);\r
- }\r
-\r
- if ((PrevDevicePathNode != NULL) &&\r
- (PrevDevicePathNode->Type == MEDIA_DEVICE_PATH) &&\r
- (PrevDevicePathNode->SubType == MEDIA_FILEPATH_DP))\r
- {\r
- FileName = ((FILEPATH_DEVICE_PATH*)PrevDevicePathNode)->PathName;\r
- } else {\r
- FileName = NULL;\r
- }\r
-\r
- if (FileName == NULL) {\r
- Print (L"Is an EFI Application? ");\r
- Status = GetHIInputBoolean (EfiBinary);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_ABORTED;\r
- }\r
- } else if (HasFilePathEfiExtension (FileName)) {\r
- *EfiBinary = TRUE;\r
- } else {\r
- // Check if the file exist\r
- Status = BdsLoadImage (DevicePath, AllocateAnyPages, &Image, &FileSize);\r
- if (!EFI_ERROR (Status)) {\r
-\r
- DosHeader = (EFI_IMAGE_DOS_HEADER *)(UINTN) Image;\r
- if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
- //\r
- // DOS image header is present,\r
- // so read the PE header after the DOS image header.\r
- //\r
- PeCoffHeaderOffset = DosHeader->e_lfanew;\r
- } else {\r
- PeCoffHeaderOffset = 0;\r
- }\r
-\r
- //\r
- // Check PE/COFF image.\r
- //\r
- NtHeader = (EFI_IMAGE_NT_HEADERS32 *)(UINTN) (Image + PeCoffHeaderOffset);\r
- if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
- *EfiBinary = FALSE;\r
- } else {\r
- *EfiBinary = TRUE;\r
- }\r
-\r
- // Free memory\r
- gBS->FreePages (Image, EFI_SIZE_TO_PAGES (FileSize));\r
- } else {\r
- // If we did not manage to open it then ask for the type\r
- Print (L"Is an EFI Application? ");\r
- Status = GetHIInputBoolean (EfiBinary);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_ABORTED;\r
- }\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011 - 2015, ARM Limited. All rights reserved.\r
-*\r
-* This program and the accompanying materials\r
-* are licensed and made available under the terms and conditions of the BSD License\r
-* which accompanies this distribution. The full text of the license may be found at\r
-* http://opensource.org/licenses/bsd-license.php\r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-\r
-#include "BdsInternal.h"\r
-\r
-#include <libfdt.h>\r
-\r
-/**\r
- Worker function that displays the list of boot options that is passed in.\r
-\r
- The function loops over the entries of the list of boot options that is passed\r
- in. For each entry, the boot option description is displayed on a single line\r
- along with the position of the option in the list. In debug mode, the UEFI\r
- device path and the arguments of the boot option are displayed as well in\r
- subsequent lines.\r
-\r
- @param[in] BootOptionsList List of the boot options\r
-\r
-**/\r
-STATIC\r
-VOID\r
-DisplayBootOptions (\r
- IN LIST_ENTRY* BootOptionsList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN BootOptionCount;\r
- LIST_ENTRY *Entry;\r
- BDS_LOAD_OPTION *BdsLoadOption;\r
- BOOLEAN IsUnicode;\r
-\r
- BootOptionCount = 0 ;\r
- for (Entry = GetFirstNode (BootOptionsList);\r
- !IsNull (BootOptionsList, Entry);\r
- Entry = GetNextNode (BootOptionsList, Entry)\r
- ) {\r
-\r
- BdsLoadOption = LOAD_OPTION_FROM_LINK (Entry);\r
- Print (L"[%d] %s\n", ++BootOptionCount, BdsLoadOption->Description);\r
-\r
- DEBUG_CODE_BEGIN ();\r
- CHAR16* DevicePathTxt;\r
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
-\r
- Status = gBS->LocateProtocol (\r
- &gEfiDevicePathToTextProtocolGuid,\r
- NULL,\r
- (VOID **)&DevicePathToTextProtocol\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (\r
- BdsLoadOption->FilePathList,\r
- TRUE,\r
- TRUE\r
- );\r
- Print (L"\t- %s\n", DevicePathTxt);\r
-\r
- if (IsPrintableString (BdsLoadOption->OptionalData, &IsUnicode)) {\r
- if (IsUnicode) {\r
- Print (L"\t- Arguments: %s\n", BdsLoadOption->OptionalData);\r
- } else {\r
- AsciiPrint ("\t- Arguments: %a\n", BdsLoadOption->OptionalData);\r
- }\r
- }\r
-\r
- FreePool (DevicePathTxt);\r
- DEBUG_CODE_END ();\r
- }\r
-}\r
-\r
-/**\r
- Worker function that asks for a boot option to be selected and returns a\r
- pointer to the structure describing the selected boot option.\r
-\r
- @param[in] BootOptionsList List of the boot options\r
-\r
- @retval EFI_SUCCESS Selection succeeded\r
- @retval !EFI_SUCCESS Input error or input cancelled\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-SelectBootOption (\r
- IN LIST_ENTRY* BootOptionsList,\r
- IN CONST CHAR16* InputStatement,\r
- OUT BDS_LOAD_OPTION_ENTRY** BdsLoadOptionEntry\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN BootOptionCount;\r
- UINT16 *BootOrder;\r
- LIST_ENTRY* Entry;\r
- UINTN BootOptionSelected;\r
- UINTN Index;\r
-\r
- // Get the number of boot options\r
- Status = GetGlobalEnvironmentVariable (\r
- L"BootOrder", NULL, &BootOptionCount, (VOID**)&BootOrder\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ErrorExit;\r
- }\r
- FreePool (BootOrder);\r
- BootOptionCount /= sizeof (UINT16);\r
-\r
- // Check if a valid boot option(s) is found\r
- if (BootOptionCount == 0) {\r
- if (StrCmp (InputStatement, DELETE_BOOT_ENTRY) == 0) {\r
- Print (L"Nothing to remove!\n");\r
- } else if (StrCmp (InputStatement, UPDATE_BOOT_ENTRY) == 0) {\r
- Print (L"Nothing to update!\n");\r
- } else if (StrCmp (InputStatement, MOVE_BOOT_ENTRY) == 0) {\r
- Print (L"Nothing to move!\n");\r
- } else {\r
- Print (L"No supported Boot Entry.\n");\r
- }\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- // Get the index of the boot device to delete\r
- BootOptionSelected = 0;\r
- while (BootOptionSelected == 0) {\r
- Print (InputStatement);\r
- Status = GetHIInputInteger (&BootOptionSelected);\r
- if (EFI_ERROR (Status)) {\r
- Print (L"\n");\r
- goto ErrorExit;\r
- } else if ((BootOptionSelected == 0) || (BootOptionSelected > BootOptionCount)) {\r
- Print (L"Invalid input (max %d)\n", BootOptionCount);\r
- BootOptionSelected = 0;\r
- }\r
- }\r
-\r
- // Get the structure of the Boot device to delete\r
- Index = 1;\r
- for (Entry = GetFirstNode (BootOptionsList);\r
- !IsNull (BootOptionsList, Entry);\r
- Entry = GetNextNode (BootOptionsList,Entry)\r
- )\r
- {\r
- if (Index == BootOptionSelected) {\r
- *BdsLoadOptionEntry = LOAD_OPTION_ENTRY_FROM_LINK (Entry);\r
- break;\r
- }\r
- Index++;\r
- }\r
-\r
-ErrorExit:\r
- return Status;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-SelectBootDevice (\r
- OUT BDS_SUPPORTED_DEVICE** SupportedBootDevice\r
- )\r
-{\r
- EFI_STATUS Status;\r
- LIST_ENTRY SupportedDeviceList;\r
- UINTN SupportedDeviceCount;\r
- LIST_ENTRY* Entry;\r
- UINTN SupportedDeviceSelected;\r
- UINTN Index;\r
-\r
- //\r
- // List the Boot Devices supported\r
- //\r
-\r
- // Start all the drivers first\r
- BdsConnectAllDrivers ();\r
-\r
- // List the supported devices\r
- Status = BootDeviceListSupportedInit (&SupportedDeviceList);\r
- ASSERT_EFI_ERROR(Status);\r
-\r
- SupportedDeviceCount = 0;\r
- for (Entry = GetFirstNode (&SupportedDeviceList);\r
- !IsNull (&SupportedDeviceList,Entry);\r
- Entry = GetNextNode (&SupportedDeviceList,Entry)\r
- )\r
- {\r
- *SupportedBootDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry);\r
- Print(L"[%d] %s\n",SupportedDeviceCount+1,(*SupportedBootDevice)->Description);\r
-\r
- DEBUG_CODE_BEGIN();\r
- CHAR16* DevicePathTxt;\r
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
-\r
- Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
- ASSERT_EFI_ERROR(Status);\r
- DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ((*SupportedBootDevice)->DevicePathProtocol,TRUE,TRUE);\r
-\r
- Print(L"\t- %s\n",DevicePathTxt);\r
-\r
- FreePool(DevicePathTxt);\r
- DEBUG_CODE_END();\r
-\r
- SupportedDeviceCount++;\r
- }\r
-\r
- if (SupportedDeviceCount == 0) {\r
- Print(L"There is no supported device.\n");\r
- Status = EFI_ABORTED;\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // Select the Boot Device\r
- //\r
- SupportedDeviceSelected = 0;\r
- while (SupportedDeviceSelected == 0) {\r
- Print(L"Select the Boot Device: ");\r
- Status = GetHIInputInteger (&SupportedDeviceSelected);\r
- if (EFI_ERROR(Status)) {\r
- Status = EFI_ABORTED;\r
- goto EXIT;\r
- } else if ((SupportedDeviceSelected == 0) || (SupportedDeviceSelected > SupportedDeviceCount)) {\r
- Print(L"Invalid input (max %d)\n",SupportedDeviceCount);\r
- SupportedDeviceSelected = 0;\r
- }\r
- }\r
-\r
- //\r
- // Get the Device Path for the selected boot device\r
- //\r
- Index = 1;\r
- for (Entry = GetFirstNode (&SupportedDeviceList);\r
- !IsNull (&SupportedDeviceList,Entry);\r
- Entry = GetNextNode (&SupportedDeviceList,Entry)\r
- )\r
- {\r
- if (Index == SupportedDeviceSelected) {\r
- *SupportedBootDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry);\r
- break;\r
- }\r
- Index++;\r
- }\r
-\r
-EXIT:\r
- BootDeviceListSupportedFree (&SupportedDeviceList, *SupportedBootDevice);\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-BootMenuAddBootOption (\r
- IN LIST_ENTRY *BootOptionsList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BDS_SUPPORTED_DEVICE* SupportedBootDevice;\r
- CHAR16 BootDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
- CHAR16 CmdLine[BOOT_DEVICE_OPTION_MAX];\r
- UINT32 Attributes;\r
- BDS_LOAD_OPTION_ENTRY *BdsLoadOptionEntry;\r
- EFI_DEVICE_PATH *DevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePathNodes;\r
- UINT8* OptionalData;\r
- UINTN OptionalDataSize;\r
- BOOLEAN EfiBinary;\r
- CHAR16 *LinuxDevicePath;\r
-\r
- Attributes = 0;\r
- SupportedBootDevice = NULL;\r
-\r
- // List the Boot Devices supported\r
- Status = SelectBootDevice (&SupportedBootDevice);\r
- if (EFI_ERROR(Status)) {\r
- Status = EFI_ABORTED;\r
- goto EXIT;\r
- }\r
-\r
- // Create the specific device path node\r
- if (FeaturePcdGet (PcdBdsLinuxSupport) && mLinuxLoaderDevicePath) {\r
- Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application or the kernel", &DevicePathNodes);\r
- } else {\r
- Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application", &DevicePathNodes);\r
- }\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_ABORTED;\r
- goto EXIT;\r
- }\r
- // Append the Device Path to the selected device path\r
- DevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)DevicePathNodes);\r
- if (DevicePath == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto EXIT;\r
- }\r
-\r
- // Is it an EFI application?\r
- if (FeaturePcdGet (PcdBdsLinuxSupport) && mLinuxLoaderDevicePath) {\r
- Status = IsEfiBinary (DevicePath, &EfiBinary);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_ABORTED;\r
- goto EXIT;\r
- }\r
-\r
- if (EfiBinary == FALSE) {\r
- Print (L"It is assumed the binary is a Linux kernel and the embedded Linux Loader is going to be used.\n");\r
- Print (L"Supported command line formats by the embedded Linux Loader:\n");\r
- Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\"\n");\r
- Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\" -f <EFI Device Path of the Linux initrd>\n");\r
- Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\" -a <Machine Type for ATAG Linux kernel>\n");\r
-\r
- // Copy the Linux path into the command line\r
- LinuxDevicePath = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
- CopyMem (CmdLine, LinuxDevicePath, MAX (sizeof (CmdLine), StrSize (LinuxDevicePath)));\r
- FreePool (LinuxDevicePath);\r
-\r
- // Free the generated Device Path\r
- FreePool (DevicePath);\r
- // and use the embedded Linux Loader as the EFI application\r
- DevicePath = mLinuxLoaderDevicePath;\r
- } else {\r
- CmdLine[0] = L'\0';\r
- }\r
- } else {\r
- CmdLine[0] = L'\0';\r
- }\r
-\r
- Print (L"Arguments to pass to the EFI Application: ");\r
- Status = EditHIInputStr (CmdLine, BOOT_DEVICE_OPTION_MAX);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_ABORTED;\r
- goto EXIT;\r
- }\r
-\r
- OptionalData = (UINT8*)CmdLine;\r
- OptionalDataSize = StrSize (CmdLine);\r
-\r
- Print(L"Description for this new Entry: ");\r
- Status = GetHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX);\r
- if (EFI_ERROR(Status)) {\r
- Status = EFI_ABORTED;\r
- goto FREE_DEVICE_PATH;\r
- }\r
-\r
- // Create new entry\r
- BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof(BDS_LOAD_OPTION_ENTRY));\r
- Status = BootOptionCreate (Attributes, BootDescription, DevicePath, OptionalData, OptionalDataSize, &BdsLoadOptionEntry->BdsLoadOption);\r
- if (!EFI_ERROR(Status)) {\r
- InsertTailList (BootOptionsList, &BdsLoadOptionEntry->Link);\r
- }\r
-\r
-FREE_DEVICE_PATH:\r
- FreePool (DevicePath);\r
-\r
-EXIT:\r
- if (Status == EFI_ABORTED) {\r
- Print(L"\n");\r
- }\r
- FreePool(SupportedBootDevice);\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-BootMenuRemoveBootOption (\r
- IN LIST_ENTRY *BootOptionsList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BDS_LOAD_OPTION_ENTRY* BootOptionEntry;\r
-\r
- DisplayBootOptions (BootOptionsList);\r
- Status = SelectBootOption (BootOptionsList, DELETE_BOOT_ENTRY, &BootOptionEntry);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- // If the Boot Option was attached to a list remove it\r
- if (!IsListEmpty (&BootOptionEntry->Link)) {\r
- // Remove the entry from the list\r
- RemoveEntryList (&BootOptionEntry->Link);\r
- }\r
-\r
- // Delete the BDS Load option structures\r
- BootOptionDelete (BootOptionEntry->BdsLoadOption);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-BootMenuUpdateBootOption (\r
- IN LIST_ENTRY *BootOptionsList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BDS_LOAD_OPTION_ENTRY *BootOptionEntry;\r
- BDS_LOAD_OPTION *BootOption;\r
- BDS_LOAD_OPTION_SUPPORT* DeviceSupport;\r
- CHAR16 BootDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
- CHAR8 CmdLine[BOOT_DEVICE_OPTION_MAX];\r
- CHAR16 UnicodeCmdLine[BOOT_DEVICE_OPTION_MAX];\r
- CHAR16 *LinuxDevicePath;\r
- EFI_DEVICE_PATH *DevicePath;\r
- UINT8* OptionalData;\r
- UINTN OptionalDataSize;\r
- BOOLEAN IsPrintable;\r
- BOOLEAN IsUnicode;\r
- BOOLEAN EfiBinary;\r
-\r
- DisplayBootOptions (BootOptionsList);\r
- Status = SelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, &BootOptionEntry);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- BootOption = BootOptionEntry->BdsLoadOption;\r
-\r
- // Get the device support for this Boot Option\r
- Status = BootDeviceGetDeviceSupport (BootOption->FilePathList, &DeviceSupport);\r
- if (EFI_ERROR(Status)) {\r
- Print(L"Not possible to retrieve the supported device for the update\n");\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- EfiBinary = TRUE;\r
- if (FeaturePcdGet (PcdBdsLinuxSupport) && mLinuxLoaderDevicePath) {\r
- Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_ABORTED;\r
- goto EXIT;\r
- }\r
-\r
- // Is it an EFI application?\r
- Status = IsEfiBinary (DevicePath, &EfiBinary);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_ABORTED;\r
- goto EXIT;\r
- }\r
-\r
- if (EfiBinary == FALSE) {\r
- Print (L"It is assumed the binary is a Linux kernel and the embedded Linux Loader is going to be used.\n");\r
- Print (L"Supported command line formats by the embedded Linux Loader:\n");\r
- Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\"\n");\r
- Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\" -f <EFI Device Path of the Linux initrd>\n");\r
- Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\" -a <Machine Type for ATAG Linux kernel>\n");\r
-\r
- // Copy the Linux path into the command line\r
- LinuxDevicePath = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
- CopyMem (UnicodeCmdLine, LinuxDevicePath, MAX (sizeof (UnicodeCmdLine), StrSize (LinuxDevicePath)));\r
- FreePool (LinuxDevicePath);\r
-\r
- // Free the generated Device Path\r
- FreePool (DevicePath);\r
- // and use the embedded Linux Loader as the EFI application\r
- DevicePath = mLinuxLoaderDevicePath;\r
-\r
- // The command line is a unicode printable string\r
- IsPrintable = TRUE;\r
- IsUnicode = TRUE;\r
- }\r
- } else {\r
- Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application", &DevicePath);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_ABORTED;\r
- goto EXIT;\r
- }\r
- }\r
-\r
- Print (L"Arguments to pass to the EFI Application: ");\r
-\r
- // When the command line has not been initialized by the embedded Linux loader earlier\r
- if (EfiBinary) {\r
- if (BootOption->OptionalDataSize > 0) {\r
- IsPrintable = IsPrintableString (BootOption->OptionalData, &IsUnicode);\r
- if (IsPrintable) {\r
- //\r
- // The size in bytes of the string, final zero included, should\r
- // be equal to or at least lower than "BootOption->OptionalDataSize"\r
- // and the "IsPrintableString()" has already tested that the length\r
- // in number of characters is smaller than BOOT_DEVICE_OPTION_MAX,\r
- // final '\0' included. We can thus copy the string for editing\r
- // using "CopyMem()". Furthermore, note that in the case of an Unicode\r
- // string "StrnCpy()" and "StrCpy()" can not be used to copy the\r
- // string because the data pointed to by "BootOption->OptionalData"\r
- // is not necessarily 2-byte aligned.\r
- //\r
- if (IsUnicode) {\r
- CopyMem (\r
- UnicodeCmdLine, BootOption->OptionalData,\r
- MIN (sizeof (UnicodeCmdLine),\r
- BootOption->OptionalDataSize)\r
- );\r
- } else {\r
- CopyMem (\r
- CmdLine, BootOption->OptionalData,\r
- MIN (sizeof (CmdLine),\r
- BootOption->OptionalDataSize)\r
- );\r
- }\r
- }\r
- } else {\r
- UnicodeCmdLine[0] = L'\0';\r
- IsPrintable = TRUE;\r
- IsUnicode = TRUE;\r
- }\r
- }\r
-\r
- // We do not request arguments for OptionalData that cannot be printed\r
- if (IsPrintable) {\r
- if (IsUnicode) {\r
- Status = EditHIInputStr (UnicodeCmdLine, BOOT_DEVICE_OPTION_MAX);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_ABORTED;\r
- goto FREE_DEVICE_PATH;\r
- }\r
-\r
- OptionalData = (UINT8*)UnicodeCmdLine;\r
- OptionalDataSize = StrSize (UnicodeCmdLine);\r
- } else {\r
- Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_ABORTED;\r
- goto FREE_DEVICE_PATH;\r
- }\r
-\r
- OptionalData = (UINT8*)CmdLine;\r
- OptionalDataSize = AsciiStrSize (CmdLine);\r
- }\r
- } else {\r
- // We keep the former OptionalData\r
- OptionalData = BootOption->OptionalData;\r
- OptionalDataSize = BootOption->OptionalDataSize;\r
- }\r
-\r
- Print(L"Description for this new Entry: ");\r
- StrnCpy (BootDescription, BootOption->Description, BOOT_DEVICE_DESCRIPTION_MAX);\r
- Status = EditHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX);\r
- if (EFI_ERROR(Status)) {\r
- Status = EFI_ABORTED;\r
- goto FREE_DEVICE_PATH;\r
- }\r
-\r
- // Update the entry\r
- Status = BootOptionUpdate (BootOption, BootOption->Attributes, BootDescription, DevicePath, OptionalData, OptionalDataSize);\r
-\r
-FREE_DEVICE_PATH:\r
- FreePool (DevicePath);\r
-\r
-EXIT:\r
- if (Status == EFI_ABORTED) {\r
- Print(L"\n");\r
- }\r
- return Status;\r
-}\r
-\r
-/**\r
- Reorder boot options\r
-\r
- Ask for the boot option to move and then move it when up or down arrows\r
- are pressed. This function is called when the user selects the "Reorder Boot\r
- Device Entries" entry in the boot manager menu.\r
- The order of the boot options in BootOptionList and in the UEFI BootOrder\r
- global variable are kept coherent until the user confirm his reordering (ie:\r
- he does not exit by pressing escape).\r
-\r
- @param[in] BootOptionsList List of the boot devices constructed in\r
- BootMenuMain()\r
-\r
- @retval EFI_SUCCESS No error encountered.\r
- @retval !EFI_SUCCESS An error has occured either in the selection of the\r
- boot option to move or while interacting with the user.\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-BootMenuReorderBootOptions (\r
- IN LIST_ENTRY *BootOptionsList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BDS_LOAD_OPTION_ENTRY *BootOptionEntry;\r
- LIST_ENTRY *SelectedEntry;\r
- LIST_ENTRY *PrevEntry;\r
- BOOLEAN Move;\r
- BOOLEAN Save;\r
- BOOLEAN Cancel;\r
- UINTN WaitIndex;\r
- EFI_INPUT_KEY Key;\r
- LIST_ENTRY *SecondEntry;\r
- UINTN BootOrderSize;\r
- UINT16 *BootOrder;\r
- LIST_ENTRY *Entry;\r
- UINTN Index;\r
-\r
- DisplayBootOptions (BootOptionsList);\r
-\r
- // Ask to select the boot option to move\r
- while (TRUE) {\r
- Status = SelectBootOption (BootOptionsList, MOVE_BOOT_ENTRY, &BootOptionEntry);\r
- if (EFI_ERROR (Status)) {\r
- goto ErrorExit;\r
- }\r
-\r
- SelectedEntry = &BootOptionEntry->Link;\r
- SecondEntry = NULL;\r
- // Note down the previous entry in the list to be able to cancel changes\r
- PrevEntry = GetPreviousNode (BootOptionsList, SelectedEntry);\r
-\r
- // Start of interaction\r
- while (TRUE) {\r
- Print (\r
- L"* Use up/down arrows to move the entry '%s'",\r
- BootOptionEntry->BdsLoadOption->Description\r
- );\r
-\r
- // Wait for a move, save or cancel request\r
- Move = FALSE;\r
- Save = FALSE;\r
- Cancel = FALSE;\r
- do {\r
- Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex);\r
- if (!EFI_ERROR (Status)) {\r
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
- }\r
- if (EFI_ERROR (Status)) {\r
- Print (L"\n");\r
- goto ErrorExit;\r
- }\r
-\r
- switch (Key.ScanCode) {\r
- case SCAN_NULL:\r
- Save = (Key.UnicodeChar == CHAR_LINEFEED) ||\r
- (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) ||\r
- (Key.UnicodeChar == 0x7f);\r
- break;\r
-\r
- case SCAN_UP:\r
- SecondEntry = GetPreviousNode (BootOptionsList, SelectedEntry);\r
- Move = SecondEntry != BootOptionsList;\r
- break;\r
-\r
- case SCAN_DOWN:\r
- SecondEntry = GetNextNode (BootOptionsList, SelectedEntry);\r
- Move = SecondEntry != BootOptionsList;\r
- break;\r
-\r
- case SCAN_ESC:\r
- Cancel = TRUE;\r
- break;\r
- }\r
- } while ((!Move) && (!Save) && (!Cancel));\r
-\r
- if (Move) {\r
- if ((SelectedEntry != NULL) && (SecondEntry != NULL)) {\r
- SwapListEntries (SelectedEntry, SecondEntry);\r
- }\r
- } else {\r
- if (Save) {\r
- Status = GetGlobalEnvironmentVariable (\r
- L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder\r
- );\r
- BootOrderSize /= sizeof (UINT16);\r
-\r
- if (!EFI_ERROR (Status)) {\r
- // The order of the boot options in the 'BootOptionsList' is the\r
- // new order that has been just defined by the user. Save this new\r
- // order in "BootOrder" UEFI global variable.\r
- Entry = GetFirstNode (BootOptionsList);\r
- for (Index = 0; Index < BootOrderSize; Index++) {\r
- BootOrder[Index] = (LOAD_OPTION_FROM_LINK (Entry))->LoadOptionIndex;\r
- Entry = GetNextNode (BootOptionsList, Entry);\r
- }\r
- Status = gRT->SetVariable (\r
- (CHAR16*)L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE |\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS |\r
- EFI_VARIABLE_RUNTIME_ACCESS,\r
- BootOrderSize * sizeof (UINT16),\r
- BootOrder\r
- );\r
- FreePool (BootOrder);\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- Print (L"\nAn error occurred, move not completed!\n");\r
- Cancel = TRUE;\r
- }\r
- }\r
-\r
- if (Cancel) {\r
- //\r
- // Restore initial position of the selected boot option\r
- //\r
- RemoveEntryList (SelectedEntry);\r
- InsertHeadList (PrevEntry, SelectedEntry);\r
- }\r
- }\r
-\r
- Print (L"\n");\r
- DisplayBootOptions (BootOptionsList);\r
- // Saved or cancelled, back to the choice of boot option to move\r
- if (!Move) {\r
- break;\r
- }\r
- }\r
- }\r
-\r
-ErrorExit:\r
- return Status ;\r
-}\r
-\r
-EFI_STATUS\r
-UpdateFdtPath (\r
- IN LIST_ENTRY *BootOptionsList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BDS_SUPPORTED_DEVICE *SupportedBootDevice;\r
- EFI_DEVICE_PATH_PROTOCOL *FdtDevicePathNodes;\r
- EFI_DEVICE_PATH_PROTOCOL *FdtDevicePath;\r
- CHAR16 *FdtTextDevicePath;\r
- EFI_PHYSICAL_ADDRESS FdtBlobBase;\r
- UINTN FdtBlobSize;\r
- UINTN NumPages;\r
- EFI_PHYSICAL_ADDRESS FdtConfigurationTableBase;\r
-\r
- SupportedBootDevice = NULL;\r
-\r
- Status = SelectBootDevice (&SupportedBootDevice);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_ABORTED;\r
- goto EXIT;\r
- }\r
-\r
- // Create the specific device path node\r
- Status = SupportedBootDevice->Support->CreateDevicePathNode (L"FDT blob", &FdtDevicePathNodes);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_ABORTED;\r
- goto EXIT;\r
- }\r
-\r
- if (FdtDevicePathNodes != NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
-\r
- FdtDevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, FdtDevicePathNodes);\r
- FreePool (FdtDevicePathNodes);\r
- if (FdtDevicePath == NULL) {\r
- goto EXIT;\r
- }\r
-\r
- FdtTextDevicePath = ConvertDevicePathToText (FdtDevicePath, TRUE, TRUE);\r
- if (FdtTextDevicePath == NULL) {\r
- goto EXIT;\r
- }\r
-\r
- Status = gRT->SetVariable (\r
- (CHAR16*)L"Fdt",\r
- &gFdtVariableGuid,\r
- EFI_VARIABLE_RUNTIME_ACCESS |\r
- EFI_VARIABLE_NON_VOLATILE |\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
- StrSize (FdtTextDevicePath),\r
- FdtTextDevicePath\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- FreePool (FdtTextDevicePath);\r
- } else {\r
- Status = gRT->SetVariable (\r
- (CHAR16*)L"Fdt",\r
- &gFdtVariableGuid,\r
- EFI_VARIABLE_RUNTIME_ACCESS |\r
- EFI_VARIABLE_NON_VOLATILE |\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
- 0,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- return Status;\r
- }\r
-\r
- //\r
- // Try to load FDT from the new EFI Device Path\r
- //\r
-\r
- //\r
- // Load the FDT given its device path.\r
- // This operation may fail if the device path is not supported.\r
- //\r
- FdtBlobBase = 0;\r
- NumPages = 0;\r
- Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);\r
- FreePool (FdtDevicePath);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto EXIT_LOAD_FDT;\r
- }\r
-\r
- // Check the FDT header is valid. We only make this check in DEBUG mode in\r
- // case the FDT header change on production device and this ASSERT() becomes\r
- // not valid.\r
- ASSERT (fdt_check_header ((VOID*)(UINTN)FdtBlobBase) == 0);\r
-\r
- //\r
- // Ensure the Size of the Device Tree is smaller than the size of the read file\r
- //\r
- ASSERT ((UINTN)fdt_totalsize ((VOID*)(UINTN)FdtBlobBase) <= FdtBlobSize);\r
-\r
- //\r
- // Store the FDT as Runtime Service Data to prevent the Kernel from\r
- // overwritting its data.\r
- //\r
- NumPages = EFI_SIZE_TO_PAGES (FdtBlobSize);\r
- Status = gBS->AllocatePages (\r
- AllocateAnyPages, EfiRuntimeServicesData,\r
- NumPages, &FdtConfigurationTableBase\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto EXIT_LOAD_FDT;\r
- }\r
- gBS->CopyMem (\r
- (VOID*)(UINTN)FdtConfigurationTableBase,\r
- (VOID*)(UINTN)FdtBlobBase,\r
- FdtBlobSize\r
- );\r
-\r
- //\r
- // Install the FDT into the Configuration Table\r
- //\r
- Status = gBS->InstallConfigurationTable (\r
- &gFdtTableGuid,\r
- (VOID*)(UINTN)FdtConfigurationTableBase\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->FreePages (FdtConfigurationTableBase, NumPages);\r
- }\r
-\r
-EXIT_LOAD_FDT:\r
- if (EFI_ERROR (Status)) {\r
- Print (L"\nWarning: Did not manage to install the new device tree. Try to restart the platform.\n");\r
- }\r
-\r
- if (FdtBlobBase != 0) {\r
- gBS->FreePages (FdtBlobBase, NumPages);\r
- }\r
-\r
-EXIT:\r
- if (Status == EFI_ABORTED) {\r
- Print (L"\n");\r
- }\r
-\r
- if (SupportedBootDevice != NULL) {\r
- FreePool (SupportedBootDevice);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Set boot timeout\r
-\r
- Ask for the boot timeout in seconds and if the input succeeds assign the\r
- input value to the UEFI global variable "Timeout". This function is called\r
- when the user selects the "Set Boot Timeout" of the boot manager menu.\r
-\r
- @param[in] BootOptionsList List of the boot devices, not used here\r
-\r
- @retval EFI_SUCCESS Boot timeout in second retrieved from the standard\r
- input and assigned to the UEFI "Timeout" global\r
- variable\r
- @retval !EFI_SUCCESS Either the input or the setting of the UEFI global\r
- variable "Timeout" has failed.\r
-**/\r
-EFI_STATUS\r
-STATIC\r
-BootMenuSetBootTimeout (\r
- IN LIST_ENTRY *BootOptionsList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Input;\r
- UINT16 Timeout;\r
-\r
- Print (L"Timeout duration (in seconds): ");\r
- Status = GetHIInputInteger (&Input);\r
- if (EFI_ERROR (Status)) {\r
- Print (L"\n");\r
- goto ErrorExit;\r
- }\r
-\r
- Timeout = Input;\r
- Status = gRT->SetVariable (\r
- (CHAR16*)L"Timeout",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE |\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS |\r
- EFI_VARIABLE_RUNTIME_ACCESS,\r
- sizeof (UINT16),\r
- &Timeout\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
-ErrorExit:\r
- return Status;\r
-}\r
-\r
-struct BOOT_MANAGER_ENTRY {\r
- CONST CHAR16* Description;\r
- EFI_STATUS (*Callback) (IN LIST_ENTRY *BootOptionsList);\r
-} BootManagerEntries[] = {\r
- { L"Add Boot Device Entry", BootMenuAddBootOption },\r
- { L"Update Boot Device Entry", BootMenuUpdateBootOption },\r
- { L"Remove Boot Device Entry", BootMenuRemoveBootOption },\r
- { L"Reorder Boot Device Entries", BootMenuReorderBootOptions },\r
- { L"Update FDT path", UpdateFdtPath },\r
- { L"Set Boot Timeout", BootMenuSetBootTimeout },\r
-};\r
-\r
-EFI_STATUS\r
-BootMenuManager (\r
- IN LIST_ENTRY *BootOptionsList\r
- )\r
-{\r
- UINTN Index;\r
- UINTN OptionSelected;\r
- UINTN BootManagerEntryCount;\r
- EFI_STATUS Status;\r
-\r
- BootManagerEntryCount = sizeof(BootManagerEntries) / sizeof(struct BOOT_MANAGER_ENTRY);\r
-\r
- while (TRUE) {\r
- // Display Boot Manager menu\r
- for (Index = 0; Index < BootManagerEntryCount; Index++) {\r
- Print(L"[%d] %s\n",Index+1,BootManagerEntries[Index]);\r
- }\r
- Print(L"[%d] Return to main menu\n",Index+1);\r
-\r
- // Select which entry to call\r
- Print(L"Choice: ");\r
- Status = GetHIInputInteger (&OptionSelected);\r
- if (EFI_ERROR(Status) || (OptionSelected == (BootManagerEntryCount+1))) {\r
- if (EFI_ERROR(Status)) {\r
- Print(L"\n");\r
- }\r
- return EFI_SUCCESS;\r
- } else if ((OptionSelected > 0) && (OptionSelected <= BootManagerEntryCount)) {\r
- BootManagerEntries[OptionSelected-1].Callback (BootOptionsList);\r
- }\r
- }\r
- // Should never go here\r
-}\r
-\r
-EFI_STATUS\r
-BootShell (\r
- IN LIST_ENTRY *BootOptionsList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH* EfiShellDevicePath;\r
-\r
- // Find the EFI Shell\r
- Status = LocateEfiApplicationInFvByName (L"Shell", &EfiShellDevicePath);\r
- if (Status == EFI_NOT_FOUND) {\r
- Print (L"Error: EFI Application not found.\n");\r
- return Status;\r
- } else if (EFI_ERROR (Status)) {\r
- Print (L"Error: Status Code: 0x%X\n", (UINT32)Status);\r
- return Status;\r
- } else {\r
- // Need to connect every drivers to ensure no dependencies are missing for the application\r
- Status = BdsConnectAllDrivers ();\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n"));\r
- return Status;\r
- }\r
-\r
- return BdsStartEfiApplication (gImageHandle, EfiShellDevicePath, 0, NULL);\r
- }\r
-}\r
-\r
-struct BOOT_MAIN_ENTRY {\r
- CONST CHAR16* Description;\r
- EFI_STATUS (*Callback) (IN LIST_ENTRY *BootOptionsList);\r
-} BootMainEntries[] = {\r
- { L"Shell", BootShell },\r
- { L"Boot Manager", BootMenuManager },\r
-};\r
-\r
-EFI_STATUS\r
-BootMenuMain (\r
- VOID\r
- )\r
-{\r
- LIST_ENTRY BootOptionsList;\r
- UINTN OptionCount;\r
- UINTN BootOptionCount;\r
- EFI_STATUS Status;\r
- LIST_ENTRY* Entry;\r
- BDS_LOAD_OPTION* BootOption;\r
- UINTN BootOptionSelected;\r
- UINTN Index;\r
- UINTN BootMainEntryCount;\r
- BOOLEAN IsUnicode;\r
-\r
- BootOption = NULL;\r
- BootMainEntryCount = sizeof(BootMainEntries) / sizeof(struct BOOT_MAIN_ENTRY);\r
-\r
- if (FeaturePcdGet (PcdBdsLinuxSupport)) {\r
- // Check Linux Loader is present\r
- Status = LocateEfiApplicationInFvByGuid (&mLinuxLoaderAppGuid, &mLinuxLoaderDevicePath);\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
-\r
- while (TRUE) {\r
- // Get Boot#### list\r
- BootOptionList (&BootOptionsList);\r
-\r
- OptionCount = 1;\r
-\r
- // Display the Boot options\r
- for (Entry = GetFirstNode (&BootOptionsList);\r
- !IsNull (&BootOptionsList,Entry);\r
- Entry = GetNextNode (&BootOptionsList,Entry)\r
- )\r
- {\r
- BootOption = LOAD_OPTION_FROM_LINK(Entry);\r
-\r
- Print(L"[%d] %s\n", OptionCount, BootOption->Description);\r
-\r
- DEBUG_CODE_BEGIN();\r
- CHAR16* DevicePathTxt;\r
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
-\r
- Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
- if (EFI_ERROR(Status)) {\r
- // You must provide an implementation of DevicePathToTextProtocol in your firmware (eg: DevicePathDxe)\r
- DEBUG((EFI_D_ERROR,"Error: Bds requires DevicePathToTextProtocol\n"));\r
- return Status;\r
- }\r
- DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (BootOption->FilePathList, TRUE, TRUE);\r
-\r
- Print(L"\t- %s\n",DevicePathTxt);\r
-\r
- if (BootOption->OptionalData != NULL) {\r
- if (IsPrintableString (BootOption->OptionalData, &IsUnicode)) {\r
- if (IsUnicode) {\r
- Print (L"\t- Arguments: %s\n", BootOption->OptionalData);\r
- } else {\r
- AsciiPrint ("\t- Arguments: %a\n", BootOption->OptionalData);\r
- }\r
- }\r
- }\r
- FreePool(DevicePathTxt);\r
- DEBUG_CODE_END();\r
-\r
- OptionCount++;\r
- }\r
- BootOptionCount = OptionCount-1;\r
-\r
- // Display the hardcoded Boot entries\r
- for (Index = 0; Index < BootMainEntryCount; Index++) {\r
- Print(L"[%d] %s\n",OptionCount,BootMainEntries[Index]);\r
- OptionCount++;\r
- }\r
-\r
- // Request the boot entry from the user\r
- BootOptionSelected = 0;\r
- while (BootOptionSelected == 0) {\r
- Print(L"Start: ");\r
- Status = GetHIInputInteger (&BootOptionSelected);\r
- if (EFI_ERROR(Status) || (BootOptionSelected == 0) || (BootOptionSelected > OptionCount)) {\r
- Print(L"Invalid input (max %d)\n",(OptionCount-1));\r
- BootOptionSelected = 0;\r
- }\r
- }\r
-\r
- // Start the selected entry\r
- if (BootOptionSelected > BootOptionCount) {\r
- // Start the hardcoded entry\r
- Status = BootMainEntries[BootOptionSelected - BootOptionCount - 1].Callback (&BootOptionsList);\r
- } else {\r
- // Find the selected entry from the Boot#### list\r
- Index = 1;\r
- for (Entry = GetFirstNode (&BootOptionsList);\r
- !IsNull (&BootOptionsList,Entry);\r
- Entry = GetNextNode (&BootOptionsList,Entry)\r
- )\r
- {\r
- if (Index == BootOptionSelected) {\r
- BootOption = LOAD_OPTION_FROM_LINK(Entry);\r
- break;\r
- }\r
- Index++;\r
- }\r
-\r
- Status = BootOptionStart (BootOption);\r
- }\r
- }\r
- // Should never go here\r
-}\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011-2015, ARM Limited. All rights reserved.\r
-*\r
-* This program and the accompanying materials\r
-* are licensed and made available under the terms and conditions of the BSD License\r
-* which accompanies this distribution. The full text of the license may be found at\r
-* http://opensource.org/licenses/bsd-license.php\r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-\r
-#include "BdsInternal.h"\r
-\r
-EFI_STATUS\r
-BootOptionStart (\r
- IN BDS_LOAD_OPTION *BootOption\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT16 LoadOptionIndexSize;\r
-\r
- // Connect all the drivers if the EFI Application is not a EFI OS Loader\r
- if ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_APP) {\r
- BdsConnectAllDrivers ();\r
- }\r
-\r
- // Set BootCurrent variable\r
- LoadOptionIndexSize = sizeof (UINT16);\r
- gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- LoadOptionIndexSize, &(BootOption->LoadOptionIndex));\r
-\r
- Status = BdsStartEfiApplication (gImageHandle, BootOption->FilePathList, BootOption->OptionalDataSize, BootOption->OptionalData);\r
-\r
- // Clear BootCurrent variable\r
- LoadOptionIndexSize = sizeof (UINT16);\r
- gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- 0, NULL);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-BootOptionList (\r
- IN OUT LIST_ENTRY *BootOptionList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- UINT16* BootOrder;\r
- UINTN BootOrderSize;\r
- BDS_LOAD_OPTION* BdsLoadOption;\r
- BDS_LOAD_OPTION_ENTRY* BdsLoadOptionEntry;\r
-\r
- InitializeListHead (BootOptionList);\r
-\r
- // Get the Boot Option Order from the environment variable\r
- Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
- Status = BootOptionFromLoadOptionIndex (BootOrder[Index], &BdsLoadOption);\r
- if (!EFI_ERROR(Status)) {\r
- BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool(sizeof(BDS_LOAD_OPTION_ENTRY));\r
- BdsLoadOptionEntry->BdsLoadOption = BdsLoadOption;\r
- InsertTailList (BootOptionList,&BdsLoadOptionEntry->Link);\r
- }\r
- }\r
-\r
- FreePool (BootOrder);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-BootOptionSetFields (\r
- IN BDS_LOAD_OPTION* BootOption,\r
- IN UINT32 Attributes,\r
- IN CHAR16* BootDescription,\r
- IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,\r
- IN UINT8* OptionalData,\r
- IN UINTN OptionalDataSize\r
- )\r
-{\r
- EFI_LOAD_OPTION *EfiLoadOption;\r
- UINTN EfiLoadOptionSize;\r
- UINTN BootDescriptionSize;\r
- UINT16 FilePathListLength;\r
- UINT8* EfiLoadOptionPtr;\r
-\r
- // If we are overwriting an existent Boot Option then we have to free previously allocated memory\r
- if (BootOption->LoadOption) {\r
- FreePool (BootOption->LoadOption);\r
- }\r
-\r
- BootDescriptionSize = StrSize (BootDescription);\r
-\r
- // Compute the size of the FilePath list\r
- FilePathListLength = GetUnalignedDevicePathSize (DevicePath);\r
-\r
- // Allocate the memory for the EFI Load Option\r
- EfiLoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + BootDescriptionSize + FilePathListLength + OptionalDataSize;\r
- EfiLoadOption = (EFI_LOAD_OPTION *)AllocatePool(EfiLoadOptionSize);\r
- EfiLoadOptionPtr = (UINT8 *)EfiLoadOption;\r
-\r
- //\r
- // Populate the EFI Load Option and BDS Boot Option structures\r
- //\r
-\r
- // Attributes fields\r
- BootOption->Attributes = Attributes;\r
- *(UINT32*)EfiLoadOptionPtr = Attributes;\r
- EfiLoadOptionPtr += sizeof(UINT32);\r
-\r
- // FilePath List fields\r
- BootOption->FilePathListLength = FilePathListLength;\r
- *(UINT16*)EfiLoadOptionPtr = FilePathListLength;\r
- EfiLoadOptionPtr += sizeof(UINT16);\r
-\r
- // Boot description fields\r
- BootOption->Description = (CHAR16*)EfiLoadOptionPtr;\r
- CopyMem (EfiLoadOptionPtr, BootDescription, BootDescriptionSize);\r
- EfiLoadOptionPtr += BootDescriptionSize;\r
-\r
- // File path fields\r
- BootOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)EfiLoadOptionPtr;\r
- CopyMem (EfiLoadOptionPtr, DevicePath, FilePathListLength);\r
- EfiLoadOptionPtr += FilePathListLength;\r
-\r
- // Optional Data fields, Do unaligned writes\r
- BootOption->OptionalData = EfiLoadOptionPtr;\r
-\r
- if (OptionalData != NULL) {\r
- CopyMem (BootOption->OptionalData, OptionalData, OptionalDataSize);\r
- }\r
-\r
- BootOption->OptionalDataSize = OptionalDataSize;\r
-\r
- // If this function is called at the creation of the Boot Device entry (not at the update) the\r
- // BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry\r
- if (BootOption->LoadOptionSize == 0) {\r
- BootOption->LoadOptionIndex = BootOptionAllocateBootIndex ();\r
- }\r
-\r
- // Fill the EFI Load option fields\r
- BootOption->LoadOption = EfiLoadOption;\r
- BootOption->LoadOptionSize = EfiLoadOptionSize;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-BootOptionCreate (\r
- IN UINT32 Attributes,\r
- IN CHAR16* BootDescription,\r
- IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,\r
- IN UINT8* OptionalData,\r
- IN UINTN OptionalDataSize,\r
- OUT BDS_LOAD_OPTION** BdsLoadOption\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BDS_LOAD_OPTION_ENTRY* BootOptionEntry;\r
- BDS_LOAD_OPTION* BootOption;\r
- CHAR16 BootVariableName[9];\r
- UINT16* BootOrder;\r
- UINTN BootOrderSize;\r
-\r
- //\r
- // Allocate and fill the memory for the BDS Load Option structure\r
- //\r
- BootOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof (BDS_LOAD_OPTION_ENTRY));\r
- InitializeListHead (&BootOptionEntry->Link);\r
- BootOptionEntry->BdsLoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));\r
-\r
- BootOption = BootOptionEntry->BdsLoadOption;\r
- BootOptionSetFields (BootOption, Attributes, BootDescription, DevicePath, OptionalData, OptionalDataSize);\r
-\r
- //\r
- // Set the related environment variables\r
- //\r
-\r
- // Create Boot#### environment variable\r
- UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOption->LoadOptionIndex);\r
- Status = gRT->SetVariable (\r
- BootVariableName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- BootOption->LoadOptionSize,\r
- BootOption->LoadOption\r
- );\r
-\r
- // Add the new Boot Index to the list\r
- Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
- if (!EFI_ERROR(Status)) {\r
- BootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof(UINT16), BootOrder);\r
- // Add the new index at the end\r
- BootOrder[BootOrderSize / sizeof(UINT16)] = BootOption->LoadOptionIndex;\r
- BootOrderSize += sizeof(UINT16);\r
- } else {\r
- // BootOrder does not exist. Create it\r
- BootOrderSize = sizeof(UINT16);\r
- BootOrder = &(BootOption->LoadOptionIndex);\r
- }\r
-\r
- // Update (or Create) the BootOrder environment variable\r
- Status = gRT->SetVariable (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- BootOrderSize,\r
- BootOrder\r
- );\r
-\r
- // We only free it if the UEFI Variable 'BootOrder' was already existing\r
- if (BootOrderSize > sizeof(UINT16)) {\r
- FreePool (BootOrder);\r
- }\r
-\r
- *BdsLoadOption = BootOption;\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-BootOptionUpdate (\r
- IN BDS_LOAD_OPTION* BdsLoadOption,\r
- IN UINT32 Attributes,\r
- IN CHAR16* BootDescription,\r
- IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,\r
- IN UINT8* OptionalData,\r
- IN UINTN OptionalDataSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 BootVariableName[9];\r
-\r
- // Update the BDS Load Option structure\r
- BootOptionSetFields (BdsLoadOption, Attributes, BootDescription, DevicePath, OptionalData, OptionalDataSize);\r
-\r
- // Update the related environment variables\r
- UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex);\r
-\r
- Status = gRT->SetVariable (\r
- BootVariableName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- BdsLoadOption->LoadOptionSize,\r
- BdsLoadOption->LoadOption\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-BootOptionDelete (\r
- IN BDS_LOAD_OPTION *BootOption\r
- )\r
-{\r
- UINTN Index;\r
- UINTN BootOrderSize;\r
- UINT16* BootOrder;\r
- UINTN BootOrderCount;\r
- CHAR16 BootVariableName[9];\r
- EFI_STATUS Status;\r
-\r
- // Remove the entry from the BootOrder environment variable\r
- Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);\r
- if (!EFI_ERROR(Status)) {\r
- BootOrderCount = BootOrderSize / sizeof(UINT16);\r
-\r
- // Find the index of the removed entry\r
- for (Index = 0; Index < BootOrderCount; Index++) {\r
- if (BootOrder[Index] == BootOption->LoadOptionIndex) {\r
- // If it the last entry we do not need to rearrange the BootOrder list\r
- if (Index + 1 != BootOrderCount) {\r
- CopyMem (\r
- &BootOrder[Index],\r
- &BootOrder[Index + 1],\r
- (BootOrderCount - (Index + 1)) * sizeof(UINT16)\r
- );\r
- }\r
- break;\r
- }\r
- }\r
-\r
- // Update the BootOrder environment variable\r
- Status = gRT->SetVariable (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- BootOrderSize - sizeof(UINT16),\r
- BootOrder\r
- );\r
- }\r
-\r
- // Delete Boot#### environment variable\r
- UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOption->LoadOptionIndex);\r
- Status = gRT->SetVariable (\r
- BootVariableName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- 0,\r
- NULL\r
- );\r
-\r
- FreePool (BootOrder);\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
-*\r
-* This program and the accompanying materials\r
-* are licensed and made available under the terms and conditions of the BSD License\r
-* which accompanies this distribution. The full text of the license may be found at\r
-* http://opensource.org/licenses/bsd-license.php\r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-\r
-#include "BdsInternal.h"\r
-\r
-#include <Library/NetLib.h>\r
-\r
-#include <Protocol/BlockIo.h>\r
-#include <Protocol/DevicePathToText.h>\r
-#include <Protocol/FirmwareVolumeBlock.h>\r
-#include <Protocol/PxeBaseCode.h>\r
-#include <Protocol/SimpleFileSystem.h>\r
-#include <Protocol/SimpleNetwork.h>\r
-#include <Protocol/Dhcp4.h>\r
-#include <Protocol/Mtftp4.h>\r
-\r
-#include <Guid/FileSystemInfo.h>\r
-\r
-#define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))\r
-\r
-EFI_STATUS\r
-BdsLoadOptionFileSystemList (\r
- IN OUT LIST_ENTRY* BdsLoadOptionList\r
- );\r
-\r
-EFI_STATUS\r
-BdsLoadOptionFileSystemCreateDevicePath (\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes\r
- );\r
-\r
-EFI_STATUS\r
-BdsLoadOptionFileSystemUpdateDevicePath (\r
- IN EFI_DEVICE_PATH *OldDevicePath,\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath\r
- );\r
-\r
-BOOLEAN\r
-BdsLoadOptionFileSystemIsSupported (\r
- IN EFI_DEVICE_PATH *DevicePath\r
- );\r
-\r
-EFI_STATUS\r
-BdsLoadOptionMemMapList (\r
- IN OUT LIST_ENTRY* BdsLoadOptionList\r
- );\r
-\r
-EFI_STATUS\r
-BdsLoadOptionMemMapCreateDevicePath (\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes\r
- );\r
-\r
-EFI_STATUS\r
-BdsLoadOptionMemMapUpdateDevicePath (\r
- IN EFI_DEVICE_PATH *OldDevicePath,\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath\r
- );\r
-\r
-BOOLEAN\r
-BdsLoadOptionMemMapIsSupported (\r
- IN EFI_DEVICE_PATH *DevicePath\r
- );\r
-\r
-EFI_STATUS\r
-BdsLoadOptionPxeList (\r
- IN OUT LIST_ENTRY* BdsLoadOptionList\r
- );\r
-\r
-EFI_STATUS\r
-BdsLoadOptionPxeCreateDevicePath (\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes\r
- );\r
-\r
-EFI_STATUS\r
-BdsLoadOptionPxeUpdateDevicePath (\r
- IN EFI_DEVICE_PATH *OldDevicePath,\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath\r
- );\r
-\r
-BOOLEAN\r
-BdsLoadOptionPxeIsSupported (\r
- IN EFI_DEVICE_PATH *DevicePath\r
- );\r
-\r
-EFI_STATUS\r
-BdsLoadOptionTftpList (\r
- IN OUT LIST_ENTRY* BdsLoadOptionList\r
- );\r
-\r
-EFI_STATUS\r
-BdsLoadOptionTftpCreateDevicePath (\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes\r
- );\r
-\r
-EFI_STATUS\r
-BdsLoadOptionTftpUpdateDevicePath (\r
- IN EFI_DEVICE_PATH *OldDevicePath,\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath\r
- );\r
-\r
-BOOLEAN\r
-BdsLoadOptionTftpIsSupported (\r
- IN EFI_DEVICE_PATH *DevicePath\r
- );\r
-\r
-BDS_LOAD_OPTION_SUPPORT BdsLoadOptionSupportList[] = {\r
- {\r
- BDS_DEVICE_FILESYSTEM,\r
- BdsLoadOptionFileSystemList,\r
- BdsLoadOptionFileSystemIsSupported,\r
- BdsLoadOptionFileSystemCreateDevicePath,\r
- BdsLoadOptionFileSystemUpdateDevicePath,\r
- TRUE\r
- },\r
- {\r
- BDS_DEVICE_MEMMAP,\r
- BdsLoadOptionMemMapList,\r
- BdsLoadOptionMemMapIsSupported,\r
- BdsLoadOptionMemMapCreateDevicePath,\r
- BdsLoadOptionMemMapUpdateDevicePath,\r
- TRUE\r
- },\r
- {\r
- BDS_DEVICE_PXE,\r
- BdsLoadOptionPxeList,\r
- BdsLoadOptionPxeIsSupported,\r
- BdsLoadOptionPxeCreateDevicePath,\r
- BdsLoadOptionPxeUpdateDevicePath,\r
- FALSE\r
- },\r
- {\r
- BDS_DEVICE_TFTP,\r
- BdsLoadOptionTftpList,\r
- BdsLoadOptionTftpIsSupported,\r
- BdsLoadOptionTftpCreateDevicePath,\r
- BdsLoadOptionTftpUpdateDevicePath,\r
- TRUE\r
- }\r
-};\r
-\r
-EFI_STATUS\r
-BootDeviceListSupportedInit (\r
- IN OUT LIST_ENTRY *SupportedDeviceList\r
- )\r
-{\r
- UINTN Index;\r
-\r
- // Initialize list of supported devices\r
- InitializeListHead (SupportedDeviceList);\r
-\r
- for (Index = 0; Index < BDS_DEVICE_MAX; Index++) {\r
- BdsLoadOptionSupportList[Index].ListDevices (SupportedDeviceList);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-BootDeviceListSupportedFree (\r
- IN LIST_ENTRY *SupportedDeviceList,\r
- IN BDS_SUPPORTED_DEVICE *Except\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- BDS_SUPPORTED_DEVICE* SupportedDevice;\r
-\r
- Entry = GetFirstNode (SupportedDeviceList);\r
- while (Entry != SupportedDeviceList) {\r
- SupportedDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry);\r
- Entry = RemoveEntryList (Entry);\r
- if (SupportedDevice != Except) {\r
- FreePool (SupportedDevice);\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-BootDeviceGetDeviceSupport (\r
- IN EFI_DEVICE_PATH *DevicePath,\r
- OUT BDS_LOAD_OPTION_SUPPORT **DeviceSupport\r
- )\r
-{\r
- UINTN Index;\r
-\r
- // Find which supported device is the most appropriate\r
- for (Index = 0; Index < BDS_DEVICE_MAX; Index++) {\r
- if (BdsLoadOptionSupportList[Index].IsSupported (DevicePath)) {\r
- *DeviceSupport = &BdsLoadOptionSupportList[Index];\r
- return EFI_SUCCESS;\r
- }\r
- }\r
-\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-EFI_STATUS\r
-BdsLoadOptionFileSystemList (\r
- IN OUT LIST_ENTRY* BdsLoadOptionList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN HandleCount;\r
- EFI_HANDLE *HandleBuffer;\r
- UINTN Index;\r
- BDS_SUPPORTED_DEVICE *SupportedDevice;\r
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* FileProtocol;\r
- EFI_FILE_HANDLE Fs;\r
- UINTN Size;\r
- EFI_FILE_SYSTEM_INFO* FsInfo;\r
- EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
-\r
- // List all the Simple File System Protocols\r
- Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- for (Index = 0; Index < HandleCount; Index++) {\r
- Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
- if (!EFI_ERROR(Status)) {\r
- // Allocate BDS Supported Device structure\r
- SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool (sizeof(BDS_SUPPORTED_DEVICE));\r
-\r
- FileProtocol = NULL;\r
- Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FileProtocol);\r
- ASSERT_EFI_ERROR(Status);\r
-\r
- FileProtocol->OpenVolume (FileProtocol, &Fs);\r
-\r
- // Generate a Description from the file system\r
- Size = 0;\r
- FsInfo = NULL;\r
- Status = Fs->GetInfo (Fs, &gEfiFileSystemInfoGuid, &Size, FsInfo);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- FsInfo = AllocatePool (Size);\r
- Status = Fs->GetInfo (Fs, &gEfiFileSystemInfoGuid, &Size, FsInfo);\r
- }\r
- UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"%s (%d MB)",FsInfo->VolumeLabel,(UINT32)(FsInfo->VolumeSize / (1024 * 1024)));\r
- FreePool(FsInfo);\r
- Fs->Close (Fs);\r
-\r
- SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
- SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_FILESYSTEM];\r
-\r
- InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-BdsLoadOptionFileSystemCreateDevicePath (\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes\r
- )\r
-{\r
- EFI_STATUS Status;\r
- FILEPATH_DEVICE_PATH* FilePathDevicePath;\r
- CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];\r
- UINTN BootFilePathSize;\r
-\r
- Print(L"File path of the %s: ", FileName);\r
- Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);\r
- if (EFI_ERROR(Status)) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- BootFilePathSize = StrSize (BootFilePath);\r
- if (BootFilePathSize == 2) {\r
- *DevicePathNodes = NULL;\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- // Create the FilePath Device Path node\r
- FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize + END_DEVICE_PATH_LENGTH);\r
- FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH;\r
- FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP;\r
- SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
- CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize);\r
- SetDevicePathEndNode ((VOID*)((UINTN)FilePathDevicePath + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize));\r
- *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)FilePathDevicePath;\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-BdsLoadOptionFileSystemUpdateDevicePath (\r
- IN EFI_DEVICE_PATH *OldDevicePath,\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];\r
- UINTN BootFilePathSize;\r
- FILEPATH_DEVICE_PATH* EndingDevicePath;\r
- FILEPATH_DEVICE_PATH* FilePathDevicePath;\r
- EFI_DEVICE_PATH* DevicePath;\r
-\r
- DevicePath = DuplicateDevicePath (OldDevicePath);\r
-\r
- EndingDevicePath = (FILEPATH_DEVICE_PATH*)GetLastDevicePathNode (DevicePath);\r
-\r
- Print(L"File path of the %s: ", FileName);\r
- StrnCpy (BootFilePath, EndingDevicePath->PathName, BOOT_DEVICE_FILEPATH_MAX);\r
- Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- BootFilePathSize = StrSize(BootFilePath);\r
- if (BootFilePathSize == 2) {\r
- *NewDevicePath = NULL;\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- // Create the FilePath Device Path node\r
- FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
- FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH;\r
- FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP;\r
- SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
- CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize);\r
-\r
- // Generate the new Device Path by replacing the last node by the updated node\r
- SetDevicePathEndNode (EndingDevicePath);\r
- *NewDevicePath = AppendDevicePathNode (DevicePath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FilePathDevicePath);\r
- FreePool(DevicePath);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Check if a boot option path is a file system boot option path or not.\r
-\r
- The device specified by the beginning of the path has to support the Simple File\r
- System protocol. Furthermore, the remaining part of the path has to be composed of\r
- a single node of type MEDIA_DEVICE_PATH and sub-type MEDIA_FILEPATH_DP.\r
-\r
- @param[in] DevicePath Complete device path of a boot option.\r
-\r
- @retval FALSE The boot option path has not been identified as that of a\r
- file system boot option.\r
- @retval TRUE The boot option path is a file system boot option.\r
-**/\r
-BOOLEAN\r
-BdsLoadOptionFileSystemIsSupported (\r
- IN EFI_DEVICE_PATH *DevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE Handle;\r
- EFI_DEVICE_PATH *RemainingDevicePath;\r
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileProtocol;\r
-\r
- Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- }\r
-\r
- Status = gBS->HandleProtocol (\r
- Handle,\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- (VOID **)(&FileProtocol)\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- }\r
-\r
- if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP))\r
- return FALSE;\r
-\r
- return TRUE;\r
-}\r
-\r
-STATIC\r
-BOOLEAN\r
-IsParentDevicePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath\r
- )\r
-{\r
- UINTN ParentSize;\r
- UINTN ChildSize;\r
-\r
- ParentSize = GetDevicePathSize (ParentDevicePath);\r
- ChildSize = GetDevicePathSize (ChildDevicePath);\r
-\r
- if (ParentSize > ChildSize) {\r
- return FALSE;\r
- }\r
-\r
- if (CompareMem (ParentDevicePath, ChildDevicePath, ParentSize - END_DEVICE_PATH_LENGTH) != 0) {\r
- return FALSE;\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-EFI_STATUS\r
-BdsLoadOptionMemMapList (\r
- IN OUT LIST_ENTRY* BdsLoadOptionList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN HandleCount;\r
- EFI_HANDLE *HandleBuffer;\r
- UINTN DevicePathHandleCount;\r
- EFI_HANDLE *DevicePathHandleBuffer;\r
- BOOLEAN IsParent;\r
- UINTN Index;\r
- UINTN Index2;\r
- BDS_SUPPORTED_DEVICE *SupportedDevice;\r
- EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
- EFI_DEVICE_PATH* DevicePath;\r
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileProtocol;\r
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;\r
-\r
- // List all the BlockIo Protocols\r
- Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- for (Index = 0; Index < HandleCount; Index++) {\r
- // We only select handles WITH a Device Path AND not part of Media (to\r
- // avoid duplication with HardDisk, CDROM, etc). Skip handles used by\r
- // Simple Filesystem or used for Variable Storage.\r
-\r
-\r
- Status = gBS->HandleProtocol (HandleBuffer[Index],\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- (VOID *)&FileProtocol);\r
- if (!EFI_ERROR(Status)) {\r
- // SimpleFilesystem supported on this handle, skip\r
- continue;\r
- }\r
-\r
- Status = gBS->HandleProtocol (HandleBuffer[Index],\r
- &gEfiFirmwareVolumeBlockProtocolGuid,\r
- (VOID *)&FvbProtocol);\r
- if (!EFI_ERROR(Status)) {\r
- // Firmware Volme Block / Variable storage supported on this handle, skip\r
- continue;\r
- }\r
-\r
- Status = gBS->HandleProtocol (HandleBuffer[Index],\r
- &gEfiFirmwareVolumeBlock2ProtocolGuid,\r
- (VOID *)&FvbProtocol);\r
- if (!EFI_ERROR(Status)) {\r
- // Firmware Volme Block / Variable storage supported on this handle, skip\r
- continue;\r
- }\r
-\r
- Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
- if (!EFI_ERROR(Status)) {\r
- // BlockIo is not part of Media Device Path\r
- DevicePath = DevicePathProtocol;\r
- while (!IsDevicePathEndType (DevicePath) && (DevicePathType (DevicePath) != MEDIA_DEVICE_PATH)) {\r
- DevicePath = NextDevicePathNode (DevicePath);\r
- }\r
- if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) {\r
- continue;\r
- }\r
-\r
- // Open all the handle supporting the DevicePath protocol and verify this handle has not got any child\r
- Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &DevicePathHandleCount, &DevicePathHandleBuffer);\r
- ASSERT_EFI_ERROR (Status);\r
- IsParent = FALSE;\r
- for (Index2 = 0; (Index2 < DevicePathHandleCount) && !IsParent; Index2++) {\r
- if (HandleBuffer[Index] != DevicePathHandleBuffer[Index2]) {\r
- gBS->HandleProtocol (DevicePathHandleBuffer[Index2], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);\r
- if (IsParentDevicePath (DevicePathProtocol, DevicePath)) {\r
- IsParent = TRUE;\r
- }\r
- }\r
- }\r
- if (IsParent) {\r
- continue;\r
- }\r
-\r
- // Allocate BDS Supported Device structure\r
- SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));\r
-\r
- Status = GenerateDeviceDescriptionName (HandleBuffer[Index], SupportedDevice->Description);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
- SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_MEMMAP];\r
-\r
- InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-BdsLoadOptionMemMapCreateDevicePath (\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes\r
- )\r
-{\r
- EFI_STATUS Status;\r
- MEMMAP_DEVICE_PATH *MemMapDevicePath;\r
- CHAR16 StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX];\r
- CHAR16 StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX];\r
-\r
- Print(L"Starting Address of the %s: ", FileName);\r
- Status = GetHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX);\r
- if (EFI_ERROR(Status)) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- Print(L"Ending Address of the %s: ", FileName);\r
- Status = GetHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX);\r
- if (EFI_ERROR(Status)) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- // Create the MemMap Device Path Node\r
- MemMapDevicePath = (MEMMAP_DEVICE_PATH*)AllocatePool (sizeof(MEMMAP_DEVICE_PATH) + END_DEVICE_PATH_LENGTH);\r
- MemMapDevicePath->Header.Type = HARDWARE_DEVICE_PATH;\r
- MemMapDevicePath->Header.SubType = HW_MEMMAP_DP;\r
- SetDevicePathNodeLength (MemMapDevicePath, sizeof(MEMMAP_DEVICE_PATH));\r
- MemMapDevicePath->MemoryType = EfiBootServicesData;\r
- MemMapDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress);\r
- MemMapDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress);\r
-\r
- // Set a Device Path End Node after the Memory Map Device Path Node\r
- SetDevicePathEndNode (MemMapDevicePath + 1);\r
- *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)MemMapDevicePath;\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-BdsLoadOptionMemMapUpdateDevicePath (\r
- IN EFI_DEVICE_PATH *OldDevicePath,\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX];\r
- CHAR16 StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX];\r
- MEMMAP_DEVICE_PATH* EndingDevicePath;\r
- EFI_DEVICE_PATH* DevicePath;\r
-\r
- DevicePath = DuplicateDevicePath (OldDevicePath);\r
- EndingDevicePath = (MEMMAP_DEVICE_PATH*)GetLastDevicePathNode (DevicePath);\r
-\r
- Print(L"Starting Address of the %s: ", FileName);\r
- UnicodeSPrint (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->StartingAddress);\r
- Status = EditHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX);\r
- if (EFI_ERROR(Status)) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- Print(L"Ending Address of the %s: ", FileName);\r
- UnicodeSPrint (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->EndingAddress);\r
- Status = EditHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX);\r
- if (EFI_ERROR(Status)) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- EndingDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress);\r
- EndingDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress);\r
-\r
- if (EFI_ERROR(Status)) {\r
- FreePool(DevicePath);\r
- } else {\r
- *NewDevicePath = DevicePath;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Check if a boot option path is a memory map boot option path or not.\r
-\r
- The device specified by the beginning of the path has to support the BlockIo\r
- protocol. Furthermore, the remaining part of the path has to be composed of\r
- a single node of type HARDWARE_DEVICE_PATH and sub-type HW_MEMMAP_DP.\r
-\r
- @param[in] DevicePath Complete device path of a boot option.\r
-\r
- @retval FALSE The boot option path has not been identified as that of a\r
- memory map boot option.\r
- @retval TRUE The boot option path is a a memory map boot option.\r
-**/\r
-BOOLEAN\r
-BdsLoadOptionMemMapIsSupported (\r
- IN EFI_DEVICE_PATH *DevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE Handle;\r
- EFI_DEVICE_PATH *RemainingDevicePath;\r
- EFI_BLOCK_IO_PROTOCOL *BlockIoProtocol;\r
-\r
- Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- }\r
-\r
- Status = gBS->HandleProtocol (\r
- Handle,\r
- &gEfiBlockIoProtocolGuid,\r
- (VOID **)(&BlockIoProtocol)\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- }\r
-\r
- if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP))\r
- return FALSE;\r
-\r
- return TRUE;\r
-}\r
-\r
-EFI_STATUS\r
-BdsLoadOptionPxeList (\r
- IN OUT LIST_ENTRY* BdsLoadOptionList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN HandleCount;\r
- EFI_HANDLE *HandleBuffer;\r
- UINTN Index;\r
- BDS_SUPPORTED_DEVICE *SupportedDevice;\r
- EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;\r
- EFI_SIMPLE_NETWORK_PROTOCOL* SimpleNet;\r
- CHAR16 DeviceDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
- EFI_MAC_ADDRESS *Mac;\r
-\r
- // List all the PXE Protocols\r
- Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPxeBaseCodeProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- for (Index = 0; Index < HandleCount; Index++) {\r
- // We only select the handle WITH a Device Path AND the PXE Protocol\r
- Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol);\r
- if (!EFI_ERROR(Status)) {\r
- // Allocate BDS Supported Device structure\r
- SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE));\r
-\r
- Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimpleNetworkProtocolGuid, (VOID **)&SimpleNet);\r
- if (!EFI_ERROR(Status)) {\r
- Mac = &SimpleNet->Mode->CurrentAddress;\r
- UnicodeSPrint (DeviceDescription,BOOT_DEVICE_DESCRIPTION_MAX,L"MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", Mac->Addr[0], Mac->Addr[1], Mac->Addr[2], Mac->Addr[3], Mac->Addr[4], Mac->Addr[5]);\r
- } else {\r
- Status = GenerateDeviceDescriptionName (HandleBuffer[Index], DeviceDescription);\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
- UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"PXE on %s",DeviceDescription);\r
-\r
- SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
- SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_PXE];\r
-\r
- InsertTailList (BdsLoadOptionList,&SupportedDevice->Link);\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-BdsLoadOptionPxeCreateDevicePath (\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes\r
- )\r
-{\r
- *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);\r
- SetDevicePathEndNode (*DevicePathNodes);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Update the parameters of a Pxe boot option\r
-\r
- @param[in] OldDevicePath Current complete device path of the Pxe boot option.\r
- This has to be a valid complete Pxe boot option path.\r
- @param[in] FileName Description of the file the path is asked for\r
- @param[out] NewDevicePath Pointer to the new complete device path.\r
-\r
- @retval EFI_SUCCESS Update completed\r
- @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource\r
-**/\r
-EFI_STATUS\r
-BdsLoadOptionPxeUpdateDevicePath (\r
- IN EFI_DEVICE_PATH *OldDevicePath,\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath\r
- )\r
-{\r
- //\r
- // Make a copy of the complete device path that is made of :\r
- // the device path of the device supporting the Pxe base code protocol\r
- // followed by an end node.\r
- //\r
- *NewDevicePath = DuplicateDevicePath (OldDevicePath);\r
- if (*NewDevicePath == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- } else {\r
- return EFI_SUCCESS;\r
- }\r
-}\r
-\r
-BOOLEAN\r
-BdsLoadOptionPxeIsSupported (\r
- IN EFI_DEVICE_PATH *DevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE Handle;\r
- EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
- EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol;\r
-\r
- Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);\r
- if (EFI_ERROR(Status)) {\r
- return FALSE;\r
- }\r
-\r
- if (!IsDevicePathEnd(RemainingDevicePath)) {\r
- return FALSE;\r
- }\r
-\r
- Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- } else {\r
- return TRUE;\r
- }\r
-}\r
-\r
-/**\r
- Add to the list of boot devices the devices allowing a TFTP boot\r
-\r
- @param[in] BdsLoadOptionList List of devices to boot from\r
-\r
- @retval EFI_SUCCESS Update completed\r
- @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource\r
-**/\r
-EFI_STATUS\r
-BdsLoadOptionTftpList (\r
- IN OUT LIST_ENTRY* BdsLoadOptionList\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN HandleCount;\r
- EFI_HANDLE *HandleBuffer;\r
- EFI_HANDLE Handle;\r
- UINTN Index;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePathProtocol;\r
- VOID *Interface;\r
- EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetworkProtocol;\r
- BDS_SUPPORTED_DEVICE *SupportedDevice;\r
- EFI_MAC_ADDRESS *Mac;\r
-\r
- //\r
- // List all the handles on which the Simple Network Protocol is installed.\r
- //\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiSimpleNetworkProtocolGuid,\r
- NULL,\r
- &HandleCount,\r
- &HandleBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- for (Index = 0; Index < HandleCount; Index++) {\r
- Handle = HandleBuffer[Index];\r
- //\r
- // We select the handles that support :\r
- // . the Device Path Protocol\r
- // . the MTFTP4 Protocol\r
- //\r
- Status = gBS->HandleProtocol (\r
- Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **)&DevicePathProtocol\r
- );\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- Status = gBS->HandleProtocol (\r
- Handle,\r
- &gEfiMtftp4ServiceBindingProtocolGuid,\r
- &Interface\r
- );\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- Status = gBS->HandleProtocol (\r
- Handle,\r
- &gEfiSimpleNetworkProtocolGuid,\r
- (VOID **)&SimpleNetworkProtocol\r
- );\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- // Allocate BDS Supported Device structure\r
- SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool (sizeof (BDS_SUPPORTED_DEVICE));\r
- if (SupportedDevice == NULL) {\r
- continue;\r
- }\r
-\r
- Mac = &SimpleNetworkProtocol->Mode->CurrentAddress;\r
- UnicodeSPrint (\r
- SupportedDevice->Description,\r
- BOOT_DEVICE_DESCRIPTION_MAX,\r
- L"TFTP on MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",\r
- Mac->Addr[0], Mac->Addr[1], Mac->Addr[2], Mac->Addr[3], Mac->Addr[4], Mac->Addr[5]\r
- );\r
-\r
- SupportedDevice->DevicePathProtocol = DevicePathProtocol;\r
- SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_TFTP];\r
-\r
- InsertTailList (BdsLoadOptionList, &SupportedDevice->Link);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-BdsLoadOptionTftpCreateDevicePath (\r
- IN CHAR16* FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BOOLEAN IsDHCP;\r
- EFI_IP_ADDRESS LocalIp;\r
- EFI_IP_ADDRESS SubnetMask;\r
- EFI_IP_ADDRESS GatewayIp;\r
- EFI_IP_ADDRESS RemoteIp;\r
- IPv4_DEVICE_PATH *IPv4DevicePathNode;\r
- FILEPATH_DEVICE_PATH *FilePathDevicePath;\r
- CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];\r
- UINTN BootFilePathSize;\r
-\r
- Print (L"Get the IP address from DHCP: ");\r
- Status = GetHIInputBoolean (&IsDHCP);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- if (!IsDHCP) {\r
- Print (L"Local static IP address: ");\r
- Status = GetHIInputIP (&LocalIp);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_ABORTED;\r
- }\r
- Print (L"Get the network mask: ");\r
- Status = GetHIInputIP (&SubnetMask);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_ABORTED;\r
- }\r
- Print (L"Get the gateway IP address: ");\r
- Status = GetHIInputIP (&GatewayIp);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_ABORTED;\r
- }\r
- }\r
-\r
- Print (L"Get the TFTP server IP address: ");\r
- Status = GetHIInputIP (&RemoteIp);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- Print (L"File path of the %s : ", FileName);\r
- Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- BootFilePathSize = StrSize(BootFilePath);\r
- if (BootFilePathSize == 2) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- // Allocate the memory for the IPv4 + File Path Device Path Nodes\r
- IPv4DevicePathNode = (IPv4_DEVICE_PATH*)AllocatePool(sizeof(IPv4_DEVICE_PATH) + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize + END_DEVICE_PATH_LENGTH);\r
-\r
- // Create the IPv4 Device Path\r
- IPv4DevicePathNode->Header.Type = MESSAGING_DEVICE_PATH;\r
- IPv4DevicePathNode->Header.SubType = MSG_IPv4_DP;\r
- SetDevicePathNodeLength (&IPv4DevicePathNode->Header, sizeof(IPv4_DEVICE_PATH));\r
-\r
- if (!IsDHCP) {\r
- CopyMem (&IPv4DevicePathNode->LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
- CopyMem (&IPv4DevicePathNode->SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));\r
- CopyMem (&IPv4DevicePathNode->GatewayIpAddress, &GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
- }\r
-\r
- CopyMem (&IPv4DevicePathNode->RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
- IPv4DevicePathNode->LocalPort = 0;\r
- IPv4DevicePathNode->RemotePort = 0;\r
- IPv4DevicePathNode->Protocol = EFI_IP_PROTO_TCP;\r
- IPv4DevicePathNode->StaticIpAddress = (IsDHCP != TRUE);\r
-\r
- // Create the FilePath Device Path node\r
- FilePathDevicePath = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1);\r
- FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH;\r
- FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP;\r
- SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize);\r
- CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize);\r
-\r
- // Set the End Device Path Node\r
- SetDevicePathEndNode ((VOID*)((UINTN)FilePathDevicePath + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize));\r
- *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)IPv4DevicePathNode;\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Update the parameters of a TFTP boot option\r
-\r
- The function asks sequentially to update the IPv4 parameters as well as the boot file path,\r
- providing the previously set value if any.\r
-\r
- @param[in] OldDevicePath Current complete device path of the Tftp boot option.\r
- This has to be a valid complete Tftp boot option path.\r
- By complete, we mean that it is not only the Tftp\r
- specific end part built by the\r
- "BdsLoadOptionTftpCreateDevicePath()" function.\r
- This path is handled as read only.\r
- @param[in] FileName Description of the file the path is asked for\r
- @param[out] NewDevicePath Pointer to the new complete device path.\r
-\r
- @retval EFI_SUCCESS Update completed\r
- @retval EFI_ABORTED Update aborted by the user\r
- @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource\r
-**/\r
-EFI_STATUS\r
-BdsLoadOptionTftpUpdateDevicePath (\r
- IN EFI_DEVICE_PATH *OldDevicePath,\r
- IN CHAR16 *FileName,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH *DevicePath;\r
- EFI_DEVICE_PATH *DevicePathNode;\r
- UINT8 *Ipv4NodePtr;\r
- IPv4_DEVICE_PATH Ipv4Node;\r
- BOOLEAN IsDHCP;\r
- EFI_IP_ADDRESS OldIp;\r
- EFI_IP_ADDRESS OldSubnetMask;\r
- EFI_IP_ADDRESS OldGatewayIp;\r
- EFI_IP_ADDRESS LocalIp;\r
- EFI_IP_ADDRESS SubnetMask;\r
- EFI_IP_ADDRESS GatewayIp;\r
- EFI_IP_ADDRESS RemoteIp;\r
- UINT8 *FileNodePtr;\r
- CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX];\r
- UINTN PathSize;\r
- UINTN BootFilePathSize;\r
- FILEPATH_DEVICE_PATH *NewFilePathNode;\r
-\r
- Ipv4NodePtr = NULL;\r
-\r
- //\r
- // Make a copy of the complete device path that is made of :\r
- // the device path of the device that support the Simple Network protocol\r
- // followed by an IPv4 node (type IPv4_DEVICE_PATH),\r
- // followed by a file path node (type FILEPATH_DEVICE_PATH) and ended up\r
- // by an end node. The IPv6 case is not handled yet.\r
- //\r
-\r
- DevicePath = DuplicateDevicePath (OldDevicePath);\r
- if (DevicePath == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ErrorExit;\r
- }\r
-\r
- //\r
- // Because of the check done by "BdsLoadOptionTftpIsSupported()" prior to the\r
- // call to this function, we know that the device path ends with an IPv4 node\r
- // followed by a file path node and finally an end node. To get the address of\r
- // the last IPv4 node, we loop over the whole device path, noting down the\r
- // address of each encountered IPv4 node.\r
- //\r
-\r
- for (DevicePathNode = DevicePath;\r
- !IsDevicePathEnd (DevicePathNode);\r
- DevicePathNode = NextDevicePathNode (DevicePathNode))\r
- {\r
- if (IS_DEVICE_PATH_NODE (DevicePathNode, MESSAGING_DEVICE_PATH, MSG_IPv4_DP)) {\r
- Ipv4NodePtr = (UINT8*)DevicePathNode;\r
- }\r
- }\r
-\r
- // Copy for alignment of the IPv4 node data\r
- CopyMem (&Ipv4Node, Ipv4NodePtr, sizeof (IPv4_DEVICE_PATH));\r
-\r
- Print (L"Get the IP address from DHCP: ");\r
- Status = GetHIInputBoolean (&IsDHCP);\r
- if (EFI_ERROR (Status)) {\r
- goto ErrorExit;\r
- }\r
-\r
- if (!IsDHCP) {\r
- Print (L"Local static IP address: ");\r
- if (Ipv4Node.StaticIpAddress) {\r
- CopyMem (&OldIp.v4, &Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
- Status = EditHIInputIP (&OldIp, &LocalIp);\r
- } else {\r
- Status = GetHIInputIP (&LocalIp);\r
- }\r
- if (EFI_ERROR (Status)) {\r
- goto ErrorExit;\r
- }\r
-\r
- Print (L"Get the network mask: ");\r
- if (Ipv4Node.StaticIpAddress) {\r
- CopyMem (&OldSubnetMask.v4, &Ipv4Node.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
- Status = EditHIInputIP (&OldSubnetMask, &SubnetMask);\r
- } else {\r
- Status = GetHIInputIP (&SubnetMask);\r
- }\r
- if (EFI_ERROR (Status)) {\r
- goto ErrorExit;\r
- }\r
-\r
- Print (L"Get the gateway IP address: ");\r
- if (Ipv4Node.StaticIpAddress) {\r
- CopyMem (&OldGatewayIp.v4, &Ipv4Node.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
- Status = EditHIInputIP (&OldGatewayIp, &GatewayIp);\r
- } else {\r
- Status = GetHIInputIP (&GatewayIp);\r
- }\r
- if (EFI_ERROR (Status)) {\r
- goto ErrorExit;\r
- }\r
- }\r
-\r
- Print (L"TFTP server IP address: ");\r
- // Copy remote IPv4 address into IPv4 or IPv6 union\r
- CopyMem (&OldIp.v4, &Ipv4Node.RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
-\r
- Status = EditHIInputIP (&OldIp, &RemoteIp);\r
- if (EFI_ERROR (Status)) {\r
- goto ErrorExit;\r
- }\r
-\r
- // Get the path of the boot file and its size in number of bytes\r
- FileNodePtr = Ipv4NodePtr + sizeof (IPv4_DEVICE_PATH);\r
- BootFilePathSize = DevicePathNodeLength (FileNodePtr) - SIZE_OF_FILEPATH_DEVICE_PATH;\r
-\r
- //\r
- // Ask for update of the boot file path\r
- //\r
- do {\r
- // Copy for 2-byte alignment of the Unicode string\r
- CopyMem (\r
- BootFilePath, FileNodePtr + SIZE_OF_FILEPATH_DEVICE_PATH,\r
- MIN (BootFilePathSize, BOOT_DEVICE_FILEPATH_MAX)\r
- );\r
- BootFilePath[BOOT_DEVICE_FILEPATH_MAX - 1] = L'\0';\r
-\r
- Print (L"File path of the %s: ", FileName);\r
- Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX);\r
- if (EFI_ERROR (Status)) {\r
- goto ErrorExit;\r
- }\r
- PathSize = StrSize (BootFilePath);\r
- if (PathSize > 2) {\r
- break;\r
- }\r
- // Empty string, give the user another try\r
- Print (L"Empty string - Invalid path\n");\r
- } while (PathSize <= 2) ;\r
-\r
- //\r
- // Update the IPv4 node. IPv6 case not handled yet.\r
- //\r
- if (IsDHCP) {\r
- Ipv4Node.StaticIpAddress = FALSE;\r
- ZeroMem (&Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
- ZeroMem (&Ipv4Node.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
- ZeroMem (&Ipv4Node.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));\r
- } else {\r
- Ipv4Node.StaticIpAddress = TRUE;\r
- CopyMem (&Ipv4Node.LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
- CopyMem (&Ipv4Node.SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));\r
- CopyMem (&Ipv4Node.GatewayIpAddress, &GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
- }\r
-\r
- CopyMem (&Ipv4Node.RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS));\r
- CopyMem (Ipv4NodePtr, &Ipv4Node, sizeof (IPv4_DEVICE_PATH));\r
-\r
- //\r
- // Create the new file path node\r
- //\r
- NewFilePathNode = (FILEPATH_DEVICE_PATH*)AllocatePool (\r
- SIZE_OF_FILEPATH_DEVICE_PATH +\r
- PathSize\r
- );\r
- NewFilePathNode->Header.Type = MEDIA_DEVICE_PATH;\r
- NewFilePathNode->Header.SubType = MEDIA_FILEPATH_DP;\r
- SetDevicePathNodeLength (\r
- NewFilePathNode,\r
- SIZE_OF_FILEPATH_DEVICE_PATH + PathSize\r
- );\r
- CopyMem (NewFilePathNode->PathName, BootFilePath, PathSize);\r
-\r
- //\r
- // Generate the new Device Path by replacing the file path node at address\r
- // "FileNodePtr" by the new one "NewFilePathNode" and return its address.\r
- //\r
- SetDevicePathEndNode (FileNodePtr);\r
- *NewDevicePath = AppendDevicePathNode (\r
- DevicePath,\r
- (CONST EFI_DEVICE_PATH_PROTOCOL*)NewFilePathNode\r
- );\r
-\r
-ErrorExit:\r
- if (DevicePath != NULL) {\r
- FreePool (DevicePath) ;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-BOOLEAN\r
-BdsLoadOptionTftpIsSupported (\r
- IN EFI_DEVICE_PATH *DevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE Handle;\r
- EFI_DEVICE_PATH *RemainingDevicePath;\r
- EFI_DEVICE_PATH *NextDevicePath;\r
- EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol;\r
-\r
- Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath);\r
- if (EFI_ERROR(Status)) {\r
- return FALSE;\r
- }\r
-\r
- // Validate the Remaining Device Path\r
- if (IsDevicePathEnd(RemainingDevicePath)) {\r
- return FALSE;\r
- }\r
- if (!IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv4_DP) &&\r
- !IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv6_DP)) {\r
- return FALSE;\r
- }\r
- NextDevicePath = NextDevicePathNode (RemainingDevicePath);\r
- if (IsDevicePathEnd(NextDevicePath)) {\r
- return FALSE;\r
- }\r
- if (!IS_DEVICE_PATH_NODE(NextDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP)) {\r
- return FALSE;\r
- }\r
-\r
- Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol);\r
- if (EFI_ERROR (Status)) {\r
- return FALSE;\r
- } else {\r
- return TRUE;\r
- }\r
-}\r