mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-29 16:44:10 +02:00
MdeModulePkg: Process Sys Prep load options in BdsDxe driver.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Reviewed-by: Eric Dong <eric.dong@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17403 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
573b8a86d0
commit
1634214dbb
@ -27,8 +27,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
// Load Option Type
|
// Load Option Type
|
||||||
//
|
//
|
||||||
typedef enum {
|
typedef enum {
|
||||||
LoadOptionTypeBoot,
|
|
||||||
LoadOptionTypeDriver,
|
LoadOptionTypeDriver,
|
||||||
|
LoadOptionTypeSysPrep,
|
||||||
|
LoadOptionTypeBoot,
|
||||||
LoadOptionTypeMax
|
LoadOptionTypeMax
|
||||||
} EFI_BOOT_MANAGER_LOAD_OPTION_TYPE;
|
} EFI_BOOT_MANAGER_LOAD_OPTION_TYPE;
|
||||||
|
|
||||||
@ -51,6 +52,7 @@ typedef struct {
|
|||||||
EFI_DEVICE_PATH_PROTOCOL *FilePath; // Load Option Device Path
|
EFI_DEVICE_PATH_PROTOCOL *FilePath; // Load Option Device Path
|
||||||
UINT8 *OptionalData; // Load Option optional data to pass into image
|
UINT8 *OptionalData; // Load Option optional data to pass into image
|
||||||
UINT32 OptionalDataSize; // Load Option size of OptionalData
|
UINT32 OptionalDataSize; // Load Option size of OptionalData
|
||||||
|
EFI_GUID VendorGuid;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Used at runtime
|
// Used at runtime
|
||||||
@ -172,11 +174,11 @@ EfiBootManagerLoadOptionToVariable (
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This function will update the Boot####/Driver#### and the BootOrder/DriverOrder
|
This function will update the Boot####/Driver####/SysPrep#### and the
|
||||||
to add a new load option.
|
BootOrder/DriverOrder/SysPrepOrder to add a new load option.
|
||||||
|
|
||||||
@param Option Pointer to load option to add.
|
@param Option Pointer to load option to add.
|
||||||
@param Position Position of the new load option to put in the BootOrder/DriverOrder.
|
@param Position Position of the new load option to put in the BootOrder/DriverOrder/SysPrepOrder.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The load option has been successfully added.
|
@retval EFI_SUCCESS The load option has been successfully added.
|
||||||
@retval Others Error status returned by RT->SetVariable.
|
@retval Others Error status returned by RT->SetVariable.
|
||||||
@ -458,17 +460,20 @@ EfiBootManagerConnectAll (
|
|||||||
/**
|
/**
|
||||||
This function will create all handles associate with every device
|
This function will create all handles associate with every device
|
||||||
path node. If the handle associate with one device path node can not
|
path node. If the handle associate with one device path node can not
|
||||||
be created successfully, then still give one chance to do the dispatch,
|
be created successfully, then still give chance to do the dispatch,
|
||||||
which load the missing drivers if possible.
|
which load the missing drivers if possible.
|
||||||
|
|
||||||
@param DevicePathToConnect The device path which will be connected, it CANNOT be
|
@param DevicePathToConnect The device path which will be connected, it can be
|
||||||
a multi-instance device path
|
a multi-instance device path
|
||||||
@param MatchingHandle Return the controller handle closest to the DevicePathToConnect
|
@param MatchingHandle Return the controller handle closest to the DevicePathToConnect
|
||||||
|
|
||||||
@retval EFI_INVALID_PARAMETER DevicePathToConnect is NULL.
|
@retval EFI_SUCCESS All handles associate with every device path node
|
||||||
@retval EFI_NOT_FOUND Failed to create all handles associate with every device path node.
|
have been created.
|
||||||
@retval EFI_SUCCESS Successful to create all handles associate with every device path node.
|
@retval EFI_OUT_OF_RESOURCES There is no resource to create new handles.
|
||||||
|
@retval EFI_NOT_FOUND Create the handle associate with one device path
|
||||||
|
node failed.
|
||||||
|
@retval EFI_SECURITY_VIOLATION The user has no permission to start UEFI device
|
||||||
|
drivers on the DevicePath.
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
@ -508,8 +513,12 @@ typedef enum {
|
|||||||
/**
|
/**
|
||||||
This function will connect all the console devices base on the console
|
This function will connect all the console devices base on the console
|
||||||
device variable ConIn, ConOut and ErrOut.
|
device variable ConIn, ConOut and ErrOut.
|
||||||
|
|
||||||
|
@retval EFI_DEVICE_ERROR All the consoles were not connected due to an error.
|
||||||
|
@retval EFI_SUCCESS Success connect any one instance of the console
|
||||||
|
device path base on the variable ConVarName.
|
||||||
**/
|
**/
|
||||||
VOID
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EfiBootManagerConnectAllDefaultConsoles (
|
EfiBootManagerConnectAllDefaultConsoles (
|
||||||
VOID
|
VOID
|
||||||
@ -654,4 +663,19 @@ EfiBootManagerFreeDriverHealthInfo (
|
|||||||
UINTN Count
|
UINTN Count
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Process (load and execute) the load option.
|
||||||
|
|
||||||
|
@param LoadOption Pointer to the load option.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER The load option type is invalid,
|
||||||
|
or the load option file path doesn't point to a valid file.
|
||||||
|
@retval EFI_UNSUPPORTED The load option type is of LoadOptionTypeBoot.
|
||||||
|
@retval EFI_SUCCESS The load option is inactive, or successfully loaded and executed.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerProcessLoadOption (
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
|
||||||
|
);
|
||||||
#endif
|
#endif
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -103,11 +103,12 @@ EfiBootManagerConnectAll (
|
|||||||
@param MatchingHandle Return the controller handle closest to the DevicePathToConnect
|
@param MatchingHandle Return the controller handle closest to the DevicePathToConnect
|
||||||
|
|
||||||
@retval EFI_SUCCESS All handles associate with every device path node
|
@retval EFI_SUCCESS All handles associate with every device path node
|
||||||
have been created
|
have been created.
|
||||||
@retval EFI_OUT_OF_RESOURCES There is no resource to create new handles
|
@retval EFI_OUT_OF_RESOURCES There is no resource to create new handles.
|
||||||
@retval EFI_NOT_FOUND Create the handle associate with one device path
|
@retval EFI_NOT_FOUND Create the handle associate with one device path
|
||||||
node failed
|
node failed.
|
||||||
|
@retval EFI_SECURITY_VIOLATION The user has no permission to start UEFI device
|
||||||
|
drivers on the DevicePath.
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
@ -166,9 +167,8 @@ EfiBootManagerConnectDevicePath (
|
|||||||
// Connect all drivers that apply to Handle and RemainingDevicePath,
|
// Connect all drivers that apply to Handle and RemainingDevicePath,
|
||||||
// the Recursive flag is FALSE so only one level will be expanded.
|
// the Recursive flag is FALSE so only one level will be expanded.
|
||||||
//
|
//
|
||||||
// Do not check the connect status here, if the connect controller fail,
|
// If ConnectController fails to find a driver, then still give the chance to
|
||||||
// then still give the chance to do dispatch, because partial
|
// do dispatch, because partial RemainingDevicePath may be in the new FV
|
||||||
// RemainingDevicepath may be in the new FV
|
|
||||||
//
|
//
|
||||||
// 1. If the connect fail, RemainingDevicepath and handle will not
|
// 1. If the connect fail, RemainingDevicepath and handle will not
|
||||||
// change, so next time will do the dispatch, then dispatch's status
|
// change, so next time will do the dispatch, then dispatch's status
|
||||||
@ -177,7 +177,10 @@ EfiBootManagerConnectDevicePath (
|
|||||||
// change, then avoid the dispatch, we have chance to continue the
|
// change, then avoid the dispatch, we have chance to continue the
|
||||||
// next connection
|
// next connection
|
||||||
//
|
//
|
||||||
gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
|
Status = gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
|
||||||
|
if (Status == EFI_NOT_FOUND) {
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
}
|
||||||
if (MatchingHandle != NULL) {
|
if (MatchingHandle != NULL) {
|
||||||
*MatchingHandle = Handle;
|
*MatchingHandle = Handle;
|
||||||
}
|
}
|
||||||
|
@ -695,28 +695,42 @@ EfiBootManagerConnectAllConsoles (
|
|||||||
/**
|
/**
|
||||||
This function will connect all the console devices base on the console
|
This function will connect all the console devices base on the console
|
||||||
device variable ConIn, ConOut and ErrOut.
|
device variable ConIn, ConOut and ErrOut.
|
||||||
|
|
||||||
|
@retval EFI_DEVICE_ERROR All the consoles were not connected due to an error.
|
||||||
|
@retval EFI_SUCCESS Success connect any one instance of the console
|
||||||
|
device path base on the variable ConVarName.
|
||||||
**/
|
**/
|
||||||
VOID
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EfiBootManagerConnectAllDefaultConsoles (
|
EfiBootManagerConnectAllDefaultConsoles (
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
BOOLEAN OneConnected;
|
||||||
BOOLEAN SystemTableUpdated;
|
BOOLEAN SystemTableUpdated;
|
||||||
|
|
||||||
EfiBootManagerConnectConsoleVariable (ConOut);
|
OneConnected = FALSE;
|
||||||
|
|
||||||
|
Status = EfiBootManagerConnectConsoleVariable (ConOut);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
OneConnected = TRUE;
|
||||||
|
}
|
||||||
PERF_START (NULL, "ConOutReady", "BDS", 1);
|
PERF_START (NULL, "ConOutReady", "BDS", 1);
|
||||||
PERF_END (NULL, "ConOutReady", "BDS", 0);
|
PERF_END (NULL, "ConOutReady", "BDS", 0);
|
||||||
|
|
||||||
|
|
||||||
EfiBootManagerConnectConsoleVariable (ConIn);
|
Status = EfiBootManagerConnectConsoleVariable (ConIn);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
OneConnected = TRUE;
|
||||||
|
}
|
||||||
PERF_START (NULL, "ConInReady", "BDS", 1);
|
PERF_START (NULL, "ConInReady", "BDS", 1);
|
||||||
PERF_END (NULL, "ConInReady", "BDS", 0);
|
PERF_END (NULL, "ConInReady", "BDS", 0);
|
||||||
|
|
||||||
//
|
Status = EfiBootManagerConnectConsoleVariable (ErrOut);
|
||||||
// The _ModuleEntryPoint err out var is legal.
|
if (!EFI_ERROR (Status)) {
|
||||||
//
|
OneConnected = TRUE;
|
||||||
EfiBootManagerConnectConsoleVariable (ErrOut);
|
}
|
||||||
PERF_START (NULL, "ErrOutReady", "BDS", 1);
|
PERF_START (NULL, "ErrOutReady", "BDS", 1);
|
||||||
PERF_END (NULL, "ErrOutReady", "BDS", 0);
|
PERF_END (NULL, "ErrOutReady", "BDS", 0);
|
||||||
|
|
||||||
@ -745,4 +759,6 @@ EfiBootManagerConnectAllDefaultConsoles (
|
|||||||
&gST->Hdr.CRC32
|
&gST->Hdr.CRC32
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return OneConnected ? EFI_SUCCESS : EFI_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -14,20 +14,76 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
|
|
||||||
#include "InternalBm.h"
|
#include "InternalBm.h"
|
||||||
|
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED
|
||||||
|
CHAR16 *mBmLoadOptionName[] = {
|
||||||
|
L"Driver",
|
||||||
|
L"SysPrep",
|
||||||
|
L"Boot"
|
||||||
|
};
|
||||||
|
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED
|
||||||
|
CHAR16 *mBmLoadOptionOrderName[] = {
|
||||||
|
EFI_DRIVER_ORDER_VARIABLE_NAME,
|
||||||
|
EFI_SYS_PREP_ORDER_VARIABLE_NAME,
|
||||||
|
EFI_BOOT_ORDER_VARIABLE_NAME
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Call Visitor function for each variable in variable storage.
|
||||||
|
|
||||||
|
@param Visitor Visitor function.
|
||||||
|
@param Context The context passed to Visitor function.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmForEachVariable (
|
||||||
|
VARIABLE_VISITOR Visitor,
|
||||||
|
VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
CHAR16 *Name;
|
||||||
|
EFI_GUID Guid;
|
||||||
|
UINTN NameSize;
|
||||||
|
UINTN NewNameSize;
|
||||||
|
|
||||||
|
NameSize = sizeof (CHAR16);
|
||||||
|
Name = AllocateZeroPool (NameSize);
|
||||||
|
ASSERT (Name != NULL);
|
||||||
|
while (TRUE) {
|
||||||
|
NewNameSize = NameSize;
|
||||||
|
Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
|
||||||
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||||
|
Name = ReallocatePool (NameSize, NewNameSize, Name);
|
||||||
|
ASSERT (Name != NULL);
|
||||||
|
Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
|
||||||
|
NameSize = NewNameSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Status == EFI_NOT_FOUND) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
Visitor (Name, &Guid, Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool (Name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the Option Number that wasn't used.
|
Get the Option Number that wasn't used.
|
||||||
|
|
||||||
@param OrderVariableName Could be L"BootOrder" or L"DriverOrder".
|
@param LoadOptionType The load option type.
|
||||||
@param FreeOptionNumber To receive the minimal free option number.
|
@param FreeOptionNumber Return the minimal free option number.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The option number is found
|
@retval EFI_SUCCESS The option number is found and will be returned.
|
||||||
@retval EFI_OUT_OF_RESOURCES There is no free option number that can be used.
|
@retval EFI_OUT_OF_RESOURCES There is no free option number that can be used.
|
||||||
@retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
|
@retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BmGetFreeOptionNumber (
|
BmGetFreeOptionNumber (
|
||||||
IN CHAR16 *OrderVariableName,
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType,
|
||||||
OUT UINT16 *FreeOptionNumber
|
OUT UINT16 *FreeOptionNumber
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -38,13 +94,14 @@ BmGetFreeOptionNumber (
|
|||||||
UINTN OptionOrderSize;
|
UINTN OptionOrderSize;
|
||||||
UINT16 *BootNext;
|
UINT16 *BootNext;
|
||||||
|
|
||||||
if (FreeOptionNumber == NULL) {
|
ASSERT (FreeOptionNumber != NULL);
|
||||||
return EFI_INVALID_PARAMETER;
|
ASSERT (LoadOptionType == LoadOptionTypeDriver ||
|
||||||
}
|
LoadOptionType == LoadOptionTypeBoot ||
|
||||||
|
LoadOptionType == LoadOptionTypeSysPrep);
|
||||||
|
|
||||||
GetEfiGlobalVariable2 (OrderVariableName, (VOID **) &OptionOrder, &OptionOrderSize);
|
GetEfiGlobalVariable2 (mBmLoadOptionOrderName[LoadOptionType], (VOID **) &OptionOrder, &OptionOrderSize);
|
||||||
BootNext = NULL;
|
BootNext = NULL;
|
||||||
if (*OrderVariableName == L'B') {
|
if (LoadOptionType == LoadOptionTypeBoot) {
|
||||||
GetEfiGlobalVariable2 (L"BootNext", (VOID**) &BootNext, NULL);
|
GetEfiGlobalVariable2 (L"BootNext", (VOID**) &BootNext, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +150,96 @@ BmGetFreeOptionNumber (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create the Boot####, Driver####, SysPrep####, variable from the load option.
|
||||||
|
|
||||||
|
@param LoadOption Pointer to the load option.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The variable was created.
|
||||||
|
@retval Others Error status returned by RT->SetVariable.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerLoadOptionToVariable (
|
||||||
|
IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Option
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN VariableSize;
|
||||||
|
UINT8 *Variable;
|
||||||
|
UINT8 *Ptr;
|
||||||
|
CHAR16 OptionName[BM_OPTION_NAME_LEN];
|
||||||
|
CHAR16 *Description;
|
||||||
|
CHAR16 NullChar;
|
||||||
|
UINT32 VariableAttributes;
|
||||||
|
|
||||||
|
if ((Option->OptionNumber == LoadOptionNumberUnassigned) ||
|
||||||
|
(Option->FilePath == NULL) ||
|
||||||
|
((UINT32) Option->OptionType >= LoadOptionTypeMax)
|
||||||
|
) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convert NULL description to empty description
|
||||||
|
//
|
||||||
|
NullChar = L'\0';
|
||||||
|
Description = Option->Description;
|
||||||
|
if (Description == NULL) {
|
||||||
|
Description = &NullChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
UINT32 Attributes;
|
||||||
|
UINT16 FilePathListLength;
|
||||||
|
CHAR16 Description[];
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL FilePathList[];
|
||||||
|
UINT8 OptionalData[];
|
||||||
|
TODO: FilePathList[] IS:
|
||||||
|
A packed array of UEFI device paths. The first element of the
|
||||||
|
array is a device path that describes the device and location of the
|
||||||
|
Image for this load option. The FilePathList[0] is specific
|
||||||
|
to the device type. Other device paths may optionally exist in the
|
||||||
|
FilePathList, but their usage is OSV specific. Each element
|
||||||
|
in the array is variable length, and ends at the device path end
|
||||||
|
structure.
|
||||||
|
*/
|
||||||
|
VariableSize = sizeof (Option->Attributes)
|
||||||
|
+ sizeof (UINT16)
|
||||||
|
+ StrSize (Description)
|
||||||
|
+ GetDevicePathSize (Option->FilePath)
|
||||||
|
+ Option->OptionalDataSize;
|
||||||
|
|
||||||
|
Variable = AllocatePool (VariableSize);
|
||||||
|
ASSERT (Variable != NULL);
|
||||||
|
|
||||||
|
Ptr = Variable;
|
||||||
|
WriteUnaligned32 ((UINT32 *) Ptr, Option->Attributes);
|
||||||
|
Ptr += sizeof (Option->Attributes);
|
||||||
|
|
||||||
|
WriteUnaligned16 ((UINT16 *) Ptr, (UINT16) GetDevicePathSize (Option->FilePath));
|
||||||
|
Ptr += sizeof (UINT16);
|
||||||
|
|
||||||
|
CopyMem (Ptr, Description, StrSize (Description));
|
||||||
|
Ptr += StrSize (Description);
|
||||||
|
|
||||||
|
CopyMem (Ptr, Option->FilePath, GetDevicePathSize (Option->FilePath));
|
||||||
|
Ptr += GetDevicePathSize (Option->FilePath);
|
||||||
|
|
||||||
|
CopyMem (Ptr, Option->OptionalData, Option->OptionalDataSize);
|
||||||
|
|
||||||
|
UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[Option->OptionType], Option->OptionNumber);
|
||||||
|
|
||||||
|
VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
|
||||||
|
|
||||||
|
return gRT->SetVariable (
|
||||||
|
OptionName,
|
||||||
|
&gEfiGlobalVariableGuid,
|
||||||
|
VariableAttributes,
|
||||||
|
VariableSize,
|
||||||
|
Variable
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Update order variable .
|
Update order variable .
|
||||||
|
|
||||||
@ -159,101 +306,13 @@ BmAddOptionNumberToOrderVariable (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create the Boot#### or Driver#### variable from the load option.
|
This function will register the new Boot####, Driver#### or SysPrep#### option.
|
||||||
|
After the *#### is updated, the *Order will also be updated.
|
||||||
@param LoadOption Pointer to the load option.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The variable was created.
|
|
||||||
@retval Others Error status returned by RT->SetVariable.
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
EfiBootManagerLoadOptionToVariable (
|
|
||||||
IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Option
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UINTN VariableSize;
|
|
||||||
UINT8 *Variable;
|
|
||||||
UINT8 *Ptr;
|
|
||||||
CHAR16 OptionName[sizeof ("Driver####")];
|
|
||||||
CHAR16 *Description;
|
|
||||||
CHAR16 NullChar;
|
|
||||||
|
|
||||||
if ((Option->OptionNumber == LoadOptionNumberUnassigned) ||
|
|
||||||
(Option->FilePath == NULL) ||
|
|
||||||
(Option->OptionType >= LoadOptionTypeMax)
|
|
||||||
) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Convert NULL description to empty description
|
|
||||||
//
|
|
||||||
NullChar = L'\0';
|
|
||||||
Description = Option->Description;
|
|
||||||
if (Description == NULL) {
|
|
||||||
Description = &NullChar;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
UINT32 Attributes;
|
|
||||||
UINT16 FilePathListLength;
|
|
||||||
CHAR16 Description[];
|
|
||||||
EFI_DEVICE_PATH_PROTOCOL FilePathList[];
|
|
||||||
UINT8 OptionalData[];
|
|
||||||
TODO: FilePathList[] IS:
|
|
||||||
A packed array of UEFI device paths. The first element of the
|
|
||||||
array is a device path that describes the device and location of the
|
|
||||||
Image for this load option. The FilePathList[0] is specific
|
|
||||||
to the device type. Other device paths may optionally exist in the
|
|
||||||
FilePathList, but their usage is OSV specific. Each element
|
|
||||||
in the array is variable length, and ends at the device path end
|
|
||||||
structure.
|
|
||||||
*/
|
|
||||||
VariableSize = sizeof (Option->Attributes)
|
|
||||||
+ sizeof (UINT16)
|
|
||||||
+ StrSize (Description)
|
|
||||||
+ GetDevicePathSize (Option->FilePath)
|
|
||||||
+ Option->OptionalDataSize;
|
|
||||||
|
|
||||||
Variable = AllocatePool (VariableSize);
|
|
||||||
ASSERT (Variable != NULL);
|
|
||||||
|
|
||||||
Ptr = Variable;
|
|
||||||
*(UINT32 *) Ptr = Option->Attributes;
|
|
||||||
Ptr += sizeof (Option->Attributes);
|
|
||||||
*(UINT16 *) Ptr = (UINT16) GetDevicePathSize (Option->FilePath);
|
|
||||||
Ptr += sizeof (UINT16);
|
|
||||||
CopyMem (Ptr, Description, StrSize (Description));
|
|
||||||
Ptr += StrSize (Description);
|
|
||||||
CopyMem (Ptr, Option->FilePath, GetDevicePathSize (Option->FilePath));
|
|
||||||
Ptr += GetDevicePathSize (Option->FilePath);
|
|
||||||
CopyMem (Ptr, Option->OptionalData, Option->OptionalDataSize);
|
|
||||||
|
|
||||||
UnicodeSPrint (
|
|
||||||
OptionName,
|
|
||||||
sizeof (OptionName),
|
|
||||||
(Option->OptionType == LoadOptionTypeBoot) ? L"Boot%04x" : L"Driver%04x",
|
|
||||||
Option->OptionNumber
|
|
||||||
);
|
|
||||||
|
|
||||||
return gRT->SetVariable (
|
|
||||||
OptionName,
|
|
||||||
&gEfiGlobalVariableGuid,
|
|
||||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
|
||||||
VariableSize,
|
|
||||||
Variable
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function will register the new boot#### or driver#### option.
|
|
||||||
After the boot#### or driver#### updated, the BootOrder or DriverOrder will also be updated.
|
|
||||||
|
|
||||||
@param Option Pointer to load option to add.
|
@param Option Pointer to load option to add.
|
||||||
@param Position Position of the new load option to put in the ****Order variable.
|
@param Position Position of the new load option to put in the ****Order variable.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The boot#### or driver#### have been successfully registered.
|
@retval EFI_SUCCESS The *#### have been successfully registered.
|
||||||
@retval EFI_INVALID_PARAMETER The option number exceeds 0xFFFF.
|
@retval EFI_INVALID_PARAMETER The option number exceeds 0xFFFF.
|
||||||
@retval EFI_ALREADY_STARTED The option number of Option is being used already.
|
@retval EFI_ALREADY_STARTED The option number of Option is being used already.
|
||||||
Note: this API only adds new load option, no replacement support.
|
Note: this API only adds new load option, no replacement support.
|
||||||
@ -276,14 +335,18 @@ EfiBootManagerAddLoadOptionVariable (
|
|||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Option->OptionType != LoadOptionTypeDriver &&
|
||||||
|
Option->OptionType != LoadOptionTypeSysPrep &&
|
||||||
|
Option->OptionType != LoadOptionTypeBoot
|
||||||
|
) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the free option number if the option number is unassigned
|
// Get the free option number if the option number is unassigned
|
||||||
//
|
//
|
||||||
if (Option->OptionNumber == LoadOptionNumberUnassigned) {
|
if (Option->OptionNumber == LoadOptionNumberUnassigned) {
|
||||||
Status = BmGetFreeOptionNumber (
|
Status = BmGetFreeOptionNumber (Option->OptionType, &OptionNumber);
|
||||||
Option->OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
|
|
||||||
&OptionNumber
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
@ -294,11 +357,7 @@ EfiBootManagerAddLoadOptionVariable (
|
|||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = BmAddOptionNumberToOrderVariable (
|
Status = BmAddOptionNumberToOrderVariable (mBmLoadOptionOrderName[Option->OptionType], (UINT16) Option->OptionNumber, Position);
|
||||||
Option->OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
|
|
||||||
(UINT16) Option->OptionNumber,
|
|
||||||
Position
|
|
||||||
);
|
|
||||||
if (!EFI_ERROR (Status)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
//
|
//
|
||||||
// Save the Boot#### or Driver#### variable
|
// Save the Boot#### or Driver#### variable
|
||||||
@ -306,7 +365,7 @@ EfiBootManagerAddLoadOptionVariable (
|
|||||||
Status = EfiBootManagerLoadOptionToVariable (Option);
|
Status = EfiBootManagerLoadOptionToVariable (Option);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
//
|
//
|
||||||
// Remove the #### from *Order variable when the Boot####/Driver#### cannot be saved.
|
// Remove the #### from *Order variable when the Driver####/SysPrep####/Boot#### cannot be saved.
|
||||||
//
|
//
|
||||||
EfiBootManagerDeleteLoadOptionVariable (Option->OptionNumber, Option->OptionType);
|
EfiBootManagerDeleteLoadOptionVariable (Option->OptionNumber, Option->OptionType);
|
||||||
}
|
}
|
||||||
@ -357,7 +416,7 @@ EfiBootManagerSortLoadOptionVariable (
|
|||||||
}
|
}
|
||||||
|
|
||||||
Status = gRT->SetVariable (
|
Status = gRT->SetVariable (
|
||||||
OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
|
mBmLoadOptionOrderName[OptionType],
|
||||||
&gEfiGlobalVariableGuid,
|
&gEfiGlobalVariableGuid,
|
||||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
||||||
LoadOptionCount * sizeof (UINT16),
|
LoadOptionCount * sizeof (UINT16),
|
||||||
@ -409,6 +468,10 @@ EfiBootManagerInitializeLoadOption (
|
|||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((UINT32) OptionType >= LoadOptionTypeMax) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
ZeroMem (Option, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
|
ZeroMem (Option, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
|
||||||
Option->OptionNumber = OptionNumber;
|
Option->OptionNumber = OptionNumber;
|
||||||
Option->OptionType = OptionType;
|
Option->OptionType = OptionType;
|
||||||
@ -461,19 +524,21 @@ BmFindLoadOption (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Update the BootOrder or DriverOrder to delete OptionNumber .
|
Delete the load option.
|
||||||
|
|
||||||
@param OptionOrderVariable Order variable name which need to be updated.
|
|
||||||
@param OptionNumber Indicate the option number of load option
|
@param OptionNumber Indicate the option number of load option
|
||||||
|
@param OptionType Indicate the type of load option
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER OptionType or OptionNumber is invalid.
|
||||||
@retval EFI_NOT_FOUND The load option cannot be found
|
@retval EFI_NOT_FOUND The load option cannot be found
|
||||||
@retval EFI_SUCCESS The load option was deleted
|
@retval EFI_SUCCESS The load option was deleted
|
||||||
@retval others Status of RT->SetVariable()
|
@retval others Status of RT->SetVariable()
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BmDeleteOptionVariable (
|
EFIAPI
|
||||||
IN CHAR16 *OptionOrderVariable,
|
EfiBootManagerDeleteLoadOptionVariable (
|
||||||
IN UINT16 OptionNumber
|
IN UINTN OptionNumber,
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT16 *OptionOrder;
|
UINT16 *OptionOrder;
|
||||||
@ -481,14 +546,23 @@ BmDeleteOptionVariable (
|
|||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
|
|
||||||
|
if (((UINT32) OptionType >= LoadOptionTypeMax) || (OptionNumber >= LoadOptionNumberMax)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
Status = EFI_NOT_FOUND;
|
Status = EFI_NOT_FOUND;
|
||||||
GetEfiGlobalVariable2 (OptionOrderVariable, (VOID **) &OptionOrder, &OptionOrderSize);
|
|
||||||
|
if (OptionType == LoadOptionTypeDriver || OptionType == LoadOptionTypeSysPrep || OptionType == LoadOptionTypeBoot) {
|
||||||
|
//
|
||||||
|
// If the associated *Order exists, just remove the reference in *Order.
|
||||||
|
//
|
||||||
|
GetEfiGlobalVariable2 (mBmLoadOptionOrderName[OptionType], &OptionOrder, &OptionOrderSize);
|
||||||
for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
|
for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
|
||||||
if (OptionOrder[Index] == OptionNumber) {
|
if (OptionOrder[Index] == OptionNumber) {
|
||||||
OptionOrderSize -= sizeof (UINT16);
|
OptionOrderSize -= sizeof (UINT16);
|
||||||
CopyMem (&OptionOrder[Index], &OptionOrder[Index + 1], OptionOrderSize - Index * sizeof (UINT16));
|
CopyMem (&OptionOrder[Index], &OptionOrder[Index + 1], OptionOrderSize - Index * sizeof (UINT16));
|
||||||
Status = gRT->SetVariable (
|
Status = gRT->SetVariable (
|
||||||
OptionOrderVariable,
|
mBmLoadOptionOrderName[OptionType],
|
||||||
&gEfiGlobalVariableGuid,
|
&gEfiGlobalVariableGuid,
|
||||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
||||||
OptionOrderSize,
|
OptionOrderSize,
|
||||||
@ -500,35 +574,9 @@ BmDeleteOptionVariable (
|
|||||||
if (OptionOrder != NULL) {
|
if (OptionOrder != NULL) {
|
||||||
FreePool (OptionOrder);
|
FreePool (OptionOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Update the BootOrder or DriverOrder according to the OptionType to delete OptionNumber .
|
|
||||||
|
|
||||||
@param OptionNumber Indicate the option number of load option
|
|
||||||
@param OptionType Indicate the type of load option
|
|
||||||
|
|
||||||
@retval EFI_INVALID_PARAMETER OptionType or OptionNumber is invalid.
|
|
||||||
@retval EFI_NOT_FOUND The load option cannot be found
|
|
||||||
@retval EFI_SUCCESS The load option was deleted
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
EfiBootManagerDeleteLoadOptionVariable (
|
|
||||||
IN UINTN OptionNumber,
|
|
||||||
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if ((OptionType >= LoadOptionTypeMax) || (OptionNumber >= LoadOptionNumberMax)) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return BmDeleteOptionVariable (
|
return Status;
|
||||||
OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
|
|
||||||
(UINT16) OptionNumber
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -551,7 +599,7 @@ BmCharToUint (
|
|||||||
}
|
}
|
||||||
|
|
||||||
ASSERT (FALSE);
|
ASSERT (FALSE);
|
||||||
return 0;
|
return (UINTN) -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -645,10 +693,10 @@ BmStrSizeEx (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Validate the EFI Boot#### variable (VendorGuid/Name)
|
Validate the Boot####, Driver####, SysPrep#### variable (VendorGuid/Name)
|
||||||
|
|
||||||
@param Variable Boot#### variable data.
|
@param Variable The variable data.
|
||||||
@param VariableSize Returns the size of the EFI variable that was read
|
@param VariableSize The variable size.
|
||||||
|
|
||||||
@retval TRUE The variable data is correct.
|
@retval TRUE The variable data is correct.
|
||||||
@retval FALSE The variable data is corrupted.
|
@retval FALSE The variable data is corrupted.
|
||||||
@ -661,9 +709,8 @@ BmValidateOption (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT16 FilePathSize;
|
UINT16 FilePathSize;
|
||||||
UINT8 *TempPtr;
|
|
||||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||||
UINTN TempSize;
|
UINTN DescriptionSize;
|
||||||
|
|
||||||
if (VariableSize <= sizeof (UINT16) + sizeof (UINT32)) {
|
if (VariableSize <= sizeof (UINT16) + sizeof (UINT32)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -672,47 +719,100 @@ BmValidateOption (
|
|||||||
//
|
//
|
||||||
// Skip the option attribute
|
// Skip the option attribute
|
||||||
//
|
//
|
||||||
TempPtr = Variable;
|
Variable += sizeof (UINT32);
|
||||||
TempPtr += sizeof (UINT32);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the option's device path size
|
// Get the option's device path size
|
||||||
//
|
//
|
||||||
FilePathSize = *(UINT16 *) TempPtr;
|
FilePathSize = ReadUnaligned16 ((UINT16 *) Variable);
|
||||||
TempPtr += sizeof (UINT16);
|
Variable += sizeof (UINT16);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the option's description string size
|
// Get the option's description string size
|
||||||
//
|
//
|
||||||
TempSize = BmStrSizeEx ((CHAR16 *) TempPtr, VariableSize - sizeof (UINT16) - sizeof (UINT32));
|
DescriptionSize = BmStrSizeEx ((CHAR16 *) Variable, VariableSize - sizeof (UINT16) - sizeof (UINT32));
|
||||||
TempPtr += TempSize;
|
Variable += DescriptionSize;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the option's device path
|
// Get the option's device path
|
||||||
//
|
//
|
||||||
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
|
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Variable;
|
||||||
TempPtr += FilePathSize;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Validation boot option variable.
|
// Validation boot option variable.
|
||||||
//
|
//
|
||||||
if ((FilePathSize == 0) || (TempSize == 0)) {
|
if ((FilePathSize == 0) || (DescriptionSize == 0)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TempSize + FilePathSize + sizeof (UINT16) + sizeof (UINT32) > VariableSize) {
|
if (sizeof (UINT32) + sizeof (UINT16) + DescriptionSize + FilePathSize > VariableSize) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (BOOLEAN) (BmGetDevicePathSizeEx (DevicePath, FilePathSize) != 0);
|
return (BOOLEAN) (BmGetDevicePathSizeEx (DevicePath, FilePathSize) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check whether the VariableName is a valid load option variable name
|
||||||
|
and return the load option type and option number.
|
||||||
|
|
||||||
|
@param VariableName The name of the load option variable.
|
||||||
|
@param OptionType Return the load option type.
|
||||||
|
@param OptionNumber Return the load option number.
|
||||||
|
|
||||||
|
@retval TRUE The variable name is valid; The load option type and
|
||||||
|
load option number is returned.
|
||||||
|
@retval FALSE The variable name is NOT valid.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
BmIsValidLoadOptionVariableName (
|
||||||
|
IN CHAR16 *VariableName,
|
||||||
|
OUT EFI_BOOT_MANAGER_LOAD_OPTION_TYPE *OptionType,
|
||||||
|
OUT UINT16 *OptionNumber
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN VariableNameLen;
|
||||||
|
UINTN Index;
|
||||||
|
UINTN Uint;
|
||||||
|
|
||||||
|
VariableNameLen = StrLen (VariableName);
|
||||||
|
|
||||||
|
if (VariableNameLen <= 4) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Index = 0; Index < sizeof (mBmLoadOptionName) / sizeof (mBmLoadOptionName[0]); Index++) {
|
||||||
|
if ((VariableNameLen - 4 == StrLen (mBmLoadOptionName[Index])) &&
|
||||||
|
(StrnCmp (VariableName, mBmLoadOptionName[Index], VariableNameLen - 4) == 0)
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Index == sizeof (mBmLoadOptionName) / sizeof (mBmLoadOptionName[0])) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*OptionType = (EFI_BOOT_MANAGER_LOAD_OPTION_TYPE) Index;
|
||||||
|
*OptionNumber = 0;
|
||||||
|
for (Index = VariableNameLen - 4; Index < VariableNameLen; Index++) {
|
||||||
|
Uint = BmCharToUint (VariableName[Index]);
|
||||||
|
if (Uint == -1) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
*OptionNumber = (UINT16) Uint + *OptionNumber * 0x10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (BOOLEAN) (Index == VariableNameLen);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Build the Boot#### or Driver#### option from the VariableName.
|
Build the Boot#### or Driver#### option from the VariableName.
|
||||||
|
|
||||||
@param VariableName EFI Variable name indicate if it is Boot#### or
|
@param VariableName Variable name of the load option
|
||||||
Driver####
|
@param VendorGuid Variable GUID of the load option
|
||||||
@param Option Return the Boot#### or Driver#### option.
|
@param Option Return the load option.
|
||||||
|
|
||||||
@retval EFI_SUCCESS Get the option just been created
|
@retval EFI_SUCCESS Get the option just been created
|
||||||
@retval EFI_NOT_FOUND Failed to get the new option
|
@retval EFI_NOT_FOUND Failed to get the new option
|
||||||
@ -720,8 +820,9 @@ BmValidateOption (
|
|||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EfiBootManagerVariableToLoadOption (
|
EfiBootManagerVariableToLoadOptionEx (
|
||||||
IN CHAR16 *VariableName,
|
IN CHAR16 *VariableName,
|
||||||
|
IN EFI_GUID *VendorGuid,
|
||||||
IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option
|
IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -729,13 +830,12 @@ EfiBootManagerVariableToLoadOption (
|
|||||||
UINT32 Attribute;
|
UINT32 Attribute;
|
||||||
UINT16 FilePathSize;
|
UINT16 FilePathSize;
|
||||||
UINT8 *Variable;
|
UINT8 *Variable;
|
||||||
UINT8 *TempPtr;
|
UINT8 *VariablePtr;
|
||||||
UINTN VariableSize;
|
UINTN VariableSize;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *FilePath;
|
EFI_DEVICE_PATH_PROTOCOL *FilePath;
|
||||||
UINT8 *OptionalData;
|
UINT8 *OptionalData;
|
||||||
UINT32 OptionalDataSize;
|
UINT32 OptionalDataSize;
|
||||||
CHAR16 *Description;
|
CHAR16 *Description;
|
||||||
UINT8 NumOff;
|
|
||||||
EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType;
|
EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType;
|
||||||
UINT16 OptionNumber;
|
UINT16 OptionNumber;
|
||||||
|
|
||||||
@ -743,80 +843,62 @@ EfiBootManagerVariableToLoadOption (
|
|||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!BmIsValidLoadOptionVariableName (VariableName, &OptionType, &OptionNumber)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Read the variable
|
// Read the variable
|
||||||
//
|
//
|
||||||
GetEfiGlobalVariable2 (VariableName, (VOID **) &Variable, &VariableSize);
|
GetVariable2 (VariableName, VendorGuid, (VOID **) &Variable, &VariableSize);
|
||||||
if (Variable == NULL) {
|
if (Variable == NULL) {
|
||||||
return EFI_NOT_FOUND;
|
return EFI_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Validate Boot#### variable data.
|
// Validate *#### variable data.
|
||||||
//
|
//
|
||||||
if (!BmValidateOption(Variable, VariableSize)) {
|
if (!BmValidateOption(Variable, VariableSize)) {
|
||||||
FreePool (Variable);
|
FreePool (Variable);
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Notes: careful defined the variable of Boot#### or
|
|
||||||
// Driver####, consider use some macro to abstract the code
|
|
||||||
//
|
|
||||||
//
|
//
|
||||||
// Get the option attribute
|
// Get the option attribute
|
||||||
//
|
//
|
||||||
TempPtr = Variable;
|
VariablePtr = Variable;
|
||||||
Attribute = *(UINT32 *) Variable;
|
Attribute = ReadUnaligned32 ((UINT32 *) VariablePtr);
|
||||||
TempPtr += sizeof (UINT32);
|
VariablePtr += sizeof (UINT32);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the option's device path size
|
// Get the option's device path size
|
||||||
//
|
//
|
||||||
FilePathSize = *(UINT16 *) TempPtr;
|
FilePathSize = ReadUnaligned16 ((UINT16 *) VariablePtr);
|
||||||
TempPtr += sizeof (UINT16);
|
VariablePtr += sizeof (UINT16);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the option's description string
|
// Get the option's description string
|
||||||
//
|
//
|
||||||
Description = (CHAR16 *) TempPtr;
|
Description = (CHAR16 *) VariablePtr;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the option's description string size
|
// Get the option's description string size
|
||||||
//
|
//
|
||||||
TempPtr += StrSize ((CHAR16 *) TempPtr);
|
VariablePtr += StrSize ((CHAR16 *) VariablePtr);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the option's device path
|
// Get the option's device path
|
||||||
//
|
//
|
||||||
FilePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
|
FilePath = (EFI_DEVICE_PATH_PROTOCOL *) VariablePtr;
|
||||||
TempPtr += FilePathSize;
|
VariablePtr += FilePathSize;
|
||||||
|
|
||||||
OptionalDataSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));
|
OptionalDataSize = (UINT32) (VariableSize - (UINTN) (VariablePtr - Variable));
|
||||||
if (OptionalDataSize == 0) {
|
if (OptionalDataSize == 0) {
|
||||||
OptionalData = NULL;
|
OptionalData = NULL;
|
||||||
} else {
|
} else {
|
||||||
OptionalData = TempPtr;
|
OptionalData = VariablePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*VariableName == L'B') {
|
|
||||||
OptionType = LoadOptionTypeBoot;
|
|
||||||
NumOff = (UINT8) (sizeof (L"Boot") / sizeof (CHAR16) - 1);
|
|
||||||
} else {
|
|
||||||
OptionType = LoadOptionTypeDriver;
|
|
||||||
NumOff = (UINT8) (sizeof (L"Driver") / sizeof (CHAR16) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get the value from VariableName Unicode string
|
|
||||||
// since the ISO standard assumes ASCII equivalent abbreviations, we can be safe in converting this
|
|
||||||
// Unicode stream to ASCII without any loss in meaning.
|
|
||||||
//
|
|
||||||
OptionNumber = (UINT16) (BmCharToUint (VariableName[NumOff+0]) * 0x1000)
|
|
||||||
+ (UINT16) (BmCharToUint (VariableName[NumOff+1]) * 0x100)
|
|
||||||
+ (UINT16) (BmCharToUint (VariableName[NumOff+2]) * 0x10)
|
|
||||||
+ (UINT16) (BmCharToUint (VariableName[NumOff+3]) * 0x1);
|
|
||||||
|
|
||||||
Status = EfiBootManagerInitializeLoadOption (
|
Status = EfiBootManagerInitializeLoadOption (
|
||||||
Option,
|
Option,
|
||||||
OptionNumber,
|
OptionNumber,
|
||||||
@ -829,10 +911,31 @@ EfiBootManagerVariableToLoadOption (
|
|||||||
);
|
);
|
||||||
ASSERT_EFI_ERROR (Status);
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
CopyGuid (&Option->VendorGuid, VendorGuid);
|
||||||
|
|
||||||
FreePool (Variable);
|
FreePool (Variable);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Build the Boot#### or Driver#### option from the VariableName.
|
||||||
|
|
||||||
|
@param VariableName EFI Variable name indicate if it is Boot#### or Driver####
|
||||||
|
@param Option Return the Boot#### or Driver#### option.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Get the option just been created
|
||||||
|
@retval EFI_NOT_FOUND Failed to get the new option
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerVariableToLoadOption (
|
||||||
|
IN CHAR16 *VariableName,
|
||||||
|
IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return EfiBootManagerVariableToLoadOptionEx (VariableName, &gEfiGlobalVariableGuid, Option);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns an array of load options based on the EFI variable
|
Returns an array of load options based on the EFI variable
|
||||||
L"BootOrder"/L"DriverOrder" and the L"Boot####"/L"Driver####" variables impled by it.
|
L"BootOrder"/L"DriverOrder" and the L"Boot####"/L"Driver####" variables impled by it.
|
||||||
@ -857,44 +960,37 @@ EfiBootManagerGetLoadOptions (
|
|||||||
UINTN OptionOrderSize;
|
UINTN OptionOrderSize;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
UINTN OptionIndex;
|
UINTN OptionIndex;
|
||||||
EFI_BOOT_MANAGER_LOAD_OPTION *Option;
|
EFI_BOOT_MANAGER_LOAD_OPTION *Options;
|
||||||
CHAR16 OptionName[sizeof ("Driver####")];
|
CHAR16 OptionName[BM_OPTION_NAME_LEN];
|
||||||
UINT16 OptionNumber;
|
UINT16 OptionNumber;
|
||||||
|
|
||||||
*OptionCount = 0;
|
*OptionCount = 0;
|
||||||
|
|
||||||
|
if (LoadOptionType == LoadOptionTypeDriver || LoadOptionType == LoadOptionTypeSysPrep || LoadOptionType == LoadOptionTypeBoot) {
|
||||||
//
|
//
|
||||||
// Read the BootOrder, or DriverOrder variable.
|
// Read the BootOrder, or DriverOrder variable.
|
||||||
//
|
//
|
||||||
GetEfiGlobalVariable2 (
|
GetEfiGlobalVariable2 (mBmLoadOptionOrderName[LoadOptionType], (VOID **) &OptionOrder, &OptionOrderSize);
|
||||||
(LoadOptionType == LoadOptionTypeBoot) ? L"BootOrder" : L"DriverOrder",
|
|
||||||
(VOID **) &OptionOrder,
|
|
||||||
&OptionOrderSize
|
|
||||||
);
|
|
||||||
if (OptionOrder == NULL) {
|
if (OptionOrder == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*OptionCount = OptionOrderSize / sizeof (UINT16);
|
*OptionCount = OptionOrderSize / sizeof (UINT16);
|
||||||
|
|
||||||
Option = AllocatePool (*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
|
Options = AllocatePool (*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
|
||||||
ASSERT (Option != NULL);
|
ASSERT (Options != NULL);
|
||||||
|
|
||||||
OptionIndex = 0;
|
OptionIndex = 0;
|
||||||
for (Index = 0; Index < *OptionCount; Index++) {
|
for (Index = 0; Index < *OptionCount; Index++) {
|
||||||
OptionNumber = OptionOrder[Index];
|
OptionNumber = OptionOrder[Index];
|
||||||
if (LoadOptionType == LoadOptionTypeBoot) {
|
UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[LoadOptionType], OptionNumber);
|
||||||
UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionNumber);
|
|
||||||
} else {
|
|
||||||
UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = EfiBootManagerVariableToLoadOption (OptionName, &Option[OptionIndex]);
|
Status = EfiBootManagerVariableToLoadOption (OptionName, &Options[OptionIndex]);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((EFI_D_INFO, "[Bds] %s doesn't exist - Update ****Order variable to remove the reference!!", OptionName));
|
DEBUG ((EFI_D_INFO, "[Bds] %s doesn't exist - Update ****Order variable to remove the reference!!", OptionName));
|
||||||
EfiBootManagerDeleteLoadOptionVariable (OptionNumber, LoadOptionTypeBoot);
|
EfiBootManagerDeleteLoadOptionVariable (OptionNumber, LoadOptionType);
|
||||||
} else {
|
} else {
|
||||||
ASSERT (Option[OptionIndex].OptionNumber == OptionNumber);
|
ASSERT (Options[OptionIndex].OptionNumber == OptionNumber);
|
||||||
OptionIndex++;
|
OptionIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -904,16 +1000,16 @@ EfiBootManagerGetLoadOptions (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (OptionIndex < *OptionCount) {
|
if (OptionIndex < *OptionCount) {
|
||||||
Option = ReallocatePool (
|
Options = ReallocatePool (*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION), OptionIndex * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION), Options);
|
||||||
*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),
|
ASSERT (Options != NULL);
|
||||||
OptionIndex * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),
|
|
||||||
Option
|
|
||||||
);
|
|
||||||
ASSERT (Option != NULL);
|
|
||||||
*OptionCount = OptionIndex;
|
*OptionCount = OptionIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Option;
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Options;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -980,3 +1076,173 @@ EfiBootManagerFreeLoadOptions (
|
|||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return whether the PE header of the load option is valid or not.
|
||||||
|
|
||||||
|
@param[in] Type The load option type.
|
||||||
|
@param[in] FileBuffer The PE file buffer of the load option.
|
||||||
|
@param[in] FileSize The size of the load option file.
|
||||||
|
|
||||||
|
@retval TRUE The PE header of the load option is valid.
|
||||||
|
@retval FALSE The PE header of the load option is not valid.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
BmIsLoadOptionPeHeaderValid (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type,
|
||||||
|
IN VOID *FileBuffer,
|
||||||
|
IN UINTN FileSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_IMAGE_DOS_HEADER *DosHeader;
|
||||||
|
EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHeader;
|
||||||
|
EFI_IMAGE_OPTIONAL_HEADER32 *OptionalHeader;
|
||||||
|
UINT16 Subsystem;
|
||||||
|
|
||||||
|
if (FileBuffer == NULL || FileSize == 0) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read dos header
|
||||||
|
//
|
||||||
|
DosHeader = (EFI_IMAGE_DOS_HEADER *) FileBuffer;
|
||||||
|
if (FileSize >= sizeof (EFI_IMAGE_DOS_HEADER) &&
|
||||||
|
FileSize > DosHeader->e_lfanew && DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
// Read and check PE signature
|
||||||
|
//
|
||||||
|
PeHeader = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) FileBuffer + DosHeader->e_lfanew);
|
||||||
|
if (FileSize >= DosHeader->e_lfanew + sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) &&
|
||||||
|
PeHeader->Pe32.Signature == EFI_IMAGE_NT_SIGNATURE
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
// Check PE32 or PE32+ magic, and machine type
|
||||||
|
//
|
||||||
|
OptionalHeader = (EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHeader->Pe32.OptionalHeader;
|
||||||
|
if ((OptionalHeader->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC ||
|
||||||
|
OptionalHeader->Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) &&
|
||||||
|
EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeHeader->Pe32.FileHeader.Machine)
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
// Check the Subsystem:
|
||||||
|
// Driver#### must be of type BootServiceDriver or RuntimeDriver
|
||||||
|
// SysPrep####, Boot####, OsRecovery####, PlatformRecovery#### must be of type Application
|
||||||
|
//
|
||||||
|
Subsystem = OptionalHeader->Subsystem;
|
||||||
|
if ((Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
|
||||||
|
(Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ||
|
||||||
|
(Type == LoadOptionTypeSysPrep && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) ||
|
||||||
|
(Type == LoadOptionTypeBoot && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)
|
||||||
|
) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Process (load and execute) the load option.
|
||||||
|
|
||||||
|
@param LoadOption Pointer to the load option.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER The load option type is invalid,
|
||||||
|
or the load option file path doesn't point to a valid file.
|
||||||
|
@retval EFI_UNSUPPORTED The load option type is of LoadOptionTypeBoot.
|
||||||
|
@retval EFI_SUCCESS The load option is inactive, or successfully loaded and executed.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerProcessLoadOption (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *FilePath;
|
||||||
|
EFI_HANDLE ImageHandle;
|
||||||
|
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
|
||||||
|
VOID *FileBuffer;
|
||||||
|
UINTN FileSize;
|
||||||
|
|
||||||
|
if ((UINT32) LoadOption->OptionType >= LoadOptionTypeMax) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LoadOption->OptionType == LoadOptionTypeBoot) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If a load option is not marked as LOAD_OPTION_ACTIVE,
|
||||||
|
// the boot manager will not automatically load the option.
|
||||||
|
//
|
||||||
|
if ((LoadOption->Attributes & LOAD_OPTION_ACTIVE) == 0) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Load and start the load option.
|
||||||
|
//
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO | DEBUG_LOAD, "Process Load Option (%s%04x) ...\n",
|
||||||
|
mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber
|
||||||
|
));
|
||||||
|
ImageHandle = NULL;
|
||||||
|
FileBuffer = BmGetLoadOptionBuffer (LoadOption->FilePath, &FilePath, &FileSize);
|
||||||
|
DEBUG_CODE (
|
||||||
|
if (FileBuffer != NULL && CompareMem (LoadOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {
|
||||||
|
DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));
|
||||||
|
BmPrintDp (LoadOption->FilePath);
|
||||||
|
DEBUG ((EFI_D_INFO, " -> "));
|
||||||
|
BmPrintDp (FilePath);
|
||||||
|
DEBUG ((EFI_D_INFO, "\n"));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (BmIsLoadOptionPeHeaderValid (LoadOption->OptionType, FileBuffer, FileSize)) {
|
||||||
|
Status = gBS->LoadImage (
|
||||||
|
FALSE,
|
||||||
|
gImageHandle,
|
||||||
|
FilePath,
|
||||||
|
FileBuffer,
|
||||||
|
FileSize,
|
||||||
|
&ImageHandle
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (FilePath != NULL) {
|
||||||
|
FreePool (FilePath);
|
||||||
|
}
|
||||||
|
if (FileBuffer != NULL) {
|
||||||
|
FreePool (FileBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
ImageInfo->LoadOptionsSize = LoadOption->OptionalDataSize;
|
||||||
|
ImageInfo->LoadOptions = LoadOption->OptionalData;
|
||||||
|
//
|
||||||
|
// Before calling the image, enable the Watchdog Timer for the 5-minute period
|
||||||
|
//
|
||||||
|
gBS->SetWatchdogTimer (5 * 60, 0, 0, NULL);
|
||||||
|
|
||||||
|
LoadOption->Status = gBS->StartImage (ImageHandle, &LoadOption->ExitDataSize, &LoadOption->ExitData);
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO | DEBUG_LOAD, "Load Option (%s%04x) Return Status = %r\n",
|
||||||
|
mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber, LoadOption->Status
|
||||||
|
));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Clear the Watchdog Timer after the image returns
|
||||||
|
//
|
||||||
|
gBS->SetWatchdogTimer (0, 0, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
@ -120,146 +120,6 @@ BmMatchDevicePaths (
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Get the headers (dos, image, optional header) from an image
|
|
||||||
|
|
||||||
@param Device SimpleFileSystem device handle
|
|
||||||
@param FileName File name for the image
|
|
||||||
@param DosHeader Pointer to dos header
|
|
||||||
@param Hdr The buffer in which to return the PE32, PE32+, or TE header.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS Successfully get the machine type.
|
|
||||||
@retval EFI_NOT_FOUND The file is not found.
|
|
||||||
@retval EFI_LOAD_ERROR File is not a valid image file.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
BmGetImageHeader (
|
|
||||||
IN EFI_HANDLE Device,
|
|
||||||
IN CHAR16 *FileName,
|
|
||||||
OUT EFI_IMAGE_DOS_HEADER *DosHeader,
|
|
||||||
OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
|
|
||||||
EFI_FILE_HANDLE Root;
|
|
||||||
EFI_FILE_HANDLE ThisFile;
|
|
||||||
UINTN BufferSize;
|
|
||||||
UINT64 FileSize;
|
|
||||||
EFI_FILE_INFO *Info;
|
|
||||||
|
|
||||||
Root = NULL;
|
|
||||||
ThisFile = NULL;
|
|
||||||
//
|
|
||||||
// Handle the file system interface to the device
|
|
||||||
//
|
|
||||||
Status = gBS->HandleProtocol (
|
|
||||||
Device,
|
|
||||||
&gEfiSimpleFileSystemProtocolGuid,
|
|
||||||
(VOID *) &Volume
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = Volume->OpenVolume (
|
|
||||||
Volume,
|
|
||||||
&Root
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
Root = NULL;
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
ASSERT (Root != NULL);
|
|
||||||
Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
ASSERT (ThisFile != NULL);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get file size
|
|
||||||
//
|
|
||||||
BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
|
|
||||||
do {
|
|
||||||
Info = NULL;
|
|
||||||
Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
Status = ThisFile->GetInfo (
|
|
||||||
ThisFile,
|
|
||||||
&gEfiFileInfoGuid,
|
|
||||||
&BufferSize,
|
|
||||||
Info
|
|
||||||
);
|
|
||||||
if (!EFI_ERROR (Status)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (Status != EFI_BUFFER_TOO_SMALL) {
|
|
||||||
FreePool (Info);
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
FreePool (Info);
|
|
||||||
} while (TRUE);
|
|
||||||
|
|
||||||
FileSize = Info->FileSize;
|
|
||||||
FreePool (Info);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Read dos header
|
|
||||||
//
|
|
||||||
BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);
|
|
||||||
Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader);
|
|
||||||
if (EFI_ERROR (Status) ||
|
|
||||||
BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) ||
|
|
||||||
FileSize <= DosHeader->e_lfanew ||
|
|
||||||
DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
|
|
||||||
Status = EFI_LOAD_ERROR;
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Move to PE signature
|
|
||||||
//
|
|
||||||
Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
Status = EFI_LOAD_ERROR;
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Read and check PE signature
|
|
||||||
//
|
|
||||||
BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
|
|
||||||
Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32);
|
|
||||||
if (EFI_ERROR (Status) ||
|
|
||||||
BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) ||
|
|
||||||
Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
|
|
||||||
Status = EFI_LOAD_ERROR;
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check PE32 or PE32+ magic
|
|
||||||
//
|
|
||||||
if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
|
|
||||||
Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
|
||||||
Status = EFI_LOAD_ERROR;
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
Done:
|
|
||||||
if (ThisFile != NULL) {
|
|
||||||
ThisFile->Close (ThisFile);
|
|
||||||
}
|
|
||||||
if (Root != NULL) {
|
|
||||||
Root->Close (Root);
|
|
||||||
}
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This routine adjust the memory information for different memory type and
|
This routine adjust the memory information for different memory type and
|
||||||
save them into the variables for next boot.
|
save them into the variables for next boot.
|
||||||
@ -505,3 +365,22 @@ BmSetVariableAndReportStatusCodeOnError (
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Print the device path info.
|
||||||
|
|
||||||
|
@param DevicePath The device path need to print.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmPrintDp (
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CHAR16 *Str;
|
||||||
|
|
||||||
|
Str = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
|
||||||
|
DEBUG ((EFI_D_INFO, "%s", Str));
|
||||||
|
if (Str != NULL) {
|
||||||
|
FreePool (Str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -100,6 +100,37 @@ CHAR16 *
|
|||||||
IN EFI_HANDLE Handle
|
IN EFI_HANDLE Handle
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#define BM_OPTION_NAME_LEN sizeof ("SysPrep####")
|
||||||
|
extern CHAR16 *mBmLoadOptionName[];
|
||||||
|
|
||||||
|
typedef
|
||||||
|
VOID
|
||||||
|
(*VARIABLE_VISITOR) (
|
||||||
|
CHAR16 *Name,
|
||||||
|
EFI_GUID *Guid,
|
||||||
|
VOID *Context
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Call Visitor function for each variable in variable storage.
|
||||||
|
|
||||||
|
@param Visitor Visitor function.
|
||||||
|
@param Context The context passed to Visitor function.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
ForEachVariable (
|
||||||
|
VARIABLE_VISITOR Visitor,
|
||||||
|
VOID *Context
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Repair all the controllers according to the Driver Health status queried.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmRepairAllControllers (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
#define BM_HOTKEY_SIGNATURE SIGNATURE_32 ('b', 'm', 'h', 'k')
|
#define BM_HOTKEY_SIGNATURE SIGNATURE_32 ('b', 'm', 'h', 'k')
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT32 Signature;
|
UINT32 Signature;
|
||||||
@ -139,7 +170,7 @@ BmLoadEfiBootOption (
|
|||||||
/**
|
/**
|
||||||
Get the Option Number that wasn't used.
|
Get the Option Number that wasn't used.
|
||||||
|
|
||||||
@param OrderVariableName Could be L"BootOrder" or L"DriverOrder".
|
@param LoadOptionType Load option type.
|
||||||
@param FreeOptionNumber To receive the minimal free option number.
|
@param FreeOptionNumber To receive the minimal free option number.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The option number is found
|
@retval EFI_SUCCESS The option number is found
|
||||||
@ -149,7 +180,7 @@ BmLoadEfiBootOption (
|
|||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BmGetFreeOptionNumber (
|
BmGetFreeOptionNumber (
|
||||||
IN CHAR16 *OrderVariableName,
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType,
|
||||||
OUT UINT16 *FreeOptionNumber
|
OUT UINT16 *FreeOptionNumber
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -294,6 +325,42 @@ BmSetVariableAndReportStatusCodeOnError (
|
|||||||
IN VOID *Data
|
IN VOID *Data
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the load option by its device path.
|
||||||
|
|
||||||
|
@param FilePath The device path pointing to a load option.
|
||||||
|
It could be a short-form device path.
|
||||||
|
@param FullPath Return the full device path of the load option after
|
||||||
|
short-form device path expanding.
|
||||||
|
Caller is responsible to free it.
|
||||||
|
@param FileSize Return the load option size.
|
||||||
|
|
||||||
|
@return The load option buffer. Caller is responsible to free the memory.
|
||||||
|
**/
|
||||||
|
VOID *
|
||||||
|
BmGetLoadOptionBuffer (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||||
|
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
||||||
|
OUT UINTN *FileSize
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return whether the PE header of the load option is valid or not.
|
||||||
|
|
||||||
|
@param[in] Type The load option type.
|
||||||
|
@param[in] FileBuffer The PE file buffer of the load option.
|
||||||
|
@param[in] FileSize The size of the load option file.
|
||||||
|
|
||||||
|
@retval TRUE The PE header of the load option is valid.
|
||||||
|
@retval FALSE The PE header of the load option is not valid.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
BmIsLoadOptionPeHeaderValid (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type,
|
||||||
|
IN VOID *FileBuffer,
|
||||||
|
IN UINTN FileSize
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Function compares a device path data structure to that of all the nodes of a
|
Function compares a device path data structure to that of all the nodes of a
|
||||||
second device path instance.
|
second device path instance.
|
||||||
@ -361,4 +428,14 @@ BmRepairAllControllers (
|
|||||||
VOID
|
VOID
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Print the device path info.
|
||||||
|
|
||||||
|
@param DevicePath The device path need to print.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmPrintDp (
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||||
|
);
|
||||||
|
|
||||||
#endif // _INTERNAL_BM_H_
|
#endif // _INTERNAL_BM_H_
|
||||||
|
@ -47,6 +47,12 @@ CHAR16 *mReadOnlyVariables[] = {
|
|||||||
EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME
|
EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CHAR16 *mBdsLoadOptionName[] = {
|
||||||
|
L"Driver",
|
||||||
|
L"SysPrep",
|
||||||
|
L"Boot"
|
||||||
|
};
|
||||||
|
|
||||||
CHAR16 mRecoveryBoot[] = L"Recovery Boot";
|
CHAR16 mRecoveryBoot[] = L"Recovery Boot";
|
||||||
/**
|
/**
|
||||||
Event to Connect ConIn.
|
Event to Connect ConIn.
|
||||||
@ -75,7 +81,7 @@ BdsDxeOnConnectConInCallBack (
|
|||||||
// Should not enter this case, if enter, the keyboard will not work.
|
// Should not enter this case, if enter, the keyboard will not work.
|
||||||
// May need platfrom policy to connect keyboard.
|
// May need platfrom policy to connect keyboard.
|
||||||
//
|
//
|
||||||
DEBUG ((EFI_D_WARN, "[Bds] ASSERT Connect ConIn failed!!!\n"));
|
DEBUG ((EFI_D_WARN, "[Bds] Connect ConIn failed - %r!!!\n", Status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,37 +559,44 @@ DefaultBootBehavior (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The function will go through the driver option link list, load and start
|
The function will load and start every Driver####/SysPrep####.
|
||||||
every driver the driver option device path point to.
|
|
||||||
|
|
||||||
@param DriverOption Input driver option array.
|
@param LoadOptions Load option array.
|
||||||
@param DriverOptionCount Input driver option count.
|
@param LoadOptionCount Load option count.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
VOID
|
VOID
|
||||||
LoadDrivers (
|
ProcessLoadOptions (
|
||||||
IN EFI_BOOT_MANAGER_LOAD_OPTION *DriverOption,
|
IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOptions,
|
||||||
IN UINTN DriverOptionCount
|
IN UINTN LoadOptionCount
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
EFI_HANDLE ImageHandle;
|
|
||||||
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
|
|
||||||
BOOLEAN ReconnectAll;
|
BOOLEAN ReconnectAll;
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType;
|
||||||
|
|
||||||
ReconnectAll = FALSE;
|
ReconnectAll = FALSE;
|
||||||
|
LoadOptionType = LoadOptionTypeMax;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Process the driver option
|
// Process the driver option
|
||||||
//
|
//
|
||||||
for (Index = 0; Index < DriverOptionCount; Index++) {
|
for (Index = 0; Index < LoadOptionCount; Index++) {
|
||||||
//
|
//
|
||||||
// If a load option is not marked as LOAD_OPTION_ACTIVE,
|
// All the load options in the array should be of the same type.
|
||||||
// the boot manager will not automatically load the option.
|
|
||||||
//
|
//
|
||||||
if ((DriverOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0) {
|
if (LoadOptionType == LoadOptionTypeMax) {
|
||||||
continue;
|
LoadOptionType = LoadOptions[Index].OptionType;
|
||||||
|
}
|
||||||
|
ASSERT (LoadOptionType == LoadOptions[Index].OptionType);
|
||||||
|
ASSERT (LoadOptionType == LoadOptionTypeDriver || LoadOptionType == LoadOptionTypeSysPrep);
|
||||||
|
|
||||||
|
Status = EfiBootManagerProcessLoadOption (&LoadOptions[Index]);
|
||||||
|
|
||||||
|
if (!EFI_ERROR (Status) && ((LoadOptions[Index].Attributes & LOAD_OPTION_FORCE_RECONNECT) != 0)) {
|
||||||
|
ReconnectAll = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -591,65 +604,10 @@ LoadDrivers (
|
|||||||
// then all of the EFI drivers in the system will be disconnected and
|
// then all of the EFI drivers in the system will be disconnected and
|
||||||
// reconnected after the last driver load option is processed.
|
// reconnected after the last driver load option is processed.
|
||||||
//
|
//
|
||||||
if ((DriverOption[Index].Attributes & LOAD_OPTION_FORCE_RECONNECT) != 0) {
|
if (ReconnectAll && LoadOptionType == LoadOptionTypeDriver) {
|
||||||
ReconnectAll = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Make sure the driver path is connected.
|
|
||||||
//
|
|
||||||
EfiBootManagerConnectDevicePath (DriverOption[Index].FilePath, NULL);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Load and start the image that Driver#### describes
|
|
||||||
//
|
|
||||||
Status = gBS->LoadImage (
|
|
||||||
FALSE,
|
|
||||||
gImageHandle,
|
|
||||||
DriverOption[Index].FilePath,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
&ImageHandle
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!EFI_ERROR (Status)) {
|
|
||||||
gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Verify whether this image is a driver, if not,
|
|
||||||
// exit it and continue to parse next load option
|
|
||||||
//
|
|
||||||
if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {
|
|
||||||
gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageInfo->LoadOptionsSize = DriverOption[Index].OptionalDataSize;
|
|
||||||
ImageInfo->LoadOptions = DriverOption[Index].OptionalData;
|
|
||||||
//
|
|
||||||
// Before calling the image, enable the Watchdog Timer for
|
|
||||||
// the 5 Minute period
|
|
||||||
//
|
|
||||||
gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
|
|
||||||
|
|
||||||
DriverOption[Index].Status = gBS->StartImage (ImageHandle, &DriverOption[Index].ExitDataSize, &DriverOption[Index].ExitData);
|
|
||||||
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Driver Return Status = %r\n", DriverOption[Index].Status));
|
|
||||||
|
|
||||||
//
|
|
||||||
// Clear the Watchdog Timer after the image returns
|
|
||||||
//
|
|
||||||
gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Process the LOAD_OPTION_FORCE_RECONNECT driver option
|
|
||||||
//
|
|
||||||
if (ReconnectAll) {
|
|
||||||
EfiBootManagerDisconnectAll ();
|
EfiBootManagerDisconnectAll ();
|
||||||
EfiBootManagerConnectAll ();
|
EfiBootManagerConnectAll ();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -855,9 +813,8 @@ BdsEntry (
|
|||||||
IN EFI_BDS_ARCH_PROTOCOL *This
|
IN EFI_BDS_ARCH_PROTOCOL *This
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_BOOT_MANAGER_LOAD_OPTION *DriverOption;
|
EFI_BOOT_MANAGER_LOAD_OPTION *LoadOptions;
|
||||||
EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
|
UINTN LoadOptionCount;
|
||||||
UINTN DriverOptionCount;
|
|
||||||
CHAR16 *FirmwareVendor;
|
CHAR16 *FirmwareVendor;
|
||||||
EFI_EVENT HotkeyTriggered;
|
EFI_EVENT HotkeyTriggered;
|
||||||
UINT64 OsIndication;
|
UINT64 OsIndication;
|
||||||
@ -867,8 +824,11 @@ BdsEntry (
|
|||||||
UINT16 BootTimeOut;
|
UINT16 BootTimeOut;
|
||||||
EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
|
EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
|
||||||
UINT16 *BootNext;
|
UINT16 *BootNext;
|
||||||
CHAR16 BootNextVariableName[sizeof ("Boot####")];
|
CHAR16 BootNextVariableName[sizeof ("Boot####")];
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
|
||||||
|
BOOLEAN BootFwUi;
|
||||||
|
|
||||||
HotkeyTriggered = NULL;
|
HotkeyTriggered = NULL;
|
||||||
Status = EFI_SUCCESS;
|
Status = EFI_SUCCESS;
|
||||||
@ -939,7 +899,7 @@ BdsEntry (
|
|||||||
// Initialize L"BootOptionSupport" EFI global variable.
|
// Initialize L"BootOptionSupport" EFI global variable.
|
||||||
// Lazy-ConIn implictly disables BDS hotkey.
|
// Lazy-ConIn implictly disables BDS hotkey.
|
||||||
//
|
//
|
||||||
BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_APP;
|
BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_APP | EFI_BOOT_OPTION_SUPPORT_SYSPREP;
|
||||||
if (!PcdGetBool (PcdConInConnectOnDemand)) {
|
if (!PcdGetBool (PcdConInConnectOnDemand)) {
|
||||||
BootOptionSupport |= EFI_BOOT_OPTION_SUPPORT_KEY;
|
BootOptionSupport |= EFI_BOOT_OPTION_SUPPORT_KEY;
|
||||||
SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);
|
SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);
|
||||||
@ -1010,11 +970,11 @@ BdsEntry (
|
|||||||
EfiBootManagerStartHotkeyService (&HotkeyTriggered);
|
EfiBootManagerStartHotkeyService (&HotkeyTriggered);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Load Driver Options
|
// Execute Driver Options
|
||||||
//
|
//
|
||||||
DriverOption = EfiBootManagerGetLoadOptions (&DriverOptionCount, LoadOptionTypeDriver);
|
LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypeDriver);
|
||||||
LoadDrivers (DriverOption, DriverOptionCount);
|
ProcessLoadOptions (LoadOptions, LoadOptionCount);
|
||||||
EfiBootManagerFreeLoadOptions (DriverOption, DriverOptionCount);
|
EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Connect consoles
|
// Connect consoles
|
||||||
@ -1059,22 +1019,27 @@ BdsEntry (
|
|||||||
PERF_END (NULL, "PlatformBootManagerAfterConsole", "BDS", 0);
|
PERF_END (NULL, "PlatformBootManagerAfterConsole", "BDS", 0);
|
||||||
|
|
||||||
DEBUG_CODE (
|
DEBUG_CODE (
|
||||||
EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
|
|
||||||
UINTN BootOptionCount;
|
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType;
|
||||||
BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
|
DEBUG ((EFI_D_INFO, "[Bds]=============Begin Load Options Dumping ...=============\n"));
|
||||||
DEBUG ((EFI_D_INFO, "[Bds]=============Dumping Boot Options=============\n"));
|
for (LoadOptionType = 0; LoadOptionType < LoadOptionTypeMax; LoadOptionType++) {
|
||||||
for (Index = 0; Index < BootOptionCount; Index++) {
|
|
||||||
DEBUG ((
|
DEBUG ((
|
||||||
EFI_D_INFO, "[Bds]Boot%04x: %s \t\t 0x%04x\n",
|
EFI_D_INFO, " %s Options:\n",
|
||||||
BootOptions[Index].OptionNumber,
|
mBdsLoadOptionName[LoadOptionType]
|
||||||
BootOptions[Index].Description,
|
));
|
||||||
BootOptions[Index].Attributes
|
LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionType);
|
||||||
|
for (Index = 0; Index < LoadOptionCount; Index++) {
|
||||||
|
DEBUG ((
|
||||||
|
EFI_D_INFO, " %s%04x: %s \t\t 0x%04x\n",
|
||||||
|
mBdsLoadOptionName[LoadOptionType],
|
||||||
|
LoadOptions[Index].OptionNumber,
|
||||||
|
LoadOptions[Index].Description,
|
||||||
|
LoadOptions[Index].Attributes
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
DEBUG ((EFI_D_INFO, "[Bds]=============Dumping Boot Options Finished====\n"));
|
EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
|
||||||
EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
|
}
|
||||||
|
DEBUG ((EFI_D_INFO, "[Bds]=============End Load Options Dumping=============\n"));
|
||||||
);
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1088,10 +1053,15 @@ BdsEntry (
|
|||||||
&DataSize,
|
&DataSize,
|
||||||
&OsIndication
|
&OsIndication
|
||||||
);
|
);
|
||||||
if (!EFI_ERROR(Status) && ((OsIndication & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0)) {
|
if (EFI_ERROR (Status)) {
|
||||||
|
OsIndication = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BootFwUi = (BOOLEAN) ((OsIndication & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0);
|
||||||
//
|
//
|
||||||
// Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS
|
// Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS
|
||||||
//
|
//
|
||||||
|
if (BootFwUi) {
|
||||||
OsIndication &= ~((UINT64) EFI_OS_INDICATIONS_BOOT_TO_FW_UI);
|
OsIndication &= ~((UINT64) EFI_OS_INDICATIONS_BOOT_TO_FW_UI);
|
||||||
Status = gRT->SetVariable (
|
Status = gRT->SetVariable (
|
||||||
L"OsIndications",
|
L"OsIndications",
|
||||||
@ -1104,7 +1074,12 @@ BdsEntry (
|
|||||||
// Changing the content without increasing its size with current variable implementation shouldn't fail.
|
// Changing the content without increasing its size with current variable implementation shouldn't fail.
|
||||||
//
|
//
|
||||||
ASSERT_EFI_ERROR (Status);
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Launch Boot Manager Menu directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot
|
||||||
|
//
|
||||||
|
if (BootFwUi) {
|
||||||
//
|
//
|
||||||
// Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI
|
// Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI
|
||||||
//
|
//
|
||||||
@ -1113,12 +1088,24 @@ BdsEntry (
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Directly boot to Boot Manager Menu.
|
// Directly enter the setup page.
|
||||||
|
// BootManagerMenu always contains the correct information even call fails.
|
||||||
|
//
|
||||||
|
EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
|
||||||
|
EfiBootManagerBoot (&BootManagerMenu);
|
||||||
|
EfiBootManagerFreeLoadOption (&BootManagerMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Execute SysPrep####
|
||||||
|
//
|
||||||
|
LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypeSysPrep);
|
||||||
|
ProcessLoadOptions (LoadOptions, LoadOptionCount);
|
||||||
|
EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Execute Key####
|
||||||
//
|
//
|
||||||
EfiBootManagerGetBootManagerMenu (&BootOption);
|
|
||||||
EfiBootManagerBoot (&BootOption);
|
|
||||||
EfiBootManagerFreeLoadOption (&BootOption);
|
|
||||||
} else {
|
|
||||||
PERF_START (NULL, "BdsWait", "BDS", 0);
|
PERF_START (NULL, "BdsWait", "BDS", 0);
|
||||||
BdsWait (HotkeyTriggered);
|
BdsWait (HotkeyTriggered);
|
||||||
PERF_END (NULL, "BdsWait", "BDS", 0);
|
PERF_END (NULL, "BdsWait", "BDS", 0);
|
||||||
@ -1129,7 +1116,6 @@ BdsEntry (
|
|||||||
BdsReadKeys ();
|
BdsReadKeys ();
|
||||||
|
|
||||||
EfiBootManagerHotkeyBoot ();
|
EfiBootManagerHotkeyBoot ();
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Boot to "BootNext"
|
// Boot to "BootNext"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user