MdeModulePkg: Add UefiBootManagerLib

UefiBootManagerLib provides:
 load option library functions;
 hot key library functions;
 boot library functions;
 connect and disconnect library functions;
 driver health library functions.

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@17327 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Ruiyu Ni 2015-05-06 04:47:02 +00:00 committed by niruiyu
parent 58183d391c
commit 1d11222925
14 changed files with 8018 additions and 3 deletions

View File

@ -0,0 +1,657 @@
/** @file
Provide Boot Manager related library APIs.
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
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.
**/
#ifndef _UEFI_BOOT_MANAGER_LIB_H_
#define _UEFI_BOOT_MANAGER_LIB_H_
#include <Protocol/DriverHealth.h>
#include <Library/SortLib.h>
//
// Boot Manager load option library functions.
//
//
// Load Option Type
//
typedef enum {
LoadOptionTypeBoot,
LoadOptionTypeDriver,
LoadOptionTypeMax
} EFI_BOOT_MANAGER_LOAD_OPTION_TYPE;
typedef enum {
LoadOptionNumberMax = 0x10000,
LoadOptionNumberUnassigned = LoadOptionNumberMax
} EFI_BOOT_MANAGER_LOAD_OPTION_NUMBER;
//
// Common structure definition for DriverOption and BootOption
//
typedef struct {
//
// Data read from UEFI NV variables
//
UINTN OptionNumber; // #### numerical value, could be LoadOptionNumberUnassigned
EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType; // LoadOptionTypeBoot or LoadOptionTypeDriver
UINT32 Attributes; // Load Option Attributes
CHAR16 *Description; // Load Option Description
EFI_DEVICE_PATH_PROTOCOL *FilePath; // Load Option Device Path
UINT8 *OptionalData; // Load Option optional data to pass into image
UINT32 OptionalDataSize; // Load Option size of OptionalData
//
// Used at runtime
//
EFI_STATUS Status; // Status returned from boot attempt gBS->StartImage ()
CHAR16 *ExitData; // Exit data returned from gBS->StartImage ()
UINTN ExitDataSize; // Size of ExitData
} EFI_BOOT_MANAGER_LOAD_OPTION;
/**
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.
#### is the hex value of the UINT16 in each BootOrder/DriverOrder entry.
@param LoadOptionCount Returns number of entries in the array.
@param LoadOptionType The type of the load option.
@retval NULL No load options exist.
@retval !NULL Array of load option entries.
**/
EFI_BOOT_MANAGER_LOAD_OPTION *
EFIAPI
EfiBootManagerGetLoadOptions (
OUT UINTN *LoadOptionCount,
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType
);
/**
Free an array of load options returned from EfiBootManagerGetLoadOptions().
@param LoadOptions Pointer to the array of load options to free.
@param LoadOptionCount Number of array entries in LoadOptions.
@return EFI_SUCCESS LoadOptions was freed.
@return EFI_INVALID_PARAMETER LoadOptions is NULL.
**/
EFI_STATUS
EFIAPI
EfiBootManagerFreeLoadOptions (
IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOptions,
IN UINTN LoadOptionCount
);
/**
Initialize a load option.
@param Option Pointer to the load option to be initialized.
@param OptionNumber Option number of the load option.
@param OptionType Type of the load option.
@param Attributes Attributes of the load option.
@param Description Description of the load option.
@param FilePath Device path of the load option.
@param OptionalData Optional data of the load option.
@param OptionalDataSize Size of the optional data of the load option.
@retval EFI_SUCCESS The load option was initialized successfully.
@retval EFI_INVALID_PARAMETER Option, Description or FilePath is NULL.
**/
EFI_STATUS
EFIAPI
EfiBootManagerInitializeLoadOption (
IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option,
IN UINTN OptionNumber,
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
IN UINT32 Attributes,
IN CHAR16 *Description,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
IN UINT8 *OptionalData,
IN UINT32 OptionalDataSize
);
/**
Free a load option created by EfiBootManagerInitializeLoadOption()
or EfiBootManagerVariableToLoadOption().
@param LoadOption Pointer to the load option to free.
CONCERN: Check Boot#### instead of BootOrder, optimize, spec clarify
@return EFI_SUCCESS LoadOption was freed.
@return EFI_INVALID_PARAMETER LoadOption is NULL.
**/
EFI_STATUS
EFIAPI
EfiBootManagerFreeLoadOption (
IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
);
/**
Initialize the load option from the VariableName.
@param VariableName EFI Variable name which could be Boot#### or
Driver####
@param LoadOption Pointer to the load option to be initialized
@retval EFI_SUCCESS The option was created
@retval EFI_INVALID_PARAMETER VariableName or LoadOption is NULL.
@retval EFI_NOT_FOUND The variable specified by VariableName cannot be found.
**/
EFI_STATUS
EFIAPI
EfiBootManagerVariableToLoadOption (
IN CHAR16 *VariableName,
IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
);
/**
Create the Boot#### or Driver#### 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 *LoadOption
);
/**
This function will update the Boot####/Driver#### and the BootOrder/DriverOrder
to add a new load option.
@param Option Pointer to load option to add.
@param Position Position of the new load option to put in the BootOrder/DriverOrder.
@retval EFI_SUCCESS The load option has been successfully added.
@retval Others Error status returned by RT->SetVariable.
**/
EFI_STATUS
EFIAPI
EfiBootManagerAddLoadOptionVariable (
IN EFI_BOOT_MANAGER_LOAD_OPTION *Option,
IN UINTN Position
);
/**
Delete the load option according to the OptionNumber and OptionType.
Only the BootOrder/DriverOrder is updated to remove the reference of the OptionNumber.
@param OptionNumber Option number of the load option.
@param OptionType Type of the load option.
@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
);
/**
Sort the load options. The DriverOrder/BootOrder variables will be re-created to
reflect the new order.
@param OptionType The type of the load option.
@param Comparator The comparator function pointer.
**/
VOID
EFIAPI
EfiBootManagerSortLoadOptionVariable (
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
IN SORT_COMPARE CompareFunction
);
//
// Boot Manager hot key library functions.
//
#pragma pack(1)
///
/// EFI Key Option.
///
typedef struct {
///
/// Specifies options about how the key will be processed.
///
EFI_BOOT_KEY_DATA KeyData;
///
/// The CRC-32 which should match the CRC-32 of the entire EFI_LOAD_OPTION to
/// which BootOption refers. If the CRC-32s do not match this value, then this key
/// option is ignored.
///
UINT32 BootOptionCrc;
///
/// The Boot#### option which will be invoked if this key is pressed and the boot option
/// is active (LOAD_OPTION_ACTIVE is set).
///
UINT16 BootOption;
///
/// The key codes to compare against those returned by the
/// EFI_SIMPLE_TEXT_INPUT and EFI_SIMPLE_TEXT_INPUT_EX protocols.
/// The number of key codes (0-3) is specified by the EFI_KEY_CODE_COUNT field in KeyOptions.
///
EFI_INPUT_KEY Keys[3];
UINT16 OptionNumber;
} EFI_BOOT_MANAGER_KEY_OPTION;
#pragma pack()
/**
Start the hot key service so that the key press can trigger the boot option.
@param HotkeyTriggered Return the waitable event and it will be signaled
when a valid hot key is pressed.
@retval EFI_SUCCESS The hot key service is started.
**/
EFI_STATUS
EFIAPI
EfiBootManagerStartHotkeyService (
IN EFI_EVENT *HotkeyTriggered
);
//
// Modifier for EfiBootManagerAddKeyOptionVariable and EfiBootManagerDeleteKeyOptionVariable
//
#define EFI_BOOT_MANAGER_SHIFT_PRESSED 0x00000001
#define EFI_BOOT_MANAGER_CONTROL_PRESSED 0x00000002
#define EFI_BOOT_MANAGER_ALT_PRESSED 0x00000004
#define EFI_BOOT_MANAGER_LOGO_PRESSED 0x00000008
#define EFI_BOOT_MANAGER_MENU_KEY_PRESSED 0x00000010
#define EFI_BOOT_MANAGER_SYS_REQ_PRESSED 0x00000020
/**
Add the key option.
It adds the key option variable and the key option takes affect immediately.
@param AddedOption Return the added key option.
@param BootOptionNumber The boot option number for the key option.
@param Modifier Key shift state.
@param ... Parameter list of pointer of EFI_INPUT_KEY.
@retval EFI_SUCCESS The key option is added.
@retval EFI_ALREADY_STARTED The hot key is already used by certain key option.
**/
EFI_STATUS
EFIAPI
EfiBootManagerAddKeyOptionVariable (
OUT EFI_BOOT_MANAGER_KEY_OPTION *AddedOption, OPTIONAL
IN UINT16 BootOptionNumber,
IN UINT32 Modifier,
...
);
/**
Delete the Key Option variable and unregister the hot key
@param DeletedOption Return the deleted key options.
@param Modifier Key shift state.
@param ... Parameter list of pointer of EFI_INPUT_KEY.
@retval EFI_SUCCESS The key option is deleted.
@retval EFI_NOT_FOUND The key option cannot be found.
**/
EFI_STATUS
EFIAPI
EfiBootManagerDeleteKeyOptionVariable (
IN EFI_BOOT_MANAGER_KEY_OPTION *DeletedOption, OPTIONAL
IN UINT32 Modifier,
...
);
/**
Register the key option to exit the waiting of the Boot Manager timeout.
Platform should ensure that the continue key option isn't conflict with
other boot key options.
@param Modifier Key shift state.
@param ... Parameter list of pointer of EFI_INPUT_KEY.
@retval EFI_SUCCESS Successfully register the continue key option.
@retval EFI_ALREADY_STARTED The continue key option is already registered.
**/
EFI_STATUS
EFIAPI
EfiBootManagerRegisterContinueKeyOption (
IN UINT32 Modifier,
...
);
/**
Try to boot the boot option triggered by hot key.
**/
VOID
EFIAPI
EfiBootManagerHotkeyBoot (
VOID
);
//
// Boot Manager boot library functions.
//
/**
The function creates boot options for all possible bootable medias in the following order:
1. Removable BlockIo - The boot option only points to the removable media
device, like USB key, DVD, Floppy etc.
2. Fixed BlockIo - The boot option only points to a Fixed blockIo device,
like HardDisk.
3. Non-BlockIo SimpleFileSystem - The boot option points to a device supporting
SimpleFileSystem Protocol, but not supporting BlockIo
protocol.
4. LoadFile - The boot option points to the media supporting
LoadFile protocol.
Reference: UEFI Spec chapter 3.3 Boot Option Variables Default Boot Behavior
The function won't delete the boot option not added by itself.
**/
VOID
EFIAPI
EfiBootManagerRefreshAllBootOption (
VOID
);
/**
Attempt to boot the EFI boot option. This routine sets L"BootCurent" and
signals the EFI ready to boot event. If the device path for the option starts
with a BBS device path a legacy boot is attempted. Short form device paths are
also supported via this rountine. A device path starting with
MEDIA_HARDDRIVE_DP, MSG_USB_WWID_DP, MSG_USB_CLASS_DP gets expaned out
to find the first device that matches. If the BootOption Device Path
fails the removable media boot algorithm is attempted (\EFI\BOOTIA32.EFI,
\EFI\BOOTX64.EFI,... only one file type is tried per processor type)
@param BootOption Boot Option to try and boot.
On return, BootOption->Status contains the boot status:
EFI_SUCCESS BootOption was booted
EFI_UNSUPPORTED BootOption isn't supported.
EFI_NOT_FOUND The BootOption was not found on the system
Others BootOption failed with this error status
**/
VOID
EFIAPI
EfiBootManagerBoot (
IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
);
/**
Return the Boot Manager Menu.
@param BootOption Return the Boot Manager Menu.
@retval EFI_SUCCESS The Boot Manager Menu is successfully returned.
@retval EFI_NOT_FOUND The Boot Manager Menu is not found.
**/
EFI_STATUS
EFIAPI
EfiBootManagerGetBootManagerMenu (
EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
);
/**
The function enumerates all the legacy boot options, creates them and
registers them in the BootOrder variable.
**/
typedef
VOID
(EFIAPI *EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION) (
VOID
);
/**
The function boots a legacy boot option.
**/
typedef
VOID
(EFIAPI *EFI_BOOT_MANAGER_LEGACY_BOOT) (
IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
);
/**
The function registers the legacy boot support capabilities.
@param RefreshLegacyBootOption The function pointer to create all the legacy boot options.
@param LegacyBoot The function pointer to boot the legacy boot option.
**/
VOID
EFIAPI
EfiBootManagerRegisterLegacyBootSupport (
EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION RefreshLegacyBootOption,
EFI_BOOT_MANAGER_LEGACY_BOOT LegacyBoot
);
//
// Boot Manager connect and disconnect library functions
//
/**
This function will connect all the system driver to controller
first, and then special connect the default console, this make
sure all the system controller available and the platform default
console connected.
**/
VOID
EFIAPI
EfiBootManagerConnectAll (
VOID
);
/**
This function will create all handles associate with every device
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,
which load the missing drivers if possible.
@param DevicePathToConnect The device path which will be connected, it CANNOT be
a multi-instance device path
@param MatchingHandle Return the controller handle closest to the DevicePathToConnect
@retval EFI_INVALID_PARAMETER DevicePathToConnect is NULL.
@retval EFI_NOT_FOUND Failed to create all handles associate with every device path node.
@retval EFI_SUCCESS Successful to create all handles associate with every device path node.
**/
EFI_STATUS
EFIAPI
EfiBootManagerConnectDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect,
OUT EFI_HANDLE *MatchingHandle OPTIONAL
);
/**
This function will disconnect all current system handles.
gBS->DisconnectController() is invoked for each handle exists in system handle buffer.
If handle is a bus type handle, all childrens also are disconnected recursively by
gBS->DisconnectController().
**/
VOID
EFIAPI
EfiBootManagerDisconnectAll (
VOID
);
//
// Boot Manager console library functions
//
typedef enum {
ConIn,
ConOut,
ErrOut,
ConInDev,
ConOutDev,
ErrOutDev,
ConsoleTypeMax
} CONSOLE_TYPE;
/**
This function will connect all the console devices base on the console
device variable ConIn, ConOut and ErrOut.
**/
VOID
EFIAPI
EfiBootManagerConnectAllDefaultConsoles (
VOID
);
/**
This function updates the console variable based on ConVarName. It can
add or remove one specific console device path from the variable
@param ConsoleType ConIn, ConOut, ErrOut, ConInDev, ConOutDev or ErrOutDev.
@param CustomizedConDevicePath The console device path to be added to
the console variable. Cannot be multi-instance.
@param ExclusiveDevicePath The console device path to be removed
from the console variable. Cannot be multi-instance.
@retval EFI_UNSUPPORTED The added device path is the same as a removed one.
@retval EFI_SUCCESS Successfully added or removed the device path from the
console variable.
**/
EFI_STATUS
EFIAPI
EfiBootManagerUpdateConsoleVariable (
IN CONSOLE_TYPE ConsoleType,
IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,
IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath
);
/**
Connect the console device base on the variable ConVarName, if
device path of the ConVarName is multi-instance device path, if
anyone of the instances is connected success, then this function
will return success.
@param ConsoleType ConIn, ConOut or ErrOut.
@retval EFI_NOT_FOUND There is not any console devices connected
success
@retval EFI_SUCCESS Success connect any one instance of the console
device path base on the variable ConVarName.
**/
EFI_STATUS
EFIAPI
EfiBootManagerConnectConsoleVariable (
IN CONSOLE_TYPE ConsoleType
);
/**
Query all the children of VideoController and return the device paths of all the
children that support GraphicsOutput protocol.
@param VideoController PCI handle of video controller.
@return Device paths of all the children that support GraphicsOutput protocol.
**/
EFI_DEVICE_PATH_PROTOCOL *
EFIAPI
EfiBootManagerGetGopDevicePath (
IN EFI_HANDLE VideoController
);
/**
Connect the platform active active video controller.
@param VideoController PCI handle of video controller.
@retval EFI_NOT_FOUND There is no active video controller.
@retval EFI_SUCCESS The video controller is connected.
**/
EFI_STATUS
EFIAPI
EfiBootManagerConnectVideoController (
EFI_HANDLE VideoController OPTIONAL
);
//
// Boot Manager driver health library functions.
//
typedef struct {
EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;
///
/// Driver relative handles
///
EFI_HANDLE DriverHealthHandle;
EFI_HANDLE ControllerHandle;
EFI_HANDLE ChildHandle;
///
/// Driver health messages of the specify Driver
///
EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList;
///
/// HII relative handles
///
EFI_HII_HANDLE HiiHandle;
///
/// Driver Health status
///
EFI_DRIVER_HEALTH_STATUS HealthStatus;
} EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO;
/**
Return all the Driver Health information.
When the cumulative health status of all the controllers managed by the
driver who produces the EFI_DRIVER_HEALTH_PROTOCOL is healthy, only one
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry is created for such
EFI_DRIVER_HEALTH_PROTOCOL instance.
Otherwise, every controller creates one EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO
entry. Additionally every child controller creates one
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry if the driver is a bus driver.
@param Count Return the count of the Driver Health information.
@retval NULL No Driver Health information is returned.
@retval !NULL Pointer to the Driver Health information array.
**/
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *
EFIAPI
EfiBootManagerGetDriverHealthInfo (
UINTN *Count
);
/**
Free the Driver Health information array.
@param DriverHealthInfo Pointer to array of the Driver Health information.
@param Count Count of the array.
@retval EFI_SUCCESS The array is freed.
@retval EFI_INVALID_PARAMETER The array is NULL.
**/
EFI_STATUS
EFIAPI
EfiBootManagerFreeDriverHealthInfo (
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo,
UINTN Count
);
#endif

View File

@ -1,7 +1,7 @@
## @file
# Library used for sorting routines.
#
# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved. <BR>
# Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved. <BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@ -19,7 +19,7 @@
FILE_GUID = 03F3331B-F12D-494f-BF37-E55A657F2497
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = SortLib|UEFI_APPLICATION UEFI_DRIVER
LIBRARY_CLASS = SortLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,318 @@
/** @file
Library functions which relate with connecting the device.
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "InternalBm.h"
/**
Connect all the drivers to all the controllers.
This function makes sure all the current system drivers manage the correspoinding
controllers if have. And at the same time, makes sure all the system controllers
have driver to manage it if have.
**/
VOID
BmConnectAllDriversToAllControllers (
VOID
)
{
EFI_STATUS Status;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
UINTN Index;
do {
//
// Connect All EFI 1.10 drivers following EFI 1.10 algorithm
//
gBS->LocateHandleBuffer (
AllHandles,
NULL,
NULL,
&HandleCount,
&HandleBuffer
);
for (Index = 0; Index < HandleCount; Index++) {
gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
}
if (HandleBuffer != NULL) {
FreePool (HandleBuffer);
}
//
// Check to see if it's possible to dispatch an more DXE drivers.
// The above code may have made new DXE drivers show up.
// If any new driver is dispatched (Status == EFI_SUCCESS) and we will try
// the connect again.
//
Status = gDS->Dispatch ();
} while (!EFI_ERROR (Status));
}
/**
This function will connect all the system driver to controller
first, and then special connect the default console, this make
sure all the system controller available and the platform default
console connected.
**/
VOID
EFIAPI
EfiBootManagerConnectAll (
VOID
)
{
//
// Connect the platform console first
//
EfiBootManagerConnectAllDefaultConsoles ();
//
// Generic way to connect all the drivers
//
BmConnectAllDriversToAllControllers ();
//
// Here we have the assumption that we have already had
// platform default console
//
EfiBootManagerConnectAllDefaultConsoles ();
}
/**
This function will create all handles associate with every device
path node. If the handle associate with one device path node can not
be created successfully, then still give chance to do the dispatch,
which load the missing drivers if possible.
@param DevicePathToConnect The device path which will be connected, it can be
a multi-instance device path
@param MatchingHandle Return the controller handle closest to the DevicePathToConnect
@retval EFI_SUCCESS All handles associate with every device path node
have been created
@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
**/
EFI_STATUS
EFIAPI
EfiBootManagerConnectDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect,
OUT EFI_HANDLE *MatchingHandle OPTIONAL
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
EFI_HANDLE Handle;
EFI_HANDLE PreviousHandle;
EFI_TPL CurrentTpl;
if (DevicePathToConnect == NULL) {
return EFI_INVALID_PARAMETER;
}
CurrentTpl = EfiGetCurrentTpl ();
//
// Start the real work of connect with RemainingDevicePath
//
PreviousHandle = NULL;
do {
//
// Find the handle that best matches the Device Path. If it is only a
// partial match the remaining part of the device path is returned in
// RemainingDevicePath.
//
RemainingDevicePath = DevicePathToConnect;
Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
if (!EFI_ERROR (Status)) {
if (Handle == PreviousHandle) {
//
// If no forward progress is made try invoking the Dispatcher.
// A new FV may have been added to the system an new drivers
// may now be found.
// Status == EFI_SUCCESS means a driver was dispatched
// Status == EFI_NOT_FOUND means no new drivers were dispatched
//
if (CurrentTpl == TPL_APPLICATION) {
Status = gDS->Dispatch ();
} else {
//
// Always return EFI_NOT_FOUND here
// to prevent dead loop when control handle is found but connection failded case
//
Status = EFI_NOT_FOUND;
}
}
if (!EFI_ERROR (Status)) {
PreviousHandle = Handle;
//
// Connect all drivers that apply to Handle and RemainingDevicePath,
// the Recursive flag is FALSE so only one level will be expanded.
//
// Do not check the connect status here, if the connect controller fail,
// then still give the chance to do dispatch, because partial
// RemainingDevicepath may be in the new FV
//
// 1. If the connect fail, RemainingDevicepath and handle will not
// change, so next time will do the dispatch, then dispatch's status
// will take effect
// 2. If the connect success, the RemainingDevicepath and handle will
// change, then avoid the dispatch, we have chance to continue the
// next connection
//
gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
if (MatchingHandle != NULL) {
*MatchingHandle = Handle;
}
}
}
//
// Loop until RemainingDevicePath is an empty device path
//
} while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
ASSERT (EFI_ERROR (Status) || IsDevicePathEnd (RemainingDevicePath));
return Status;
}
/**
This function will disconnect all current system handles.
gBS->DisconnectController() is invoked for each handle exists in system handle buffer.
If handle is a bus type handle, all childrens also are disconnected recursively by
gBS->DisconnectController().
**/
VOID
EFIAPI
EfiBootManagerDisconnectAll (
VOID
)
{
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
UINTN Index;
//
// Disconnect all
//
gBS->LocateHandleBuffer (
AllHandles,
NULL,
NULL,
&HandleCount,
&HandleBuffer
);
for (Index = 0; Index < HandleCount; Index++) {
gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
}
if (HandleBuffer != NULL) {
FreePool (HandleBuffer);
}
}
/**
Connect the specific Usb device which match the short form device path,
and whose bus is determined by Host Controller (Uhci or Ehci).
@param DevicePath A short-form device path that starts with the first
element being a USB WWID or a USB Class device
path
@return EFI_INVALID_PARAMETER DevicePath is NULL pointer.
DevicePath is not a USB device path.
@return EFI_SUCCESS Success to connect USB device
@return EFI_NOT_FOUND Fail to find handle for USB controller to connect.
**/
EFI_STATUS
BmConnectUsbShortFormDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
EFI_STATUS Status;
EFI_HANDLE *Handles;
UINTN HandleCount;
UINTN Index;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT8 Class[3];
BOOLEAN AtLeastOneConnected;
//
// Check the passed in parameters
//
if (DevicePath == NULL) {
return EFI_INVALID_PARAMETER;
}
if ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||
((DevicePathSubType (DevicePath) != MSG_USB_CLASS_DP) && (DevicePathSubType (DevicePath) != MSG_USB_WWID_DP))
) {
return EFI_INVALID_PARAMETER;
}
//
// Find the usb host controller firstly, then connect with the remaining device path
//
AtLeastOneConnected = FALSE;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiPciIoProtocolGuid,
NULL,
&HandleCount,
&Handles
);
if (!EFI_ERROR (Status)) {
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (
Handles[Index],
&gEfiPciIoProtocolGuid,
(VOID **) &PciIo
);
if (!EFI_ERROR (Status)) {
//
// Check whether the Pci device is the wanted usb host controller
//
Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
if (!EFI_ERROR (Status) &&
((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))
) {
Status = gBS->ConnectController (
Handles[Index],
NULL,
DevicePath,
FALSE
);
if (!EFI_ERROR(Status)) {
AtLeastOneConnected = TRUE;
}
}
}
}
if (Handles != NULL) {
FreePool (Handles);
}
}
return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;
}

View File

@ -0,0 +1,748 @@
/** @file
Library functions which contain all the code to connect console device.
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "InternalBm.h"
CHAR16 *mConVarName[] = {
L"ConIn",
L"ConOut",
L"ErrOut",
L"ConInDev",
L"ConOutDev",
L"ErrOutDev"
};
/**
Search out the video controller.
@return PCI device path of the video controller.
**/
EFI_HANDLE
BmGetVideoController (
VOID
)
{
EFI_STATUS Status;
UINTN RootBridgeHandleCount;
EFI_HANDLE *RootBridgeHandleBuffer;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
UINTN RootBridgeIndex;
UINTN Index;
EFI_HANDLE VideoController;
EFI_PCI_IO_PROTOCOL *PciIo;
PCI_TYPE00 Pci;
//
// Make all the PCI_IO protocols show up
//
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiPciRootBridgeIoProtocolGuid,
NULL,
&RootBridgeHandleCount,
&RootBridgeHandleBuffer
);
if (EFI_ERROR (Status) || (RootBridgeHandleCount == 0)) {
return NULL;
}
VideoController = NULL;
for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {
gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);
//
// Start to check all the pci io to find the first video controller
//
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiPciIoProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
if (EFI_ERROR (Status)) {
continue;
}
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
if (!EFI_ERROR (Status)) {
//
// Check for all video controller
//
Status = PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint32,
0,
sizeof (Pci) / sizeof (UINT32),
&Pci
);
if (!EFI_ERROR (Status) && IS_PCI_VGA (&Pci)) {
// TODO: use IS_PCI_DISPLAY??
VideoController = HandleBuffer[Index];
break;
}
}
}
FreePool (HandleBuffer);
if (VideoController != NULL) {
break;
}
}
FreePool (RootBridgeHandleBuffer);
return VideoController;
}
/**
Query all the children of VideoController and return the device paths of all the
children that support GraphicsOutput protocol.
@param VideoController PCI handle of video controller.
@return Device paths of all the children that support GraphicsOutput protocol.
**/
EFI_DEVICE_PATH_PROTOCOL *
EFIAPI
EfiBootManagerGetGopDevicePath (
IN EFI_HANDLE VideoController
)
{
UINTN Index;
EFI_STATUS Status;
EFI_GUID **ProtocolBuffer;
UINTN ProtocolBufferCount;
UINTN ProtocolIndex;
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
UINTN EntryCount;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_DEVICE_PATH_PROTOCOL *Next;
EFI_DEVICE_PATH_PROTOCOL *Previous;
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
EFI_DEVICE_PATH_PROTOCOL *GopPool;
EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;
Status = gBS->ProtocolsPerHandle (
VideoController,
&ProtocolBuffer,
&ProtocolBufferCount
);
if (EFI_ERROR (Status)) {
return NULL;
}
GopPool = NULL;
for (ProtocolIndex = 0; ProtocolIndex < ProtocolBufferCount; ProtocolIndex++) {
Status = gBS->OpenProtocolInformation (
VideoController,
ProtocolBuffer[ProtocolIndex],
&OpenInfoBuffer,
&EntryCount
);
if (EFI_ERROR (Status)) {
continue;
}
for (Index = 0; Index < EntryCount; Index++) {
//
// Query all the children
//
if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
Status = gBS->OpenProtocol (
OpenInfoBuffer[Index].ControllerHandle,
&gEfiDevicePathProtocolGuid,
(VOID **) &DevicePath,
NULL,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
continue;
}
Previous = NULL;
for (Next = DevicePath; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {
Previous = Next;
}
ASSERT (Previous != NULL);
if (DevicePathType (Previous) == ACPI_DEVICE_PATH && DevicePathSubType (Previous) == ACPI_ADR_DP) {
Status = gBS->OpenProtocol (
OpenInfoBuffer[Index].ControllerHandle,
&gEfiGraphicsOutputProtocolGuid,
NULL,
NULL,
NULL,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (!EFI_ERROR (Status)) {
//
// Append the device path to GOP pool when there is GOP protocol installed.
//
TempDevicePath = GopPool;
GopPool = AppendDevicePathInstance (GopPool, DevicePath);
gBS->FreePool (TempDevicePath);
}
}
if (DevicePathType (Previous) == HARDWARE_DEVICE_PATH && DevicePathSubType (Previous) == HW_CONTROLLER_DP) {
//
// Recursively look for GOP child in this frame buffer handle
//
DEBUG ((EFI_D_INFO, "[Bds] Looking for GOP child deeper ... \n"));
TempDevicePath = GopPool;
ReturnDevicePath = EfiBootManagerGetGopDevicePath (OpenInfoBuffer[Index].ControllerHandle);
GopPool = AppendDevicePathInstance (GopPool, ReturnDevicePath);
gBS->FreePool (ReturnDevicePath);
gBS->FreePool (TempDevicePath);
}
}
}
FreePool (OpenInfoBuffer);
}
FreePool (ProtocolBuffer);
return GopPool;
}
/**
Connect the platform active active video controller.
@param VideoController PCI handle of video controller.
@retval EFI_NOT_FOUND There is no active video controller.
@retval EFI_SUCCESS The video controller is connected.
**/
EFI_STATUS
EFIAPI
EfiBootManagerConnectVideoController (
EFI_HANDLE VideoController OPTIONAL
)
{
EFI_DEVICE_PATH_PROTOCOL *Gop;
if (VideoController == NULL) {
//
// Get the platform vga device
//
VideoController = BmGetVideoController ();
}
if (VideoController == NULL) {
return EFI_NOT_FOUND;
}
//
// Try to connect the PCI device path, so that GOP dirver could start on this
// device and create child handles with GraphicsOutput Protocol installed
// on them, then we get device paths of these child handles and select
// them as possible console device.
//
gBS->ConnectController (VideoController, NULL, NULL, FALSE);
Gop = EfiBootManagerGetGopDevicePath (VideoController);
if (Gop == NULL) {
return EFI_NOT_FOUND;
}
EfiBootManagerUpdateConsoleVariable (ConOut, Gop, NULL);
FreePool (Gop);
//
// Necessary for ConPlatform and ConSplitter driver to start up again after ConOut is updated.
//
return gBS->ConnectController (VideoController, NULL, NULL, TRUE);
}
/**
Fill console handle in System Table if there are no valid console handle in.
Firstly, check the validation of console handle in System Table. If it is invalid,
update it by the first console device handle from EFI console variable.
@param VarName The name of the EFI console variable.
@param ConsoleGuid Specified Console protocol GUID.
@param ConsoleHandle On IN, console handle in System Table to be checked.
On OUT, new console handle in system table.
@param ProtocolInterface On IN, console protocol on console handle in System Table to be checked.
On OUT, new console protocol on new console handle in system table.
@retval TRUE System Table has been updated.
@retval FALSE System Table hasn't been updated.
**/
BOOLEAN
BmUpdateSystemTableConsole (
IN CHAR16 *VarName,
IN EFI_GUID *ConsoleGuid,
IN OUT EFI_HANDLE *ConsoleHandle,
IN OUT VOID **ProtocolInterface
)
{
EFI_STATUS Status;
UINTN DevicePathSize;
EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;
EFI_DEVICE_PATH_PROTOCOL *VarConsole;
EFI_DEVICE_PATH_PROTOCOL *Instance;
VOID *Interface;
EFI_HANDLE NewHandle;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
ASSERT (VarName != NULL);
ASSERT (ConsoleHandle != NULL);
ASSERT (ConsoleGuid != NULL);
ASSERT (ProtocolInterface != NULL);
if (*ConsoleHandle != NULL) {
Status = gBS->HandleProtocol (
*ConsoleHandle,
ConsoleGuid,
&Interface
);
if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) {
//
// If ConsoleHandle is valid and console protocol on this handle also
// also matched, just return.
//
return FALSE;
}
}
//
// Get all possible consoles device path from EFI variable
//
GetEfiGlobalVariable2 (VarName, (VOID **) &VarConsole, NULL);
if (VarConsole == NULL) {
//
// If there is no any console device, just return.
//
return FALSE;
}
FullDevicePath = VarConsole;
do {
//
// Check every instance of the console variable
//
Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);
if (Instance == NULL) {
DEBUG ((EFI_D_ERROR, "[Bds] No valid console instance is found for %s!\n", VarName));
// We should not ASSERT when all the console devices are removed.
// ASSERT_EFI_ERROR (EFI_NOT_FOUND);
FreePool (FullDevicePath);
return FALSE;
}
//
// Find console device handle by device path instance
//
Status = gBS->LocateDevicePath (
ConsoleGuid,
&Instance,
&NewHandle
);
if (!EFI_ERROR (Status)) {
//
// Get the console protocol on this console device handle
//
Status = gBS->HandleProtocol (
NewHandle,
ConsoleGuid,
&Interface
);
if (!EFI_ERROR (Status)) {
//
// Update new console handle in System Table.
//
*ConsoleHandle = NewHandle;
*ProtocolInterface = Interface;
if (CompareGuid (ConsoleGuid, &gEfiSimpleTextOutProtocolGuid)) {
//
// If it is console out device, set console mode 80x25 if current mode is invalid.
//
TextOut = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *) Interface;
if (TextOut->Mode->Mode == -1) {
TextOut->SetMode (TextOut, 0);
}
}
return TRUE;
}
}
} while (Instance != NULL);
//
// No any available console devcie found.
//
return FALSE;
}
/**
This function updates the console variable based on ConVarName. It can
add or remove one specific console device path from the variable
@param ConsoleType ConIn, ConOut, ErrOut, ConInDev, ConOutDev or ErrOutDev.
@param CustomizedConDevicePath The console device path to be added to
the console variable. Cannot be multi-instance.
@param ExclusiveDevicePath The console device path to be removed
from the console variable. Cannot be multi-instance.
@retval EFI_UNSUPPORTED The added device path is the same as a removed one.
@retval EFI_SUCCESS Successfully added or removed the device path from the
console variable.
@retval others Return status of RT->SetVariable().
**/
EFI_STATUS
EFIAPI
EfiBootManagerUpdateConsoleVariable (
IN CONSOLE_TYPE ConsoleType,
IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,
IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *VarConsole;
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
if (ConsoleType >= sizeof (mConVarName) / sizeof (mConVarName[0])) {
return EFI_INVALID_PARAMETER;
}
//
// Notes: check the device path point, here should check
// with compare memory
//
if (CustomizedConDevicePath == ExclusiveDevicePath) {
return EFI_UNSUPPORTED;
}
//
// Delete the ExclusiveDevicePath from current default console
//
GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **) &VarConsole, NULL);
//
// Initialize NewDevicePath
//
NewDevicePath = VarConsole;
//
// If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.
// In the end, NewDevicePath is the final device path.
//
if (ExclusiveDevicePath != NULL && VarConsole != NULL) {
NewDevicePath = BmDelPartMatchInstance (VarConsole, ExclusiveDevicePath);
}
//
// Try to append customized device path to NewDevicePath.
//
if (CustomizedConDevicePath != NULL) {
if (!BmMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {
//
// Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.
//
NewDevicePath = BmDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);
//
// In the first check, the default console variable will be _ModuleEntryPoint,
// just append current customized device path
//
TempNewDevicePath = NewDevicePath;
NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);
if (TempNewDevicePath != NULL) {
FreePool(TempNewDevicePath);
}
}
}
//
// Finally, Update the variable of the default console by NewDevicePath
//
Status = gRT->SetVariable (
mConVarName[ConsoleType],
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
| ((ConsoleType < ConInDev) ? EFI_VARIABLE_NON_VOLATILE : 0),
GetDevicePathSize (NewDevicePath),
NewDevicePath
);
if (VarConsole == NewDevicePath) {
if (VarConsole != NULL) {
FreePool(VarConsole);
}
} else {
if (VarConsole != NULL) {
FreePool(VarConsole);
}
if (NewDevicePath != NULL) {
FreePool(NewDevicePath);
}
}
return Status;
}
/**
Connect the console device base on the variable ConsoleType.
@param ConsoleType ConIn, ConOut or ErrOut.
@retval EFI_NOT_FOUND There is not any console devices connected
success
@retval EFI_SUCCESS Success connect any one instance of the console
device path base on the variable ConVarName.
**/
EFI_STATUS
EFIAPI
EfiBootManagerConnectConsoleVariable (
IN CONSOLE_TYPE ConsoleType
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;
EFI_DEVICE_PATH_PROTOCOL *Instance;
EFI_DEVICE_PATH_PROTOCOL *Next;
EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;
UINTN Size;
BOOLEAN DeviceExist;
EFI_HANDLE Handle;
if ((ConsoleType != ConIn) && (ConsoleType != ConOut) && (ConsoleType != ErrOut)) {
return EFI_INVALID_PARAMETER;
}
Status = EFI_SUCCESS;
DeviceExist = FALSE;
Handle = NULL;
//
// Check if the console variable exist
//
GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **) &StartDevicePath, NULL);
if (StartDevicePath == NULL) {
return EFI_UNSUPPORTED;
}
CopyOfDevicePath = StartDevicePath;
do {
//
// Check every instance of the console variable
//
Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);
if (Instance == NULL) {
FreePool (StartDevicePath);
return EFI_UNSUPPORTED;
}
Next = Instance;
while (!IsDevicePathEndType (Next)) {
Next = NextDevicePathNode (Next);
}
SetDevicePathEndNode (Next);
//
// Connect the USB console
// USB console device path is a short-form device path that
// starts with the first element being a USB WWID
// or a USB Class device path
//
if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&
((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) || (DevicePathSubType (Instance) == MSG_USB_WWID_DP))
) {
Status = BmConnectUsbShortFormDevicePath (Instance);
if (!EFI_ERROR (Status)) {
DeviceExist = TRUE;
}
} else {
for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {
if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) {
break;
} else if (DevicePathType (Next) == HARDWARE_DEVICE_PATH &&
DevicePathSubType (Next) == HW_CONTROLLER_DP &&
DevicePathType (NextDevicePathNode (Next)) == ACPI_DEVICE_PATH &&
DevicePathSubType (NextDevicePathNode (Next)) == ACPI_ADR_DP
) {
break;
}
}
if (!IsDevicePathEnd (Next)) {
//
// For GOP device path, start the video driver with NULL remaining device path
//
SetDevicePathEndNode (Next);
Status = EfiBootManagerConnectDevicePath (Instance, &Handle);
if (!EFI_ERROR (Status)) {
gBS->ConnectController (Handle, NULL, NULL, TRUE);
}
} else {
Status = EfiBootManagerConnectDevicePath (Instance, NULL);
}
if (EFI_ERROR (Status)) {
//
// Delete the instance from the console varialbe
//
EfiBootManagerUpdateConsoleVariable (ConsoleType, NULL, Instance);
} else {
DeviceExist = TRUE;
}
}
FreePool(Instance);
} while (CopyOfDevicePath != NULL);
FreePool (StartDevicePath);
if (!DeviceExist) {
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
/**
This function will search every input/output device in current system,
and make every input/output device as potential console device.
**/
VOID
EFIAPI
EfiBootManagerConnectAllConsoles (
VOID
)
{
UINTN Index;
EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
Index = 0;
HandleCount = 0;
HandleBuffer = NULL;
ConDevicePath = NULL;
//
// Update all the console variables
//
gBS->LocateHandleBuffer (
ByProtocol,
&gEfiSimpleTextInProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
for (Index = 0; Index < HandleCount; Index++) {
gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiDevicePathProtocolGuid,
(VOID **) &ConDevicePath
);
EfiBootManagerUpdateConsoleVariable (ConIn, ConDevicePath, NULL);
}
if (HandleBuffer != NULL) {
FreePool(HandleBuffer);
HandleBuffer = NULL;
}
gBS->LocateHandleBuffer (
ByProtocol,
&gEfiSimpleTextOutProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
for (Index = 0; Index < HandleCount; Index++) {
gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiDevicePathProtocolGuid,
(VOID **) &ConDevicePath
);
EfiBootManagerUpdateConsoleVariable (ConOut, ConDevicePath, NULL);
EfiBootManagerUpdateConsoleVariable (ErrOut, ConDevicePath, NULL);
}
if (HandleBuffer != NULL) {
FreePool(HandleBuffer);
}
//
// Connect all console variables
//
EfiBootManagerConnectAllDefaultConsoles ();
}
/**
This function will connect all the console devices base on the console
device variable ConIn, ConOut and ErrOut.
**/
VOID
EFIAPI
EfiBootManagerConnectAllDefaultConsoles (
VOID
)
{
BOOLEAN SystemTableUpdated;
EfiBootManagerConnectConsoleVariable (ConOut);
PERF_START (NULL, "ConOutReady", "BDS", 1);
PERF_END (NULL, "ConOutReady", "BDS", 0);
EfiBootManagerConnectConsoleVariable (ConIn);
PERF_START (NULL, "ConInReady", "BDS", 1);
PERF_END (NULL, "ConInReady", "BDS", 0);
//
// The _ModuleEntryPoint err out var is legal.
//
EfiBootManagerConnectConsoleVariable (ErrOut);
PERF_START (NULL, "ErrOutReady", "BDS", 1);
PERF_END (NULL, "ErrOutReady", "BDS", 0);
SystemTableUpdated = FALSE;
//
// Fill console handles in System Table if no console device assignd.
//
if (BmUpdateSystemTableConsole (L"ConIn", &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **) &gST->ConIn)) {
SystemTableUpdated = TRUE;
}
if (BmUpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) {
SystemTableUpdated = TRUE;
}
if (BmUpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) {
SystemTableUpdated = TRUE;
}
if (SystemTableUpdated) {
//
// Update the CRC32 in the EFI System Table header
//
gST->Hdr.CRC32 = 0;
gBS->CalculateCrc32 (
(UINT8 *) &gST->Hdr,
gST->Hdr.HeaderSize,
&gST->Hdr.CRC32
);
}
}

View File

@ -0,0 +1,578 @@
/** @file
Library functions which relates with driver health.
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "InternalBm.h"
GLOBAL_REMOVE_IF_UNREFERENCED
CHAR16 *mBmHealthStatusText[] = {
L"Healthy",
L"Repair Required",
L"Configuration Required",
L"Failed",
L"Reconnect Required",
L"Reboot Required"
};
/**
Return the controller name.
@param DriverHealthHandle The handle on which the Driver Health protocol instance is retrieved.
@param ControllerHandle The handle of a controller that the driver specified by DriverBindingHandle is managing.
This handle specifies the controller whose name is to be returned.
@param ChildHandle The handle of the child controller to retrieve the name of. This is an
optional parameter that may be NULL. It will be NULL for device drivers.
It will also be NULL for bus drivers that attempt to retrieve the name
of the bus controller. It will not be NULL for a bus driver that attempts
to retrieve the name of a child controller.
@return A pointer to the Unicode string to return. This Unicode string is the name of the controller
specified by ControllerHandle and ChildHandle.
**/
CHAR16 *
BmGetControllerName (
IN EFI_HANDLE DriverHealthHandle,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle
)
{
EFI_STATUS Status;
CHAR16 *ControllerName;
CHAR8 *LanguageVariable;
CHAR8 *BestLanguage;
BOOLEAN Iso639Language;
EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
ControllerName = NULL;
//
// Locate Component Name (2) protocol on the driver binging handle.
//
Iso639Language = FALSE;
Status = gBS->HandleProtocol (
DriverHealthHandle,
&gEfiComponentName2ProtocolGuid,
(VOID **) &ComponentName
);
if (EFI_ERROR (Status)) {
Status = gBS->HandleProtocol (
DriverHealthHandle,
&gEfiComponentNameProtocolGuid,
(VOID **) &ComponentName
);
if (!EFI_ERROR (Status)) {
Iso639Language = TRUE;
}
}
if (!EFI_ERROR (Status)) {
LanguageVariable = GetEfiGlobalVariable (Iso639Language ? L"Lang" : L"PlatformLang");
BestLanguage = GetBestLanguage(
ComponentName->SupportedLanguages,
Iso639Language,
(LanguageVariable != NULL) ? LanguageVariable : "",
Iso639Language ? "eng" : "en-US",
NULL
);
if (LanguageVariable != NULL) {
FreePool (LanguageVariable);
}
Status = ComponentName->GetControllerName (
ComponentName,
ControllerHandle,
ChildHandle,
BestLanguage,
&ControllerName
);
}
if (!EFI_ERROR (Status)) {
return AllocateCopyPool (StrSize (ControllerName), ControllerName);
} else {
return ConvertDevicePathToText (
DevicePathFromHandle (ChildHandle != NULL ? ChildHandle : ControllerHandle),
FALSE,
FALSE
);
}
}
/**
Display a set of messages returned by the GetHealthStatus () service of the EFI Driver Health Protocol
@param DriverHealthInfo Pointer to the Driver Health information entry.
**/
VOID
BmDisplayMessages (
IN EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo
)
{
UINTN Index;
EFI_STRING String;
CHAR16 *ControllerName;
if (DriverHealthInfo->MessageList == NULL ||
DriverHealthInfo->MessageList[0].HiiHandle == NULL) {
return;
}
ControllerName = BmGetControllerName (
DriverHealthInfo->DriverHealthHandle,
DriverHealthInfo->ControllerHandle,
DriverHealthInfo->ChildHandle
);
DEBUG ((EFI_D_INFO, "Controller: %s\n", ControllerName));
Print (L"Controller: %s\n", ControllerName);
for (Index = 0; DriverHealthInfo->MessageList[Index].HiiHandle != NULL; Index++) {
String = HiiGetString (
DriverHealthInfo->MessageList[Index].HiiHandle,
DriverHealthInfo->MessageList[Index].StringId,
NULL
);
if (String != NULL) {
Print (L" %s\n", String);
DEBUG ((EFI_D_INFO, " %s\n", String));
FreePool (String);
}
}
if (ControllerName != NULL) {
FreePool (ControllerName);
}
}
/**
The repair notify function.
@param Value A value between 0 and Limit that identifies the current progress
of the repair operation.
@param Limit The maximum value of Value for the current repair operation.
If Limit is 0, then the completion progress is indeterminate.
For example, a driver that wants to specify progress in percent
would use a Limit value of 100.
@retval EFI_SUCCESS Successfully return from the notify function.
**/
EFI_STATUS
EFIAPI
BmRepairNotify (
IN UINTN Value,
IN UINTN Limit
)
{
DEBUG ((EFI_D_INFO, "[BDS]RepairNotify: %d/%d\n", Value, Limit));
Print (L"[BDS]RepairNotify: %d/%d\n", Value, Limit);
return EFI_SUCCESS;
}
/**
Collect the Driver Health status of a single controller.
@param DriverHealthInfo A pointer to the array containing all of the platform driver health information.
@param Count Return the updated array count.
@param DriverHealthHandle The handle on which the Driver Health protocol instance is retrieved.
@param ControllerHandle The handle of the controller..
@param ChildHandle The handle of the child controller to retrieve the health
status on. This is an optional parameter that may be NULL.
@retval Status The status returned from GetHealthStatus.
@retval EFI_ABORTED The health status is healthy so no further query is needed.
**/
EFI_STATUS
BmGetSingleControllerHealthStatus (
IN OUT EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO **DriverHealthInfo,
IN OUT UINTN *Count,
IN EFI_HANDLE DriverHealthHandle,
IN EFI_HANDLE ControllerHandle, OPTIONAL
IN EFI_HANDLE ChildHandle OPTIONAL
)
{
EFI_STATUS Status;
EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;
EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList;
EFI_HII_HANDLE FormHiiHandle;
EFI_DRIVER_HEALTH_STATUS HealthStatus;
ASSERT (DriverHealthHandle != NULL);
//
// Retrieve the Driver Health Protocol from DriverHandle
//
Status = gBS->HandleProtocol (
DriverHealthHandle,
&gEfiDriverHealthProtocolGuid,
(VOID **) &DriverHealth
);
ASSERT_EFI_ERROR (Status);
if (ControllerHandle == NULL) {
//
// If ControllerHandle is NULL, the return the cumulative health status of the driver
//
Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, &HealthStatus, NULL, NULL);
if (!EFI_ERROR (Status) && HealthStatus == EfiDriverHealthStatusHealthy) {
*DriverHealthInfo = ReallocatePool (
(*Count) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
(*Count + 1) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
*DriverHealthInfo
);
ASSERT (*DriverHealthInfo != NULL);
(*DriverHealthInfo)[*Count].DriverHealthHandle = DriverHealthHandle;
(*DriverHealthInfo)[*Count].DriverHealth = DriverHealth;
(*DriverHealthInfo)[*Count].HealthStatus = HealthStatus;
*Count = *Count + 1;
Status = EFI_ABORTED;
}
return Status;
}
MessageList = NULL;
FormHiiHandle = NULL;
//
// Collect the health status with the optional HII message list
//
Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, &HealthStatus, &MessageList, &FormHiiHandle);
if (!EFI_ERROR (Status)) {
*DriverHealthInfo = ReallocatePool (
(*Count) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
(*Count + 1) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
*DriverHealthInfo
);
ASSERT (*DriverHealthInfo != NULL);
(*DriverHealthInfo)[*Count].DriverHealth = DriverHealth;
(*DriverHealthInfo)[*Count].DriverHealthHandle = DriverHealthHandle;
(*DriverHealthInfo)[*Count].ControllerHandle = ControllerHandle;
(*DriverHealthInfo)[*Count].ChildHandle = ChildHandle;
(*DriverHealthInfo)[*Count].HiiHandle = FormHiiHandle;
(*DriverHealthInfo)[*Count].MessageList = MessageList;
(*DriverHealthInfo)[*Count].HealthStatus = HealthStatus;
*Count = *Count + 1;
}
return Status;
}
/**
Return all the Driver Health information.
When the cumulative health status of all the controllers managed by the
driver who produces the EFI_DRIVER_HEALTH_PROTOCOL is healthy, only one
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry is created for such
EFI_DRIVER_HEALTH_PROTOCOL instance.
Otherwise, every controller creates one EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO
entry. Additionally every child controller creates one
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry if the driver is a bus driver.
@param Count Return the count of the Driver Health information.
@retval NULL No Driver Health information is returned.
@retval !NULL Pointer to the Driver Health information array.
**/
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *
EFIAPI
EfiBootManagerGetDriverHealthInfo (
UINTN *Count
)
{
EFI_STATUS Status;
UINTN NumHandles;
EFI_HANDLE *DriverHealthHandles;
EFI_DRIVER_HEALTH_STATUS HealthStatus;
UINTN DriverHealthIndex;
EFI_HANDLE *Handles;
UINTN HandleCount;
UINTN ControllerIndex;
UINTN ChildIndex;
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo;
//
// Initialize local variables
//
*Count = 0;
DriverHealthInfo = NULL;
Handles = NULL;
DriverHealthHandles = NULL;
NumHandles = 0;
HandleCount = 0;
HealthStatus = EfiDriverHealthStatusHealthy;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiDriverHealthProtocolGuid,
NULL,
&NumHandles,
&DriverHealthHandles
);
if (Status == EFI_NOT_FOUND || NumHandles == 0) {
//
// If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
//
return NULL;
}
ASSERT_EFI_ERROR (Status);
ASSERT (DriverHealthHandles != NULL);
//
// Check the health status of all controllers in the platform
// Start by looping through all the Driver Health Protocol handles in the handle database
//
for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) {
//
// Get the cumulative health status of the driver
//
Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], NULL, NULL);
if (EFI_ERROR (Status)) {
continue;
}
//
// See if the list of all handles in the handle database has been retrieved
//
//
if (Handles == NULL) {
//
// Retrieve the list of all handles from the handle database
//
Status = gBS->LocateHandleBuffer (
AllHandles,
NULL,
NULL,
&HandleCount,
&Handles
);
ASSERT_EFI_ERROR (Status);
}
//
// Loop through all the controller handles in the handle database
//
for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) {
Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL);
if (EFI_ERROR (Status)) {
continue;
}
//
// Loop through all the child handles in the handle database
//
for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) {
Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex]);
if (EFI_ERROR (Status)) {
continue;
}
}
}
}
Status = EFI_SUCCESS;
if (Handles != NULL) {
FreePool (Handles);
}
if (DriverHealthHandles != NULL) {
FreePool (DriverHealthHandles);
}
return DriverHealthInfo;
}
/**
Free the Driver Health information array.
@param DriverHealthInfo Pointer to array of the Driver Health information.
@param Count Count of the array.
@retval EFI_SUCCESS The array is freed.
@retval EFI_INVALID_PARAMETER The array is NULL.
**/
EFI_STATUS
EFIAPI
EfiBootManagerFreeDriverHealthInfo (
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo,
UINTN Count
)
{
UINTN Index;
for (Index = 0; Index < Count; Index++) {
if (DriverHealthInfo[Index].MessageList != NULL) {
FreePool (DriverHealthInfo[Index].MessageList);
}
}
return gBS->FreePool (DriverHealthInfo);
}
/**
Repair all the controllers according to the Driver Health status queried.
**/
VOID
BmRepairAllControllers (
VOID
)
{
EFI_STATUS Status;
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo;
EFI_DRIVER_HEALTH_STATUS HealthStatus;
UINTN Count;
UINTN Index;
BOOLEAN RepairRequired;
BOOLEAN ConfigurationRequired;
BOOLEAN ReconnectRequired;
BOOLEAN RebootRequired;
EFI_HII_HANDLE *HiiHandles;
EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
//
// Configure PcdDriverHealthConfigureForm to ZeroGuid to disable driver health check.
//
if (CompareGuid (PcdGetPtr (PcdDriverHealthConfigureForm), &gZeroGuid)) {
return;
}
Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
ASSERT_EFI_ERROR (Status);
do {
RepairRequired = FALSE;
ConfigurationRequired = FALSE;
//
// Deal with Repair Required
//
DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
for (Index = 0; Index < Count; Index++) {
if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusConfigurationRequired) {
ConfigurationRequired = TRUE;
}
if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusRepairRequired) {
RepairRequired = TRUE;
BmDisplayMessages (&DriverHealthInfo[Index]);
Status = DriverHealthInfo[Index].DriverHealth->Repair (
DriverHealthInfo[Index].DriverHealth,
DriverHealthInfo[Index].ControllerHandle,
DriverHealthInfo[Index].ChildHandle,
BmRepairNotify
);
if (!EFI_ERROR (Status) && !ConfigurationRequired) {
Status = DriverHealthInfo[Index].DriverHealth->GetHealthStatus (
DriverHealthInfo[Index].DriverHealth,
DriverHealthInfo[Index].ControllerHandle,
DriverHealthInfo[Index].ChildHandle,
&HealthStatus,
NULL,
NULL
);
if (!EFI_ERROR (Status) && (HealthStatus == EfiDriverHealthStatusConfigurationRequired)) {
ConfigurationRequired = TRUE;
}
}
}
}
if (ConfigurationRequired) {
HiiHandles = HiiGetHiiHandles (NULL);
if (HiiHandles != NULL) {
for (Index = 0; HiiHandles[Index] != NULL; Index++) {
Status = FormBrowser2->SendForm (
FormBrowser2,
&HiiHandles[Index],
1,
PcdGetPtr (PcdDriverHealthConfigureForm),
0,
NULL,
NULL
);
if (!EFI_ERROR (Status)) {
break;
}
}
FreePool (HiiHandles);
}
}
EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
} while (RepairRequired || ConfigurationRequired);
RebootRequired = FALSE;
ReconnectRequired = FALSE;
DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
for (Index = 0; Index < Count; Index++) {
BmDisplayMessages (&DriverHealthInfo[Index]);
if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusReconnectRequired) {
Status = gBS->DisconnectController (DriverHealthInfo[Index].ControllerHandle, NULL, NULL);
if (EFI_ERROR (Status)) {
//
// Disconnect failed. Need to promote reconnect to a reboot.
//
RebootRequired = TRUE;
} else {
gBS->ConnectController (DriverHealthInfo[Index].ControllerHandle, NULL, NULL, TRUE);
ReconnectRequired = TRUE;
}
}
if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusRebootRequired) {
RebootRequired = TRUE;
}
}
EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
if (ReconnectRequired) {
BmRepairAllControllers ();
}
DEBUG_CODE (
CHAR16 *ControllerName;
DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
for (Index = 0; Index < Count; Index++) {
ControllerName = BmGetControllerName (
DriverHealthInfo[Index].DriverHealthHandle,
DriverHealthInfo[Index].ControllerHandle,
DriverHealthInfo[Index].ChildHandle
);
DEBUG ((
EFI_D_INFO,
"%02d: %s - %s\n",
Index,
ControllerName,
mBmHealthStatusText[DriverHealthInfo[Index].HealthStatus]
));
if (ControllerName != NULL) {
FreePool (ControllerName);
}
}
EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
);
if (RebootRequired) {
DEBUG ((EFI_D_INFO, "[BDS] One of the Driver Health instances requires rebooting.\n"));
gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,982 @@
/** @file
Load option library functions which relate with creating and processing load options.
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "InternalBm.h"
/**
Get the Option Number that wasn't used.
@param OrderVariableName Could be L"BootOrder" or L"DriverOrder".
@param FreeOptionNumber To receive the minimal free option number.
@retval EFI_SUCCESS The option number is found
@retval EFI_OUT_OF_RESOURCES There is no free option number that can be used.
@retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
**/
EFI_STATUS
BmGetFreeOptionNumber (
IN CHAR16 *OrderVariableName,
OUT UINT16 *FreeOptionNumber
)
{
UINTN OptionNumber;
UINTN Index;
UINT16 *OptionOrder;
UINTN OptionOrderSize;
UINT16 *BootNext;
if (FreeOptionNumber == NULL) {
return EFI_INVALID_PARAMETER;
}
GetEfiGlobalVariable2 (OrderVariableName, (VOID **) &OptionOrder, &OptionOrderSize);
BootNext = NULL;
if (*OrderVariableName == L'B') {
GetEfiGlobalVariable2 (L"BootNext", (VOID**) &BootNext, NULL);
}
for (OptionNumber = 0;
OptionNumber < OptionOrderSize / sizeof (UINT16)
+ ((BootNext != NULL) ? 1 : 0);
OptionNumber++
) {
//
// Search in OptionOrder whether the OptionNumber exists
//
for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
if (OptionNumber == OptionOrder[Index]) {
break;
}
}
//
// We didn't find it in the ****Order array and it doesn't equal to BootNext
// Otherwise, OptionNumber equals to OptionOrderSize / sizeof (UINT16) + 1
//
if ((Index == OptionOrderSize / sizeof (UINT16)) &&
((BootNext == NULL) || (OptionNumber != *BootNext))
) {
break;
}
}
if (OptionOrder != NULL) {
FreePool (OptionOrder);
}
if (BootNext != NULL) {
FreePool (BootNext);
}
//
// When BootOrder & BootNext conver all numbers in the range [0 ... 0xffff],
// OptionNumber equals to 0x10000 which is not valid.
//
ASSERT (OptionNumber <= 0x10000);
if (OptionNumber == 0x10000) {
return EFI_OUT_OF_RESOURCES;
} else {
*FreeOptionNumber = (UINT16) OptionNumber;
return EFI_SUCCESS;
}
}
/**
Update order variable .
@param OptionOrderName Order variable name which need to be updated.
@param OptionNumber Option number for the new option.
@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_ALREADY_STARTED The option number of Option is being used already.
@retval EFI_STATUS Return the status of gRT->SetVariable ().
**/
EFI_STATUS
BmAddOptionNumberToOrderVariable (
IN CHAR16 *OptionOrderName,
IN UINT16 OptionNumber,
IN UINTN Position
)
{
EFI_STATUS Status;
UINTN Index;
UINT16 *OptionOrder;
UINT16 *NewOptionOrder;
UINTN OptionOrderSize;
//
// Update the option order variable
//
GetEfiGlobalVariable2 (OptionOrderName, (VOID **) &OptionOrder, &OptionOrderSize);
Status = EFI_SUCCESS;
for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
if (OptionOrder[Index] == OptionNumber) {
Status = EFI_ALREADY_STARTED;
break;
}
}
if (!EFI_ERROR (Status)) {
Position = MIN (Position, OptionOrderSize / sizeof (UINT16));
NewOptionOrder = AllocatePool (OptionOrderSize + sizeof (UINT16));
ASSERT (NewOptionOrder != NULL);
if (OptionOrderSize != 0) {
CopyMem (NewOptionOrder, OptionOrder, Position * sizeof (UINT16));
CopyMem (&NewOptionOrder[Position + 1], &OptionOrder[Position], OptionOrderSize - Position * sizeof (UINT16));
}
NewOptionOrder[Position] = OptionNumber;
Status = gRT->SetVariable (
OptionOrderName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
OptionOrderSize + sizeof (UINT16),
NewOptionOrder
);
FreePool (NewOptionOrder);
}
if (OptionOrder != NULL) {
FreePool (OptionOrder);
}
return Status;
}
/**
Create the Boot#### or Driver#### 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[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 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_INVALID_PARAMETER The option number exceeds 0xFFFF.
@retval EFI_ALREADY_STARTED The option number of Option is being used already.
Note: this API only adds new load option, no replacement support.
@retval EFI_OUT_OF_RESOURCES There is no free option number that can be used when the
option number specified in the Option is LoadOptionNumberUnassigned.
@retval EFI_STATUS Return the status of gRT->SetVariable ().
**/
EFI_STATUS
EFIAPI
EfiBootManagerAddLoadOptionVariable (
IN EFI_BOOT_MANAGER_LOAD_OPTION *Option,
IN UINTN Position
)
{
EFI_STATUS Status;
UINT16 OptionNumber;
if (Option == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Get the free option number if the option number is unassigned
//
if (Option->OptionNumber == LoadOptionNumberUnassigned) {
Status = BmGetFreeOptionNumber (
Option->OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
&OptionNumber
);
if (EFI_ERROR (Status)) {
return Status;
}
Option->OptionNumber = OptionNumber;
}
if (Option->OptionNumber >= LoadOptionNumberMax) {
return EFI_INVALID_PARAMETER;
}
Status = BmAddOptionNumberToOrderVariable (
Option->OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
(UINT16) Option->OptionNumber,
Position
);
if (!EFI_ERROR (Status)) {
//
// Save the Boot#### or Driver#### variable
//
Status = EfiBootManagerLoadOptionToVariable (Option);
if (EFI_ERROR (Status)) {
//
// Remove the #### from *Order variable when the Boot####/Driver#### cannot be saved.
//
EfiBootManagerDeleteLoadOptionVariable (Option->OptionNumber, Option->OptionType);
}
}
return Status;
}
/**
Sort the load option. The DriverOrder or BootOrder will be re-created to
reflect the new order.
@param OptionType Load option type
@param CompareFunction The comparator
**/
VOID
EFIAPI
EfiBootManagerSortLoadOptionVariable (
EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
SORT_COMPARE CompareFunction
)
{
EFI_STATUS Status;
EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption;
UINTN LoadOptionCount;
UINTN Index;
UINT16 *OptionOrder;
LoadOption = EfiBootManagerGetLoadOptions (&LoadOptionCount, OptionType);
//
// Insertion sort algorithm
//
PerformQuickSort (
LoadOption,
LoadOptionCount,
sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),
CompareFunction
);
//
// Create new ****Order variable
//
OptionOrder = AllocatePool (LoadOptionCount * sizeof (UINT16));
ASSERT (OptionOrder != NULL);
for (Index = 0; Index < LoadOptionCount; Index++) {
OptionOrder[Index] = (UINT16) LoadOption[Index].OptionNumber;
}
Status = gRT->SetVariable (
OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
LoadOptionCount * sizeof (UINT16),
OptionOrder
);
//
// Changing the *Order content without increasing its size with current variable implementation shouldn't fail.
//
ASSERT_EFI_ERROR (Status);
FreePool (OptionOrder);
EfiBootManagerFreeLoadOptions (LoadOption, LoadOptionCount);
}
/**
Initialize a load option.
@param Option Pointer to the load option to be initialized.
@param OptionNumber Option number of the load option.
@param OptionType Type of the load option.
@param Attributes Attributes of the load option.
@param Description Description of the load option.
@param FilePath Device path of the load option.
@param OptionalData Optional data of the load option.
@param OptionalDataSize Size of the optional data of the load option.
@retval EFI_SUCCESS The load option was initialized successfully.
@retval EFI_INVALID_PARAMETER Option, Description or FilePath is NULL.
**/
EFI_STATUS
EFIAPI
EfiBootManagerInitializeLoadOption (
IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option,
IN UINTN OptionNumber,
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
IN UINT32 Attributes,
IN CHAR16 *Description,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
IN UINT8 *OptionalData, OPTIONAL
IN UINT32 OptionalDataSize
)
{
if ((Option == NULL) || (Description == NULL) || (FilePath == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (((OptionalData != NULL) && (OptionalDataSize == 0)) ||
((OptionalData == NULL) && (OptionalDataSize != 0))) {
return EFI_INVALID_PARAMETER;
}
ZeroMem (Option, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
Option->OptionNumber = OptionNumber;
Option->OptionType = OptionType;
Option->Attributes = Attributes;
Option->Description = AllocateCopyPool (StrSize (Description), Description);
Option->FilePath = DuplicateDevicePath (FilePath);
if (OptionalData != NULL) {
Option->OptionalData = AllocateCopyPool (OptionalDataSize, OptionalData);
Option->OptionalDataSize = OptionalDataSize;
}
return EFI_SUCCESS;
}
/**
Return the index of the load option in the load option array.
The function consider two load options are equal when the
OptionType, Attributes, Description, FilePath and OptionalData are equal.
@param Key Pointer to the load option to be found.
@param Array Pointer to the array of load options to be found.
@param Count Number of entries in the Array.
@retval -1 Key wasn't found in the Array.
@retval 0 ~ Count-1 The index of the Key in the Array.
**/
INTN
BmFindLoadOption (
IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
IN UINTN Count
)
{
UINTN Index;
for (Index = 0; Index < Count; Index++) {
if ((Key->OptionType == Array[Index].OptionType) &&
(Key->Attributes == Array[Index].Attributes) &&
(StrCmp (Key->Description, Array[Index].Description) == 0) &&
(CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
(Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
(CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
return (INTN) Index;
}
}
return -1;
}
/**
Update the BootOrder or DriverOrder to delete OptionNumber .
@param OptionOrderVariable Order variable name which need to be updated.
@param OptionNumber Indicate the option number of load option
@retval EFI_NOT_FOUND The load option cannot be found
@retval EFI_SUCCESS The load option was deleted
@retval others Status of RT->SetVariable()
**/
EFI_STATUS
BmDeleteOptionVariable (
IN CHAR16 *OptionOrderVariable,
IN UINT16 OptionNumber
)
{
UINT16 *OptionOrder;
UINTN OptionOrderSize;
EFI_STATUS Status;
UINTN Index;
Status = EFI_NOT_FOUND;
GetEfiGlobalVariable2 (OptionOrderVariable, (VOID **) &OptionOrder, &OptionOrderSize);
for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
if (OptionOrder[Index] == OptionNumber) {
OptionOrderSize -= sizeof (UINT16);
CopyMem (&OptionOrder[Index], &OptionOrder[Index + 1], OptionOrderSize - Index * sizeof (UINT16));
Status = gRT->SetVariable (
OptionOrderVariable,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
OptionOrderSize,
OptionOrder
);
break;
}
}
if (OptionOrder != NULL) {
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 (
OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
(UINT16) OptionNumber
);
}
/**
Convert a single character to number.
It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F'
@param Char The input char which need to convert to int.
**/
UINTN
BmCharToUint (
IN CHAR16 Char
)
{
if ((Char >= L'0') && (Char <= L'9')) {
return (UINTN) (Char - L'0');
}
if ((Char >= L'A') && (Char <= L'F')) {
return (UINTN) (Char - L'A' + 0xA);
}
ASSERT (FALSE);
return 0;
}
/**
Returns the size of a device path in bytes.
This function returns the size, in bytes, of the device path data structure
specified by DevicePath including the end of device path node. If DevicePath
is NULL, then 0 is returned. If the length of the device path is bigger than
MaxSize, also return 0 to indicate this is an invalidate device path.
@param DevicePath A pointer to a device path data structure.
@param MaxSize Max valid device path size. If big than this size,
return error.
@retval 0 An invalid device path.
@retval Others The size of a device path in bytes.
**/
UINTN
BmGetDevicePathSizeEx (
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN UINTN MaxSize
)
{
UINTN Size;
UINTN NodeSize;
if (DevicePath == NULL) {
return 0;
}
//
// Search for the end of the device path structure
//
Size = 0;
while (!IsDevicePathEnd (DevicePath)) {
NodeSize = DevicePathNodeLength (DevicePath);
if (NodeSize == 0) {
return 0;
}
Size += NodeSize;
if (Size > MaxSize) {
return 0;
}
DevicePath = NextDevicePathNode (DevicePath);
}
Size += DevicePathNodeLength (DevicePath);
if (Size > MaxSize) {
return 0;
}
return Size;
}
/**
Returns the length of a Null-terminated Unicode string. If the length is
bigger than MaxStringLen, return length 0 to indicate that this is an
invalidate string.
This function returns the number of Unicode characters in the Null-terminated
Unicode string specified by String.
If String is NULL, then ASSERT().
If String is not aligned on a 16-bit boundary, then ASSERT().
@param String A pointer to a Null-terminated Unicode string.
@param MaxStringLen Max string len in this string.
@retval 0 An invalid string.
@retval Others The length of String.
**/
UINTN
BmStrSizeEx (
IN CONST CHAR16 *String,
IN UINTN MaxStringLen
)
{
UINTN Length;
ASSERT (String != NULL && MaxStringLen != 0);
ASSERT (((UINTN) String & BIT0) == 0);
for (Length = 0; *String != L'\0' && MaxStringLen != Length; String++, Length+=2);
if (*String != L'\0' && MaxStringLen == Length) {
return 0;
}
return Length + 2;
}
/**
Validate the EFI Boot#### variable (VendorGuid/Name)
@param Variable Boot#### variable data.
@param VariableSize Returns the size of the EFI variable that was read
@retval TRUE The variable data is correct.
@retval FALSE The variable data is corrupted.
**/
BOOLEAN
BmValidateOption (
UINT8 *Variable,
UINTN VariableSize
)
{
UINT16 FilePathSize;
UINT8 *TempPtr;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
UINTN TempSize;
if (VariableSize <= sizeof (UINT16) + sizeof (UINT32)) {
return FALSE;
}
//
// Skip the option attribute
//
TempPtr = Variable;
TempPtr += sizeof (UINT32);
//
// Get the option's device path size
//
FilePathSize = *(UINT16 *) TempPtr;
TempPtr += sizeof (UINT16);
//
// Get the option's description string size
//
TempSize = BmStrSizeEx ((CHAR16 *) TempPtr, VariableSize - sizeof (UINT16) - sizeof (UINT32));
TempPtr += TempSize;
//
// Get the option's device path
//
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
TempPtr += FilePathSize;
//
// Validation boot option variable.
//
if ((FilePathSize == 0) || (TempSize == 0)) {
return FALSE;
}
if (TempSize + FilePathSize + sizeof (UINT16) + sizeof (UINT32) > VariableSize) {
return FALSE;
}
return (BOOLEAN) (BmGetDevicePathSizeEx (DevicePath, FilePathSize) != 0);
}
/**
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
)
{
EFI_STATUS Status;
UINT32 Attribute;
UINT16 FilePathSize;
UINT8 *Variable;
UINT8 *TempPtr;
UINTN VariableSize;
EFI_DEVICE_PATH_PROTOCOL *FilePath;
UINT8 *OptionalData;
UINT32 OptionalDataSize;
CHAR16 *Description;
UINT8 NumOff;
EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType;
UINT16 OptionNumber;
if ((VariableName == NULL) || (Option == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// Read the variable
//
GetEfiGlobalVariable2 (VariableName, (VOID **) &Variable, &VariableSize);
if (Variable == NULL) {
return EFI_NOT_FOUND;
}
//
// Validate Boot#### variable data.
//
if (!BmValidateOption(Variable, VariableSize)) {
FreePool (Variable);
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
//
TempPtr = Variable;
Attribute = *(UINT32 *) Variable;
TempPtr += sizeof (UINT32);
//
// Get the option's device path size
//
FilePathSize = *(UINT16 *) TempPtr;
TempPtr += sizeof (UINT16);
//
// Get the option's description string
//
Description = (CHAR16 *) TempPtr;
//
// Get the option's description string size
//
TempPtr += StrSize ((CHAR16 *) TempPtr);
//
// Get the option's device path
//
FilePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
TempPtr += FilePathSize;
OptionalDataSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));
if (OptionalDataSize == 0) {
OptionalData = NULL;
} else {
OptionalData = TempPtr;
}
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 (
Option,
OptionNumber,
OptionType,
Attribute,
Description,
FilePath,
OptionalData,
OptionalDataSize
);
ASSERT_EFI_ERROR (Status);
FreePool (Variable);
return Status;
}
/**
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.
#### is the hex value of the UINT16 in each BootOrder/DriverOrder entry.
@param LoadOptionCount Returns number of entries in the array.
@param LoadOptionType The type of the load option.
@retval NULL No load options exist.
@retval !NULL Array of load option entries.
**/
EFI_BOOT_MANAGER_LOAD_OPTION *
EFIAPI
EfiBootManagerGetLoadOptions (
OUT UINTN *OptionCount,
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType
)
{
EFI_STATUS Status;
UINT16 *OptionOrder;
UINTN OptionOrderSize;
UINTN Index;
UINTN OptionIndex;
EFI_BOOT_MANAGER_LOAD_OPTION *Option;
CHAR16 OptionName[sizeof ("Driver####")];
UINT16 OptionNumber;
*OptionCount = 0;
//
// Read the BootOrder, or DriverOrder variable.
//
GetEfiGlobalVariable2 (
(LoadOptionType == LoadOptionTypeBoot) ? L"BootOrder" : L"DriverOrder",
(VOID **) &OptionOrder,
&OptionOrderSize
);
if (OptionOrder == NULL) {
return NULL;
}
*OptionCount = OptionOrderSize / sizeof (UINT16);
Option = AllocatePool (*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
ASSERT (Option != NULL);
OptionIndex = 0;
for (Index = 0; Index < *OptionCount; Index++) {
OptionNumber = OptionOrder[Index];
if (LoadOptionType == LoadOptionTypeBoot) {
UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionNumber);
} else {
UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionNumber);
}
Status = EfiBootManagerVariableToLoadOption (OptionName, &Option[OptionIndex]);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_INFO, "[Bds] %s doesn't exist - Update ****Order variable to remove the reference!!", OptionName));
EfiBootManagerDeleteLoadOptionVariable (OptionNumber, LoadOptionTypeBoot);
} else {
ASSERT (Option[OptionIndex].OptionNumber == OptionNumber);
OptionIndex++;
}
}
if (OptionOrder != NULL) {
FreePool (OptionOrder);
}
if (OptionIndex < *OptionCount) {
Option = ReallocatePool (
*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),
OptionIndex * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),
Option
);
ASSERT (Option != NULL);
*OptionCount = OptionIndex;
}
return Option;
}
/**
Free an EFI_BOOT_MANGER_LOAD_OPTION entry that was allocate by the library.
@param LoadOption Pointer to boot option to Free.
@return EFI_SUCCESS BootOption was freed
@return EFI_NOT_FOUND BootOption == NULL
**/
EFI_STATUS
EFIAPI
EfiBootManagerFreeLoadOption (
IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
)
{
if (LoadOption == NULL) {
return EFI_NOT_FOUND;
}
if (LoadOption->Description != NULL) {
FreePool (LoadOption->Description);
}
if (LoadOption->FilePath != NULL) {
FreePool (LoadOption->FilePath);
}
if (LoadOption->OptionalData != NULL) {
FreePool (LoadOption->OptionalData);
}
return EFI_SUCCESS;
}
/**
Free an EFI_BOOT_MANGER_LOAD_OPTION array that was allocated by
EfiBootManagerGetLoadOptions().
@param Option Pointer to boot option array to free.
@param OptionCount Number of array entries in BootOption
@return EFI_SUCCESS BootOption was freed
@return EFI_NOT_FOUND BootOption == NULL
**/
EFI_STATUS
EFIAPI
EfiBootManagerFreeLoadOptions (
IN EFI_BOOT_MANAGER_LOAD_OPTION *Option,
IN UINTN OptionCount
)
{
UINTN Index;
if (Option == NULL) {
return EFI_NOT_FOUND;
}
for (Index = 0;Index < OptionCount; Index++) {
EfiBootManagerFreeLoadOption (&Option[Index]);
}
FreePool (Option);
return EFI_SUCCESS;
}

View File

@ -0,0 +1,507 @@
/** @file
Misc library functions.
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "InternalBm.h"
/**
Delete the instance in Multi which matches partly with Single instance
@param Multi A pointer to a multi-instance device path data
structure.
@param Single A pointer to a single-instance device path data
structure.
@return This function will remove the device path instances in Multi which partly
match with the Single, and return the result device path. If there is no
remaining device path as a result, this function will return NULL.
**/
EFI_DEVICE_PATH_PROTOCOL *
BmDelPartMatchInstance (
IN EFI_DEVICE_PATH_PROTOCOL *Multi,
IN EFI_DEVICE_PATH_PROTOCOL *Single
)
{
EFI_DEVICE_PATH_PROTOCOL *Instance;
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
UINTN InstanceSize;
UINTN SingleDpSize;
NewDevicePath = NULL;
TempNewDevicePath = NULL;
if (Multi == NULL || Single == NULL) {
return Multi;
}
Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
SingleDpSize = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;
InstanceSize -= END_DEVICE_PATH_LENGTH;
while (Instance != NULL) {
if (CompareMem (Instance, Single, MIN (SingleDpSize, InstanceSize)) != 0) {
//
// Append the device path instance which does not match with Single
//
TempNewDevicePath = NewDevicePath;
NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);
if (TempNewDevicePath != NULL) {
FreePool(TempNewDevicePath);
}
}
FreePool(Instance);
Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
InstanceSize -= END_DEVICE_PATH_LENGTH;
}
return NewDevicePath;
}
/**
Function compares a device path data structure to that of all the nodes of a
second device path instance.
@param Multi A pointer to a multi-instance device path data
structure.
@param Single A pointer to a single-instance device path data
structure.
@retval TRUE If the Single device path is contained within Multi device path.
@retval FALSE The Single device path is not match within Multi device path.
**/
BOOLEAN
BmMatchDevicePaths (
IN EFI_DEVICE_PATH_PROTOCOL *Multi,
IN EFI_DEVICE_PATH_PROTOCOL *Single
)
{
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
UINTN Size;
if (Multi == NULL || Single == NULL) {
return FALSE;
}
DevicePath = Multi;
DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
//
// Search for the match of 'Single' in 'Multi'
//
while (DevicePathInst != NULL) {
//
// If the single device path is found in multiple device paths,
// return success
//
if (CompareMem (Single, DevicePathInst, Size) == 0) {
FreePool (DevicePathInst);
return TRUE;
}
FreePool (DevicePathInst);
DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
}
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
save them into the variables for next boot.
**/
VOID
BmSetMemoryTypeInformationVariable (
VOID
)
{
EFI_STATUS Status;
EFI_MEMORY_TYPE_INFORMATION *PreviousMemoryTypeInformation;
EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation;
UINTN VariableSize;
UINTN Index;
UINTN Index1;
UINT32 Previous;
UINT32 Current;
UINT32 Next;
EFI_HOB_GUID_TYPE *GuidHob;
BOOLEAN MemoryTypeInformationModified;
BOOLEAN MemoryTypeInformationVariableExists;
EFI_BOOT_MODE BootMode;
MemoryTypeInformationModified = FALSE;
MemoryTypeInformationVariableExists = FALSE;
BootMode = GetBootModeHob ();
//
// In BOOT_IN_RECOVERY_MODE, Variable region is not reliable.
//
if (BootMode == BOOT_IN_RECOVERY_MODE) {
return;
}
//
// Only check the the Memory Type Information variable in the boot mode
// other than BOOT_WITH_DEFAULT_SETTINGS because the Memory Type
// Information is not valid in this boot mode.
//
if (BootMode != BOOT_WITH_DEFAULT_SETTINGS) {
VariableSize = 0;
Status = gRT->GetVariable (
EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
&gEfiMemoryTypeInformationGuid,
NULL,
&VariableSize,
NULL
);
if (Status == EFI_BUFFER_TOO_SMALL) {
MemoryTypeInformationVariableExists = TRUE;
}
}
//
// Retrieve the current memory usage statistics. If they are not found, then
// no adjustments can be made to the Memory Type Information variable.
//
Status = EfiGetSystemConfigurationTable (
&gEfiMemoryTypeInformationGuid,
(VOID **) &CurrentMemoryTypeInformation
);
if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) {
return;
}
//
// Get the Memory Type Information settings from Hob if they exist,
// PEI is responsible for getting them from variable and build a Hob to save them.
// If the previous Memory Type Information is not available, then set defaults
//
GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
if (GuidHob == NULL) {
//
// If Platform has not built Memory Type Info into the Hob, just return.
//
return;
}
PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
//
// Use a heuristic to adjust the Memory Type Information for the next boot
//
DEBUG ((EFI_D_INFO, "Memory Previous Current Next \n"));
DEBUG ((EFI_D_INFO, " Type Pages Pages Pages \n"));
DEBUG ((EFI_D_INFO, "====== ======== ======== ========\n"));
for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {
if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {
break;
}
}
if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {
continue;
}
//
// Previous is the number of pages pre-allocated
// Current is the number of pages actually needed
//
Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;
Current = CurrentMemoryTypeInformation[Index1].NumberOfPages;
Next = Previous;
//
// Inconsistent Memory Reserved across bootings may lead to S4 fail
// Write next varible to 125% * current when the pre-allocated memory is:
// 1. More than 150% of needed memory and boot mode is BOOT_WITH_DEFAULT_SETTING
// 2. Less than the needed memory
//
if ((Current + (Current >> 1)) < Previous) {
if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
Next = Current + (Current >> 2);
}
} else if (Current > Previous) {
Next = Current + (Current >> 2);
}
if (Next > 0 && Next < 4) {
Next = 4;
}
if (Next != Previous) {
PreviousMemoryTypeInformation[Index].NumberOfPages = Next;
MemoryTypeInformationModified = TRUE;
}
DEBUG ((EFI_D_INFO, " %02x %08x %08x %08x\n", PreviousMemoryTypeInformation[Index].Type, Previous, Current, Next));
}
//
// If any changes were made to the Memory Type Information settings, then set the new variable value;
// Or create the variable in first boot.
//
if (MemoryTypeInformationModified || !MemoryTypeInformationVariableExists) {
Status = BmSetVariableAndReportStatusCodeOnError (
EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
&gEfiMemoryTypeInformationGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
VariableSize,
PreviousMemoryTypeInformation
);
if (!EFI_ERROR (Status)) {
//
// If the Memory Type Information settings have been modified, then reset the platform
// so the new Memory Type Information setting will be used to guarantee that an S4
// entry/resume cycle will not fail.
//
if (MemoryTypeInformationModified) {
DEBUG ((EFI_D_INFO, "Memory Type Information settings change. Warm Reset!!!\n"));
gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
}
} else {
DEBUG ((EFI_D_ERROR, "Memory Type Information settings cannot be saved. OS S4 may fail!\n"));
}
}
}
/**
Set the variable and report the error through status code upon failure.
@param VariableName A Null-terminated string that is the name of the vendor's variable.
Each VariableName is unique for each VendorGuid. VariableName must
contain 1 or more characters. If VariableName is an empty string,
then EFI_INVALID_PARAMETER is returned.
@param VendorGuid A unique identifier for the vendor.
@param Attributes Attributes bitmask to set for the variable.
@param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE,
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero
causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is
set, then a SetVariable() call with a DataSize of zero will not cause any change to
the variable value (the timestamp associated with the variable may be updated however
even if no new data value is provided,see the description of the
EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not
be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated).
@param Data The contents for the variable.
@retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
defined by the Attributes.
@retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the
DataSize exceeds the maximum allowed.
@retval EFI_INVALID_PARAMETER VariableName is an empty string.
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
@retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
@retval EFI_WRITE_PROTECTED The variable in question is read-only.
@retval EFI_WRITE_PROTECTED The variable in question cannot be deleted.
@retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo
does NOT pass the validation check carried out by the firmware.
@retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
**/
EFI_STATUS
BmSetVariableAndReportStatusCodeOnError (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
EFI_STATUS Status;
EDKII_SET_VARIABLE_STATUS *SetVariableStatus;
UINTN NameSize;
Status = gRT->SetVariable (
VariableName,
VendorGuid,
Attributes,
DataSize,
Data
);
if (EFI_ERROR (Status)) {
NameSize = StrSize (VariableName);
SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize);
if (SetVariableStatus != NULL) {
CopyGuid (&SetVariableStatus->Guid, VendorGuid);
SetVariableStatus->NameSize = NameSize;
SetVariableStatus->DataSize = DataSize;
SetVariableStatus->SetStatus = Status;
SetVariableStatus->Attributes = Attributes;
CopyMem (SetVariableStatus + 1, VariableName, NameSize);
CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data, DataSize);
REPORT_STATUS_CODE_EX (
EFI_ERROR_CODE,
PcdGet32 (PcdErrorCodeSetVariable),
0,
NULL,
&gEdkiiStatusCodeDataTypeVariableGuid,
SetVariableStatus,
sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize
);
FreePool (SetVariableStatus);
}
}
return Status;
}

View File

@ -0,0 +1,358 @@
/** @file
This file include the file which can help to get the system
performance, all the function will only include if the performance
switch is set.
Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "InternalBm.h"
PERF_HEADER mBmPerfHeader;
PERF_DATA mBmPerfData;
EFI_PHYSICAL_ADDRESS mBmAcpiLowMemoryBase = 0x0FFFFFFFFULL;
/**
Get the short verion of PDB file name to be
used in performance data logging.
@param PdbFileName The long PDB file name.
@param GaugeString The output string to be logged by performance logger.
**/
VOID
BmGetShortPdbFileName (
IN CONST CHAR8 *PdbFileName,
OUT CHAR8 *GaugeString
)
{
UINTN Index;
UINTN Index1;
UINTN StartIndex;
UINTN EndIndex;
if (PdbFileName == NULL) {
AsciiStrCpy (GaugeString, " ");
} else {
StartIndex = 0;
for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
;
for (Index = 0; PdbFileName[Index] != 0; Index++) {
if (PdbFileName[Index] == '\\') {
StartIndex = Index + 1;
}
if (PdbFileName[Index] == '.') {
EndIndex = Index;
}
}
Index1 = 0;
for (Index = StartIndex; Index < EndIndex; Index++) {
GaugeString[Index1] = PdbFileName[Index];
Index1++;
if (Index1 == PERF_TOKEN_LENGTH - 1) {
break;
}
}
GaugeString[Index1] = 0;
}
return ;
}
/**
Get the name from the Driver handle, which can be a handle with
EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.
This name can be used in performance data logging.
@param Handle Driver handle.
@param GaugeString The output string to be logged by performance logger.
**/
VOID
BmGetNameFromHandle (
IN EFI_HANDLE Handle,
OUT CHAR8 *GaugeString
)
{
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *Image;
CHAR8 *PdbFileName;
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
AsciiStrCpy (GaugeString, " ");
//
// Get handle name from image protocol
//
Status = gBS->HandleProtocol (
Handle,
&gEfiLoadedImageProtocolGuid,
(VOID **) &Image
);
if (EFI_ERROR (Status)) {
Status = gBS->OpenProtocol (
Handle,
&gEfiDriverBindingProtocolGuid,
(VOID **) &DriverBinding,
NULL,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return ;
}
//
// Get handle name from image protocol
//
Status = gBS->HandleProtocol (
DriverBinding->ImageHandle,
&gEfiLoadedImageProtocolGuid,
(VOID **) &Image
);
}
PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
if (PdbFileName != NULL) {
BmGetShortPdbFileName (PdbFileName, GaugeString);
}
return ;
}
/**
Writes performance data of booting into the allocated memory.
OS can process these records.
@param Event The triggered event.
@param Context Context for this event.
**/
VOID
EFIAPI
BmWriteBootToOsPerformanceData (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
UINT32 LimitCount;
EFI_HANDLE *Handles;
UINTN NoHandles;
CHAR8 GaugeString[PERF_TOKEN_LENGTH];
UINT8 *Ptr;
UINT32 Index;
UINT64 Ticker;
UINT64 Freq;
UINT32 Duration;
UINTN LogEntryKey;
CONST VOID *Handle;
CONST CHAR8 *Token;
CONST CHAR8 *Module;
UINT64 StartTicker;
UINT64 EndTicker;
UINT64 StartValue;
UINT64 EndValue;
BOOLEAN CountUp;
UINTN EntryIndex;
UINTN NumPerfEntries;
//
// List of flags indicating PerfEntry contains DXE handle
//
BOOLEAN *PerfEntriesAsDxeHandle;
UINTN VarSize;
//
// Record the performance data for End of BDS
//
PERF_END(NULL, "BDS", NULL, 0);
//
// Retrieve time stamp count as early as possible
//
Ticker = GetPerformanceCounter ();
Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);
Freq = DivU64x32 (Freq, 1000);
mBmPerfHeader.CpuFreq = Freq;
//
// Record BDS raw performance data
//
if (EndValue >= StartValue) {
mBmPerfHeader.BDSRaw = Ticker - StartValue;
CountUp = TRUE;
} else {
mBmPerfHeader.BDSRaw = StartValue - Ticker;
CountUp = FALSE;
}
if (mBmAcpiLowMemoryBase == 0x0FFFFFFFF) {
VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
Status = gRT->GetVariable (
L"PerfDataMemAddr",
&gPerformanceProtocolGuid,
NULL,
&VarSize,
&mBmAcpiLowMemoryBase
);
if (EFI_ERROR (Status)) {
//
// Fail to get the variable, return.
//
return;
}
}
//
// Put Detailed performance data into memory
//
Handles = NULL;
Status = gBS->LocateHandleBuffer (
AllHandles,
NULL,
NULL,
&NoHandles,
&Handles
);
if (EFI_ERROR (Status)) {
return ;
}
Ptr = (UINT8 *) ((UINT32) mBmAcpiLowMemoryBase + sizeof (PERF_HEADER));
LimitCount = (UINT32) (PERF_DATA_MAX_LENGTH - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
NumPerfEntries = 0;
LogEntryKey = 0;
while ((LogEntryKey = GetPerformanceMeasurement (
LogEntryKey,
&Handle,
&Token,
&Module,
&StartTicker,
&EndTicker)) != 0) {
NumPerfEntries++;
}
PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));
ASSERT (PerfEntriesAsDxeHandle != NULL);
//
// Get DXE drivers performance
//
for (Index = 0; Index < NoHandles; Index++) {
Ticker = 0;
LogEntryKey = 0;
EntryIndex = 0;
while ((LogEntryKey = GetPerformanceMeasurement (
LogEntryKey,
&Handle,
&Token,
&Module,
&StartTicker,
&EndTicker)) != 0) {
if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {
PerfEntriesAsDxeHandle[EntryIndex] = TRUE;
}
EntryIndex++;
if ((Handle == Handles[Index]) && (EndTicker != 0)) {
if (StartTicker == 1) {
StartTicker = StartValue;
}
if (EndTicker == 1) {
EndTicker = StartValue;
}
Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
}
}
Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
if (Duration > 0) {
BmGetNameFromHandle (Handles[Index], GaugeString);
AsciiStrCpy (mBmPerfData.Token, GaugeString);
mBmPerfData.Duration = Duration;
CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));
Ptr += sizeof (PERF_DATA);
mBmPerfHeader.Count++;
if (mBmPerfHeader.Count == LimitCount) {
goto Done;
}
}
}
//
// Get inserted performance data
//
LogEntryKey = 0;
EntryIndex = 0;
while ((LogEntryKey = GetPerformanceMeasurement (
LogEntryKey,
&Handle,
&Token,
&Module,
&StartTicker,
&EndTicker)) != 0) {
if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {
ZeroMem (&mBmPerfData, sizeof (PERF_DATA));
AsciiStrnCpy (mBmPerfData.Token, Token, PERF_TOKEN_LENGTH);
if (StartTicker == 1) {
StartTicker = StartValue;
}
if (EndTicker == 1) {
EndTicker = StartValue;
}
Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
mBmPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));
Ptr += sizeof (PERF_DATA);
mBmPerfHeader.Count++;
if (mBmPerfHeader.Count == LimitCount) {
goto Done;
}
}
EntryIndex++;
}
Done:
FreePool (Handles);
FreePool (PerfEntriesAsDxeHandle);
mBmPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
//
// Put performance data to Reserved memory
//
CopyMem (
(UINTN *) (UINTN) mBmAcpiLowMemoryBase,
&mBmPerfHeader,
sizeof (PERF_HEADER)
);
return ;
}

View File

@ -0,0 +1,364 @@
/** @file
BDS library definition, include the file and data structure
Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
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.
**/
#ifndef _INTERNAL_BM_H_
#define _INTERNAL_BM_H_
#include <PiDxe.h>
#include <IndustryStandard/Pci.h>
#include <IndustryStandard/PeImage.h>
#include <IndustryStandard/Atapi.h>
#include <IndustryStandard/Scsi.h>
#include <Protocol/PciRootBridgeIo.h>
#include <Protocol/BlockIo.h>
#include <Protocol/LoadedImage.h>
#include <Protocol/SimpleFileSystem.h>
#include <Protocol/LoadFile.h>
#include <Protocol/DevicePath.h>
#include <Protocol/SimpleTextIn.h>
#include <Protocol/SimpleTextInEx.h>
#include <Protocol/SimpleTextOut.h>
#include <Protocol/SimpleNetwork.h>
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/PciIo.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/UsbIo.h>
#include <Protocol/DiskInfo.h>
#include <Protocol/IdeControllerInit.h>
#include <Protocol/BootLogo.h>
#include <Protocol/DriverHealth.h>
#include <Protocol/FormBrowser2.h>
#include <Guid/ZeroGuid.h>
#include <Guid/MemoryTypeInformation.h>
#include <Guid/FileInfo.h>
#include <Guid/GlobalVariable.h>
#include <Guid/Performance.h>
#include <Guid/StatusCodeDataTypeVariable.h>
#include <Library/PrintLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/HobLib.h>
#include <Library/BaseLib.h>
#include <Library/DevicePathLib.h>
#include <Library/PerformanceLib.h>
#include <Library/PcdLib.h>
#include <Library/PeCoffGetEntryPointLib.h>
#include <Library/UefiBootManagerLib.h>
#include <Library/TimerLib.h>
#include <Library/DxeServicesLib.h>
#include <Library/ReportStatusCodeLib.h>
#include <Library/CapsuleLib.h>
#include <Library/PerformanceLib.h>
#include <Library/HiiLib.h>
#if !defined (EFI_REMOVABLE_MEDIA_FILE_NAME)
#if defined (MDE_CPU_EBC)
//
// Uefi specification only defines the default boot file name for IA32, X64
// and IPF processor, so need define boot file name for EBC architecture here.
//
#define EFI_REMOVABLE_MEDIA_FILE_NAME L"\\EFI\\BOOT\\BOOTEBC.EFI"
#else
#error "Can not determine the default boot file name for unknown processor type!"
#endif
#endif
typedef enum {
BmAcpiFloppyBoot,
BmHardwareDeviceBoot,
BmMessageAtapiBoot,
BmMessageSataBoot,
BmMessageUsbBoot,
BmMessageScsiBoot,
BmMessageNetworkBoot,
BmMiscBoot
} BM_BOOT_TYPE;
typedef
CHAR16 *
(* BM_GET_BOOT_DESCRIPTION) (
IN EFI_HANDLE Handle
);
#define BM_HOTKEY_SIGNATURE SIGNATURE_32 ('b', 'm', 'h', 'k')
typedef struct {
UINT32 Signature;
LIST_ENTRY Link;
BOOLEAN IsContinue;
UINT16 BootOption;
UINT8 CodeCount;
UINT8 WaitingKey;
EFI_KEY_DATA KeyData[3];
} BM_HOTKEY;
#define BM_HOTKEY_FROM_LINK(a) CR (a, BM_HOTKEY, Link, BM_HOTKEY_SIGNATURE)
/**
Get the image file buffer data and buffer size by its device path.
@param FilePath On input, a pointer to an allocated buffer containing the device
path of the file.
On output the pointer could be NULL when the function fails to
load the boot option, or could point to an allocated buffer containing
the device path of the file.
It could be updated by either short-form device path expanding,
or default boot file path appending.
Caller is responsible to free it when it's non-NULL.
@param FileSize A pointer to the size of the file buffer.
@retval NULL File is NULL, or FileSize is NULL. Or, the file can't be found.
@retval other The file buffer. The caller is responsible to free the memory.
**/
VOID *
BmLoadEfiBootOption (
IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
OUT UINTN *FileSize
);
/**
Get the Option Number that wasn't used.
@param OrderVariableName Could be L"BootOrder" or L"DriverOrder".
@param FreeOptionNumber To receive the minimal free option number.
@retval EFI_SUCCESS The option number is found
@retval EFI_OUT_OF_RESOURCES There is no free option number that can be used.
@retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
**/
EFI_STATUS
BmGetFreeOptionNumber (
IN CHAR16 *OrderVariableName,
OUT UINT16 *FreeOptionNumber
);
/**
Writes performance data of booting into the allocated memory.
OS can process these records.
@param Event The triggered event.
@param Context Context for this event.
**/
VOID
EFIAPI
BmWriteBootToOsPerformanceData (
IN EFI_EVENT Event,
IN VOID *Context
);
/**
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
);
/**
This routine adjust the memory information for different memory type and
save them into the variables for next boot.
**/
VOID
BmSetMemoryTypeInformationVariable (
VOID
);
/**
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
BmMatchPartitionDevicePathNode (
IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,
IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath
);
/**
Connect the specific Usb device which match the short form device path.
@param DevicePath A short-form device path that starts with the first
element being a USB WWID or a USB Class device
path
@return EFI_INVALID_PARAMETER DevicePath is NULL pointer.
DevicePath is not a USB device path.
@return EFI_SUCCESS Success to connect USB device
@return EFI_NOT_FOUND Fail to find handle for USB controller to connect.
**/
EFI_STATUS
BmConnectUsbShortFormDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
);
/**
Stop the hotkey processing.
@param Event Event pointer related to hotkey service.
@param Context Context pass to this function.
**/
VOID
EFIAPI
BmStopHotkeyService (
IN EFI_EVENT Event,
IN VOID *Context
);
/**
Set the variable and report the error through status code upon failure.
@param VariableName A Null-terminated string that is the name of the vendor's variable.
Each VariableName is unique for each VendorGuid. VariableName must
contain 1 or more characters. If VariableName is an empty string,
then EFI_INVALID_PARAMETER is returned.
@param VendorGuid A unique identifier for the vendor.
@param Attributes Attributes bitmask to set for the variable.
@param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE,
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero
causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is
set, then a SetVariable() call with a DataSize of zero will not cause any change to
the variable value (the timestamp associated with the variable may be updated however
even if no new data value is provided,see the description of the
EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not
be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated).
@param Data The contents for the variable.
@retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
defined by the Attributes.
@retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the
DataSize exceeds the maximum allowed.
@retval EFI_INVALID_PARAMETER VariableName is an empty string.
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
@retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
@retval EFI_WRITE_PROTECTED The variable in question is read-only.
@retval EFI_WRITE_PROTECTED The variable in question cannot be deleted.
@retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo
does NOT pass the validation check carried out by the firmware.
@retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
**/
EFI_STATUS
BmSetVariableAndReportStatusCodeOnError (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
);
/**
Function compares a device path data structure to that of all the nodes of a
second device path instance.
@param Multi A pointer to a multi-instance device path data
structure.
@param Single A pointer to a single-instance device path data
structure.
@retval TRUE If the Single device path is contained within Multi device path.
@retval FALSE The Single device path is not match within Multi device path.
**/
BOOLEAN
BmMatchDevicePaths (
IN EFI_DEVICE_PATH_PROTOCOL *Multi,
IN EFI_DEVICE_PATH_PROTOCOL *Single
);
/**
Delete the instance in Multi which matches partly with Single instance
@param Multi A pointer to a multi-instance device path data
structure.
@param Single A pointer to a single-instance device path data
structure.
@return This function will remove the device path instances in Multi which partly
match with the Single, and return the result device path. If there is no
remaining device path as a result, this function will return NULL.
**/
EFI_DEVICE_PATH_PROTOCOL *
BmDelPartMatchInstance (
IN EFI_DEVICE_PATH_PROTOCOL *Multi,
IN EFI_DEVICE_PATH_PROTOCOL *Single
);
/**
Return the index of the load option in the load option array.
The function consider two load options are equal when the
OptionType, Attributes, Description, FilePath and OptionalData are equal.
@param Key Pointer to the load option to be found.
@param Array Pointer to the array of load options to be found.
@param Count Number of entries in the Array.
@retval -1 Key wasn't found in the Array.
@retval 0 ~ Count-1 The index of the Key in the Array.
**/
INTN
BmFindLoadOption (
IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
IN UINTN Count
);
/**
Repair all the controllers according to the Driver Health status queried.
**/
VOID
BmRepairAllControllers (
VOID
);
#endif // _INTERNAL_BM_H_

View File

@ -0,0 +1,110 @@
## @file
# Define and produce general Boot Manager related interfaces.
#
# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
# 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.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = UefiBootManagerLib
FILE_GUID = 8D4752BC-595E-49a2-B4AF-F3F57B601DE9
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = UefiBootManagerLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
BmPerformance.c
BmConnect.c
BmMisc.c
BmConsole.c
BmBoot.c
BmLoadOption.c
BmHotkey.c
BmDriverHealth.c
InternalBm.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
HobLib
PcdLib
BaseLib
UefiLib
TimerLib
DebugLib
PrintLib
BaseMemoryLib
DevicePathLib
PerformanceLib
PeCoffGetEntryPointLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
DxeServicesTableLib
MemoryAllocationLib
DxeServicesLib
ReportStatusCodeLib
PerformanceLib
HiiLib
BaseSortLib
[Guids]
gEfiMemoryTypeInformationGuid ## CONSUMES ## GUID (The identifier of memory type information type in system table)
## CONSUMES ## GUID HOB (The hob holding memory type information)
gEfiGlobalVariableGuid ## SOMETIMES_PRODUCES ## Variable:L"BootCurrent" (The boot option of current boot)
## SOMETIMES_CONSUMES ## Variable:L"BootXX" (Boot option variable)
## CONSUMES ## Variable:L"Timeout" (The time out value in second of showing progress bar)
## SOMETIMES_CONSUMES ## Variable:L"BootOrder" (The boot option array)
## SOMETIMES_CONSUMES ## Variable:L"DriverOrder" (The driver order list)
## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device)
## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device)
## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device)
gEfiFileInfoGuid ## CONSUMES ## GUID
gPerformanceProtocolGuid ## SOMETIMES_PRODUCES ## Variable:L"PerfDataMemAddr" (The ACPI address of performance data)
gEdkiiStatusCodeDataTypeVariableGuid ## SOMETIMES_CONSUMES ## GUID
gEfiDiskInfoAhciInterfaceGuid ## SOMETIMES_CONSUMES ## GUID
gEfiDiskInfoIdeInterfaceGuid ## SOMETIMES_CONSUMES ## GUID
gEfiDiskInfoScsiInterfaceGuid ## SOMETIMES_CONSUMES ## GUID
gZeroGuid ## CONSUMES ## GUID
[Protocols]
gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
gEfiSimpleFileSystemProtocolGuid ## CONSUMES
gEfiLoadFileProtocolGuid ## CONSUMES
gEfiSimpleTextOutProtocolGuid ## CONSUMES
gEfiPciIoProtocolGuid ## CONSUMES
gEfiLoadedImageProtocolGuid ## CONSUMES
gEfiSimpleNetworkProtocolGuid ## CONSUMES
gEfiSimpleTextInProtocolGuid ## CONSUMES
gEfiBlockIoProtocolGuid ## CONSUMES
gEfiFirmwareVolume2ProtocolGuid ## CONSUMES
gEfiDevicePathProtocolGuid ## CONSUMES
gEfiBootLogoProtocolGuid ## CONSUMES
gEfiSimpleTextInputExProtocolGuid ## CONSUMES
gEfiGraphicsOutputProtocolGuid ## SOMETIMES_CONSUMES
gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES
gEfiDiskInfoProtocolGuid ## SOMETIMES_CONSUMES
gEfiDriverHealthProtocolGuid ## SOMETIMES_CONSUMES
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderLoad ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderStart ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdDriverHealthConfigureForm ## SOMETIMES_CONSUMES

View File

@ -105,6 +105,9 @@
## @libraryclass Provides sorting functions
SortLib|Include/Library/SortLib.h
## @libraryclass Provides core boot manager functions
UefiBootManagerLib|Include/Library/UefiBootManagerLib.h
[Guids]
## MdeModule package token space guid
# Include/Guid/MdeModulePkgTokenSpace.h
@ -922,7 +925,16 @@
## Serial Port Extended Transmit FIFO Size. The default is 64 bytes.
# @Prompt Serial Port Extended Transmit FIFO Size in Bytes
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialExtendedTxFifoSize|64|UINT32|0x00010068
## This PCD points to the file name GUID of the BootManagerMenuApp
# Platform can customize the PCD to point to different application for Boot Manager Menu
gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0xdc, 0x5b, 0xc2, 0xee, 0xf2, 0x67, 0x95, 0x4d, 0xb1, 0xd5, 0xf8, 0x1b, 0x20, 0x39, 0xd1, 0x1d }|VOID*|0x0001006b
## This PCD points to the formset GUID of the driver health management form
# The form will be popped up by BDS core when there are Configuration Required driver health intances.
# Platform can customize the PCD to point to different formset.
gEfiMdeModulePkgTokenSpaceGuid.PcdDriverHealthConfigureForm|{ 0xf4, 0xd9, 0x96, 0x42, 0xfc, 0xf6, 0xde, 0x4d, 0x86, 0x85, 0x8c, 0xe2, 0xd7, 0x9d, 0x90, 0xf0 }|VOID*|0x0001006c
## The number of bytes between registers in serial device. The default is 1 byte.
# @Prompt Serial Port Register Stride in Bytes
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1|UINT32|0x0001006B

View File

@ -46,6 +46,7 @@
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
BaseSortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
#
# UEFI & PI
#
@ -267,6 +268,7 @@
MdeModulePkg/Library/PlatformHookLibSerialPortPpi/PlatformHookLibSerialPortPpi.inf
MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf