mirror of https://github.com/acidanthera/audk.git
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:
parent
58183d391c
commit
1d11222925
|
@ -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
|
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 ;
|
||||
}
|
|
@ -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_
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue