bdsmisc.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,279 行 · 第 1/3 页
C
1,279 行
/*++
Copyright (c) 2004 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
BdsMisc.c
Abstract:
Misc BDS library function
--*/
#include "BdsLib.h"
#include EFI_PROTOCOL_DEFINITION (FormBrowser)
#define MAX_STRING_LEN 200
static BOOLEAN mFeaturerSwitch = TRUE;
static BOOLEAN mResetRequired = FALSE;
extern UINT16 gPlatformBootTimeOutDefault;
UINT16
BdsLibGetTimeout (
VOID
)
/*++
Routine Description:
Return the default value for system Timeout variable.
Arguments:
None
Returns:
Timeout value.
--*/
{
UINT16 Timeout;
UINTN Size;
EFI_STATUS Status;
//
// Return Timeout variable or 0xffff if no valid
// Timeout variable exists.
//
Size = sizeof (UINT16);
Status = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);
if (!EFI_ERROR (Status)) {
return Timeout;
}
//
// To make the current EFI Automatic-Test activity possible, just add
// following code to make AutoBoot enabled when this variable is not
// present.
// This code should be removed later.
//
Timeout = gPlatformBootTimeOutDefault;
//
// Notes: Platform should set default variable if non exists on all error cases!!!
//
Status = gRT->SetVariable (
L"Timeout",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
sizeof (UINT16),
&Timeout
);
return Timeout;
}
VOID
BdsLibLoadDrivers (
IN EFI_LIST_ENTRY *BdsDriverLists
)
/*++
Routine Description:
The function will go through the driver optoin link list, load and start
every driver the driver optoin device path point to.
Arguments:
BdsDriverLists - The header of the current driver option link list
Returns:
None
--*/
{
EFI_STATUS Status;
EFI_LIST_ENTRY *Link;
BDS_COMMON_OPTION *Option;
EFI_HANDLE ImageHandle;
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
UINTN ExitDataSize;
CHAR16 *ExitData;
BOOLEAN ReconnectAll;
ReconnectAll = FALSE;
//
// Process the driver option
//
for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) {
Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
//
// If a load option is not marked as LOAD_OPTION_ACTIVE,
// the boot manager will not automatically load the option.
//
if (!IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_ACTIVE)) {
continue;
}
//
// If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,
// then all of the EFI drivers in the system will be disconnected and
// reconnected after the last driver load option is processed.
//
if (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) {
ReconnectAll = TRUE;
}
//
// Make sure the driver path is connected.
//
BdsLibConnectDevicePath (Option->DevicePath);
//
// Load and start the image that Driver#### describes
//
Status = gBS->LoadImage (
FALSE,
mBdsImageHandle,
Option->DevicePath,
NULL,
0,
&ImageHandle
);
if (!EFI_ERROR (Status)) {
gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, &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;
}
if (Option->LoadOptionsSize != 0) {
ImageInfo->LoadOptionsSize = Option->LoadOptionsSize;
ImageInfo->LoadOptions = Option->LoadOptions;
}
//
// Before calling the image, enable the Watchdog Timer for
// the 5 Minute period
//
gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);
DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Driver Return Status = %r\n", 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) {
BdsLibDisconnectAllEfi ();
BdsLibConnectAll ();
}
}
EFI_STATUS
BdsLibRegisterNewOption (
IN EFI_LIST_ENTRY *BdsOptionList,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN CHAR16 *String,
IN CHAR16 *VariableName
)
/*++
Routine Description:
This function will register the new boot#### or driver#### option base on
the VariableName. The new registered boot#### or driver#### will be linked
to BdsOptionList and also update to the VariableName. After the boot#### or
driver#### updated, the BootOrder or DriverOrder will also be updated.
Arguments:
BdsOptionList - The header of the boot#### or driver#### link list
DevicePath - The device path which the boot####
or driver#### option present
String - The description of the boot#### or driver####
VariableName - Indicate if the boot#### or driver#### option
Returns:
EFI_SUCCESS - The boot#### or driver#### have been success registered
EFI_STATUS - Return the status of gRT->SetVariable ().
--*/
{
EFI_STATUS Status;
UINTN Index;
UINT16 MaxOptionNumber;
UINT16 RegisterOptionNumber;
UINT16 *TempOptionPtr;
UINTN TempOptionSize;
UINT16 *OptionOrderPtr;
VOID *OptionPtr;
UINTN OptionSize;
UINT8 *TempPtr;
EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;
CHAR16 *Description;
CHAR16 OptionName[10];
BOOLEAN UpdateBootDevicePath;
OptionPtr = NULL;
OptionSize = 0;
TempPtr = NULL;
OptionDevicePath = NULL;
Description = NULL;
MaxOptionNumber = 0;
OptionOrderPtr = NULL;
UpdateBootDevicePath = FALSE;
EfiZeroMem (OptionName, sizeof (OptionName));
TempOptionSize = 0;
TempOptionPtr = BdsLibGetVariableAndSize (
VariableName,
&gEfiGlobalVariableGuid,
&TempOptionSize
);
//
// Compare with current option variable
//
for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) {
//
// Got the max option#### number
//
if (MaxOptionNumber < TempOptionPtr[Index]) {
MaxOptionNumber = TempOptionPtr[Index];
}
if (*VariableName == 'B') {
SPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]);
} else {
SPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]);
}
OptionPtr = BdsLibGetVariableAndSize (
OptionName,
&gEfiGlobalVariableGuid,
&OptionSize
);
TempPtr = OptionPtr;
TempPtr += sizeof (UINT32) + sizeof (UINT16);
Description = (CHAR16 *) TempPtr;
TempPtr += EfiStrSize ((CHAR16 *) TempPtr);
OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
//
// Notes: the description may will change base on the GetStringToken
//
if (EfiCompareMem (Description, String, EfiStrSize (Description)) == 0) {
if (EfiCompareMem (OptionDevicePath, DevicePath, EfiDevicePathSize (OptionDevicePath)) == 0) {
//
// Got the option, so just return
//
gBS->FreePool (OptionPtr);
gBS->FreePool (TempOptionPtr);
return EFI_SUCCESS;
} else {
//
// Boot device path changed, need update.
//
UpdateBootDevicePath = TRUE;
break;
}
}
gBS->FreePool (OptionPtr);
}
OptionSize = sizeof (UINT32) + sizeof (UINT16) + EfiStrSize (String) + EfiDevicePathSize (DevicePath);
OptionPtr = EfiLibAllocateZeroPool (OptionSize);
TempPtr = OptionPtr;
*(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE;
TempPtr += sizeof (UINT32);
*(UINT16 *) TempPtr = (UINT16) EfiDevicePathSize (DevicePath);
TempPtr += sizeof (UINT16);
EfiCopyMem (TempPtr, String, EfiStrSize (String));
TempPtr += EfiStrSize (String);
EfiCopyMem (TempPtr, DevicePath, EfiDevicePathSize (DevicePath));
if (UpdateBootDevicePath) {
//
// The number in option#### to be updated
//
RegisterOptionNumber = TempOptionPtr[Index];
} else {
//
// The new option#### number
//
RegisterOptionNumber = MaxOptionNumber + 1;
}
if (*VariableName == 'B') {
SPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber);
} else {
SPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber);
}
Status = gRT->SetVariable (
OptionName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
OptionSize,
OptionPtr
);
if (EFI_ERROR (Status) || UpdateBootDevicePath) {
gBS->FreePool (OptionPtr);
gBS->FreePool (TempOptionPtr);
return Status;
}
gBS->FreePool (OptionPtr);
//
// Update the option order variable
//
OptionOrderPtr = EfiLibAllocateZeroPool ((Index + 1) * sizeof (UINT16));
EfiCopyMem (OptionOrderPtr, TempOptionPtr, Index * sizeof (UINT16));
OptionOrderPtr[Index] = RegisterOptionNumber;
Status = gRT->SetVariable (
VariableName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
(Index + 1) * sizeof (UINT16),
OptionOrderPtr
);
if (EFI_ERROR (Status)) {
gBS->FreePool (TempOptionPtr);
gBS->FreePool (OptionOrderPtr);
return Status;
}
gBS->FreePool (TempOptionPtr);
gBS->FreePool (OptionOrderPtr);
return EFI_SUCCESS;
}
BDS_COMMON_OPTION *
BdsLibVariableToOption (
IN OUT EFI_LIST_ENTRY *BdsCommonOptionList,
IN CHAR16 *VariableName
)
/*++
Routine Description:
Build the boot#### or driver#### option from the VariableName, the
build boot#### or driver#### will also be linked to BdsCommonOptionList
Arguments:
BdsCommonOptionList - The header of the boot#### or driver#### option link list
VariableName - EFI Variable name indicate if it is boot#### or driver####
Returns:
BDS_COMMON_OPTION - Get the option just been created
NULL - Failed to get the new option
--*/
{
UINT32 Attribute;
UINT16 FilePathSize;
UINT8 *Variable;
UINT8 *TempPtr;
UINTN VariableSize;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
BDS_COMMON_OPTION *Option;
VOID *LoadOptions;
UINT32 LoadOptionsSize;
CHAR16 *Description;
//
// Read the variable. We will never free this data.
//
Variable = BdsLibGetVariableAndSize (
VariableName,
&gEfiGlobalVariableGuid,
&VariableSize
);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?