2341 lines
77 KiB
C
2341 lines
77 KiB
C
/** @file
|
|
Boot menu relative functions
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2020, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include "BootMenu.h"
|
|
#include <Library/PrintLib.h>
|
|
#include <Protocol/DiskInfo.h>
|
|
#include <Protocol/BootOptionPolicy.h>
|
|
#include <Protocol/UsbIo.h>
|
|
#include <Protocol/BlockIo.h>
|
|
|
|
|
|
/**
|
|
Sync boot device info to boot config.
|
|
|
|
@retval EFI_SUCCESS Sync boot device info successfully.
|
|
@retval Other Fail to get browser data.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
BootDevInfoSyncToBootConfig (
|
|
VOID
|
|
)
|
|
{
|
|
UINT16 Index;
|
|
UINT16 EfiDevCount;
|
|
UINT16 LegacyDevCount;
|
|
EFI_STATUS Status;
|
|
SETUP_UTILITY_BROWSER_DATA *SuBrowser;
|
|
UINT16 LegacyBootDevTypeCount;
|
|
UINT16 TypeIndex;
|
|
UINT16 DevCount;
|
|
UINT8 DevType;
|
|
UINT16 Offset;
|
|
KERNEL_CONFIGURATION *KernelConfig;
|
|
BBS_TYPE_TABLE *BbsTypeTable;
|
|
|
|
//
|
|
// Update device switch of boot config from boot device info.
|
|
//
|
|
EfiDevCount = 0;
|
|
LegacyDevCount = 0;
|
|
for (Index = 0; Index < mBootDevInfoCount; Index++) {
|
|
if (mBootDevInfo[Index].IsEfiBootDev) {
|
|
mBootConfig.EfiBootDevSwitch[EfiDevCount++] = mBootDevInfo[Index].IsActive;
|
|
} else {
|
|
mBootConfig.LegacyAdvBootDevSwitch[LegacyDevCount++] = mBootDevInfo[Index].IsActive;
|
|
}
|
|
}
|
|
|
|
Status = GetSetupUtilityBrowserData (&SuBrowser);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
KernelConfig = (KERNEL_CONFIGURATION *) SuBrowser->SCBuffer;
|
|
LegacyBootDevTypeCount = GetBootTypeOrderCount (KernelConfig);
|
|
|
|
for (TypeIndex = 0; TypeIndex < LegacyBootDevTypeCount; TypeIndex++) {
|
|
BbsTypeTable = GetBbsTypeTableByDevType (KernelConfig->BootTypeOrder[TypeIndex]);
|
|
if (BbsTypeTable == NULL || BbsTypeTable->KeyBootDeviceBase < KEY_BOOT_DEVICE_TYPE_BASE) {
|
|
continue;
|
|
}
|
|
|
|
Offset = BbsTypeTable->KeyBootDeviceBase - KEY_BOOT_DEVICE_TYPE_BASE;
|
|
DevType = BbsTypeTable->DeviceType;
|
|
DevCount = 0;
|
|
|
|
for (Index = 0; Index < mBootDevInfoCount; Index++) {
|
|
if (!mBootDevInfo[Index].IsEfiBootDev &&
|
|
mBootDevInfo[Index].DevType == DevType) {
|
|
mBootConfig.LegacyTypeDevSwitch[Offset + DevCount] = mBootDevInfo[Index].IsActive;
|
|
DevCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Set active value to the specific boot option number.
|
|
|
|
@param[in] BootOptionNum Boot option number
|
|
@param[in] IsActive Active value
|
|
|
|
@retval EFI_SUCCESS Set active value successfully.
|
|
@retval EFI_NOT_FOUND Can not find the corresponding boot device info by boot option number.
|
|
**/
|
|
EFI_STATUS
|
|
BootDevInfoSetActiveValue (
|
|
IN UINT16 BootOptionNum,
|
|
IN BOOLEAN IsActive
|
|
)
|
|
{
|
|
UINT16 Index;
|
|
|
|
if (mBootDevInfo == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
for (Index = 0; Index < mBootDevInfoCount; Index++) {
|
|
if (mBootDevInfo[Index].BootOptionNum == BootOptionNum) {
|
|
mBootDevInfo[Index].IsActive = IsActive;
|
|
BootDevInfoSyncToBootConfig ();
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Get boot device info by question ID.
|
|
|
|
@return The pointer of boot device info or NULL if not found.
|
|
**/
|
|
BOOT_DEV_INFO *
|
|
GetBootDevInfo (
|
|
IN EFI_QUESTION_ID QuestionId
|
|
)
|
|
{
|
|
UINT16 KeyBase;
|
|
UINT16 TargetIndex;
|
|
UINT16 Index;
|
|
UINT16 Count;
|
|
EFI_STATUS Status;
|
|
SETUP_UTILITY_BROWSER_DATA *SuBrowser;
|
|
UINT16 LegacyBootDevTypeCount;
|
|
UINT16 TypeIndex;
|
|
KERNEL_CONFIGURATION *KernelConfig;
|
|
BBS_TYPE_TABLE *BbsTypeTable;
|
|
|
|
KeyBase = KEY_EFI_BOOT_DEVICE_BASE;
|
|
if ((QuestionId >= KeyBase) &&
|
|
(QuestionId < KeyBase + MAX_BOOT_DEVICES_NUMBER)) {
|
|
TargetIndex = QuestionId - KeyBase;
|
|
|
|
for (Index = 0, Count = 0; Index < mBootDevInfoCount; Index++) {
|
|
if (mBootDevInfo[Index].IsEfiBootDev) {
|
|
if (Count == TargetIndex) {
|
|
return &mBootDevInfo[Index];
|
|
}
|
|
Count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
KeyBase = KEY_ADV_LEGACY_BOOT_BASE;
|
|
if ((QuestionId >= KeyBase) &&
|
|
(QuestionId < KeyBase + MAX_LEGACY_BOOT_DEV_NUM)) {
|
|
TargetIndex = QuestionId - KeyBase;
|
|
|
|
for (Index = 0, Count = 0; Index < mBootDevInfoCount; Index++) {
|
|
if (!mBootDevInfo[Index].IsEfiBootDev) {
|
|
if (Count == TargetIndex) {
|
|
return &mBootDevInfo[Index];
|
|
}
|
|
Count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
Status = GetSetupUtilityBrowserData (&SuBrowser);
|
|
if (EFI_ERROR (Status)) {
|
|
return NULL;
|
|
}
|
|
|
|
KernelConfig = (KERNEL_CONFIGURATION *) SuBrowser->SCBuffer;
|
|
LegacyBootDevTypeCount = GetBootTypeOrderCount (KernelConfig);
|
|
|
|
for (TypeIndex = 0; TypeIndex < LegacyBootDevTypeCount; TypeIndex++) {
|
|
BbsTypeTable = GetBbsTypeTableByDevType (KernelConfig->BootTypeOrder[TypeIndex]);
|
|
if (BbsTypeTable == NULL || BbsTypeTable->KeyBootDeviceBase < KEY_BOOT_DEVICE_TYPE_BASE) {
|
|
continue;
|
|
}
|
|
|
|
KeyBase = BbsTypeTable->KeyBootDeviceBase;
|
|
if (!((QuestionId >= KeyBase) &&
|
|
(QuestionId < KeyBase + BbsTypeTable->DevInfoCount))) {
|
|
continue;
|
|
}
|
|
|
|
TargetIndex = QuestionId - KeyBase;
|
|
|
|
for (Index = 0, Count = 0; Index < mBootDevInfoCount; Index++) {
|
|
if (!mBootDevInfo[Index].IsEfiBootDev &&
|
|
mBootDevInfo[Index].DevType == BbsTypeTable->DeviceType) {
|
|
if (Count == TargetIndex) {
|
|
return &mBootDevInfo[Index];
|
|
}
|
|
Count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Sync current boot order to boot config varstore.
|
|
**/
|
|
VOID
|
|
SyncBootOrderToBootConfig (
|
|
VOID
|
|
)
|
|
{
|
|
BootDevInfoSortByBootOrder ();
|
|
BootDevInfoSyncToBootConfig ();
|
|
}
|
|
|
|
/**
|
|
Initialize boot configuration value.
|
|
|
|
@param[in] SuBrowser Pointer point to SETUP_UTILITY_BROWSER_DATA instance
|
|
|
|
@retval EFI_SUCCESS Initialize boot configuration successfully.
|
|
**/
|
|
EFI_STATUS
|
|
BootConfigInit (
|
|
IN SETUP_UTILITY_BROWSER_DATA *SuBrowser
|
|
)
|
|
{
|
|
UINTN Index;
|
|
SETUP_UTILITY_CONFIGURATION *SUCInfo;
|
|
KERNEL_CONFIGURATION *KernelConfig;
|
|
|
|
SUCInfo = SuBrowser->SUCInfo;
|
|
KernelConfig = (KERNEL_CONFIGURATION *) SuBrowser->SCBuffer;
|
|
|
|
BootDevInfoSyncToBootConfig ();
|
|
mBootConfig.HaveLegacyBootDevTypeOrder = (GetBootTypeOrderCount (KernelConfig) != 0) ? 1 : 0;
|
|
mBootConfig.HaveLegacyBootDev = (SUCInfo->LegacyBootDeviceNum != 0) ? 1 : 0;
|
|
mBootConfig.HaveEfiBootDev = (SUCInfo->EfiBootDeviceNum != 0) ? 1 : 0;
|
|
for (Index = 0; Index < mBbsTypeTableCount; Index++) {
|
|
mBootConfig.NoBootDevs[Index]= (mBbsTypeTable[Index].DevInfoCount != 0) ? 1 : 0;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Load the default value of boot configuration varstore.
|
|
|
|
@retval EFI_SUCCESS Load the default value successfully.
|
|
@retval Other Fail to initialize boot device switch info.
|
|
**/
|
|
EFI_STATUS
|
|
BootConfigLoadDefault (
|
|
VOID
|
|
)
|
|
{
|
|
BootDevInfoInit ();
|
|
InitBbsTypeTable ();
|
|
return BootDevInfoSyncToBootConfig ();
|
|
}
|
|
|
|
/**
|
|
Save the current settings of boot configuration varstore.
|
|
|
|
@retval EFI_SUCCESS Save the current settings successfully.
|
|
@retval Other Fail to set boot option variable by device switch info.
|
|
**/
|
|
EFI_STATUS
|
|
BootConfigSaveSetting (
|
|
VOID
|
|
)
|
|
{
|
|
return BootDevInfoSetToVariable ();
|
|
}
|
|
|
|
/**
|
|
Clean space character in the front and back of input string.
|
|
|
|
@param Str Input string
|
|
|
|
**/
|
|
VOID
|
|
CleanSpaceChar (
|
|
IN CHAR16 *Str
|
|
)
|
|
{
|
|
UINTN StrLength;
|
|
UINTN Start;
|
|
UINTN End;
|
|
UINTN ValidLength;
|
|
CHAR16 SpaceChar = ' ';
|
|
|
|
if (Str == NULL) {
|
|
return;
|
|
}
|
|
|
|
StrLength = StrLen (Str);
|
|
if (StrLength == 0) {
|
|
return;
|
|
}
|
|
|
|
Start = 0;
|
|
End = StrLength - 1;
|
|
|
|
while (Str[Start] == SpaceChar) {
|
|
Start++;
|
|
}
|
|
if (Start == StrLength) {
|
|
//
|
|
// All chars are space char, no need to remove space chars.
|
|
//
|
|
return;
|
|
}
|
|
|
|
while (Str[End] == SpaceChar) {
|
|
End--;
|
|
}
|
|
|
|
ValidLength = End - Start + 1;
|
|
if (ValidLength < StrLength) {
|
|
gBS->CopyMem (&Str[0], &Str[Start], ValidLength * sizeof(CHAR16));
|
|
gBS->SetMem (&Str[ValidLength], (StrLength - ValidLength) * sizeof(CHAR16), 0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Check whether the EFI_COMPONENT_NAME_PROTOCOL instance is valid for use.
|
|
|
|
@param[in] ComponentName A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance
|
|
@param[in] Handle The handle of Block IO device
|
|
|
|
@retval TRUE The protocol is valid
|
|
@retval FALSE The protocol is invalid
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsValidComponentNameProtocol (
|
|
IN EFI_COMPONENT_NAME_PROTOCOL *ComponentName,
|
|
IN EFI_HANDLE Handle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CHAR16 *String1;
|
|
CHAR16 *String2;
|
|
|
|
//
|
|
// Some incomplete ComponentName protocols return success regardless of invalid inputs, which brings the wrong device name received.
|
|
// Try the cases that gives illegal inputs to filter these incomplete ComponentName protocol.
|
|
//
|
|
// Give illegal inputs (ControllerHandle = NULL)
|
|
//
|
|
Status = ComponentName->GetControllerName (
|
|
ComponentName,
|
|
NULL,
|
|
Handle,
|
|
ComponentName->SupportedLanguages,
|
|
&String1
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Give illegal inputs (ControllerHandle = NULL, ChildHandle = NULL)
|
|
//
|
|
Status = ComponentName->GetControllerName (
|
|
ComponentName,
|
|
NULL,
|
|
NULL,
|
|
ComponentName->SupportedLanguages,
|
|
&String2
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// The protocol that return a fixed data in the above cases is considered invalid
|
|
//
|
|
return (CompareMem (String1, String2, StrLen (String1)) != 0);
|
|
}
|
|
|
|
/**
|
|
Get device name from Component Name (2) protocol.
|
|
|
|
@param[in] ControllerHandle The handle of a controller
|
|
@param[in] BlockIoHandle The handle of a Block IO device
|
|
@param[in] ComponentNameProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID
|
|
@param[in] ComponentNameHandleCount The number of Component Name (2) protocol handles
|
|
@param[in] ComponentNameHandleList A pointer to an array of Component Name (2) protocol handles
|
|
|
|
@return A pointer to device name or NULL if not found.
|
|
**/
|
|
CHAR16 *
|
|
GetDevNameFromComponentNameProtocol (
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_HANDLE BlockIoHandle,
|
|
IN EFI_GUID *ComponentNameProtocolGuid,
|
|
IN UINTN ComponentNameHandleCount,
|
|
IN EFI_HANDLE *ComponentNameHandleList
|
|
)
|
|
{
|
|
UINTN Index;
|
|
EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
|
|
CHAR16 *DeviceName;
|
|
EFI_STATUS Status;
|
|
|
|
for (Index = 0; Index < ComponentNameHandleCount; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
ComponentNameHandleList[Index],
|
|
ComponentNameProtocolGuid,
|
|
(VOID **) &ComponentName
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = ComponentName->GetControllerName (
|
|
ComponentName,
|
|
ControllerHandle,
|
|
BlockIoHandle,
|
|
ComponentName->SupportedLanguages,
|
|
&DeviceName
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// For some Single-LUN storages, BlockIo protocol may be installed on the ControllerHandle instead of a new handle created.
|
|
// Trying the BlockIo handle as the ControllerHandle for retrieving the device name.
|
|
//
|
|
Status = ComponentName->GetControllerName (
|
|
ComponentName,
|
|
BlockIoHandle,
|
|
BlockIoHandle,
|
|
ComponentName->SupportedLanguages,
|
|
&DeviceName
|
|
);
|
|
}
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
if (!IsValidComponentNameProtocol (ComponentName, BlockIoHandle)) {
|
|
continue;
|
|
}
|
|
return DeviceName;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Get all hardware boot device information (BlockIo device path and device name).
|
|
|
|
@param HwBootDeviceInfoCount Hardware boot device information count
|
|
@param HwBootDeviceInfo Array pointer of hardware boot device information
|
|
|
|
@retval EFI_SUCCESS Get information successfully
|
|
@return Other Invalid input parameter.
|
|
Locate protocol fail or get usb device information fail
|
|
|
|
**/
|
|
EFI_STATUS
|
|
GetAllHwBootDeviceInfo (
|
|
OUT UINTN *HwBootDeviceInfoCount,
|
|
OUT HARDWARE_BOOT_DEVICE_INFO **HwBootDeviceInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN HandleCount;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINTN Index;
|
|
EFI_DEVICE_PATH_PROTOCOL *BlkIoDevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *AppendedDevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath;
|
|
EFI_HANDLE ControllerHandle;
|
|
CHAR16 *DeviceName;
|
|
UINTN ComponentNameHandleCount;
|
|
UINTN ComponentName2HandleCount;
|
|
EFI_HANDLE *ComponentNameHandleBuffer;
|
|
EFI_HANDLE *ComponentName2HandleBuffer;
|
|
UINTN HwBootDeviceInfoLength;
|
|
UINTN Increment;
|
|
BOOLEAN StopSearching;
|
|
|
|
if (HwBootDeviceInfoCount == NULL || HwBootDeviceInfo == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
*HwBootDeviceInfoCount = 0;
|
|
*HwBootDeviceInfo = NULL;
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiBlockIoProtocolGuid,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiComponentNameProtocolGuid , NULL, &ComponentNameHandleCount , &ComponentNameHandleBuffer);
|
|
if (EFI_ERROR (Status)) {
|
|
ComponentNameHandleCount = 0;
|
|
ComponentNameHandleBuffer = NULL;
|
|
}
|
|
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiComponentName2ProtocolGuid, NULL, &ComponentName2HandleCount, &ComponentName2HandleBuffer);
|
|
if (EFI_ERROR (Status)) {
|
|
ComponentName2HandleCount = 0;
|
|
ComponentName2HandleBuffer = NULL;
|
|
}
|
|
if (ComponentNameHandleCount == 0 && ComponentName2HandleCount == 0) {
|
|
goto Exit;
|
|
}
|
|
|
|
Increment = 10;
|
|
HwBootDeviceInfoLength = 0;
|
|
for (Index = 0; Index < HandleCount; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[Index],
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID *) &BlkIoDevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Skip media level BlkIo instance
|
|
//
|
|
TempDevicePath = BlkIoDevicePath;
|
|
while (!IsDevicePathEnd (TempDevicePath) && DevicePathType (TempDevicePath) != MEDIA_DEVICE_PATH) {
|
|
TempDevicePath = NextDevicePathNode (TempDevicePath);
|
|
}
|
|
if (!IsDevicePathEnd (TempDevicePath)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Find contoller handle and retrieve the device name
|
|
//
|
|
StopSearching = FALSE;
|
|
ControllerHandle = HandleBuffer[Index];
|
|
while (!StopSearching) {
|
|
Status = gBS->HandleProtocol (
|
|
ControllerHandle,
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID *)&TempDevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
AppendedDevicePath = NULL;
|
|
ControllerDevicePath = NULL;
|
|
while (!IsDevicePathEnd (NextDevicePathNode (TempDevicePath))) {
|
|
ControllerDevicePath = AppendDevicePathNode (AppendedDevicePath, TempDevicePath);
|
|
if (AppendedDevicePath != NULL) {
|
|
FreePool (AppendedDevicePath);
|
|
}
|
|
AppendedDevicePath = ControllerDevicePath;
|
|
TempDevicePath = NextDevicePathNode (TempDevicePath);
|
|
}
|
|
|
|
//
|
|
// Stop the searching at PCI controller device path
|
|
//
|
|
StopSearching = ((DevicePathType (TempDevicePath) == HARDWARE_DEVICE_PATH) &&
|
|
(DevicePathSubType (TempDevicePath) == HW_PCI_DP));
|
|
|
|
Status = gBS->LocateDevicePath (
|
|
&gEfiDevicePathProtocolGuid,
|
|
&ControllerDevicePath,
|
|
&ControllerHandle
|
|
);
|
|
if (AppendedDevicePath != NULL) {
|
|
FreePool (AppendedDevicePath);
|
|
}
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
DeviceName = GetDevNameFromComponentNameProtocol (ControllerHandle, HandleBuffer[Index], &gEfiComponentName2ProtocolGuid, ComponentName2HandleCount, ComponentName2HandleBuffer);
|
|
if (DeviceName == NULL) {
|
|
DeviceName = GetDevNameFromComponentNameProtocol (ControllerHandle, HandleBuffer[Index], &gEfiComponentNameProtocolGuid, ComponentNameHandleCount, ComponentNameHandleBuffer);
|
|
if (DeviceName == NULL) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ((*HwBootDeviceInfoCount) >= HwBootDeviceInfoLength) {
|
|
*HwBootDeviceInfo = ReallocatePool (
|
|
HwBootDeviceInfoLength * sizeof(HARDWARE_BOOT_DEVICE_INFO),
|
|
(HwBootDeviceInfoLength + Increment) * sizeof(HARDWARE_BOOT_DEVICE_INFO),
|
|
*HwBootDeviceInfo
|
|
);
|
|
if (*HwBootDeviceInfo == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Exit;
|
|
}
|
|
HwBootDeviceInfoLength += Increment;
|
|
}
|
|
(*HwBootDeviceInfo)[*HwBootDeviceInfoCount].BlockIoDevicePath = BlkIoDevicePath;
|
|
(*HwBootDeviceInfo)[*HwBootDeviceInfoCount].HwDeviceName = AllocateCopyPool (StrSize (DeviceName), DeviceName);
|
|
CleanSpaceChar ((*HwBootDeviceInfo)[*HwBootDeviceInfoCount].HwDeviceName);
|
|
|
|
(*HwBootDeviceInfoCount)++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (HandleCount != 0) {
|
|
FreePool (HandleBuffer);
|
|
}
|
|
if (ComponentNameHandleCount != 0) {
|
|
FreePool (ComponentNameHandleBuffer);
|
|
}
|
|
if (ComponentName2HandleBuffer != NULL) {
|
|
FreePool (ComponentName2HandleBuffer);
|
|
}
|
|
if (*HwBootDeviceInfoCount == 0) {
|
|
Status = EFI_NOT_FOUND;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Check whether there is a instance in BlockIoDevicePath, which contain multi device path
|
|
instances, has the same partition node with HardDriveDevicePath device path
|
|
|
|
@param BlockIoDevicePath Multi device path instances which need to check
|
|
@param HardDriveDevicePath A device path which starts with a hard drive media device path.
|
|
|
|
@retval TRUE There is a matched device path instance
|
|
@retval FALSE There is no matched device path instance
|
|
|
|
**/
|
|
BOOLEAN
|
|
MatchPartitionDevicePathNode (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,
|
|
IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath
|
|
)
|
|
{
|
|
HARDDRIVE_DEVICE_PATH *Node;
|
|
|
|
if ((BlockIoDevicePath == NULL) || (HardDriveDevicePath == NULL)) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Match all the partition device path nodes including the nested partition nodes
|
|
//
|
|
while (!IsDevicePathEnd (BlockIoDevicePath)) {
|
|
if ((DevicePathType (BlockIoDevicePath) == MEDIA_DEVICE_PATH) &&
|
|
(DevicePathSubType (BlockIoDevicePath) == MEDIA_HARDDRIVE_DP)
|
|
) {
|
|
//
|
|
// See if the harddrive device path in blockio matches the orig Hard Drive Node
|
|
//
|
|
Node = (HARDDRIVE_DEVICE_PATH *) BlockIoDevicePath;
|
|
|
|
//
|
|
// Match Signature and PartitionNumber.
|
|
// Unused bytes in Signature are initiaized with zeros.
|
|
//
|
|
if ((Node->PartitionNumber == HardDriveDevicePath->PartitionNumber) &&
|
|
(Node->MBRType == HardDriveDevicePath->MBRType) &&
|
|
(Node->SignatureType == HardDriveDevicePath->SignatureType) &&
|
|
(CompareMem (Node->Signature, HardDriveDevicePath->Signature, sizeof (Node->Signature)) == 0)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
BlockIoDevicePath = NextDevicePathNode (BlockIoDevicePath);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
If input is a hard drive device path, append it to corresponding BlockIo device path.
|
|
If input is not a hard drive device path, output NULL.
|
|
|
|
@param HardDriveDevicePath Input device path
|
|
|
|
@return pointer to the device path which combines BlockIo and hard disk device path
|
|
or NULL if it is not hard disk device.
|
|
|
|
**/
|
|
EFI_DEVICE_PATH_PROTOCOL *
|
|
AppendHardDrivePathToBlkIoDevicePath (
|
|
IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN BlockIoHandleCount;
|
|
EFI_HANDLE *BlockIoBuffer;
|
|
EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
|
|
UINTN Index;
|
|
|
|
if (HardDriveDevicePath == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!((DevicePathType (&HardDriveDevicePath->Header) == MEDIA_DEVICE_PATH) &&
|
|
(DevicePathSubType (&HardDriveDevicePath->Header) == MEDIA_HARDDRIVE_DP))) {
|
|
return NULL;
|
|
}
|
|
|
|
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);
|
|
if (EFI_ERROR (Status) || BlockIoHandleCount == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
for (Index = 0; Index < BlockIoHandleCount; Index++) {
|
|
Status = gBS->HandleProtocol (BlockIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath);
|
|
if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) {
|
|
continue;
|
|
}
|
|
|
|
if (MatchPartitionDevicePathNode (BlockIoDevicePath, HardDriveDevicePath)) {
|
|
//
|
|
// Combine the Block IO and Hard Drive Device path together.
|
|
//
|
|
DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);
|
|
NewDevicePath = AppendDevicePath (BlockIoDevicePath, DevicePath);
|
|
|
|
FreePool (BlockIoBuffer);
|
|
return NewDevicePath;
|
|
}
|
|
}
|
|
|
|
FreePool (BlockIoBuffer);
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Compare with each BlockIo device path.
|
|
|
|
@param HardDriveDevicePath BlockIo device path
|
|
@param DevicePath BlockIo device path or hard drive device path
|
|
|
|
@retval TRUE BlockIo device paths are the same
|
|
@retval FALSE BlockIo device paths are different
|
|
|
|
**/
|
|
BOOLEAN
|
|
CompareBlockIoDevicePath (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
|
BOOLEAN Match;
|
|
|
|
Match = TRUE;
|
|
|
|
if (BlockIoDevicePath == NULL || DevicePath == NULL || IsDevicePathEnd (BlockIoDevicePath)) {
|
|
return FALSE;
|
|
}
|
|
NewDevicePath = AppendHardDrivePathToBlkIoDevicePath ((HARDDRIVE_DEVICE_PATH *) DevicePath);
|
|
if (NewDevicePath == NULL) {
|
|
NewDevicePath = DevicePath;
|
|
}
|
|
|
|
TempDevicePath = NewDevicePath;
|
|
while (!IsDevicePathEnd (BlockIoDevicePath)) {
|
|
if (CompareMem (BlockIoDevicePath, TempDevicePath, DevicePathNodeLength (BlockIoDevicePath)) != 0) {
|
|
Match = FALSE;
|
|
break;
|
|
}
|
|
|
|
BlockIoDevicePath = NextDevicePathNode (BlockIoDevicePath);
|
|
TempDevicePath = NextDevicePathNode (TempDevicePath);
|
|
}
|
|
|
|
if (NewDevicePath != DevicePath) {
|
|
FreePool (NewDevicePath);
|
|
}
|
|
|
|
if (Match) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Append device name to boot option description.
|
|
|
|
@param EfiBootDevCount Number of EFI boot option
|
|
@param EfiBootDevInfo Array pointer of BOOT_DEV_INFO which store each boot option information
|
|
|
|
@retval EFI_SUCCESS Append device name successfully
|
|
@retval EFI_INVALID_PARAMETER Invalid input parameter
|
|
|
|
**/
|
|
EFI_STATUS
|
|
BootOptionStrAppendDeviceName (
|
|
IN UINT16 EfiBootDevCount,
|
|
IN OUT BOOT_DEV_INFO *EfiBootDevInfo
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN Index2;
|
|
HARDWARE_BOOT_DEVICE_INFO *HwBootDeviceInfo;
|
|
UINTN HwBootDeviceCount;
|
|
CHAR16 *String;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
UINTN Size;
|
|
CHAR16 *HwDeviceName;
|
|
CHAR16 NoDeviceStr[] = L"No Device";
|
|
UINTN DeviceCount;
|
|
UINT8 *Ptr;
|
|
UINT8 *VarData;
|
|
|
|
if (EfiBootDevCount == 0 || EfiBootDevInfo == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
GetAllHwBootDeviceInfo (&HwBootDeviceCount, &HwBootDeviceInfo);
|
|
|
|
for (Index = 0; Index < EfiBootDevCount; Index++) {
|
|
DevicePath = EfiBootDevInfo[Index].DevicePath;
|
|
if (!((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH &&
|
|
DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP) ||
|
|
(DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH &&
|
|
DevicePathSubType (DevicePath) == MSG_USB_CLASS_DP))) {
|
|
continue;
|
|
}
|
|
|
|
VarData = NULL;
|
|
HwDeviceName = NULL;
|
|
DeviceCount = 1;
|
|
if (DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH &&
|
|
DevicePathSubType (DevicePath) == MSG_USB_CLASS_DP) {
|
|
//
|
|
// For Windows To Go, assign no device string as device name if device number is 0.
|
|
//
|
|
VarData = CommonGetVariableData (
|
|
L"WindowsToGo",
|
|
&gEfiGenericVariableGuid
|
|
);
|
|
if (VarData != NULL) {
|
|
Ptr = VarData;
|
|
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
|
|
Ptr += GetDevicePathSize (DevicePath);
|
|
DeviceCount = *(UINT16 *) Ptr;
|
|
} else {
|
|
DeviceCount = 0;
|
|
}
|
|
|
|
if (DeviceCount == 0) {
|
|
HwDeviceName = NoDeviceStr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Append device name to boot option description if BlkIo device path is match.
|
|
//
|
|
if (HwDeviceName == NULL && HwBootDeviceInfo != NULL) {
|
|
for (Index2 = 0; Index2 < HwBootDeviceCount; Index2++) {
|
|
if (CompareBlockIoDevicePath (HwBootDeviceInfo[Index2].BlockIoDevicePath, DevicePath)) {
|
|
HwDeviceName = HwBootDeviceInfo[Index2].HwDeviceName;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (HwDeviceName != NULL) {
|
|
if (DeviceCount > 1) {
|
|
Size = StrSize (EfiBootDevInfo[Index].pString) + StrSize (L" (") + StrSize (HwDeviceName) + StrSize (L",...") + StrSize (L")");
|
|
} else {
|
|
Size = StrSize (EfiBootDevInfo[Index].pString) + StrSize (L" (") + StrSize (HwDeviceName) + StrSize (L")");
|
|
}
|
|
String = AllocateZeroPool (Size);
|
|
if (String != NULL) {
|
|
StrCatS (String, Size / sizeof (CHAR16), EfiBootDevInfo[Index].pString);
|
|
StrCatS (String, Size / sizeof (CHAR16), L" (");
|
|
StrCatS (String, Size / sizeof (CHAR16), HwDeviceName);
|
|
if (DeviceCount > 1) {
|
|
StrCatS (String, Size / sizeof (CHAR16), L",...");
|
|
}
|
|
StrCatS (String, Size / sizeof (CHAR16), L")");
|
|
|
|
FreePool (EfiBootDevInfo[Index].pString);
|
|
EfiBootDevInfo[Index].pString = String;
|
|
}
|
|
}
|
|
|
|
if (VarData != NULL) {
|
|
FreePool (VarData);
|
|
}
|
|
}
|
|
|
|
if (HwBootDeviceCount != 0 && HwBootDeviceInfo != NULL) {
|
|
for (Index2 = 0; Index2 < HwBootDeviceCount; Index2++) {
|
|
FreePool (HwBootDeviceInfo[Index2].HwDeviceName);
|
|
}
|
|
FreePool (HwBootDeviceInfo);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update action/checkbox opcodes in specific label by input boot device info list.
|
|
|
|
@param[in] HiiHandle HII handle for HII get string function
|
|
@param[in] LastToken Pointer to the start string token number
|
|
@param[in] BootDevInfoList Pointer to the boot device info list
|
|
@param[in] BootDevInfoCount The number of boot device info in the list
|
|
@param[in] DeviceKeyBase Question ID base value
|
|
@param[in] BootDevLabel VFR label value
|
|
@param[in] FormId Form ID
|
|
@param[in] Offset Offset value in the varstorage
|
|
@param[in] Opcode Target opcode (action or checkbox)
|
|
|
|
@retval EFI_SUCCESS Process item movement successfully
|
|
@retval EFI_OUT_OF_RESOURCES Create HII opcode handle failed.
|
|
@retval Other Fail to get browser data.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
UpdateNewForm (
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN EFI_STRING_ID *LastToken,
|
|
IN BOOT_DEV_INFO *BootDevInfoList,
|
|
IN UINTN BootDevInfoCount,
|
|
IN UINT16 DeviceKeyBase,
|
|
IN UINT16 BootDevLabel,
|
|
IN EFI_FORM_ID FormId,
|
|
IN UINT16 Offset,
|
|
IN UINT8 Opcode
|
|
)
|
|
{
|
|
UINTN Index;
|
|
EFI_STRING_ID TempLastToken;
|
|
SETUP_UTILITY_BROWSER_DATA *SuBrowser;
|
|
EFI_STATUS Status;
|
|
EFI_IFR_GUID_LABEL *StartLabel;
|
|
EFI_IFR_CHECKBOX *CheckboxOpCode;
|
|
EFI_IFR_ACTION *ActionOpCode;
|
|
VOID *OpCodeHandle;
|
|
UINT8 IfrFlag;
|
|
|
|
Status = GetSetupUtilityBrowserData (&SuBrowser);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
OpCodeHandle = HiiAllocateOpCodeHandle ();
|
|
ASSERT (OpCodeHandle != NULL);
|
|
if (OpCodeHandle == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (OpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
|
|
StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
|
|
StartLabel->Number = BootDevLabel;
|
|
|
|
if (BootDevInfoList == NULL) {
|
|
goto Done;
|
|
}
|
|
|
|
IfrFlag = EFI_IFR_CHECKBOX_DEFAULT_MFG;
|
|
|
|
for (Index = 0; Index < BootDevInfoCount; Index++) {
|
|
TempLastToken = HiiSetString (HiiHandle, 0, BootDevInfoList[Index].pString, NULL);
|
|
if (Index == 0) {
|
|
*LastToken = TempLastToken;
|
|
}
|
|
|
|
switch (Opcode) {
|
|
|
|
case EFI_IFR_CHECKBOX_OP:
|
|
CheckboxOpCode = (EFI_IFR_CHECKBOX *) HiiCreateCheckBoxOpCode (
|
|
OpCodeHandle,
|
|
(EFI_QUESTION_ID) (DeviceKeyBase + Index),
|
|
BOOT_VARSTORE_ID,
|
|
(UINT16) (Offset + Index),
|
|
TempLastToken,
|
|
0,
|
|
EFI_IFR_FLAG_CALLBACK,
|
|
0,
|
|
NULL
|
|
);
|
|
CheckboxOpCode->Question.Flags |= IfrFlag;
|
|
break;
|
|
|
|
case EFI_IFR_ACTION_OP:
|
|
ActionOpCode = (EFI_IFR_ACTION *) HiiCreateActionOpCode (
|
|
OpCodeHandle,
|
|
(EFI_QUESTION_ID) (DeviceKeyBase + Index),
|
|
TempLastToken,
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
ActionOpCode->Question.Flags |= IfrFlag;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Done:
|
|
HiiUpdateForm (
|
|
HiiHandle,
|
|
NULL,
|
|
FormId,
|
|
OpCodeHandle,
|
|
NULL
|
|
);
|
|
|
|
HiiFreeOpCodeHandle (OpCodeHandle);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get the device info list of legacy boot type
|
|
|
|
@param[in] HiiHandle HII handle for HII get string function
|
|
@param[in] KernelConfig Pointer to kernel configuration
|
|
@param[out] LegacyBootTypeDevInfoCount Number of device info in the list
|
|
@param[out] BootTypeOrderDevInfo Double pointer to the device info list of legacy boot type
|
|
|
|
@retval EFI_SUCCESS Get the device info list successfully.
|
|
@retval EFI_OUT_OF_RESOURCES Allocate pool fail
|
|
**/
|
|
EFI_STATUS
|
|
GetLegacyBootTypeDevInfoList (
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN KERNEL_CONFIGURATION *KernelConfig,
|
|
OUT UINT16 *LegacyBootTypeDevInfoCount,
|
|
OUT BOOT_DEV_INFO **LegacyBootTypeDevInfoList
|
|
)
|
|
{
|
|
UINT16 Index;
|
|
UINT16 BootTypeCount;
|
|
BBS_TYPE_TABLE *BbsTypeTable;
|
|
BOOT_DEV_INFO *InfoList;
|
|
|
|
BootTypeCount = GetBootTypeOrderCount (KernelConfig);
|
|
|
|
InfoList = AllocateZeroPool (sizeof (BOOT_DEV_INFO) * BootTypeCount);
|
|
if (InfoList == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
for (Index = 0; Index < BootTypeCount; Index++) {
|
|
BbsTypeTable = GetBbsTypeTableByDevType (KernelConfig->BootTypeOrder[Index]);
|
|
if (BbsTypeTable != NULL) {
|
|
InfoList[Index].pString = HiiGetString (HiiHandle, BbsTypeTable->StrToken, NULL);
|
|
}
|
|
}
|
|
|
|
*LegacyBootTypeDevInfoList = InfoList;
|
|
*LegacyBootTypeDevInfoCount = BootTypeCount;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get device info list by boot type (EFI or Legacy).
|
|
|
|
@param[in] BootType Boot type (EFI or Legacy)
|
|
@param[out] BootDevInfoCount Pointer to the number of boot device info in the list
|
|
@param[out] BootDevInfoList Double pointer to the boot devices info list
|
|
|
|
@retval EFI_SUCCESS Get device info list successfully.
|
|
@retval EFI_OUT_OF_RESOURCES Allocate pool fail.
|
|
**/
|
|
EFI_STATUS
|
|
GetDevInfoListByBootType (
|
|
IN UINT16 BootType,
|
|
OUT UINT16 *BootDevInfoCount,
|
|
OUT BOOT_DEV_INFO **BootDevInfoList
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINT16 InfoCount;
|
|
BOOT_DEV_INFO *InfoList;
|
|
BOOLEAN IsEfiBootDev;
|
|
|
|
IsEfiBootDev = (BOOLEAN) (BootType == EFI_BOOT_DEV);
|
|
|
|
for (Index = 0, InfoCount = 0; Index < mBootDevInfoCount; Index++) {
|
|
if (mBootDevInfo[Index].IsEfiBootDev == IsEfiBootDev) {
|
|
InfoCount++;
|
|
}
|
|
}
|
|
if (InfoCount == 0) {
|
|
*BootDevInfoCount = 0;
|
|
*BootDevInfoList = NULL;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
InfoList = AllocateZeroPool (sizeof(BOOT_DEV_INFO) * InfoCount);
|
|
if (InfoList == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
for (Index = 0, InfoCount = 0; Index < mBootDevInfoCount; Index++) {
|
|
if (mBootDevInfo[Index].IsEfiBootDev == IsEfiBootDev) {
|
|
CopyMem (
|
|
&InfoList[InfoCount],
|
|
&mBootDevInfo[Index],
|
|
sizeof (BOOT_DEV_INFO)
|
|
);
|
|
if (mBootDevInfo[Index].pString != NULL) {
|
|
InfoList[InfoCount].pString = AllocateCopyPool (
|
|
StrSize (mBootDevInfo[Index].pString),
|
|
mBootDevInfo[Index].pString
|
|
);
|
|
}
|
|
InfoCount++;
|
|
}
|
|
}
|
|
|
|
*BootDevInfoCount = InfoCount;
|
|
*BootDevInfoList = InfoList;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Free the device info list
|
|
|
|
@param[in] DevInfoCount Number of device info in the list
|
|
@param[in] DevInfoList Pointer to the device info list
|
|
**/
|
|
VOID
|
|
FreeDevInfoList (
|
|
IN UINT16 DevInfoCount,
|
|
IN BOOT_DEV_INFO *DevInfoList
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
if (DevInfoList == NULL) {
|
|
return;
|
|
}
|
|
|
|
for (Index = 0; Index < DevInfoCount; Index++) {
|
|
if (DevInfoList[Index].pString != NULL) {
|
|
FreePool (DevInfoList[Index].pString);
|
|
}
|
|
}
|
|
FreePool (DevInfoList);
|
|
}
|
|
|
|
/**
|
|
Update legacy boot type order label
|
|
|
|
@param[in] HiiHandle HII handle for HII get string function
|
|
@param[in] KernelConfig Pointer to kernel configuration
|
|
@param[in, out] SUCInfo Pointer to setup utility configuration
|
|
|
|
@retval EFI_SUCCESS Update legacy boot type order label successfully.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateLegacyBootTypeOrderLabel (
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN KERNEL_CONFIGURATION *KernelConfig,
|
|
IN OUT SETUP_UTILITY_CONFIGURATION *SUCInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOT_DEV_INFO *LegacyBootTypeDevInfoList;
|
|
UINT16 LegacyBootTypeDevInfoCount;
|
|
|
|
Status = GetLegacyBootTypeDevInfoList (HiiHandle, KernelConfig, &LegacyBootTypeDevInfoCount, &LegacyBootTypeDevInfoList);
|
|
if (EFI_ERROR (Status)) {
|
|
LegacyBootTypeDevInfoList = NULL;
|
|
LegacyBootTypeDevInfoCount = 0;
|
|
}
|
|
|
|
SUCInfo->BootTypeTokenRecord = 0;
|
|
UpdateNewForm (
|
|
HiiHandle,
|
|
&SUCInfo->BootTypeTokenRecord,
|
|
LegacyBootTypeDevInfoList,
|
|
LegacyBootTypeDevInfoCount,
|
|
(UINT16) KEY_BOOT_TYPE_ORDER_BASE,
|
|
(UINT16) BOOT_ORDER_LABEL,
|
|
BOOT_DEVICE_LEG_NOR_BOOT_ID,
|
|
0,
|
|
EFI_IFR_ACTION_OP
|
|
);
|
|
|
|
FreeDevInfoList (LegacyBootTypeDevInfoCount, LegacyBootTypeDevInfoList);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update the strings of legacy boot type order
|
|
|
|
@param[in] HiiHandle HII handle for HII get string function
|
|
@param[in] KernelConfig Pointer to kernel configuration
|
|
@param[in, out] SUCInfo Pointer to setup utility configuration
|
|
|
|
@retval EFI_SUCCESS Update the strings of legacy boot type order successfully.
|
|
@retval Other Get device info list failed.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateLegacyBootTypeOrderStrings (
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN KERNEL_CONFIGURATION *KernelConfig,
|
|
IN OUT SETUP_UTILITY_CONFIGURATION *SUCInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOT_DEV_INFO *LegacyBootTypeDevInfoList;
|
|
UINT16 LegacyBootTypeDevInfoCount;
|
|
UINT16 Index;
|
|
EFI_STRING_ID Token;
|
|
|
|
Status = GetLegacyBootTypeDevInfoList (HiiHandle, KernelConfig, &LegacyBootTypeDevInfoCount, &LegacyBootTypeDevInfoList);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Token = SUCInfo->BootTypeTokenRecord;
|
|
if (LegacyBootTypeDevInfoList != NULL) {
|
|
for (Index = 0; Index < LegacyBootTypeDevInfoCount; Index++, Token++) {
|
|
HiiSetString (HiiHandle, Token, LegacyBootTypeDevInfoList[Index].pString, NULL);
|
|
}
|
|
}
|
|
|
|
FreeDevInfoList (LegacyBootTypeDevInfoCount, LegacyBootTypeDevInfoList);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update EFI boot order label
|
|
|
|
@param[in] HiiHandle HII handle for HII get string function
|
|
@param[in, out] SUCInfo Pointer to setup utility configuration
|
|
|
|
@retval EFI_SUCCESS Update EFI boot order label successfully.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateEfiBootOrderLabel (
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN OUT SETUP_UTILITY_CONFIGURATION *SUCInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOT_DEV_INFO *EfiBootDevInfoList;
|
|
UINT16 EfiBootDevInfoCount;
|
|
|
|
Status = GetDevInfoListByBootType (EFI_BOOT_DEV, &EfiBootDevInfoCount, &EfiBootDevInfoList);
|
|
if (EFI_ERROR (Status)) {
|
|
EfiBootDevInfoList = NULL;
|
|
EfiBootDevInfoCount = 0;
|
|
}
|
|
ASSERT (EfiBootDevInfoCount <= MAX_BOOT_DEVICES_NUMBER);
|
|
|
|
SUCInfo->EfiBootDeviceNum = EfiBootDevInfoCount;
|
|
SUCInfo->EfiTokenRecord = 0;
|
|
BootOptionStrAppendDeviceName (EfiBootDevInfoCount, EfiBootDevInfoList);
|
|
UpdateNewForm (
|
|
HiiHandle,
|
|
&SUCInfo->EfiTokenRecord,
|
|
EfiBootDevInfoList,
|
|
EfiBootDevInfoCount,
|
|
(UINT16) KEY_EFI_BOOT_DEVICE_BASE,
|
|
(UINT16) EFI_BOOT_DEVICE_LABEL,
|
|
BOOT_DEVICE_EFI_FORM_ID,
|
|
(UINT16) ((UINTN) mBootConfig.EfiBootDevSwitch - (UINTN) &mBootConfig),
|
|
EFI_IFR_CHECKBOX_OP
|
|
);
|
|
|
|
FreeDevInfoList (EfiBootDevInfoCount, EfiBootDevInfoList);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update the strings of EFI boot order
|
|
|
|
@param[in] HiiHandle HII handle for HII get string function
|
|
@param[in, out] SUCInfo Pointer to setup utility configuration
|
|
|
|
@retval EFI_SUCCESS Update the strings of EFI boot order successfully.
|
|
@retval Other Get device info list failed.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateEfiBootOrderStrings (
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN OUT SETUP_UTILITY_CONFIGURATION *SUCInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOT_DEV_INFO *EfiBootDevInfoList;
|
|
UINT16 EfiBootDevInfoCount;
|
|
UINT16 Index;
|
|
EFI_STRING_ID Token;
|
|
|
|
Status = GetDevInfoListByBootType (EFI_BOOT_DEV, &EfiBootDevInfoCount, &EfiBootDevInfoList);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Token = SUCInfo->EfiTokenRecord;
|
|
if (EfiBootDevInfoList != NULL) {
|
|
BootOptionStrAppendDeviceName (EfiBootDevInfoCount, EfiBootDevInfoList);
|
|
|
|
for (Index = 0; Index < EfiBootDevInfoCount; Index++, Token++) {
|
|
HiiSetString (HiiHandle, Token, EfiBootDevInfoList[Index].pString, NULL);
|
|
}
|
|
}
|
|
|
|
FreeDevInfoList (EfiBootDevInfoCount, EfiBootDevInfoList);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update legacy advance boot order label
|
|
|
|
@param[in] HiiHandle HII handle for HII get string function
|
|
@param[in, out] SUCInfo Pointer to setup utility configuration
|
|
|
|
@retval EFI_SUCCESS Update legacy advance boot order label successfully.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateLegacyAdvBootOrderLabel (
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN OUT SETUP_UTILITY_CONFIGURATION *SUCInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOT_DEV_INFO *LegacyBootDevInfoList;
|
|
UINT16 LegacyBootDevInfoCount;
|
|
|
|
Status = GetDevInfoListByBootType (LEGACY_BOOT_DEV, &LegacyBootDevInfoCount, &LegacyBootDevInfoList);
|
|
if (EFI_ERROR (Status)) {
|
|
LegacyBootDevInfoList = NULL;
|
|
LegacyBootDevInfoCount = 0;
|
|
}
|
|
ASSERT (LegacyBootDevInfoCount <= MAX_LEGACY_BOOT_DEV_NUM);
|
|
|
|
SUCInfo->LegacyBootDeviceNum = LegacyBootDevInfoCount;
|
|
SUCInfo->LegacyAdvanceTokenRecord = 0;
|
|
UpdateNewForm (
|
|
HiiHandle,
|
|
&SUCInfo->LegacyAdvanceTokenRecord,
|
|
LegacyBootDevInfoList,
|
|
LegacyBootDevInfoCount,
|
|
(UINT16) KEY_ADV_LEGACY_BOOT_BASE,
|
|
(UINT16) BOOT_LEGACY_ADV_BOOT_LABEL,
|
|
BOOT_OPTION_FORM_ID,
|
|
(UINT16) ((UINTN) mBootConfig.LegacyAdvBootDevSwitch - (UINTN) &mBootConfig),
|
|
EFI_IFR_CHECKBOX_OP
|
|
);
|
|
|
|
FreeDevInfoList (LegacyBootDevInfoCount, LegacyBootDevInfoList);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update the strings of legacy advance boot order
|
|
|
|
@param[in] HiiHandle HII handle for HII get string function
|
|
@param[in, out] SUCInfo Pointer to setup utility configuration
|
|
|
|
@retval EFI_SUCCESS Update the strings of legacy advance boot order successfully.
|
|
@retval Other Get device info list failed.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateLegacyAdvBootOrderStrings (
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN OUT SETUP_UTILITY_CONFIGURATION *SUCInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOT_DEV_INFO *LegacyBootDevInfoList;
|
|
UINT16 LegacyBootDevInfoCount;
|
|
UINT16 Index;
|
|
EFI_STRING_ID Token;
|
|
|
|
Status = GetDevInfoListByBootType (LEGACY_BOOT_DEV, &LegacyBootDevInfoCount, &LegacyBootDevInfoList);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Token = SUCInfo->LegacyAdvanceTokenRecord;
|
|
if (LegacyBootDevInfoList != NULL) {
|
|
for (Index = 0; Index < LegacyBootDevInfoCount; Index++, Token++) {
|
|
HiiSetString (HiiHandle, Token, LegacyBootDevInfoList[Index].pString, NULL);
|
|
}
|
|
}
|
|
|
|
FreeDevInfoList (LegacyBootDevInfoCount, LegacyBootDevInfoList);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update legacy normal boot order label
|
|
|
|
@param[in] HiiHandle HII handle for HII get string function
|
|
@param[in, out] SUCInfo Pointer to setup utility configuration
|
|
|
|
@retval EFI_SUCCESS Update legacy normal boot order label successfully.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateLegacyNormalBootOrderLabels (
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN OUT SETUP_UTILITY_CONFIGURATION *SUCInfo
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINT16 Offset;
|
|
|
|
for (Index = 0; Index < mBbsTypeTableCount; Index++) {
|
|
if (mBbsTypeTable[Index].KeyBootDeviceBase >= KEY_BOOT_DEVICE_TYPE_BASE) {
|
|
Offset = ((UINT16) (UINTN) &mBootConfig.LegacyTypeDevSwitch[mBbsTypeTable[Index].KeyBootDeviceBase - KEY_BOOT_DEVICE_TYPE_BASE]);
|
|
Offset -= (UINT16) (UINTN) &mBootConfig;
|
|
} else {
|
|
Offset = 0;
|
|
}
|
|
|
|
SUCInfo->LegacyNormalTokenRecord[Index] = 0;
|
|
UpdateNewForm (
|
|
HiiHandle,
|
|
&SUCInfo->LegacyNormalTokenRecord[Index],
|
|
mBbsTypeTable[Index].DevInfoList,
|
|
mBbsTypeTable[Index].DevInfoCount,
|
|
mBbsTypeTable[Index].KeyBootDeviceBase,
|
|
mBbsTypeTable[Index].BootDevicesLabel,
|
|
mBbsTypeTable[Index].FormId,
|
|
Offset,
|
|
EFI_IFR_CHECKBOX_OP
|
|
);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update the strings of legacy normal boot order
|
|
|
|
@param[in] HiiHandle HII handle for HII get string function
|
|
@param[in, out] SUCInfo Pointer to setup utility configuration
|
|
|
|
@retval EFI_SUCCESS Update the strings of legacy normal boot order successfully.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateLegacyNormalBootOrderStrings (
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN OUT SETUP_UTILITY_CONFIGURATION *SUCInfo
|
|
)
|
|
{
|
|
UINTN Index;
|
|
EFI_STRING_ID Token;
|
|
UINTN DevIndex;
|
|
|
|
for(Index = 0; Index < mBbsTypeTableCount; Index++) {
|
|
if (mBbsTypeTable[Index].DevInfoCount == 0) {
|
|
continue;
|
|
}
|
|
|
|
Token = SUCInfo->LegacyNormalTokenRecord[Index];
|
|
for (DevIndex = 0; DevIndex < mBbsTypeTable[Index].DevInfoCount; DevIndex++, Token++) {
|
|
HiiSetString (HiiHandle, Token, mBbsTypeTable[Index].DevInfoList[DevIndex].pString, NULL);
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update hidden boot type order label by ordered list opcode
|
|
|
|
@param[in] HiiHandle Hii hanlde for Boot page
|
|
@param[in] KernelConfig Pointer to kernel config instance
|
|
|
|
@retval EFI_SUCCESS Update boot type order label successfully
|
|
@retval EFI_OUT_OF_RESOURCES Create HII opcode failed
|
|
**/
|
|
EFI_STATUS
|
|
UpdateHiddenBootTypeOrderLabel (
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN KERNEL_CONFIGURATION *KernelConfig
|
|
)
|
|
{
|
|
VOID *OpCodeHandle;
|
|
VOID *OptionsOpCodeHandle;
|
|
EFI_IFR_GUID_LABEL *StartLabel;
|
|
UINT8 Count;
|
|
UINTN Index;
|
|
UINTN TableIndex;
|
|
EFI_STRING_ID Token;
|
|
UINT16 Offset;
|
|
|
|
OpCodeHandle = HiiAllocateOpCodeHandle ();
|
|
OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
|
|
ASSERT (OpCodeHandle != NULL && OptionsOpCodeHandle != NULL);
|
|
if (OpCodeHandle == NULL || OptionsOpCodeHandle == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (OpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
|
|
StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
|
|
StartLabel->Number = HIDDEN_BOOT_TYPE_ORDER_LABEL;
|
|
|
|
Count = 0;
|
|
for (Index = 0; Index < sizeof(KernelConfig->BootTypeOrder) && KernelConfig->BootTypeOrder[Index] != 0; Index++) {
|
|
for (TableIndex = 0, Token = 0; TableIndex < mBbsTypeTableCount; TableIndex++) {
|
|
if (mBbsTypeTable[TableIndex].DeviceType == KernelConfig->BootTypeOrder[Index]) {
|
|
Token = mBbsTypeTable[TableIndex].StrToken;
|
|
break;
|
|
}
|
|
}
|
|
if (TableIndex == mBbsTypeTableCount) {
|
|
continue;
|
|
}
|
|
|
|
HiiCreateOneOfOptionOpCode (
|
|
OptionsOpCodeHandle,
|
|
Token,
|
|
0,
|
|
EFI_IFR_NUMERIC_SIZE_1,
|
|
KernelConfig->BootTypeOrder[Index]
|
|
);
|
|
Count++;
|
|
}
|
|
|
|
Offset = (UINT16) ((UINTN) KernelConfig->BootTypeOrder - (UINTN) KernelConfig);
|
|
HiiCreateOrderedListOpCode (
|
|
OpCodeHandle,
|
|
KEY_HIDDEN_BOOT_TYPE_ORDER,
|
|
CONFIGURATION_VARSTORE_ID,
|
|
Offset,
|
|
STRING_TOKEN (STR_BOOT_TYPE_ORDER_OPTIONS),
|
|
STRING_TOKEN (STR_BOOT_TYPE_ORDER_OPTIONS),
|
|
EFI_IFR_FLAG_CALLBACK,
|
|
0,
|
|
EFI_IFR_NUMERIC_SIZE_1,
|
|
Count,
|
|
OptionsOpCodeHandle,
|
|
NULL
|
|
);
|
|
|
|
HiiUpdateForm (
|
|
HiiHandle,
|
|
NULL,
|
|
BOOT_HIDDEN_BOOT_TYPE_ORDER_ID,
|
|
OpCodeHandle,
|
|
NULL
|
|
);
|
|
|
|
HiiFreeOpCodeHandle (OpCodeHandle);
|
|
HiiFreeOpCodeHandle (OptionsOpCodeHandle);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update all of device relative stirngs
|
|
|
|
@param[in] HiiHandle Hii hanlde for Boot page
|
|
@param[in] KernelConfig Pointer to kernel configuration instance
|
|
|
|
@retval EFI_SUCCESS Update device relative strings successful.
|
|
@retval Other Fail to get browser data.
|
|
**/
|
|
EFI_STATUS
|
|
SetupUtilityLibUpdateDeviceString (
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN KERNEL_CONFIGURATION *KernelConfig
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
SETUP_UTILITY_BROWSER_DATA *SuBrowser;
|
|
SETUP_UTILITY_CONFIGURATION *SUCInfo;
|
|
|
|
Status = GetSetupUtilityBrowserData (&SuBrowser);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
SUCInfo = SuBrowser->SUCInfo;
|
|
|
|
if (SUCInfo->AdvBootDeviceNum == 0) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
BootDevInfoSortByBootOrder ();
|
|
BootDevInfoSortByKernelConfig (KernelConfig);
|
|
SortBbsTypeTable (SUCInfo->BootOrder, SUCInfo->AdvBootDeviceNum);
|
|
|
|
UpdateLegacyBootTypeOrderStrings (HiiHandle, KernelConfig, SUCInfo);
|
|
UpdateLegacyNormalBootOrderStrings (HiiHandle, SUCInfo);
|
|
UpdateLegacyAdvBootOrderStrings (HiiHandle, SUCInfo);
|
|
UpdateEfiBootOrderStrings (HiiHandle, SUCInfo);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update boot order related menu option in action/checkbox opcode in platform to boot page
|
|
|
|
@param[in] BootHiiHandle Hii hanlde for Boot page
|
|
@param[in] KernelConfig Pointer to kernel configuration instance
|
|
|
|
@retval EFI_SUCCESS Update boot menu successful.
|
|
@retval Other Fail to get browser data.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateBootOrderLabels (
|
|
IN EFI_HII_HANDLE BootHiiHandle,
|
|
IN OUT KERNEL_CONFIGURATION *KernelConfig
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
SETUP_UTILITY_CONFIGURATION *SUCInfo;
|
|
SETUP_UTILITY_BROWSER_DATA *SuBrowser;
|
|
|
|
Status = GetSetupUtilityBrowserData (&SuBrowser);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
SUCInfo = SuBrowser->SUCInfo;
|
|
ZeroMem (&mBootConfig, sizeof (mBootConfig));
|
|
|
|
if (SUCInfo->AdvBootDeviceNum == 0) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
InitBbsTypeTable ();
|
|
|
|
UpdateLegacyBootTypeOrderLabel (BootHiiHandle, KernelConfig, SUCInfo);
|
|
UpdateLegacyNormalBootOrderLabels (BootHiiHandle, SUCInfo);
|
|
UpdateLegacyAdvBootOrderLabel (BootHiiHandle, SUCInfo);
|
|
UpdateEfiBootOrderLabel (BootHiiHandle, SUCInfo);
|
|
UpdateHiddenBootTypeOrderLabel (BootHiiHandle, KernelConfig);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Move one boot type in the BootTypeOrder.
|
|
|
|
@param UpShift TRUE : move LowerType upon UpperType
|
|
FALSE: move UpperType below LowerType
|
|
@param UpperType Upper boot type
|
|
@param LowerType Lower boot type
|
|
@param BootTypeOrder Pointer to boot type order
|
|
@param TypeCount Boot type count
|
|
|
|
**/
|
|
VOID
|
|
MoveBootType (
|
|
IN BOOLEAN UpShift,
|
|
IN UINT8 UpperType,
|
|
IN UINT8 LowerType,
|
|
IN OUT UINT8 *BootTypeOrder,
|
|
IN UINTN TypeCount
|
|
)
|
|
{
|
|
UINT8 *NewBootTypeOrder;
|
|
UINTN Index;
|
|
UINTN Count;
|
|
|
|
if (TypeCount == 0) {
|
|
return;
|
|
}
|
|
|
|
NewBootTypeOrder = AllocateZeroPool (TypeCount * sizeof (UINT8));
|
|
if (NewBootTypeOrder == NULL) {
|
|
return;
|
|
}
|
|
|
|
Count = 0;
|
|
for (Index = 0; Index < TypeCount; Index++) {
|
|
if (BootTypeOrder[Index] != UpperType &&
|
|
BootTypeOrder[Index] != LowerType) {
|
|
NewBootTypeOrder[Count++] = BootTypeOrder[Index];
|
|
continue;
|
|
}
|
|
|
|
if ((UpShift && BootTypeOrder[Index] == UpperType) ||
|
|
(!UpShift && BootTypeOrder[Index] == LowerType)) {
|
|
NewBootTypeOrder[Count++] = LowerType;
|
|
NewBootTypeOrder[Count++] = UpperType;
|
|
}
|
|
}
|
|
|
|
CopyMem (BootTypeOrder, NewBootTypeOrder, Count * sizeof (UINT8));
|
|
FreePool (NewBootTypeOrder);
|
|
}
|
|
|
|
/**
|
|
Sync boot order to boot type order
|
|
|
|
@param[in] UpShift User is moving item up (TRUE) or down (FALSE)
|
|
@param[in] BootDevNum Boot device number
|
|
@param[in] BootOrder Pointer to boot order
|
|
@param[in, out] KernelConfig Pointer to kernel configuration instance
|
|
|
|
@retval EFI_SUCCESS Sync boot order to boot type order successfully
|
|
@retval EFI_OUT_OF_RESOURCES Allocate pool failed
|
|
**/
|
|
EFI_STATUS
|
|
SyncBootOrderToBootTypeOrder (
|
|
IN BOOLEAN UpShift,
|
|
IN UINT16 BootDevNum,
|
|
IN UINT16 *BootOrder,
|
|
IN OUT KERNEL_CONFIGURATION *KernelConfig
|
|
)
|
|
{
|
|
UINTN NewBootTypeCount;
|
|
UINT8 *NewBootTypeOrder;
|
|
UINT8 *OldBootTypeOrder;
|
|
UINTN OldBootTypeCount;
|
|
UINT16 Index;
|
|
UINTN TypeIndex;
|
|
BBS_TYPE_TABLE *BbsTypeTable;
|
|
UINT8 MoveType[2];
|
|
UINT16 BootTypeCount;
|
|
|
|
NewBootTypeOrder = AllocatePool (sizeof (KernelConfig->BootTypeOrder));
|
|
if (NewBootTypeOrder == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
NewBootTypeCount = 0;
|
|
for (Index = 0; Index < BootDevNum; Index++) {
|
|
BbsTypeTable = GetBbsTypeTableByBootOptionNum (BootOrder[Index]);
|
|
if (BbsTypeTable == NULL) {
|
|
continue;
|
|
}
|
|
|
|
for (TypeIndex = 0; TypeIndex < NewBootTypeCount; TypeIndex++) {
|
|
if (NewBootTypeOrder[TypeIndex] == BbsTypeTable->DeviceType) {
|
|
break;
|
|
}
|
|
}
|
|
if (TypeIndex == NewBootTypeCount) {
|
|
NewBootTypeOrder[NewBootTypeCount++] = BbsTypeTable->DeviceType;
|
|
}
|
|
}
|
|
|
|
//
|
|
// First, find out oringial boot type order which show in Boot/Legacy/Advance.
|
|
// Then comparing with new boot type order to find out which one boot type shift.
|
|
//
|
|
OldBootTypeOrder = AllocateZeroPool (sizeof (KernelConfig->BootTypeOrder));
|
|
if (OldBootTypeOrder == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
BootTypeCount = GetBootTypeOrderCount (KernelConfig);
|
|
OldBootTypeCount = 0;
|
|
for (Index = 0; Index < BootTypeCount; Index++) {
|
|
for (TypeIndex = 0; TypeIndex < NewBootTypeCount; TypeIndex++) {
|
|
if (KernelConfig->BootTypeOrder[Index] == NewBootTypeOrder[TypeIndex]) {
|
|
OldBootTypeOrder[OldBootTypeCount++] = KernelConfig->BootTypeOrder[Index];
|
|
break;
|
|
}
|
|
}
|
|
if (OldBootTypeCount == NewBootTypeCount) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
TypeIndex = 0;
|
|
for (Index = 0; Index < NewBootTypeCount; Index++) {
|
|
if (OldBootTypeOrder[Index] != NewBootTypeOrder[Index]) {
|
|
MoveType[TypeIndex++] = OldBootTypeOrder[Index];
|
|
}
|
|
if (TypeIndex == 2) {
|
|
MoveBootType (
|
|
UpShift,
|
|
MoveType[0],
|
|
MoveType[1],
|
|
KernelConfig->BootTypeOrder,
|
|
BootTypeCount
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
FreePool (OldBootTypeOrder);
|
|
FreePool (NewBootTypeOrder);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Sync boot order from boot type order
|
|
|
|
@param[in] SUCInfo Pointer to setup utility configuration instance
|
|
@param[in] KernelConfig Pointer to kernel configuration instance
|
|
@param[in] BootDevNum Boot device number
|
|
@param[in, out] BootOrder Pointer to boot order
|
|
|
|
@retval EFI_SUCCESS Sync boot order from boot type order successfully
|
|
**/
|
|
EFI_STATUS
|
|
SyncBootOrderFromBootTypeOrder (
|
|
IN SETUP_UTILITY_CONFIGURATION *SUCInfo,
|
|
IN KERNEL_CONFIGURATION *KernelConfig,
|
|
IN UINT16 BootDevNum,
|
|
IN OUT UINT16 *BootOrder
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN Count;
|
|
UINTN DevIndex;
|
|
UINTN OrderIndex;
|
|
BBS_TYPE_TABLE *BbsTypeTable;
|
|
|
|
OrderIndex = (KernelConfig->BootNormalPriority == EFI_FIRST) ? SUCInfo->EfiBootDeviceNum : 0;
|
|
Count = GetBootTypeOrderCount (KernelConfig);
|
|
|
|
for (Index = 0; Index < Count; Index++) {
|
|
BbsTypeTable = GetBbsTypeTableByDevType (KernelConfig->BootTypeOrder[Index]);
|
|
if (BbsTypeTable == NULL) {
|
|
continue;
|
|
}
|
|
|
|
for (DevIndex = 0; DevIndex < BbsTypeTable->DevInfoCount; DevIndex++) {
|
|
BootOrder[OrderIndex++] = BbsTypeTable->DevInfoList[DevIndex].BootOptionNum;
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Process item movement by user action and update the BootOrder, BootTypeOrder if need, mBbsTypeTable if need and boot config.
|
|
|
|
@param[in] This Pointer to config access protocol instance
|
|
@param[in] QuestionId Question ID
|
|
@param[in] UpShift User is moving item up (TRUE) or down (FALSE)
|
|
@param[in, out] KernelConfig Pointer to kernel configuration instance
|
|
|
|
@retval EFI_SUCCESS Process item movement successfully
|
|
@retval EFI_INVALID_PARAMETER Question ID is invalid
|
|
@retval Other Fail to get browser data.
|
|
**/
|
|
EFI_STATUS
|
|
Shiftitem (
|
|
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
|
|
IN EFI_QUESTION_ID QuestionId,
|
|
IN BOOLEAN UpShift,
|
|
IN OUT KERNEL_CONFIGURATION *KernelConfig
|
|
)
|
|
{
|
|
CHAR16 *FirstUpdateStr;
|
|
CHAR16 *SecondUpdateStr;
|
|
EFI_STRING_ID FirstToken;
|
|
EFI_STRING_ID SecondToken;
|
|
UINT16 Temp;
|
|
UINTN Index;
|
|
UINT16 BootTypeCount;
|
|
UINT16 *BootOrder;
|
|
EFI_STATUS Status;
|
|
UINTN OrderIndex;
|
|
UINTN BootMenuType;
|
|
SETUP_UTILITY_CONFIGURATION *SUCInfo;
|
|
EFI_CALLBACK_INFO *BootCallBackInfo;
|
|
SETUP_UTILITY_BROWSER_DATA *SuBrowser;
|
|
BBS_TYPE_TABLE *BbsTypeTable;
|
|
BBS_TYPE_TABLE *CurrentBbsTypeTable;
|
|
UINT16 DeviceIndex;
|
|
BOOLEAN IsFirstItem;
|
|
BOOLEAN IsLastItem;
|
|
|
|
Status = GetSetupUtilityBrowserData (&SuBrowser);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
BootCallBackInfo = EFI_CALLBACK_INFO_FROM_THIS (This);
|
|
SUCInfo = SuBrowser->SUCInfo;
|
|
BootTypeCount = GetBootTypeOrderCount (KernelConfig);
|
|
|
|
if ((QuestionId >= KEY_BOOT_TYPE_ORDER_BASE) &&
|
|
(QuestionId < (KEY_BOOT_TYPE_ORDER_BASE + BootTypeCount))) {
|
|
BootMenuType = LEGACY_DEVICE_TYPE_MENU;
|
|
DeviceIndex = QuestionId - KEY_BOOT_TYPE_ORDER_BASE;
|
|
FirstToken = SUCInfo->BootTypeTokenRecord + DeviceIndex;
|
|
IsFirstItem = (BOOLEAN) (QuestionId - KEY_BOOT_TYPE_ORDER_BASE == 0);
|
|
IsLastItem = (BOOLEAN) (QuestionId - KEY_BOOT_TYPE_ORDER_BASE + 1 == BootTypeCount);
|
|
OrderIndex = DeviceIndex;
|
|
} else if ((QuestionId >= KEY_BOOT_DEVICE_BASE) &&
|
|
(QuestionId < KEY_BOOT_DEVICE_BASE + SUCInfo->AdvBootDeviceNum)) {
|
|
BootMenuType = ADV_BOOT_MENU;
|
|
DeviceIndex = QuestionId - KEY_BOOT_DEVICE_BASE;
|
|
FirstToken = SUCInfo->AdvanceTokenRecord + DeviceIndex;
|
|
IsFirstItem = (BOOLEAN) (QuestionId - KEY_BOOT_DEVICE_BASE == 0);
|
|
IsLastItem = (BOOLEAN) (QuestionId - KEY_BOOT_DEVICE_BASE + 1 == SUCInfo->AdvBootDeviceNum);
|
|
OrderIndex = DeviceIndex;
|
|
} else if ((QuestionId >= KEY_EFI_BOOT_DEVICE_BASE) &&
|
|
(QuestionId < KEY_EFI_BOOT_DEVICE_BASE + SUCInfo->EfiBootDeviceNum)) {
|
|
BootMenuType = EFI_BOOT_MENU;
|
|
DeviceIndex = QuestionId - KEY_EFI_BOOT_DEVICE_BASE;
|
|
FirstToken = SUCInfo->EfiTokenRecord + DeviceIndex;
|
|
IsFirstItem = (BOOLEAN) (QuestionId - KEY_EFI_BOOT_DEVICE_BASE == 0);
|
|
IsLastItem = (BOOLEAN) (QuestionId - KEY_EFI_BOOT_DEVICE_BASE + 1 == SUCInfo->EfiBootDeviceNum);
|
|
OrderIndex = (KernelConfig->BootNormalPriority == LEGACY_FIRST) ? DeviceIndex + SUCInfo->LegacyBootDeviceNum : DeviceIndex;
|
|
} else if ((QuestionId >= KEY_ADV_LEGACY_BOOT_BASE) &&
|
|
(QuestionId < KEY_ADV_LEGACY_BOOT_BASE + SUCInfo->LegacyBootDeviceNum)) {
|
|
BootMenuType = LEGACY_ADV_MENU;
|
|
DeviceIndex = QuestionId - KEY_ADV_LEGACY_BOOT_BASE;
|
|
FirstToken = SUCInfo->LegacyAdvanceTokenRecord + DeviceIndex;
|
|
IsFirstItem = (BOOLEAN) (QuestionId - KEY_ADV_LEGACY_BOOT_BASE == 0);
|
|
IsLastItem = (BOOLEAN) (QuestionId - KEY_ADV_LEGACY_BOOT_BASE + 1 == SUCInfo->LegacyBootDeviceNum);
|
|
OrderIndex = (KernelConfig->BootNormalPriority == EFI_FIRST) ? DeviceIndex + SUCInfo->EfiBootDeviceNum : DeviceIndex;
|
|
} else {
|
|
for (Index = 0, BbsTypeTable = NULL; Index < mBbsTypeTableCount; Index++) {
|
|
BbsTypeTable = &mBbsTypeTable[Index];
|
|
if ((BbsTypeTable->KeyBootDeviceBase != 0) &&
|
|
(QuestionId >= BbsTypeTable->KeyBootDeviceBase) &&
|
|
(QuestionId < BbsTypeTable->KeyBootDeviceBase + BbsTypeTable->DevInfoCount)) {
|
|
break;
|
|
}
|
|
}
|
|
if (Index == mBbsTypeTableCount) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
BootMenuType = LEGACY_NORMAL_MENU;
|
|
DeviceIndex = QuestionId - BbsTypeTable->KeyBootDeviceBase;
|
|
FirstToken = SUCInfo->LegacyNormalTokenRecord[Index] + DeviceIndex;
|
|
IsFirstItem = (BOOLEAN) (QuestionId - BbsTypeTable->KeyBootDeviceBase == 0);
|
|
IsLastItem = (BOOLEAN) ((UINTN) (QuestionId - BbsTypeTable->KeyBootDeviceBase + 1) == BbsTypeTable->DevInfoCount);
|
|
OrderIndex = (KernelConfig->BootNormalPriority == EFI_FIRST) ? SUCInfo->EfiBootDeviceNum : 0;
|
|
|
|
for (Index = 0; Index < BootTypeCount; Index++) {
|
|
CurrentBbsTypeTable = GetBbsTypeTableByDevType (KernelConfig->BootTypeOrder[Index]);
|
|
if (CurrentBbsTypeTable == NULL) {
|
|
continue;
|
|
}
|
|
if (CurrentBbsTypeTable == BbsTypeTable) {
|
|
break;
|
|
}
|
|
OrderIndex += CurrentBbsTypeTable->DevInfoCount;
|
|
}
|
|
OrderIndex += DeviceIndex;
|
|
}
|
|
|
|
if ((UpShift && IsFirstItem) || (!UpShift && IsLastItem)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
BootOrder = SUCInfo->BootOrder;
|
|
if (UpShift) {
|
|
SecondToken = FirstToken - 1;
|
|
if (BootMenuType != LEGACY_DEVICE_TYPE_MENU) {
|
|
Temp = BootOrder[OrderIndex - 1];
|
|
BootOrder[OrderIndex - 1] = BootOrder[OrderIndex];
|
|
BootOrder[OrderIndex] = Temp;
|
|
} else {
|
|
Temp = KernelConfig->BootTypeOrder[OrderIndex - 1];
|
|
KernelConfig->BootTypeOrder[OrderIndex - 1] = KernelConfig->BootTypeOrder[OrderIndex];
|
|
KernelConfig->BootTypeOrder[OrderIndex] = (UINT8) Temp;
|
|
}
|
|
} else {
|
|
SecondToken = FirstToken + 1;
|
|
if (BootMenuType != LEGACY_DEVICE_TYPE_MENU) {
|
|
Temp = BootOrder[OrderIndex + 1];
|
|
BootOrder[OrderIndex + 1] = BootOrder[OrderIndex];
|
|
BootOrder[OrderIndex] = Temp;
|
|
} else {
|
|
Temp = KernelConfig->BootTypeOrder[OrderIndex + 1];
|
|
KernelConfig->BootTypeOrder[OrderIndex + 1] = KernelConfig->BootTypeOrder[OrderIndex];
|
|
KernelConfig->BootTypeOrder[OrderIndex] = (UINT8) Temp;
|
|
}
|
|
}
|
|
|
|
SecondUpdateStr = HiiGetString (BootCallBackInfo->HiiHandle, (EFI_STRING_ID) SecondToken, NULL);
|
|
FirstUpdateStr = HiiGetString (BootCallBackInfo->HiiHandle, (EFI_STRING_ID) FirstToken , NULL);
|
|
HiiSetString (BootCallBackInfo->HiiHandle, (EFI_STRING_ID) FirstToken , SecondUpdateStr, NULL);
|
|
HiiSetString (BootCallBackInfo->HiiHandle, (EFI_STRING_ID) SecondToken, FirstUpdateStr , NULL);
|
|
FreePool (FirstUpdateStr);
|
|
FreePool (SecondUpdateStr);
|
|
|
|
switch (BootMenuType) {
|
|
|
|
case ADV_BOOT_MENU:
|
|
case LEGACY_ADV_MENU:
|
|
SyncBootOrderToBootTypeOrder (UpShift, SUCInfo->AdvBootDeviceNum, BootOrder, KernelConfig);
|
|
|
|
case LEGACY_NORMAL_MENU:
|
|
SortBbsTypeTable (BootOrder, SUCInfo->AdvBootDeviceNum);
|
|
break;
|
|
|
|
case LEGACY_DEVICE_TYPE_MENU:
|
|
SyncBootOrderFromBootTypeOrder (SUCInfo, KernelConfig, SUCInfo->AdvBootDeviceNum, BootOrder);
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
|
|
SyncBootOrderToBootConfig ();
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Check the Bootxxxx number of device is EFI device or legacy device.
|
|
|
|
@param NumberOfDevice The device number in BootOrder variable (ex: Boot0001, then NumberOfDevice is 1)
|
|
|
|
@retval TRUE The device is EFI device.
|
|
@retval FALSE The device is legacy device.
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsEfiDevice (
|
|
IN UINT16 NumberOfDevice
|
|
)
|
|
{
|
|
UINT16 BootOptionName[20];
|
|
UINT8 *BootOption;
|
|
UINT8 *WorkingPtr;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
BOOLEAN IsEfiDevice;
|
|
|
|
UnicodeSPrint (
|
|
BootOptionName,
|
|
sizeof (BootOptionName),
|
|
L"Boot%04x",
|
|
NumberOfDevice
|
|
);
|
|
|
|
BootOption = CommonGetVariableData (
|
|
BootOptionName,
|
|
&gEfiGlobalVariableGuid
|
|
);
|
|
ASSERT (BootOption != NULL);
|
|
if (BootOption == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Find device path in Bootxxxx variable
|
|
//
|
|
WorkingPtr = BootOption;
|
|
WorkingPtr += sizeof (UINT32);
|
|
WorkingPtr += sizeof (UINT16);
|
|
WorkingPtr += (UINTN) StrSize ((UINT16 *) WorkingPtr);
|
|
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) WorkingPtr;
|
|
|
|
IsEfiDevice = TRUE;
|
|
if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {
|
|
IsEfiDevice = FALSE;
|
|
}
|
|
|
|
FreePool (BootOption);
|
|
return IsEfiDevice;
|
|
}
|
|
|
|
/**
|
|
Check if the boot option is a EFI shell boot option which is put in ROM image.
|
|
|
|
@param DevicePath The device path need to be processed.
|
|
|
|
@retval TRUE It is a EFI shell boot option in ROM image.
|
|
@retval FALSE It is not a EFI shell boot option in ROM image.
|
|
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
IsEfiShellBootOption (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;
|
|
EFI_DEVICE_PATH_PROTOCOL *WorkDevicePath;
|
|
BOOLEAN IsEfiShell;
|
|
EFI_GUID *FileGuid;
|
|
|
|
IsEfiShell = FALSE;
|
|
WorkDevicePath = DevicePath;
|
|
LastDeviceNode = DevicePath;
|
|
|
|
while (!IsDevicePathEnd (WorkDevicePath)) {
|
|
LastDeviceNode = WorkDevicePath;
|
|
WorkDevicePath = NextDevicePathNode (WorkDevicePath);
|
|
}
|
|
FileGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode);
|
|
if (FileGuid != NULL && (CompareGuid (FileGuid, PcdGetPtr(PcdShellFile)) || CompareGuid (FileGuid, PcdGetPtr(PcdMiniShellFile)))) {
|
|
IsEfiShell = TRUE;
|
|
}
|
|
|
|
return IsEfiShell;
|
|
}
|
|
|
|
/**
|
|
According to input parameter to adjust boot order to EFI device first or legacy device first.
|
|
|
|
@param EfiDeviceFirst TRUE : Indicate EFI device first.
|
|
FALSE: Indicate legacy device first.
|
|
@param DeviceCount Total device count
|
|
@param BootOrder Pointer to BootOrder.
|
|
|
|
@retval EFI_SUCCESS Adjust boot order successful.
|
|
@retval EFI_INVALID_PARAMETER Input parameter is invalid.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
AdjustBootOrder (
|
|
IN BOOLEAN EfiDeviceFirst,
|
|
IN UINTN DeviceCount,
|
|
IN OUT UINT16 *BootOrder
|
|
)
|
|
{
|
|
UINTN BootOrderIndex;
|
|
UINT16 *EfiDevicOrder;
|
|
UINTN EfiDeviceIndex;
|
|
UINT16 *LegacyDeviceOrder;
|
|
UINTN LegacyDeviceIndex;
|
|
|
|
if (DeviceCount == 0 || BootOrder == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
EfiDevicOrder = AllocateZeroPool (DeviceCount * sizeof (CHAR16));
|
|
if (EfiDevicOrder == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
LegacyDeviceOrder = AllocateZeroPool (DeviceCount * sizeof (CHAR16));
|
|
if (LegacyDeviceOrder == NULL) {
|
|
FreePool (EfiDevicOrder);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
EfiDeviceIndex = 0;
|
|
LegacyDeviceIndex = 0;
|
|
|
|
//
|
|
// According boot type (EFI or legacy) to put boot order respective buffer
|
|
//
|
|
for (BootOrderIndex = 0; BootOrderIndex < DeviceCount; BootOrderIndex++) {
|
|
if (IsEfiDevice (BootOrder[BootOrderIndex])) {
|
|
EfiDevicOrder[EfiDeviceIndex++] = BootOrder[BootOrderIndex];
|
|
} else {
|
|
LegacyDeviceOrder[LegacyDeviceIndex++] = BootOrder[BootOrderIndex];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Adjust boot order depend on EFI device first or legacy device first
|
|
//
|
|
if (EfiDeviceFirst) {
|
|
CopyMem (BootOrder, EfiDevicOrder, EfiDeviceIndex * sizeof (CHAR16));
|
|
CopyMem (&BootOrder[EfiDeviceIndex], LegacyDeviceOrder, LegacyDeviceIndex * sizeof (CHAR16));
|
|
} else {
|
|
CopyMem (BootOrder, LegacyDeviceOrder, LegacyDeviceIndex * sizeof (CHAR16));
|
|
CopyMem (&BootOrder[LegacyDeviceIndex], EfiDevicOrder, EfiDeviceIndex * sizeof (CHAR16));
|
|
}
|
|
|
|
FreePool (EfiDevicOrder);
|
|
FreePool (LegacyDeviceOrder);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
According to EFI device priority to sort all of EFI devices.
|
|
|
|
@param DeviceCount Total EFI device count
|
|
@param BootOrder Pointer to EFI device BootOrder.
|
|
|
|
@retval EFI_SUCCESS Change to auto boot order policy successful.
|
|
@retval EFI_INVALID_PARAMETER Input parameter is invalid.
|
|
@retval EFI_UNSUPPORTED doesn't support auto EFI Boot option oreder algorithm
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SortEfiDevices (
|
|
IN UINTN DeviceCount,
|
|
IN OUT UINT16 *BootOrder
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN SortIndex;
|
|
UINT16 BootOptionName[20];
|
|
UINTN BootOptionSize;
|
|
UINT8 *BootOption;
|
|
UINT8 *WorkingPtr;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
EFI_BOOT_ORDER_PRIORITY *BootPriority;
|
|
UINT16 Size;
|
|
EFI_STATUS Status;
|
|
UINT16 BootNumber;
|
|
UINT8 BootPriorityLevel;
|
|
EFI_BOOT_OPTION_POLICY_PROTOCOL *BootOptionPolicy;
|
|
BOOLEAN CreateByOS;
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiBootOptionPolicyProtocolGuid,
|
|
NULL,
|
|
(VOID **) &BootOptionPolicy
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
BootPriority = AllocateZeroPool (DeviceCount * sizeof (EFI_BOOT_ORDER_PRIORITY));
|
|
if (BootPriority == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
for (Index = 0; Index < DeviceCount; Index++) {
|
|
UnicodeSPrint (
|
|
BootOptionName,
|
|
sizeof (BootOptionName),
|
|
L"Boot%04x",
|
|
BootOrder[Index]
|
|
);
|
|
BootOption = NULL;
|
|
BootOptionSize = 0;
|
|
Status = CommonGetVariableDataAndSize (
|
|
BootOptionName,
|
|
&gEfiGlobalVariableGuid,
|
|
&BootOptionSize,
|
|
(VOID **) &BootOption
|
|
);
|
|
ASSERT (BootOption != NULL);
|
|
if (BootOption == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Find device path in Bootxxxx variable
|
|
//
|
|
Size = 0;
|
|
WorkingPtr = BootOption;
|
|
WorkingPtr += sizeof (UINT32) ;
|
|
Size += sizeof (UINT32) + (UINT16) (*WorkingPtr);
|
|
WorkingPtr += sizeof (UINT16) ;
|
|
Size += sizeof (UINT16) + (UINT16) StrSize ((UINT16 *) WorkingPtr);
|
|
WorkingPtr += StrSize ((UINT16 *) WorkingPtr);
|
|
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) WorkingPtr;
|
|
WorkingPtr += GetDevicePathSize (DevicePath);
|
|
CreateByOS = TRUE;
|
|
|
|
if (((BootOptionSize - Size == 2) && (AsciiStrnCmp ((CHAR8 *) WorkingPtr, "RC", 2) == 0)) ||
|
|
(IsEfiShellBootOption (DevicePath) && (BootOptionSize - Size >= 2) && (AsciiStrnCmp ((CHAR8 *) WorkingPtr, "RC", 2) == 0))) {
|
|
CreateByOS = FALSE;
|
|
}
|
|
Status = BootOptionPolicy->GetEfiOptionPriority (
|
|
BootOptionPolicy,
|
|
CreateByOS,
|
|
DevicePath,
|
|
&BootPriority[Index]
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
FreePool (BootOption);
|
|
}
|
|
//
|
|
// Sort EFI boot options based on EFI boot option priority policy
|
|
//
|
|
for (Index = 0; Index < DeviceCount; Index++) {
|
|
for (SortIndex = Index + 1; SortIndex < DeviceCount; SortIndex++) {
|
|
if (BootPriority[Index] > BootPriority[SortIndex]) {
|
|
BootPriorityLevel = BootPriority[Index];
|
|
BootPriority[Index] = BootPriority[SortIndex];
|
|
BootPriority[SortIndex] = BootPriorityLevel;
|
|
BootNumber = BootOrder[Index];
|
|
BootOrder[Index] = BootOrder[SortIndex];
|
|
BootOrder[SortIndex] = BootNumber;
|
|
}
|
|
}
|
|
}
|
|
|
|
FreePool (BootPriority);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Change boot order to suit auto boot option order policy.
|
|
|
|
@param DeviceCount Total device count
|
|
@param BootOrder Pointer to BootOrder.
|
|
|
|
@retval EFI_SUCCESS Change to auto boot order policy successful.
|
|
@retval EFI_INVALID_PARAMETER Input parameter is invalid.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
ChangeToAutoBootOrder (
|
|
IN UINTN DeviceCount,
|
|
IN OUT UINT16 *BootOrder
|
|
)
|
|
{
|
|
UINTN EfiDeviceNum;
|
|
UINTN EfiStartIndex;
|
|
UINT16 *EfiDeviceOrder;
|
|
UINTN Index;
|
|
|
|
if (DeviceCount == 0 || BootOrder == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
EfiDeviceNum = 0;
|
|
EfiStartIndex = 0;
|
|
for (Index = 0; Index < DeviceCount; Index++) {
|
|
if (IsEfiDevice (BootOrder[Index])) {
|
|
if (EfiDeviceNum == 0) {
|
|
EfiStartIndex = Index;
|
|
}
|
|
EfiDeviceNum++;
|
|
}
|
|
}
|
|
|
|
if (EfiDeviceNum == 0) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
EfiDeviceOrder = AllocateZeroPool (EfiDeviceNum * sizeof (CHAR16));
|
|
if (EfiDeviceOrder == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
CopyMem (EfiDeviceOrder, &BootOrder[EfiStartIndex], EfiDeviceNum * sizeof (UINT16));
|
|
//
|
|
// According to EFI device priority to sort EFI devices
|
|
//
|
|
SortEfiDevices (EfiDeviceNum, EfiDeviceOrder);
|
|
|
|
//
|
|
// copy sorted EFI device order to boot order
|
|
//
|
|
CopyMem (&BootOrder[EfiStartIndex], EfiDeviceOrder, EfiDeviceNum * sizeof (UINT16));
|
|
|
|
FreePool (EfiDeviceOrder);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|