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:
657
MdeModulePkg/Include/Library/UefiBootManagerLib.h
Normal file
657
MdeModulePkg/Include/Library/UefiBootManagerLib.h
Normal file
@ -0,0 +1,657 @@
|
|||||||
|
/** @file
|
||||||
|
Provide Boot Manager related library APIs.
|
||||||
|
|
||||||
|
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _UEFI_BOOT_MANAGER_LIB_H_
|
||||||
|
#define _UEFI_BOOT_MANAGER_LIB_H_
|
||||||
|
|
||||||
|
#include <Protocol/DriverHealth.h>
|
||||||
|
#include <Library/SortLib.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// Boot Manager load option library functions.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Load Option Type
|
||||||
|
//
|
||||||
|
typedef enum {
|
||||||
|
LoadOptionTypeBoot,
|
||||||
|
LoadOptionTypeDriver,
|
||||||
|
LoadOptionTypeMax
|
||||||
|
} EFI_BOOT_MANAGER_LOAD_OPTION_TYPE;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LoadOptionNumberMax = 0x10000,
|
||||||
|
LoadOptionNumberUnassigned = LoadOptionNumberMax
|
||||||
|
} EFI_BOOT_MANAGER_LOAD_OPTION_NUMBER;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Common structure definition for DriverOption and BootOption
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
//
|
||||||
|
// Data read from UEFI NV variables
|
||||||
|
//
|
||||||
|
UINTN OptionNumber; // #### numerical value, could be LoadOptionNumberUnassigned
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType; // LoadOptionTypeBoot or LoadOptionTypeDriver
|
||||||
|
UINT32 Attributes; // Load Option Attributes
|
||||||
|
CHAR16 *Description; // Load Option Description
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *FilePath; // Load Option Device Path
|
||||||
|
UINT8 *OptionalData; // Load Option optional data to pass into image
|
||||||
|
UINT32 OptionalDataSize; // Load Option size of OptionalData
|
||||||
|
|
||||||
|
//
|
||||||
|
// Used at runtime
|
||||||
|
//
|
||||||
|
EFI_STATUS Status; // Status returned from boot attempt gBS->StartImage ()
|
||||||
|
CHAR16 *ExitData; // Exit data returned from gBS->StartImage ()
|
||||||
|
UINTN ExitDataSize; // Size of ExitData
|
||||||
|
} EFI_BOOT_MANAGER_LOAD_OPTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns an array of load options based on the EFI variable
|
||||||
|
L"BootOrder"/L"DriverOrder" and the L"Boot####"/L"Driver####" variables impled by it.
|
||||||
|
#### is the hex value of the UINT16 in each BootOrder/DriverOrder entry.
|
||||||
|
|
||||||
|
@param LoadOptionCount Returns number of entries in the array.
|
||||||
|
@param LoadOptionType The type of the load option.
|
||||||
|
|
||||||
|
@retval NULL No load options exist.
|
||||||
|
@retval !NULL Array of load option entries.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION *
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerGetLoadOptions (
|
||||||
|
OUT UINTN *LoadOptionCount,
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Free an array of load options returned from EfiBootManagerGetLoadOptions().
|
||||||
|
|
||||||
|
@param LoadOptions Pointer to the array of load options to free.
|
||||||
|
@param LoadOptionCount Number of array entries in LoadOptions.
|
||||||
|
|
||||||
|
@return EFI_SUCCESS LoadOptions was freed.
|
||||||
|
@return EFI_INVALID_PARAMETER LoadOptions is NULL.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerFreeLoadOptions (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOptions,
|
||||||
|
IN UINTN LoadOptionCount
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize a load option.
|
||||||
|
|
||||||
|
@param Option Pointer to the load option to be initialized.
|
||||||
|
@param OptionNumber Option number of the load option.
|
||||||
|
@param OptionType Type of the load option.
|
||||||
|
@param Attributes Attributes of the load option.
|
||||||
|
@param Description Description of the load option.
|
||||||
|
@param FilePath Device path of the load option.
|
||||||
|
@param OptionalData Optional data of the load option.
|
||||||
|
@param OptionalDataSize Size of the optional data of the load option.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The load option was initialized successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER Option, Description or FilePath is NULL.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerInitializeLoadOption (
|
||||||
|
IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option,
|
||||||
|
IN UINTN OptionNumber,
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
|
||||||
|
IN UINT32 Attributes,
|
||||||
|
IN CHAR16 *Description,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||||
|
IN UINT8 *OptionalData,
|
||||||
|
IN UINT32 OptionalDataSize
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Free a load option created by EfiBootManagerInitializeLoadOption()
|
||||||
|
or EfiBootManagerVariableToLoadOption().
|
||||||
|
|
||||||
|
@param LoadOption Pointer to the load option to free.
|
||||||
|
CONCERN: Check Boot#### instead of BootOrder, optimize, spec clarify
|
||||||
|
@return EFI_SUCCESS LoadOption was freed.
|
||||||
|
@return EFI_INVALID_PARAMETER LoadOption is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerFreeLoadOption (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize the load option from the VariableName.
|
||||||
|
|
||||||
|
@param VariableName EFI Variable name which could be Boot#### or
|
||||||
|
Driver####
|
||||||
|
@param LoadOption Pointer to the load option to be initialized
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The option was created
|
||||||
|
@retval EFI_INVALID_PARAMETER VariableName or LoadOption is NULL.
|
||||||
|
@retval EFI_NOT_FOUND The variable specified by VariableName cannot be found.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerVariableToLoadOption (
|
||||||
|
IN CHAR16 *VariableName,
|
||||||
|
IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create the Boot#### or Driver#### variable from the load option.
|
||||||
|
|
||||||
|
@param LoadOption Pointer to the load option.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The variable was created.
|
||||||
|
@retval Others Error status returned by RT->SetVariable.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerLoadOptionToVariable (
|
||||||
|
IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function will update the Boot####/Driver#### and the BootOrder/DriverOrder
|
||||||
|
to add a new load option.
|
||||||
|
|
||||||
|
@param Option Pointer to load option to add.
|
||||||
|
@param Position Position of the new load option to put in the BootOrder/DriverOrder.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The load option has been successfully added.
|
||||||
|
@retval Others Error status returned by RT->SetVariable.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerAddLoadOptionVariable (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION *Option,
|
||||||
|
IN UINTN Position
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Delete the load option according to the OptionNumber and OptionType.
|
||||||
|
|
||||||
|
Only the BootOrder/DriverOrder is updated to remove the reference of the OptionNumber.
|
||||||
|
|
||||||
|
@param OptionNumber Option number of the load option.
|
||||||
|
@param OptionType Type of the load option.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND The load option cannot be found.
|
||||||
|
@retval EFI_SUCCESS The load option was deleted.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerDeleteLoadOptionVariable (
|
||||||
|
IN UINTN OptionNumber,
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sort the load options. The DriverOrder/BootOrder variables will be re-created to
|
||||||
|
reflect the new order.
|
||||||
|
|
||||||
|
@param OptionType The type of the load option.
|
||||||
|
@param Comparator The comparator function pointer.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerSortLoadOptionVariable (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
|
||||||
|
IN SORT_COMPARE CompareFunction
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Boot Manager hot key library functions.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
|
///
|
||||||
|
/// EFI Key Option.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
///
|
||||||
|
/// Specifies options about how the key will be processed.
|
||||||
|
///
|
||||||
|
EFI_BOOT_KEY_DATA KeyData;
|
||||||
|
///
|
||||||
|
/// The CRC-32 which should match the CRC-32 of the entire EFI_LOAD_OPTION to
|
||||||
|
/// which BootOption refers. If the CRC-32s do not match this value, then this key
|
||||||
|
/// option is ignored.
|
||||||
|
///
|
||||||
|
UINT32 BootOptionCrc;
|
||||||
|
///
|
||||||
|
/// The Boot#### option which will be invoked if this key is pressed and the boot option
|
||||||
|
/// is active (LOAD_OPTION_ACTIVE is set).
|
||||||
|
///
|
||||||
|
UINT16 BootOption;
|
||||||
|
///
|
||||||
|
/// The key codes to compare against those returned by the
|
||||||
|
/// EFI_SIMPLE_TEXT_INPUT and EFI_SIMPLE_TEXT_INPUT_EX protocols.
|
||||||
|
/// The number of key codes (0-3) is specified by the EFI_KEY_CODE_COUNT field in KeyOptions.
|
||||||
|
///
|
||||||
|
EFI_INPUT_KEY Keys[3];
|
||||||
|
UINT16 OptionNumber;
|
||||||
|
} EFI_BOOT_MANAGER_KEY_OPTION;
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
/**
|
||||||
|
Start the hot key service so that the key press can trigger the boot option.
|
||||||
|
|
||||||
|
@param HotkeyTriggered Return the waitable event and it will be signaled
|
||||||
|
when a valid hot key is pressed.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The hot key service is started.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerStartHotkeyService (
|
||||||
|
IN EFI_EVENT *HotkeyTriggered
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Modifier for EfiBootManagerAddKeyOptionVariable and EfiBootManagerDeleteKeyOptionVariable
|
||||||
|
//
|
||||||
|
#define EFI_BOOT_MANAGER_SHIFT_PRESSED 0x00000001
|
||||||
|
#define EFI_BOOT_MANAGER_CONTROL_PRESSED 0x00000002
|
||||||
|
#define EFI_BOOT_MANAGER_ALT_PRESSED 0x00000004
|
||||||
|
#define EFI_BOOT_MANAGER_LOGO_PRESSED 0x00000008
|
||||||
|
#define EFI_BOOT_MANAGER_MENU_KEY_PRESSED 0x00000010
|
||||||
|
#define EFI_BOOT_MANAGER_SYS_REQ_PRESSED 0x00000020
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add the key option.
|
||||||
|
It adds the key option variable and the key option takes affect immediately.
|
||||||
|
|
||||||
|
@param AddedOption Return the added key option.
|
||||||
|
@param BootOptionNumber The boot option number for the key option.
|
||||||
|
@param Modifier Key shift state.
|
||||||
|
@param ... Parameter list of pointer of EFI_INPUT_KEY.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The key option is added.
|
||||||
|
@retval EFI_ALREADY_STARTED The hot key is already used by certain key option.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerAddKeyOptionVariable (
|
||||||
|
OUT EFI_BOOT_MANAGER_KEY_OPTION *AddedOption, OPTIONAL
|
||||||
|
IN UINT16 BootOptionNumber,
|
||||||
|
IN UINT32 Modifier,
|
||||||
|
...
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Delete the Key Option variable and unregister the hot key
|
||||||
|
|
||||||
|
@param DeletedOption Return the deleted key options.
|
||||||
|
@param Modifier Key shift state.
|
||||||
|
@param ... Parameter list of pointer of EFI_INPUT_KEY.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The key option is deleted.
|
||||||
|
@retval EFI_NOT_FOUND The key option cannot be found.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerDeleteKeyOptionVariable (
|
||||||
|
IN EFI_BOOT_MANAGER_KEY_OPTION *DeletedOption, OPTIONAL
|
||||||
|
IN UINT32 Modifier,
|
||||||
|
...
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Register the key option to exit the waiting of the Boot Manager timeout.
|
||||||
|
Platform should ensure that the continue key option isn't conflict with
|
||||||
|
other boot key options.
|
||||||
|
|
||||||
|
@param Modifier Key shift state.
|
||||||
|
@param ... Parameter list of pointer of EFI_INPUT_KEY.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully register the continue key option.
|
||||||
|
@retval EFI_ALREADY_STARTED The continue key option is already registered.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerRegisterContinueKeyOption (
|
||||||
|
IN UINT32 Modifier,
|
||||||
|
...
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Try to boot the boot option triggered by hot key.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerHotkeyBoot (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// Boot Manager boot library functions.
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
The function creates boot options for all possible bootable medias in the following order:
|
||||||
|
1. Removable BlockIo - The boot option only points to the removable media
|
||||||
|
device, like USB key, DVD, Floppy etc.
|
||||||
|
2. Fixed BlockIo - The boot option only points to a Fixed blockIo device,
|
||||||
|
like HardDisk.
|
||||||
|
3. Non-BlockIo SimpleFileSystem - The boot option points to a device supporting
|
||||||
|
SimpleFileSystem Protocol, but not supporting BlockIo
|
||||||
|
protocol.
|
||||||
|
4. LoadFile - The boot option points to the media supporting
|
||||||
|
LoadFile protocol.
|
||||||
|
Reference: UEFI Spec chapter 3.3 Boot Option Variables Default Boot Behavior
|
||||||
|
|
||||||
|
The function won't delete the boot option not added by itself.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerRefreshAllBootOption (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Attempt to boot the EFI boot option. This routine sets L"BootCurent" and
|
||||||
|
signals the EFI ready to boot event. If the device path for the option starts
|
||||||
|
with a BBS device path a legacy boot is attempted. Short form device paths are
|
||||||
|
also supported via this rountine. A device path starting with
|
||||||
|
MEDIA_HARDDRIVE_DP, MSG_USB_WWID_DP, MSG_USB_CLASS_DP gets expaned out
|
||||||
|
to find the first device that matches. If the BootOption Device Path
|
||||||
|
fails the removable media boot algorithm is attempted (\EFI\BOOTIA32.EFI,
|
||||||
|
\EFI\BOOTX64.EFI,... only one file type is tried per processor type)
|
||||||
|
|
||||||
|
@param BootOption Boot Option to try and boot.
|
||||||
|
On return, BootOption->Status contains the boot status:
|
||||||
|
EFI_SUCCESS BootOption was booted
|
||||||
|
EFI_UNSUPPORTED BootOption isn't supported.
|
||||||
|
EFI_NOT_FOUND The BootOption was not found on the system
|
||||||
|
Others BootOption failed with this error status
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerBoot (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the Boot Manager Menu.
|
||||||
|
|
||||||
|
@param BootOption Return the Boot Manager Menu.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The Boot Manager Menu is successfully returned.
|
||||||
|
@retval EFI_NOT_FOUND The Boot Manager Menu is not found.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerGetBootManagerMenu (
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The function enumerates all the legacy boot options, creates them and
|
||||||
|
registers them in the BootOrder variable.
|
||||||
|
**/
|
||||||
|
typedef
|
||||||
|
VOID
|
||||||
|
(EFIAPI *EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION) (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The function boots a legacy boot option.
|
||||||
|
**/
|
||||||
|
typedef
|
||||||
|
VOID
|
||||||
|
(EFIAPI *EFI_BOOT_MANAGER_LEGACY_BOOT) (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
The function registers the legacy boot support capabilities.
|
||||||
|
|
||||||
|
@param RefreshLegacyBootOption The function pointer to create all the legacy boot options.
|
||||||
|
@param LegacyBoot The function pointer to boot the legacy boot option.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerRegisterLegacyBootSupport (
|
||||||
|
EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION RefreshLegacyBootOption,
|
||||||
|
EFI_BOOT_MANAGER_LEGACY_BOOT LegacyBoot
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Boot Manager connect and disconnect library functions
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function will connect all the system driver to controller
|
||||||
|
first, and then special connect the default console, this make
|
||||||
|
sure all the system controller available and the platform default
|
||||||
|
console connected.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerConnectAll (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function will create all handles associate with every device
|
||||||
|
path node. If the handle associate with one device path node can not
|
||||||
|
be created successfully, then still give one chance to do the dispatch,
|
||||||
|
which load the missing drivers if possible.
|
||||||
|
|
||||||
|
@param DevicePathToConnect The device path which will be connected, it CANNOT be
|
||||||
|
a multi-instance device path
|
||||||
|
@param MatchingHandle Return the controller handle closest to the DevicePathToConnect
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER DevicePathToConnect is NULL.
|
||||||
|
@retval EFI_NOT_FOUND Failed to create all handles associate with every device path node.
|
||||||
|
@retval EFI_SUCCESS Successful to create all handles associate with every device path node.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerConnectDevicePath (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect,
|
||||||
|
OUT EFI_HANDLE *MatchingHandle OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function will disconnect all current system handles.
|
||||||
|
|
||||||
|
gBS->DisconnectController() is invoked for each handle exists in system handle buffer.
|
||||||
|
If handle is a bus type handle, all childrens also are disconnected recursively by
|
||||||
|
gBS->DisconnectController().
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerDisconnectAll (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Boot Manager console library functions
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ConIn,
|
||||||
|
ConOut,
|
||||||
|
ErrOut,
|
||||||
|
ConInDev,
|
||||||
|
ConOutDev,
|
||||||
|
ErrOutDev,
|
||||||
|
ConsoleTypeMax
|
||||||
|
} CONSOLE_TYPE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function will connect all the console devices base on the console
|
||||||
|
device variable ConIn, ConOut and ErrOut.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerConnectAllDefaultConsoles (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function updates the console variable based on ConVarName. It can
|
||||||
|
add or remove one specific console device path from the variable
|
||||||
|
|
||||||
|
@param ConsoleType ConIn, ConOut, ErrOut, ConInDev, ConOutDev or ErrOutDev.
|
||||||
|
@param CustomizedConDevicePath The console device path to be added to
|
||||||
|
the console variable. Cannot be multi-instance.
|
||||||
|
@param ExclusiveDevicePath The console device path to be removed
|
||||||
|
from the console variable. Cannot be multi-instance.
|
||||||
|
|
||||||
|
@retval EFI_UNSUPPORTED The added device path is the same as a removed one.
|
||||||
|
@retval EFI_SUCCESS Successfully added or removed the device path from the
|
||||||
|
console variable.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerUpdateConsoleVariable (
|
||||||
|
IN CONSOLE_TYPE ConsoleType,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Connect the console device base on the variable ConVarName, if
|
||||||
|
device path of the ConVarName is multi-instance device path, if
|
||||||
|
anyone of the instances is connected success, then this function
|
||||||
|
will return success.
|
||||||
|
|
||||||
|
@param ConsoleType ConIn, ConOut or ErrOut.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND There is not any console devices connected
|
||||||
|
success
|
||||||
|
@retval EFI_SUCCESS Success connect any one instance of the console
|
||||||
|
device path base on the variable ConVarName.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerConnectConsoleVariable (
|
||||||
|
IN CONSOLE_TYPE ConsoleType
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Query all the children of VideoController and return the device paths of all the
|
||||||
|
children that support GraphicsOutput protocol.
|
||||||
|
|
||||||
|
@param VideoController PCI handle of video controller.
|
||||||
|
|
||||||
|
@return Device paths of all the children that support GraphicsOutput protocol.
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerGetGopDevicePath (
|
||||||
|
IN EFI_HANDLE VideoController
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Connect the platform active active video controller.
|
||||||
|
|
||||||
|
@param VideoController PCI handle of video controller.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND There is no active video controller.
|
||||||
|
@retval EFI_SUCCESS The video controller is connected.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerConnectVideoController (
|
||||||
|
EFI_HANDLE VideoController OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Boot Manager driver health library functions.
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Driver relative handles
|
||||||
|
///
|
||||||
|
EFI_HANDLE DriverHealthHandle;
|
||||||
|
EFI_HANDLE ControllerHandle;
|
||||||
|
EFI_HANDLE ChildHandle;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Driver health messages of the specify Driver
|
||||||
|
///
|
||||||
|
EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// HII relative handles
|
||||||
|
///
|
||||||
|
EFI_HII_HANDLE HiiHandle;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Driver Health status
|
||||||
|
///
|
||||||
|
EFI_DRIVER_HEALTH_STATUS HealthStatus;
|
||||||
|
} EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return all the Driver Health information.
|
||||||
|
|
||||||
|
When the cumulative health status of all the controllers managed by the
|
||||||
|
driver who produces the EFI_DRIVER_HEALTH_PROTOCOL is healthy, only one
|
||||||
|
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry is created for such
|
||||||
|
EFI_DRIVER_HEALTH_PROTOCOL instance.
|
||||||
|
Otherwise, every controller creates one EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO
|
||||||
|
entry. Additionally every child controller creates one
|
||||||
|
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry if the driver is a bus driver.
|
||||||
|
|
||||||
|
@param Count Return the count of the Driver Health information.
|
||||||
|
|
||||||
|
@retval NULL No Driver Health information is returned.
|
||||||
|
@retval !NULL Pointer to the Driver Health information array.
|
||||||
|
**/
|
||||||
|
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerGetDriverHealthInfo (
|
||||||
|
UINTN *Count
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Free the Driver Health information array.
|
||||||
|
|
||||||
|
@param DriverHealthInfo Pointer to array of the Driver Health information.
|
||||||
|
@param Count Count of the array.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The array is freed.
|
||||||
|
@retval EFI_INVALID_PARAMETER The array is NULL.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerFreeDriverHealthInfo (
|
||||||
|
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo,
|
||||||
|
UINTN Count
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
@ -1,7 +1,7 @@
|
|||||||
## @file
|
## @file
|
||||||
# Library used for sorting routines.
|
# 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
|
# This program and the accompanying materials
|
||||||
# are licensed and made available under the terms and conditions of the BSD License
|
# 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
|
FILE_GUID = 03F3331B-F12D-494f-BF37-E55A657F2497
|
||||||
MODULE_TYPE = UEFI_DRIVER
|
MODULE_TYPE = UEFI_DRIVER
|
||||||
VERSION_STRING = 1.0
|
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
|
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||||
|
2278
MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
Normal file
2278
MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
Normal file
File diff suppressed because it is too large
Load Diff
318
MdeModulePkg/Library/UefiBootManagerLib/BmConnect.c
Normal file
318
MdeModulePkg/Library/UefiBootManagerLib/BmConnect.c
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
/** @file
|
||||||
|
Library functions which relate with connecting the device.
|
||||||
|
|
||||||
|
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "InternalBm.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Connect all the drivers to all the controllers.
|
||||||
|
|
||||||
|
This function makes sure all the current system drivers manage the correspoinding
|
||||||
|
controllers if have. And at the same time, makes sure all the system controllers
|
||||||
|
have driver to manage it if have.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmConnectAllDriversToAllControllers (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN HandleCount;
|
||||||
|
EFI_HANDLE *HandleBuffer;
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
do {
|
||||||
|
//
|
||||||
|
// Connect All EFI 1.10 drivers following EFI 1.10 algorithm
|
||||||
|
//
|
||||||
|
gBS->LocateHandleBuffer (
|
||||||
|
AllHandles,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&HandleCount,
|
||||||
|
&HandleBuffer
|
||||||
|
);
|
||||||
|
|
||||||
|
for (Index = 0; Index < HandleCount; Index++) {
|
||||||
|
gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HandleBuffer != NULL) {
|
||||||
|
FreePool (HandleBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check to see if it's possible to dispatch an more DXE drivers.
|
||||||
|
// The above code may have made new DXE drivers show up.
|
||||||
|
// If any new driver is dispatched (Status == EFI_SUCCESS) and we will try
|
||||||
|
// the connect again.
|
||||||
|
//
|
||||||
|
Status = gDS->Dispatch ();
|
||||||
|
|
||||||
|
} while (!EFI_ERROR (Status));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function will connect all the system driver to controller
|
||||||
|
first, and then special connect the default console, this make
|
||||||
|
sure all the system controller available and the platform default
|
||||||
|
console connected.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerConnectAll (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Connect the platform console first
|
||||||
|
//
|
||||||
|
EfiBootManagerConnectAllDefaultConsoles ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Generic way to connect all the drivers
|
||||||
|
//
|
||||||
|
BmConnectAllDriversToAllControllers ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Here we have the assumption that we have already had
|
||||||
|
// platform default console
|
||||||
|
//
|
||||||
|
EfiBootManagerConnectAllDefaultConsoles ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function will create all handles associate with every device
|
||||||
|
path node. If the handle associate with one device path node can not
|
||||||
|
be created successfully, then still give chance to do the dispatch,
|
||||||
|
which load the missing drivers if possible.
|
||||||
|
|
||||||
|
@param DevicePathToConnect The device path which will be connected, it can be
|
||||||
|
a multi-instance device path
|
||||||
|
@param MatchingHandle Return the controller handle closest to the DevicePathToConnect
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS All handles associate with every device path node
|
||||||
|
have been created
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is no resource to create new handles
|
||||||
|
@retval EFI_NOT_FOUND Create the handle associate with one device path
|
||||||
|
node failed
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerConnectDevicePath (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect,
|
||||||
|
OUT EFI_HANDLE *MatchingHandle OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
|
||||||
|
EFI_HANDLE Handle;
|
||||||
|
EFI_HANDLE PreviousHandle;
|
||||||
|
EFI_TPL CurrentTpl;
|
||||||
|
|
||||||
|
if (DevicePathToConnect == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentTpl = EfiGetCurrentTpl ();
|
||||||
|
//
|
||||||
|
// Start the real work of connect with RemainingDevicePath
|
||||||
|
//
|
||||||
|
PreviousHandle = NULL;
|
||||||
|
do {
|
||||||
|
//
|
||||||
|
// Find the handle that best matches the Device Path. If it is only a
|
||||||
|
// partial match the remaining part of the device path is returned in
|
||||||
|
// RemainingDevicePath.
|
||||||
|
//
|
||||||
|
RemainingDevicePath = DevicePathToConnect;
|
||||||
|
Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
if (Handle == PreviousHandle) {
|
||||||
|
//
|
||||||
|
// If no forward progress is made try invoking the Dispatcher.
|
||||||
|
// A new FV may have been added to the system an new drivers
|
||||||
|
// may now be found.
|
||||||
|
// Status == EFI_SUCCESS means a driver was dispatched
|
||||||
|
// Status == EFI_NOT_FOUND means no new drivers were dispatched
|
||||||
|
//
|
||||||
|
if (CurrentTpl == TPL_APPLICATION) {
|
||||||
|
Status = gDS->Dispatch ();
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Always return EFI_NOT_FOUND here
|
||||||
|
// to prevent dead loop when control handle is found but connection failded case
|
||||||
|
//
|
||||||
|
Status = EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
PreviousHandle = Handle;
|
||||||
|
//
|
||||||
|
// Connect all drivers that apply to Handle and RemainingDevicePath,
|
||||||
|
// the Recursive flag is FALSE so only one level will be expanded.
|
||||||
|
//
|
||||||
|
// Do not check the connect status here, if the connect controller fail,
|
||||||
|
// then still give the chance to do dispatch, because partial
|
||||||
|
// RemainingDevicepath may be in the new FV
|
||||||
|
//
|
||||||
|
// 1. If the connect fail, RemainingDevicepath and handle will not
|
||||||
|
// change, so next time will do the dispatch, then dispatch's status
|
||||||
|
// will take effect
|
||||||
|
// 2. If the connect success, the RemainingDevicepath and handle will
|
||||||
|
// change, then avoid the dispatch, we have chance to continue the
|
||||||
|
// next connection
|
||||||
|
//
|
||||||
|
gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
|
||||||
|
if (MatchingHandle != NULL) {
|
||||||
|
*MatchingHandle = Handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Loop until RemainingDevicePath is an empty device path
|
||||||
|
//
|
||||||
|
} while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
|
||||||
|
|
||||||
|
ASSERT (EFI_ERROR (Status) || IsDevicePathEnd (RemainingDevicePath));
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function will disconnect all current system handles.
|
||||||
|
|
||||||
|
gBS->DisconnectController() is invoked for each handle exists in system handle buffer.
|
||||||
|
If handle is a bus type handle, all childrens also are disconnected recursively by
|
||||||
|
gBS->DisconnectController().
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerDisconnectAll (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN HandleCount;
|
||||||
|
EFI_HANDLE *HandleBuffer;
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Disconnect all
|
||||||
|
//
|
||||||
|
gBS->LocateHandleBuffer (
|
||||||
|
AllHandles,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&HandleCount,
|
||||||
|
&HandleBuffer
|
||||||
|
);
|
||||||
|
for (Index = 0; Index < HandleCount; Index++) {
|
||||||
|
gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HandleBuffer != NULL) {
|
||||||
|
FreePool (HandleBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Connect the specific Usb device which match the short form device path,
|
||||||
|
and whose bus is determined by Host Controller (Uhci or Ehci).
|
||||||
|
|
||||||
|
@param DevicePath A short-form device path that starts with the first
|
||||||
|
element being a USB WWID or a USB Class device
|
||||||
|
path
|
||||||
|
|
||||||
|
@return EFI_INVALID_PARAMETER DevicePath is NULL pointer.
|
||||||
|
DevicePath is not a USB device path.
|
||||||
|
|
||||||
|
@return EFI_SUCCESS Success to connect USB device
|
||||||
|
@return EFI_NOT_FOUND Fail to find handle for USB controller to connect.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmConnectUsbShortFormDevicePath (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_HANDLE *Handles;
|
||||||
|
UINTN HandleCount;
|
||||||
|
UINTN Index;
|
||||||
|
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||||
|
UINT8 Class[3];
|
||||||
|
BOOLEAN AtLeastOneConnected;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check the passed in parameters
|
||||||
|
//
|
||||||
|
if (DevicePath == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||
|
||||||
|
((DevicePathSubType (DevicePath) != MSG_USB_CLASS_DP) && (DevicePathSubType (DevicePath) != MSG_USB_WWID_DP))
|
||||||
|
) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Find the usb host controller firstly, then connect with the remaining device path
|
||||||
|
//
|
||||||
|
AtLeastOneConnected = FALSE;
|
||||||
|
Status = gBS->LocateHandleBuffer (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiPciIoProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&HandleCount,
|
||||||
|
&Handles
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
for (Index = 0; Index < HandleCount; Index++) {
|
||||||
|
Status = gBS->HandleProtocol (
|
||||||
|
Handles[Index],
|
||||||
|
&gEfiPciIoProtocolGuid,
|
||||||
|
(VOID **) &PciIo
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Check whether the Pci device is the wanted usb host controller
|
||||||
|
//
|
||||||
|
Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
|
||||||
|
if (!EFI_ERROR (Status) &&
|
||||||
|
((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))
|
||||||
|
) {
|
||||||
|
Status = gBS->ConnectController (
|
||||||
|
Handles[Index],
|
||||||
|
NULL,
|
||||||
|
DevicePath,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR(Status)) {
|
||||||
|
AtLeastOneConnected = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Handles != NULL) {
|
||||||
|
FreePool (Handles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;
|
||||||
|
}
|
748
MdeModulePkg/Library/UefiBootManagerLib/BmConsole.c
Normal file
748
MdeModulePkg/Library/UefiBootManagerLib/BmConsole.c
Normal file
@ -0,0 +1,748 @@
|
|||||||
|
/** @file
|
||||||
|
Library functions which contain all the code to connect console device.
|
||||||
|
|
||||||
|
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "InternalBm.h"
|
||||||
|
|
||||||
|
CHAR16 *mConVarName[] = {
|
||||||
|
L"ConIn",
|
||||||
|
L"ConOut",
|
||||||
|
L"ErrOut",
|
||||||
|
L"ConInDev",
|
||||||
|
L"ConOutDev",
|
||||||
|
L"ErrOutDev"
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Search out the video controller.
|
||||||
|
|
||||||
|
@return PCI device path of the video controller.
|
||||||
|
**/
|
||||||
|
EFI_HANDLE
|
||||||
|
BmGetVideoController (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN RootBridgeHandleCount;
|
||||||
|
EFI_HANDLE *RootBridgeHandleBuffer;
|
||||||
|
UINTN HandleCount;
|
||||||
|
EFI_HANDLE *HandleBuffer;
|
||||||
|
UINTN RootBridgeIndex;
|
||||||
|
UINTN Index;
|
||||||
|
EFI_HANDLE VideoController;
|
||||||
|
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||||
|
PCI_TYPE00 Pci;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Make all the PCI_IO protocols show up
|
||||||
|
//
|
||||||
|
Status = gBS->LocateHandleBuffer (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiPciRootBridgeIoProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&RootBridgeHandleCount,
|
||||||
|
&RootBridgeHandleBuffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status) || (RootBridgeHandleCount == 0)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoController = NULL;
|
||||||
|
for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {
|
||||||
|
gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Start to check all the pci io to find the first video controller
|
||||||
|
//
|
||||||
|
Status = gBS->LocateHandleBuffer (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiPciIoProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&HandleCount,
|
||||||
|
&HandleBuffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Index = 0; Index < HandleCount; Index++) {
|
||||||
|
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Check for all video controller
|
||||||
|
//
|
||||||
|
Status = PciIo->Pci.Read (
|
||||||
|
PciIo,
|
||||||
|
EfiPciIoWidthUint32,
|
||||||
|
0,
|
||||||
|
sizeof (Pci) / sizeof (UINT32),
|
||||||
|
&Pci
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status) && IS_PCI_VGA (&Pci)) {
|
||||||
|
// TODO: use IS_PCI_DISPLAY??
|
||||||
|
VideoController = HandleBuffer[Index];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreePool (HandleBuffer);
|
||||||
|
|
||||||
|
if (VideoController != NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreePool (RootBridgeHandleBuffer);
|
||||||
|
|
||||||
|
return VideoController;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Query all the children of VideoController and return the device paths of all the
|
||||||
|
children that support GraphicsOutput protocol.
|
||||||
|
|
||||||
|
@param VideoController PCI handle of video controller.
|
||||||
|
|
||||||
|
@return Device paths of all the children that support GraphicsOutput protocol.
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerGetGopDevicePath (
|
||||||
|
IN EFI_HANDLE VideoController
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_GUID **ProtocolBuffer;
|
||||||
|
UINTN ProtocolBufferCount;
|
||||||
|
UINTN ProtocolIndex;
|
||||||
|
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
|
||||||
|
UINTN EntryCount;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *Next;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *Previous;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *GopPool;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;
|
||||||
|
|
||||||
|
|
||||||
|
Status = gBS->ProtocolsPerHandle (
|
||||||
|
VideoController,
|
||||||
|
&ProtocolBuffer,
|
||||||
|
&ProtocolBufferCount
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GopPool = NULL;
|
||||||
|
|
||||||
|
for (ProtocolIndex = 0; ProtocolIndex < ProtocolBufferCount; ProtocolIndex++) {
|
||||||
|
Status = gBS->OpenProtocolInformation (
|
||||||
|
VideoController,
|
||||||
|
ProtocolBuffer[ProtocolIndex],
|
||||||
|
&OpenInfoBuffer,
|
||||||
|
&EntryCount
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Index = 0; Index < EntryCount; Index++) {
|
||||||
|
//
|
||||||
|
// Query all the children
|
||||||
|
//
|
||||||
|
if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
OpenInfoBuffer[Index].ControllerHandle,
|
||||||
|
&gEfiDevicePathProtocolGuid,
|
||||||
|
(VOID **) &DevicePath,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Previous = NULL;
|
||||||
|
for (Next = DevicePath; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {
|
||||||
|
Previous = Next;
|
||||||
|
}
|
||||||
|
ASSERT (Previous != NULL);
|
||||||
|
|
||||||
|
if (DevicePathType (Previous) == ACPI_DEVICE_PATH && DevicePathSubType (Previous) == ACPI_ADR_DP) {
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
OpenInfoBuffer[Index].ControllerHandle,
|
||||||
|
&gEfiGraphicsOutputProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Append the device path to GOP pool when there is GOP protocol installed.
|
||||||
|
//
|
||||||
|
TempDevicePath = GopPool;
|
||||||
|
GopPool = AppendDevicePathInstance (GopPool, DevicePath);
|
||||||
|
gBS->FreePool (TempDevicePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DevicePathType (Previous) == HARDWARE_DEVICE_PATH && DevicePathSubType (Previous) == HW_CONTROLLER_DP) {
|
||||||
|
//
|
||||||
|
// Recursively look for GOP child in this frame buffer handle
|
||||||
|
//
|
||||||
|
DEBUG ((EFI_D_INFO, "[Bds] Looking for GOP child deeper ... \n"));
|
||||||
|
TempDevicePath = GopPool;
|
||||||
|
ReturnDevicePath = EfiBootManagerGetGopDevicePath (OpenInfoBuffer[Index].ControllerHandle);
|
||||||
|
GopPool = AppendDevicePathInstance (GopPool, ReturnDevicePath);
|
||||||
|
gBS->FreePool (ReturnDevicePath);
|
||||||
|
gBS->FreePool (TempDevicePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool (OpenInfoBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool (ProtocolBuffer);
|
||||||
|
|
||||||
|
return GopPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Connect the platform active active video controller.
|
||||||
|
|
||||||
|
@param VideoController PCI handle of video controller.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND There is no active video controller.
|
||||||
|
@retval EFI_SUCCESS The video controller is connected.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerConnectVideoController (
|
||||||
|
EFI_HANDLE VideoController OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *Gop;
|
||||||
|
|
||||||
|
if (VideoController == NULL) {
|
||||||
|
//
|
||||||
|
// Get the platform vga device
|
||||||
|
//
|
||||||
|
VideoController = BmGetVideoController ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VideoController == NULL) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Try to connect the PCI device path, so that GOP dirver could start on this
|
||||||
|
// device and create child handles with GraphicsOutput Protocol installed
|
||||||
|
// on them, then we get device paths of these child handles and select
|
||||||
|
// them as possible console device.
|
||||||
|
//
|
||||||
|
gBS->ConnectController (VideoController, NULL, NULL, FALSE);
|
||||||
|
|
||||||
|
Gop = EfiBootManagerGetGopDevicePath (VideoController);
|
||||||
|
if (Gop == NULL) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
EfiBootManagerUpdateConsoleVariable (ConOut, Gop, NULL);
|
||||||
|
FreePool (Gop);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Necessary for ConPlatform and ConSplitter driver to start up again after ConOut is updated.
|
||||||
|
//
|
||||||
|
return gBS->ConnectController (VideoController, NULL, NULL, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fill console handle in System Table if there are no valid console handle in.
|
||||||
|
|
||||||
|
Firstly, check the validation of console handle in System Table. If it is invalid,
|
||||||
|
update it by the first console device handle from EFI console variable.
|
||||||
|
|
||||||
|
@param VarName The name of the EFI console variable.
|
||||||
|
@param ConsoleGuid Specified Console protocol GUID.
|
||||||
|
@param ConsoleHandle On IN, console handle in System Table to be checked.
|
||||||
|
On OUT, new console handle in system table.
|
||||||
|
@param ProtocolInterface On IN, console protocol on console handle in System Table to be checked.
|
||||||
|
On OUT, new console protocol on new console handle in system table.
|
||||||
|
|
||||||
|
@retval TRUE System Table has been updated.
|
||||||
|
@retval FALSE System Table hasn't been updated.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
BmUpdateSystemTableConsole (
|
||||||
|
IN CHAR16 *VarName,
|
||||||
|
IN EFI_GUID *ConsoleGuid,
|
||||||
|
IN OUT EFI_HANDLE *ConsoleHandle,
|
||||||
|
IN OUT VOID **ProtocolInterface
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN DevicePathSize;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *VarConsole;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *Instance;
|
||||||
|
VOID *Interface;
|
||||||
|
EFI_HANDLE NewHandle;
|
||||||
|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
|
||||||
|
|
||||||
|
ASSERT (VarName != NULL);
|
||||||
|
ASSERT (ConsoleHandle != NULL);
|
||||||
|
ASSERT (ConsoleGuid != NULL);
|
||||||
|
ASSERT (ProtocolInterface != NULL);
|
||||||
|
|
||||||
|
if (*ConsoleHandle != NULL) {
|
||||||
|
Status = gBS->HandleProtocol (
|
||||||
|
*ConsoleHandle,
|
||||||
|
ConsoleGuid,
|
||||||
|
&Interface
|
||||||
|
);
|
||||||
|
if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) {
|
||||||
|
//
|
||||||
|
// If ConsoleHandle is valid and console protocol on this handle also
|
||||||
|
// also matched, just return.
|
||||||
|
//
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get all possible consoles device path from EFI variable
|
||||||
|
//
|
||||||
|
GetEfiGlobalVariable2 (VarName, (VOID **) &VarConsole, NULL);
|
||||||
|
if (VarConsole == NULL) {
|
||||||
|
//
|
||||||
|
// If there is no any console device, just return.
|
||||||
|
//
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FullDevicePath = VarConsole;
|
||||||
|
|
||||||
|
do {
|
||||||
|
//
|
||||||
|
// Check every instance of the console variable
|
||||||
|
//
|
||||||
|
Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);
|
||||||
|
if (Instance == NULL) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "[Bds] No valid console instance is found for %s!\n", VarName));
|
||||||
|
// We should not ASSERT when all the console devices are removed.
|
||||||
|
// ASSERT_EFI_ERROR (EFI_NOT_FOUND);
|
||||||
|
FreePool (FullDevicePath);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Find console device handle by device path instance
|
||||||
|
//
|
||||||
|
Status = gBS->LocateDevicePath (
|
||||||
|
ConsoleGuid,
|
||||||
|
&Instance,
|
||||||
|
&NewHandle
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Get the console protocol on this console device handle
|
||||||
|
//
|
||||||
|
Status = gBS->HandleProtocol (
|
||||||
|
NewHandle,
|
||||||
|
ConsoleGuid,
|
||||||
|
&Interface
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Update new console handle in System Table.
|
||||||
|
//
|
||||||
|
*ConsoleHandle = NewHandle;
|
||||||
|
*ProtocolInterface = Interface;
|
||||||
|
if (CompareGuid (ConsoleGuid, &gEfiSimpleTextOutProtocolGuid)) {
|
||||||
|
//
|
||||||
|
// If it is console out device, set console mode 80x25 if current mode is invalid.
|
||||||
|
//
|
||||||
|
TextOut = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *) Interface;
|
||||||
|
if (TextOut->Mode->Mode == -1) {
|
||||||
|
TextOut->SetMode (TextOut, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (Instance != NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// No any available console devcie found.
|
||||||
|
//
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function updates the console variable based on ConVarName. It can
|
||||||
|
add or remove one specific console device path from the variable
|
||||||
|
|
||||||
|
@param ConsoleType ConIn, ConOut, ErrOut, ConInDev, ConOutDev or ErrOutDev.
|
||||||
|
@param CustomizedConDevicePath The console device path to be added to
|
||||||
|
the console variable. Cannot be multi-instance.
|
||||||
|
@param ExclusiveDevicePath The console device path to be removed
|
||||||
|
from the console variable. Cannot be multi-instance.
|
||||||
|
|
||||||
|
@retval EFI_UNSUPPORTED The added device path is the same as a removed one.
|
||||||
|
@retval EFI_SUCCESS Successfully added or removed the device path from the
|
||||||
|
console variable.
|
||||||
|
@retval others Return status of RT->SetVariable().
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerUpdateConsoleVariable (
|
||||||
|
IN CONSOLE_TYPE ConsoleType,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *VarConsole;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
|
||||||
|
|
||||||
|
if (ConsoleType >= sizeof (mConVarName) / sizeof (mConVarName[0])) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Notes: check the device path point, here should check
|
||||||
|
// with compare memory
|
||||||
|
//
|
||||||
|
if (CustomizedConDevicePath == ExclusiveDevicePath) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Delete the ExclusiveDevicePath from current default console
|
||||||
|
//
|
||||||
|
GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **) &VarConsole, NULL);
|
||||||
|
//
|
||||||
|
// Initialize NewDevicePath
|
||||||
|
//
|
||||||
|
NewDevicePath = VarConsole;
|
||||||
|
|
||||||
|
//
|
||||||
|
// If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.
|
||||||
|
// In the end, NewDevicePath is the final device path.
|
||||||
|
//
|
||||||
|
if (ExclusiveDevicePath != NULL && VarConsole != NULL) {
|
||||||
|
NewDevicePath = BmDelPartMatchInstance (VarConsole, ExclusiveDevicePath);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Try to append customized device path to NewDevicePath.
|
||||||
|
//
|
||||||
|
if (CustomizedConDevicePath != NULL) {
|
||||||
|
if (!BmMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {
|
||||||
|
//
|
||||||
|
// Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.
|
||||||
|
//
|
||||||
|
NewDevicePath = BmDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);
|
||||||
|
//
|
||||||
|
// In the first check, the default console variable will be _ModuleEntryPoint,
|
||||||
|
// just append current customized device path
|
||||||
|
//
|
||||||
|
TempNewDevicePath = NewDevicePath;
|
||||||
|
NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);
|
||||||
|
if (TempNewDevicePath != NULL) {
|
||||||
|
FreePool(TempNewDevicePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Finally, Update the variable of the default console by NewDevicePath
|
||||||
|
//
|
||||||
|
Status = gRT->SetVariable (
|
||||||
|
mConVarName[ConsoleType],
|
||||||
|
&gEfiGlobalVariableGuid,
|
||||||
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
|
||||||
|
| ((ConsoleType < ConInDev) ? EFI_VARIABLE_NON_VOLATILE : 0),
|
||||||
|
GetDevicePathSize (NewDevicePath),
|
||||||
|
NewDevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
if (VarConsole == NewDevicePath) {
|
||||||
|
if (VarConsole != NULL) {
|
||||||
|
FreePool(VarConsole);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (VarConsole != NULL) {
|
||||||
|
FreePool(VarConsole);
|
||||||
|
}
|
||||||
|
if (NewDevicePath != NULL) {
|
||||||
|
FreePool(NewDevicePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Connect the console device base on the variable ConsoleType.
|
||||||
|
|
||||||
|
@param ConsoleType ConIn, ConOut or ErrOut.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND There is not any console devices connected
|
||||||
|
success
|
||||||
|
@retval EFI_SUCCESS Success connect any one instance of the console
|
||||||
|
device path base on the variable ConVarName.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerConnectConsoleVariable (
|
||||||
|
IN CONSOLE_TYPE ConsoleType
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *StartDevicePath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *Instance;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *Next;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;
|
||||||
|
UINTN Size;
|
||||||
|
BOOLEAN DeviceExist;
|
||||||
|
EFI_HANDLE Handle;
|
||||||
|
|
||||||
|
if ((ConsoleType != ConIn) && (ConsoleType != ConOut) && (ConsoleType != ErrOut)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
DeviceExist = FALSE;
|
||||||
|
Handle = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check if the console variable exist
|
||||||
|
//
|
||||||
|
GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **) &StartDevicePath, NULL);
|
||||||
|
if (StartDevicePath == NULL) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyOfDevicePath = StartDevicePath;
|
||||||
|
do {
|
||||||
|
//
|
||||||
|
// Check every instance of the console variable
|
||||||
|
//
|
||||||
|
Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);
|
||||||
|
if (Instance == NULL) {
|
||||||
|
FreePool (StartDevicePath);
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Next = Instance;
|
||||||
|
while (!IsDevicePathEndType (Next)) {
|
||||||
|
Next = NextDevicePathNode (Next);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetDevicePathEndNode (Next);
|
||||||
|
//
|
||||||
|
// Connect the USB console
|
||||||
|
// USB console device path is a short-form device path that
|
||||||
|
// starts with the first element being a USB WWID
|
||||||
|
// or a USB Class device path
|
||||||
|
//
|
||||||
|
if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&
|
||||||
|
((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) || (DevicePathSubType (Instance) == MSG_USB_WWID_DP))
|
||||||
|
) {
|
||||||
|
Status = BmConnectUsbShortFormDevicePath (Instance);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
DeviceExist = TRUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {
|
||||||
|
if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) {
|
||||||
|
break;
|
||||||
|
} else if (DevicePathType (Next) == HARDWARE_DEVICE_PATH &&
|
||||||
|
DevicePathSubType (Next) == HW_CONTROLLER_DP &&
|
||||||
|
DevicePathType (NextDevicePathNode (Next)) == ACPI_DEVICE_PATH &&
|
||||||
|
DevicePathSubType (NextDevicePathNode (Next)) == ACPI_ADR_DP
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!IsDevicePathEnd (Next)) {
|
||||||
|
//
|
||||||
|
// For GOP device path, start the video driver with NULL remaining device path
|
||||||
|
//
|
||||||
|
SetDevicePathEndNode (Next);
|
||||||
|
Status = EfiBootManagerConnectDevicePath (Instance, &Handle);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
gBS->ConnectController (Handle, NULL, NULL, TRUE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Status = EfiBootManagerConnectDevicePath (Instance, NULL);
|
||||||
|
}
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Delete the instance from the console varialbe
|
||||||
|
//
|
||||||
|
EfiBootManagerUpdateConsoleVariable (ConsoleType, NULL, Instance);
|
||||||
|
} else {
|
||||||
|
DeviceExist = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreePool(Instance);
|
||||||
|
} while (CopyOfDevicePath != NULL);
|
||||||
|
|
||||||
|
FreePool (StartDevicePath);
|
||||||
|
|
||||||
|
if (!DeviceExist) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function will search every input/output device in current system,
|
||||||
|
and make every input/output device as potential console device.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerConnectAllConsoles (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
|
||||||
|
UINTN HandleCount;
|
||||||
|
EFI_HANDLE *HandleBuffer;
|
||||||
|
|
||||||
|
Index = 0;
|
||||||
|
HandleCount = 0;
|
||||||
|
HandleBuffer = NULL;
|
||||||
|
ConDevicePath = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Update all the console variables
|
||||||
|
//
|
||||||
|
gBS->LocateHandleBuffer (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiSimpleTextInProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&HandleCount,
|
||||||
|
&HandleBuffer
|
||||||
|
);
|
||||||
|
|
||||||
|
for (Index = 0; Index < HandleCount; Index++) {
|
||||||
|
gBS->HandleProtocol (
|
||||||
|
HandleBuffer[Index],
|
||||||
|
&gEfiDevicePathProtocolGuid,
|
||||||
|
(VOID **) &ConDevicePath
|
||||||
|
);
|
||||||
|
EfiBootManagerUpdateConsoleVariable (ConIn, ConDevicePath, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HandleBuffer != NULL) {
|
||||||
|
FreePool(HandleBuffer);
|
||||||
|
HandleBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gBS->LocateHandleBuffer (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiSimpleTextOutProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&HandleCount,
|
||||||
|
&HandleBuffer
|
||||||
|
);
|
||||||
|
for (Index = 0; Index < HandleCount; Index++) {
|
||||||
|
gBS->HandleProtocol (
|
||||||
|
HandleBuffer[Index],
|
||||||
|
&gEfiDevicePathProtocolGuid,
|
||||||
|
(VOID **) &ConDevicePath
|
||||||
|
);
|
||||||
|
EfiBootManagerUpdateConsoleVariable (ConOut, ConDevicePath, NULL);
|
||||||
|
EfiBootManagerUpdateConsoleVariable (ErrOut, ConDevicePath, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HandleBuffer != NULL) {
|
||||||
|
FreePool(HandleBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Connect all console variables
|
||||||
|
//
|
||||||
|
EfiBootManagerConnectAllDefaultConsoles ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function will connect all the console devices base on the console
|
||||||
|
device variable ConIn, ConOut and ErrOut.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerConnectAllDefaultConsoles (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
BOOLEAN SystemTableUpdated;
|
||||||
|
|
||||||
|
EfiBootManagerConnectConsoleVariable (ConOut);
|
||||||
|
PERF_START (NULL, "ConOutReady", "BDS", 1);
|
||||||
|
PERF_END (NULL, "ConOutReady", "BDS", 0);
|
||||||
|
|
||||||
|
|
||||||
|
EfiBootManagerConnectConsoleVariable (ConIn);
|
||||||
|
PERF_START (NULL, "ConInReady", "BDS", 1);
|
||||||
|
PERF_END (NULL, "ConInReady", "BDS", 0);
|
||||||
|
|
||||||
|
//
|
||||||
|
// The _ModuleEntryPoint err out var is legal.
|
||||||
|
//
|
||||||
|
EfiBootManagerConnectConsoleVariable (ErrOut);
|
||||||
|
PERF_START (NULL, "ErrOutReady", "BDS", 1);
|
||||||
|
PERF_END (NULL, "ErrOutReady", "BDS", 0);
|
||||||
|
|
||||||
|
SystemTableUpdated = FALSE;
|
||||||
|
//
|
||||||
|
// Fill console handles in System Table if no console device assignd.
|
||||||
|
//
|
||||||
|
if (BmUpdateSystemTableConsole (L"ConIn", &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **) &gST->ConIn)) {
|
||||||
|
SystemTableUpdated = TRUE;
|
||||||
|
}
|
||||||
|
if (BmUpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) {
|
||||||
|
SystemTableUpdated = TRUE;
|
||||||
|
}
|
||||||
|
if (BmUpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) {
|
||||||
|
SystemTableUpdated = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SystemTableUpdated) {
|
||||||
|
//
|
||||||
|
// Update the CRC32 in the EFI System Table header
|
||||||
|
//
|
||||||
|
gST->Hdr.CRC32 = 0;
|
||||||
|
gBS->CalculateCrc32 (
|
||||||
|
(UINT8 *) &gST->Hdr,
|
||||||
|
gST->Hdr.HeaderSize,
|
||||||
|
&gST->Hdr.CRC32
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
578
MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c
Normal file
578
MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c
Normal file
@ -0,0 +1,578 @@
|
|||||||
|
/** @file
|
||||||
|
Library functions which relates with driver health.
|
||||||
|
|
||||||
|
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "InternalBm.h"
|
||||||
|
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED
|
||||||
|
CHAR16 *mBmHealthStatusText[] = {
|
||||||
|
L"Healthy",
|
||||||
|
L"Repair Required",
|
||||||
|
L"Configuration Required",
|
||||||
|
L"Failed",
|
||||||
|
L"Reconnect Required",
|
||||||
|
L"Reboot Required"
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the controller name.
|
||||||
|
|
||||||
|
@param DriverHealthHandle The handle on which the Driver Health protocol instance is retrieved.
|
||||||
|
@param ControllerHandle The handle of a controller that the driver specified by DriverBindingHandle is managing.
|
||||||
|
This handle specifies the controller whose name is to be returned.
|
||||||
|
@param ChildHandle The handle of the child controller to retrieve the name of. This is an
|
||||||
|
optional parameter that may be NULL. It will be NULL for device drivers.
|
||||||
|
It will also be NULL for bus drivers that attempt to retrieve the name
|
||||||
|
of the bus controller. It will not be NULL for a bus driver that attempts
|
||||||
|
to retrieve the name of a child controller.
|
||||||
|
|
||||||
|
@return A pointer to the Unicode string to return. This Unicode string is the name of the controller
|
||||||
|
specified by ControllerHandle and ChildHandle.
|
||||||
|
**/
|
||||||
|
CHAR16 *
|
||||||
|
BmGetControllerName (
|
||||||
|
IN EFI_HANDLE DriverHealthHandle,
|
||||||
|
IN EFI_HANDLE ControllerHandle,
|
||||||
|
IN EFI_HANDLE ChildHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
CHAR16 *ControllerName;
|
||||||
|
CHAR8 *LanguageVariable;
|
||||||
|
CHAR8 *BestLanguage;
|
||||||
|
BOOLEAN Iso639Language;
|
||||||
|
EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
|
||||||
|
|
||||||
|
ControllerName = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Locate Component Name (2) protocol on the driver binging handle.
|
||||||
|
//
|
||||||
|
Iso639Language = FALSE;
|
||||||
|
Status = gBS->HandleProtocol (
|
||||||
|
DriverHealthHandle,
|
||||||
|
&gEfiComponentName2ProtocolGuid,
|
||||||
|
(VOID **) &ComponentName
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Status = gBS->HandleProtocol (
|
||||||
|
DriverHealthHandle,
|
||||||
|
&gEfiComponentNameProtocolGuid,
|
||||||
|
(VOID **) &ComponentName
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
Iso639Language = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
LanguageVariable = GetEfiGlobalVariable (Iso639Language ? L"Lang" : L"PlatformLang");
|
||||||
|
BestLanguage = GetBestLanguage(
|
||||||
|
ComponentName->SupportedLanguages,
|
||||||
|
Iso639Language,
|
||||||
|
(LanguageVariable != NULL) ? LanguageVariable : "",
|
||||||
|
Iso639Language ? "eng" : "en-US",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (LanguageVariable != NULL) {
|
||||||
|
FreePool (LanguageVariable);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ComponentName->GetControllerName (
|
||||||
|
ComponentName,
|
||||||
|
ControllerHandle,
|
||||||
|
ChildHandle,
|
||||||
|
BestLanguage,
|
||||||
|
&ControllerName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
return AllocateCopyPool (StrSize (ControllerName), ControllerName);
|
||||||
|
} else {
|
||||||
|
return ConvertDevicePathToText (
|
||||||
|
DevicePathFromHandle (ChildHandle != NULL ? ChildHandle : ControllerHandle),
|
||||||
|
FALSE,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Display a set of messages returned by the GetHealthStatus () service of the EFI Driver Health Protocol
|
||||||
|
|
||||||
|
@param DriverHealthInfo Pointer to the Driver Health information entry.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmDisplayMessages (
|
||||||
|
IN EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
EFI_STRING String;
|
||||||
|
CHAR16 *ControllerName;
|
||||||
|
|
||||||
|
if (DriverHealthInfo->MessageList == NULL ||
|
||||||
|
DriverHealthInfo->MessageList[0].HiiHandle == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ControllerName = BmGetControllerName (
|
||||||
|
DriverHealthInfo->DriverHealthHandle,
|
||||||
|
DriverHealthInfo->ControllerHandle,
|
||||||
|
DriverHealthInfo->ChildHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "Controller: %s\n", ControllerName));
|
||||||
|
Print (L"Controller: %s\n", ControllerName);
|
||||||
|
for (Index = 0; DriverHealthInfo->MessageList[Index].HiiHandle != NULL; Index++) {
|
||||||
|
String = HiiGetString (
|
||||||
|
DriverHealthInfo->MessageList[Index].HiiHandle,
|
||||||
|
DriverHealthInfo->MessageList[Index].StringId,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (String != NULL) {
|
||||||
|
Print (L" %s\n", String);
|
||||||
|
DEBUG ((EFI_D_INFO, " %s\n", String));
|
||||||
|
FreePool (String);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ControllerName != NULL) {
|
||||||
|
FreePool (ControllerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The repair notify function.
|
||||||
|
@param Value A value between 0 and Limit that identifies the current progress
|
||||||
|
of the repair operation.
|
||||||
|
@param Limit The maximum value of Value for the current repair operation.
|
||||||
|
If Limit is 0, then the completion progress is indeterminate.
|
||||||
|
For example, a driver that wants to specify progress in percent
|
||||||
|
would use a Limit value of 100.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully return from the notify function.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
BmRepairNotify (
|
||||||
|
IN UINTN Value,
|
||||||
|
IN UINTN Limit
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DEBUG ((EFI_D_INFO, "[BDS]RepairNotify: %d/%d\n", Value, Limit));
|
||||||
|
Print (L"[BDS]RepairNotify: %d/%d\n", Value, Limit);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Collect the Driver Health status of a single controller.
|
||||||
|
|
||||||
|
@param DriverHealthInfo A pointer to the array containing all of the platform driver health information.
|
||||||
|
@param Count Return the updated array count.
|
||||||
|
@param DriverHealthHandle The handle on which the Driver Health protocol instance is retrieved.
|
||||||
|
@param ControllerHandle The handle of the controller..
|
||||||
|
@param ChildHandle The handle of the child controller to retrieve the health
|
||||||
|
status on. This is an optional parameter that may be NULL.
|
||||||
|
|
||||||
|
@retval Status The status returned from GetHealthStatus.
|
||||||
|
@retval EFI_ABORTED The health status is healthy so no further query is needed.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmGetSingleControllerHealthStatus (
|
||||||
|
IN OUT EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO **DriverHealthInfo,
|
||||||
|
IN OUT UINTN *Count,
|
||||||
|
IN EFI_HANDLE DriverHealthHandle,
|
||||||
|
IN EFI_HANDLE ControllerHandle, OPTIONAL
|
||||||
|
IN EFI_HANDLE ChildHandle OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;
|
||||||
|
EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList;
|
||||||
|
EFI_HII_HANDLE FormHiiHandle;
|
||||||
|
EFI_DRIVER_HEALTH_STATUS HealthStatus;
|
||||||
|
|
||||||
|
ASSERT (DriverHealthHandle != NULL);
|
||||||
|
//
|
||||||
|
// Retrieve the Driver Health Protocol from DriverHandle
|
||||||
|
//
|
||||||
|
Status = gBS->HandleProtocol (
|
||||||
|
DriverHealthHandle,
|
||||||
|
&gEfiDriverHealthProtocolGuid,
|
||||||
|
(VOID **) &DriverHealth
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
|
||||||
|
if (ControllerHandle == NULL) {
|
||||||
|
//
|
||||||
|
// If ControllerHandle is NULL, the return the cumulative health status of the driver
|
||||||
|
//
|
||||||
|
Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, &HealthStatus, NULL, NULL);
|
||||||
|
if (!EFI_ERROR (Status) && HealthStatus == EfiDriverHealthStatusHealthy) {
|
||||||
|
*DriverHealthInfo = ReallocatePool (
|
||||||
|
(*Count) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
|
||||||
|
(*Count + 1) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
|
||||||
|
*DriverHealthInfo
|
||||||
|
);
|
||||||
|
ASSERT (*DriverHealthInfo != NULL);
|
||||||
|
|
||||||
|
(*DriverHealthInfo)[*Count].DriverHealthHandle = DriverHealthHandle;
|
||||||
|
(*DriverHealthInfo)[*Count].DriverHealth = DriverHealth;
|
||||||
|
(*DriverHealthInfo)[*Count].HealthStatus = HealthStatus;
|
||||||
|
|
||||||
|
*Count = *Count + 1;
|
||||||
|
|
||||||
|
Status = EFI_ABORTED;
|
||||||
|
}
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageList = NULL;
|
||||||
|
FormHiiHandle = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Collect the health status with the optional HII message list
|
||||||
|
//
|
||||||
|
Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, &HealthStatus, &MessageList, &FormHiiHandle);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
*DriverHealthInfo = ReallocatePool (
|
||||||
|
(*Count) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
|
||||||
|
(*Count + 1) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
|
||||||
|
*DriverHealthInfo
|
||||||
|
);
|
||||||
|
ASSERT (*DriverHealthInfo != NULL);
|
||||||
|
(*DriverHealthInfo)[*Count].DriverHealth = DriverHealth;
|
||||||
|
(*DriverHealthInfo)[*Count].DriverHealthHandle = DriverHealthHandle;
|
||||||
|
(*DriverHealthInfo)[*Count].ControllerHandle = ControllerHandle;
|
||||||
|
(*DriverHealthInfo)[*Count].ChildHandle = ChildHandle;
|
||||||
|
(*DriverHealthInfo)[*Count].HiiHandle = FormHiiHandle;
|
||||||
|
(*DriverHealthInfo)[*Count].MessageList = MessageList;
|
||||||
|
(*DriverHealthInfo)[*Count].HealthStatus = HealthStatus;
|
||||||
|
|
||||||
|
*Count = *Count + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return all the Driver Health information.
|
||||||
|
|
||||||
|
When the cumulative health status of all the controllers managed by the
|
||||||
|
driver who produces the EFI_DRIVER_HEALTH_PROTOCOL is healthy, only one
|
||||||
|
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry is created for such
|
||||||
|
EFI_DRIVER_HEALTH_PROTOCOL instance.
|
||||||
|
Otherwise, every controller creates one EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO
|
||||||
|
entry. Additionally every child controller creates one
|
||||||
|
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry if the driver is a bus driver.
|
||||||
|
|
||||||
|
@param Count Return the count of the Driver Health information.
|
||||||
|
|
||||||
|
@retval NULL No Driver Health information is returned.
|
||||||
|
@retval !NULL Pointer to the Driver Health information array.
|
||||||
|
**/
|
||||||
|
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerGetDriverHealthInfo (
|
||||||
|
UINTN *Count
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN NumHandles;
|
||||||
|
EFI_HANDLE *DriverHealthHandles;
|
||||||
|
EFI_DRIVER_HEALTH_STATUS HealthStatus;
|
||||||
|
UINTN DriverHealthIndex;
|
||||||
|
EFI_HANDLE *Handles;
|
||||||
|
UINTN HandleCount;
|
||||||
|
UINTN ControllerIndex;
|
||||||
|
UINTN ChildIndex;
|
||||||
|
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize local variables
|
||||||
|
//
|
||||||
|
*Count = 0;
|
||||||
|
DriverHealthInfo = NULL;
|
||||||
|
Handles = NULL;
|
||||||
|
DriverHealthHandles = NULL;
|
||||||
|
NumHandles = 0;
|
||||||
|
HandleCount = 0;
|
||||||
|
|
||||||
|
HealthStatus = EfiDriverHealthStatusHealthy;
|
||||||
|
|
||||||
|
Status = gBS->LocateHandleBuffer (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiDriverHealthProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&NumHandles,
|
||||||
|
&DriverHealthHandles
|
||||||
|
);
|
||||||
|
|
||||||
|
if (Status == EFI_NOT_FOUND || NumHandles == 0) {
|
||||||
|
//
|
||||||
|
// If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
|
||||||
|
//
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
ASSERT (DriverHealthHandles != NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check the health status of all controllers in the platform
|
||||||
|
// Start by looping through all the Driver Health Protocol handles in the handle database
|
||||||
|
//
|
||||||
|
for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) {
|
||||||
|
//
|
||||||
|
// Get the cumulative health status of the driver
|
||||||
|
//
|
||||||
|
Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], NULL, NULL);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// See if the list of all handles in the handle database has been retrieved
|
||||||
|
//
|
||||||
|
//
|
||||||
|
if (Handles == NULL) {
|
||||||
|
//
|
||||||
|
// Retrieve the list of all handles from the handle database
|
||||||
|
//
|
||||||
|
Status = gBS->LocateHandleBuffer (
|
||||||
|
AllHandles,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&HandleCount,
|
||||||
|
&Handles
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Loop through all the controller handles in the handle database
|
||||||
|
//
|
||||||
|
for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) {
|
||||||
|
Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Loop through all the child handles in the handle database
|
||||||
|
//
|
||||||
|
for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) {
|
||||||
|
Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex]);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
|
||||||
|
if (Handles != NULL) {
|
||||||
|
FreePool (Handles);
|
||||||
|
}
|
||||||
|
if (DriverHealthHandles != NULL) {
|
||||||
|
FreePool (DriverHealthHandles);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DriverHealthInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Free the Driver Health information array.
|
||||||
|
|
||||||
|
@param DriverHealthInfo Pointer to array of the Driver Health information.
|
||||||
|
@param Count Count of the array.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The array is freed.
|
||||||
|
@retval EFI_INVALID_PARAMETER The array is NULL.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerFreeDriverHealthInfo (
|
||||||
|
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo,
|
||||||
|
UINTN Count
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
for (Index = 0; Index < Count; Index++) {
|
||||||
|
if (DriverHealthInfo[Index].MessageList != NULL) {
|
||||||
|
FreePool (DriverHealthInfo[Index].MessageList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gBS->FreePool (DriverHealthInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Repair all the controllers according to the Driver Health status queried.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmRepairAllControllers (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo;
|
||||||
|
EFI_DRIVER_HEALTH_STATUS HealthStatus;
|
||||||
|
UINTN Count;
|
||||||
|
UINTN Index;
|
||||||
|
BOOLEAN RepairRequired;
|
||||||
|
BOOLEAN ConfigurationRequired;
|
||||||
|
BOOLEAN ReconnectRequired;
|
||||||
|
BOOLEAN RebootRequired;
|
||||||
|
EFI_HII_HANDLE *HiiHandles;
|
||||||
|
EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Configure PcdDriverHealthConfigureForm to ZeroGuid to disable driver health check.
|
||||||
|
//
|
||||||
|
if (CompareGuid (PcdGetPtr (PcdDriverHealthConfigureForm), &gZeroGuid)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
do {
|
||||||
|
RepairRequired = FALSE;
|
||||||
|
ConfigurationRequired = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Deal with Repair Required
|
||||||
|
//
|
||||||
|
DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
|
||||||
|
for (Index = 0; Index < Count; Index++) {
|
||||||
|
if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusConfigurationRequired) {
|
||||||
|
ConfigurationRequired = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusRepairRequired) {
|
||||||
|
RepairRequired = TRUE;
|
||||||
|
|
||||||
|
BmDisplayMessages (&DriverHealthInfo[Index]);
|
||||||
|
|
||||||
|
Status = DriverHealthInfo[Index].DriverHealth->Repair (
|
||||||
|
DriverHealthInfo[Index].DriverHealth,
|
||||||
|
DriverHealthInfo[Index].ControllerHandle,
|
||||||
|
DriverHealthInfo[Index].ChildHandle,
|
||||||
|
BmRepairNotify
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status) && !ConfigurationRequired) {
|
||||||
|
Status = DriverHealthInfo[Index].DriverHealth->GetHealthStatus (
|
||||||
|
DriverHealthInfo[Index].DriverHealth,
|
||||||
|
DriverHealthInfo[Index].ControllerHandle,
|
||||||
|
DriverHealthInfo[Index].ChildHandle,
|
||||||
|
&HealthStatus,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status) && (HealthStatus == EfiDriverHealthStatusConfigurationRequired)) {
|
||||||
|
ConfigurationRequired = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConfigurationRequired) {
|
||||||
|
HiiHandles = HiiGetHiiHandles (NULL);
|
||||||
|
if (HiiHandles != NULL) {
|
||||||
|
for (Index = 0; HiiHandles[Index] != NULL; Index++) {
|
||||||
|
Status = FormBrowser2->SendForm (
|
||||||
|
FormBrowser2,
|
||||||
|
&HiiHandles[Index],
|
||||||
|
1,
|
||||||
|
PcdGetPtr (PcdDriverHealthConfigureForm),
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreePool (HiiHandles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
|
||||||
|
} while (RepairRequired || ConfigurationRequired);
|
||||||
|
|
||||||
|
RebootRequired = FALSE;
|
||||||
|
ReconnectRequired = FALSE;
|
||||||
|
DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
|
||||||
|
for (Index = 0; Index < Count; Index++) {
|
||||||
|
|
||||||
|
BmDisplayMessages (&DriverHealthInfo[Index]);
|
||||||
|
|
||||||
|
if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusReconnectRequired) {
|
||||||
|
Status = gBS->DisconnectController (DriverHealthInfo[Index].ControllerHandle, NULL, NULL);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Disconnect failed. Need to promote reconnect to a reboot.
|
||||||
|
//
|
||||||
|
RebootRequired = TRUE;
|
||||||
|
} else {
|
||||||
|
gBS->ConnectController (DriverHealthInfo[Index].ControllerHandle, NULL, NULL, TRUE);
|
||||||
|
ReconnectRequired = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusRebootRequired) {
|
||||||
|
RebootRequired = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
|
||||||
|
|
||||||
|
|
||||||
|
if (ReconnectRequired) {
|
||||||
|
BmRepairAllControllers ();
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_CODE (
|
||||||
|
CHAR16 *ControllerName;
|
||||||
|
|
||||||
|
DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
|
||||||
|
for (Index = 0; Index < Count; Index++) {
|
||||||
|
ControllerName = BmGetControllerName (
|
||||||
|
DriverHealthInfo[Index].DriverHealthHandle,
|
||||||
|
DriverHealthInfo[Index].ControllerHandle,
|
||||||
|
DriverHealthInfo[Index].ChildHandle
|
||||||
|
);
|
||||||
|
DEBUG ((
|
||||||
|
EFI_D_INFO,
|
||||||
|
"%02d: %s - %s\n",
|
||||||
|
Index,
|
||||||
|
ControllerName,
|
||||||
|
mBmHealthStatusText[DriverHealthInfo[Index].HealthStatus]
|
||||||
|
));
|
||||||
|
if (ControllerName != NULL) {
|
||||||
|
FreePool (ControllerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
|
||||||
|
);
|
||||||
|
|
||||||
|
if (RebootRequired) {
|
||||||
|
DEBUG ((EFI_D_INFO, "[BDS] One of the Driver Health instances requires rebooting.\n"));
|
||||||
|
gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
1101
MdeModulePkg/Library/UefiBootManagerLib/BmHotkey.c
Normal file
1101
MdeModulePkg/Library/UefiBootManagerLib/BmHotkey.c
Normal file
File diff suppressed because it is too large
Load Diff
982
MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
Normal file
982
MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
Normal file
@ -0,0 +1,982 @@
|
|||||||
|
/** @file
|
||||||
|
Load option library functions which relate with creating and processing load options.
|
||||||
|
|
||||||
|
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "InternalBm.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the Option Number that wasn't used.
|
||||||
|
|
||||||
|
@param OrderVariableName Could be L"BootOrder" or L"DriverOrder".
|
||||||
|
@param FreeOptionNumber To receive the minimal free option number.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The option number is found
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is no free option number that can be used.
|
||||||
|
@retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmGetFreeOptionNumber (
|
||||||
|
IN CHAR16 *OrderVariableName,
|
||||||
|
OUT UINT16 *FreeOptionNumber
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
UINTN OptionNumber;
|
||||||
|
UINTN Index;
|
||||||
|
UINT16 *OptionOrder;
|
||||||
|
UINTN OptionOrderSize;
|
||||||
|
UINT16 *BootNext;
|
||||||
|
|
||||||
|
if (FreeOptionNumber == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetEfiGlobalVariable2 (OrderVariableName, (VOID **) &OptionOrder, &OptionOrderSize);
|
||||||
|
BootNext = NULL;
|
||||||
|
if (*OrderVariableName == L'B') {
|
||||||
|
GetEfiGlobalVariable2 (L"BootNext", (VOID**) &BootNext, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (OptionNumber = 0;
|
||||||
|
OptionNumber < OptionOrderSize / sizeof (UINT16)
|
||||||
|
+ ((BootNext != NULL) ? 1 : 0);
|
||||||
|
OptionNumber++
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
// Search in OptionOrder whether the OptionNumber exists
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
|
||||||
|
if (OptionNumber == OptionOrder[Index]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We didn't find it in the ****Order array and it doesn't equal to BootNext
|
||||||
|
// Otherwise, OptionNumber equals to OptionOrderSize / sizeof (UINT16) + 1
|
||||||
|
//
|
||||||
|
if ((Index == OptionOrderSize / sizeof (UINT16)) &&
|
||||||
|
((BootNext == NULL) || (OptionNumber != *BootNext))
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (OptionOrder != NULL) {
|
||||||
|
FreePool (OptionOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BootNext != NULL) {
|
||||||
|
FreePool (BootNext);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// When BootOrder & BootNext conver all numbers in the range [0 ... 0xffff],
|
||||||
|
// OptionNumber equals to 0x10000 which is not valid.
|
||||||
|
//
|
||||||
|
ASSERT (OptionNumber <= 0x10000);
|
||||||
|
if (OptionNumber == 0x10000) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
} else {
|
||||||
|
*FreeOptionNumber = (UINT16) OptionNumber;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update order variable .
|
||||||
|
|
||||||
|
@param OptionOrderName Order variable name which need to be updated.
|
||||||
|
@param OptionNumber Option number for the new option.
|
||||||
|
@param Position Position of the new load option to put in the ****Order variable.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The boot#### or driver#### have been successfully registered.
|
||||||
|
@retval EFI_ALREADY_STARTED The option number of Option is being used already.
|
||||||
|
@retval EFI_STATUS Return the status of gRT->SetVariable ().
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmAddOptionNumberToOrderVariable (
|
||||||
|
IN CHAR16 *OptionOrderName,
|
||||||
|
IN UINT16 OptionNumber,
|
||||||
|
IN UINTN Position
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN Index;
|
||||||
|
UINT16 *OptionOrder;
|
||||||
|
UINT16 *NewOptionOrder;
|
||||||
|
UINTN OptionOrderSize;
|
||||||
|
//
|
||||||
|
// Update the option order variable
|
||||||
|
//
|
||||||
|
GetEfiGlobalVariable2 (OptionOrderName, (VOID **) &OptionOrder, &OptionOrderSize);
|
||||||
|
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
|
||||||
|
if (OptionOrder[Index] == OptionNumber) {
|
||||||
|
Status = EFI_ALREADY_STARTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
Position = MIN (Position, OptionOrderSize / sizeof (UINT16));
|
||||||
|
|
||||||
|
NewOptionOrder = AllocatePool (OptionOrderSize + sizeof (UINT16));
|
||||||
|
ASSERT (NewOptionOrder != NULL);
|
||||||
|
if (OptionOrderSize != 0) {
|
||||||
|
CopyMem (NewOptionOrder, OptionOrder, Position * sizeof (UINT16));
|
||||||
|
CopyMem (&NewOptionOrder[Position + 1], &OptionOrder[Position], OptionOrderSize - Position * sizeof (UINT16));
|
||||||
|
}
|
||||||
|
NewOptionOrder[Position] = OptionNumber;
|
||||||
|
|
||||||
|
Status = gRT->SetVariable (
|
||||||
|
OptionOrderName,
|
||||||
|
&gEfiGlobalVariableGuid,
|
||||||
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
||||||
|
OptionOrderSize + sizeof (UINT16),
|
||||||
|
NewOptionOrder
|
||||||
|
);
|
||||||
|
FreePool (NewOptionOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OptionOrder != NULL) {
|
||||||
|
FreePool (OptionOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create the Boot#### or Driver#### variable from the load option.
|
||||||
|
|
||||||
|
@param LoadOption Pointer to the load option.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The variable was created.
|
||||||
|
@retval Others Error status returned by RT->SetVariable.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerLoadOptionToVariable (
|
||||||
|
IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Option
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN VariableSize;
|
||||||
|
UINT8 *Variable;
|
||||||
|
UINT8 *Ptr;
|
||||||
|
CHAR16 OptionName[sizeof ("Driver####")];
|
||||||
|
CHAR16 *Description;
|
||||||
|
CHAR16 NullChar;
|
||||||
|
|
||||||
|
if ((Option->OptionNumber == LoadOptionNumberUnassigned) ||
|
||||||
|
(Option->FilePath == NULL) ||
|
||||||
|
(Option->OptionType >= LoadOptionTypeMax)
|
||||||
|
) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convert NULL description to empty description
|
||||||
|
//
|
||||||
|
NullChar = L'\0';
|
||||||
|
Description = Option->Description;
|
||||||
|
if (Description == NULL) {
|
||||||
|
Description = &NullChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
UINT32 Attributes;
|
||||||
|
UINT16 FilePathListLength;
|
||||||
|
CHAR16 Description[];
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL FilePathList[];
|
||||||
|
UINT8 OptionalData[];
|
||||||
|
TODO: FilePathList[] IS:
|
||||||
|
A packed array of UEFI device paths. The first element of the
|
||||||
|
array is a device path that describes the device and location of the
|
||||||
|
Image for this load option. The FilePathList[0] is specific
|
||||||
|
to the device type. Other device paths may optionally exist in the
|
||||||
|
FilePathList, but their usage is OSV specific. Each element
|
||||||
|
in the array is variable length, and ends at the device path end
|
||||||
|
structure.
|
||||||
|
*/
|
||||||
|
VariableSize = sizeof (Option->Attributes)
|
||||||
|
+ sizeof (UINT16)
|
||||||
|
+ StrSize (Description)
|
||||||
|
+ GetDevicePathSize (Option->FilePath)
|
||||||
|
+ Option->OptionalDataSize;
|
||||||
|
|
||||||
|
Variable = AllocatePool (VariableSize);
|
||||||
|
ASSERT (Variable != NULL);
|
||||||
|
|
||||||
|
Ptr = Variable;
|
||||||
|
*(UINT32 *) Ptr = Option->Attributes;
|
||||||
|
Ptr += sizeof (Option->Attributes);
|
||||||
|
*(UINT16 *) Ptr = (UINT16) GetDevicePathSize (Option->FilePath);
|
||||||
|
Ptr += sizeof (UINT16);
|
||||||
|
CopyMem (Ptr, Description, StrSize (Description));
|
||||||
|
Ptr += StrSize (Description);
|
||||||
|
CopyMem (Ptr, Option->FilePath, GetDevicePathSize (Option->FilePath));
|
||||||
|
Ptr += GetDevicePathSize (Option->FilePath);
|
||||||
|
CopyMem (Ptr, Option->OptionalData, Option->OptionalDataSize);
|
||||||
|
|
||||||
|
UnicodeSPrint (
|
||||||
|
OptionName,
|
||||||
|
sizeof (OptionName),
|
||||||
|
(Option->OptionType == LoadOptionTypeBoot) ? L"Boot%04x" : L"Driver%04x",
|
||||||
|
Option->OptionNumber
|
||||||
|
);
|
||||||
|
|
||||||
|
return gRT->SetVariable (
|
||||||
|
OptionName,
|
||||||
|
&gEfiGlobalVariableGuid,
|
||||||
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
||||||
|
VariableSize,
|
||||||
|
Variable
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function will register the new boot#### or driver#### option.
|
||||||
|
After the boot#### or driver#### updated, the BootOrder or DriverOrder will also be updated.
|
||||||
|
|
||||||
|
@param Option Pointer to load option to add.
|
||||||
|
@param Position Position of the new load option to put in the ****Order variable.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The boot#### or driver#### have been successfully registered.
|
||||||
|
@retval EFI_INVALID_PARAMETER The option number exceeds 0xFFFF.
|
||||||
|
@retval EFI_ALREADY_STARTED The option number of Option is being used already.
|
||||||
|
Note: this API only adds new load option, no replacement support.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is no free option number that can be used when the
|
||||||
|
option number specified in the Option is LoadOptionNumberUnassigned.
|
||||||
|
@retval EFI_STATUS Return the status of gRT->SetVariable ().
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerAddLoadOptionVariable (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION *Option,
|
||||||
|
IN UINTN Position
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT16 OptionNumber;
|
||||||
|
|
||||||
|
if (Option == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the free option number if the option number is unassigned
|
||||||
|
//
|
||||||
|
if (Option->OptionNumber == LoadOptionNumberUnassigned) {
|
||||||
|
Status = BmGetFreeOptionNumber (
|
||||||
|
Option->OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
|
||||||
|
&OptionNumber
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
Option->OptionNumber = OptionNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Option->OptionNumber >= LoadOptionNumberMax) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = BmAddOptionNumberToOrderVariable (
|
||||||
|
Option->OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
|
||||||
|
(UINT16) Option->OptionNumber,
|
||||||
|
Position
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Save the Boot#### or Driver#### variable
|
||||||
|
//
|
||||||
|
Status = EfiBootManagerLoadOptionToVariable (Option);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Remove the #### from *Order variable when the Boot####/Driver#### cannot be saved.
|
||||||
|
//
|
||||||
|
EfiBootManagerDeleteLoadOptionVariable (Option->OptionNumber, Option->OptionType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sort the load option. The DriverOrder or BootOrder will be re-created to
|
||||||
|
reflect the new order.
|
||||||
|
|
||||||
|
@param OptionType Load option type
|
||||||
|
@param CompareFunction The comparator
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerSortLoadOptionVariable (
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
|
||||||
|
SORT_COMPARE CompareFunction
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption;
|
||||||
|
UINTN LoadOptionCount;
|
||||||
|
UINTN Index;
|
||||||
|
UINT16 *OptionOrder;
|
||||||
|
|
||||||
|
LoadOption = EfiBootManagerGetLoadOptions (&LoadOptionCount, OptionType);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Insertion sort algorithm
|
||||||
|
//
|
||||||
|
PerformQuickSort (
|
||||||
|
LoadOption,
|
||||||
|
LoadOptionCount,
|
||||||
|
sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),
|
||||||
|
CompareFunction
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create new ****Order variable
|
||||||
|
//
|
||||||
|
OptionOrder = AllocatePool (LoadOptionCount * sizeof (UINT16));
|
||||||
|
ASSERT (OptionOrder != NULL);
|
||||||
|
for (Index = 0; Index < LoadOptionCount; Index++) {
|
||||||
|
OptionOrder[Index] = (UINT16) LoadOption[Index].OptionNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gRT->SetVariable (
|
||||||
|
OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
|
||||||
|
&gEfiGlobalVariableGuid,
|
||||||
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
||||||
|
LoadOptionCount * sizeof (UINT16),
|
||||||
|
OptionOrder
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// Changing the *Order content without increasing its size with current variable implementation shouldn't fail.
|
||||||
|
//
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
FreePool (OptionOrder);
|
||||||
|
EfiBootManagerFreeLoadOptions (LoadOption, LoadOptionCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize a load option.
|
||||||
|
|
||||||
|
@param Option Pointer to the load option to be initialized.
|
||||||
|
@param OptionNumber Option number of the load option.
|
||||||
|
@param OptionType Type of the load option.
|
||||||
|
@param Attributes Attributes of the load option.
|
||||||
|
@param Description Description of the load option.
|
||||||
|
@param FilePath Device path of the load option.
|
||||||
|
@param OptionalData Optional data of the load option.
|
||||||
|
@param OptionalDataSize Size of the optional data of the load option.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The load option was initialized successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER Option, Description or FilePath is NULL.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerInitializeLoadOption (
|
||||||
|
IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option,
|
||||||
|
IN UINTN OptionNumber,
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
|
||||||
|
IN UINT32 Attributes,
|
||||||
|
IN CHAR16 *Description,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||||
|
IN UINT8 *OptionalData, OPTIONAL
|
||||||
|
IN UINT32 OptionalDataSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if ((Option == NULL) || (Description == NULL) || (FilePath == NULL)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((OptionalData != NULL) && (OptionalDataSize == 0)) ||
|
||||||
|
((OptionalData == NULL) && (OptionalDataSize != 0))) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMem (Option, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
|
||||||
|
Option->OptionNumber = OptionNumber;
|
||||||
|
Option->OptionType = OptionType;
|
||||||
|
Option->Attributes = Attributes;
|
||||||
|
Option->Description = AllocateCopyPool (StrSize (Description), Description);
|
||||||
|
Option->FilePath = DuplicateDevicePath (FilePath);
|
||||||
|
if (OptionalData != NULL) {
|
||||||
|
Option->OptionalData = AllocateCopyPool (OptionalDataSize, OptionalData);
|
||||||
|
Option->OptionalDataSize = OptionalDataSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the index of the load option in the load option array.
|
||||||
|
|
||||||
|
The function consider two load options are equal when the
|
||||||
|
OptionType, Attributes, Description, FilePath and OptionalData are equal.
|
||||||
|
|
||||||
|
@param Key Pointer to the load option to be found.
|
||||||
|
@param Array Pointer to the array of load options to be found.
|
||||||
|
@param Count Number of entries in the Array.
|
||||||
|
|
||||||
|
@retval -1 Key wasn't found in the Array.
|
||||||
|
@retval 0 ~ Count-1 The index of the Key in the Array.
|
||||||
|
**/
|
||||||
|
INTN
|
||||||
|
BmFindLoadOption (
|
||||||
|
IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
|
||||||
|
IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
|
||||||
|
IN UINTN Count
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
for (Index = 0; Index < Count; Index++) {
|
||||||
|
if ((Key->OptionType == Array[Index].OptionType) &&
|
||||||
|
(Key->Attributes == Array[Index].Attributes) &&
|
||||||
|
(StrCmp (Key->Description, Array[Index].Description) == 0) &&
|
||||||
|
(CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
|
||||||
|
(Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
|
||||||
|
(CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
|
||||||
|
return (INTN) Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update the BootOrder or DriverOrder to delete OptionNumber .
|
||||||
|
|
||||||
|
@param OptionOrderVariable Order variable name which need to be updated.
|
||||||
|
@param OptionNumber Indicate the option number of load option
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND The load option cannot be found
|
||||||
|
@retval EFI_SUCCESS The load option was deleted
|
||||||
|
@retval others Status of RT->SetVariable()
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmDeleteOptionVariable (
|
||||||
|
IN CHAR16 *OptionOrderVariable,
|
||||||
|
IN UINT16 OptionNumber
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT16 *OptionOrder;
|
||||||
|
UINTN OptionOrderSize;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
Status = EFI_NOT_FOUND;
|
||||||
|
GetEfiGlobalVariable2 (OptionOrderVariable, (VOID **) &OptionOrder, &OptionOrderSize);
|
||||||
|
for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
|
||||||
|
if (OptionOrder[Index] == OptionNumber) {
|
||||||
|
OptionOrderSize -= sizeof (UINT16);
|
||||||
|
CopyMem (&OptionOrder[Index], &OptionOrder[Index + 1], OptionOrderSize - Index * sizeof (UINT16));
|
||||||
|
Status = gRT->SetVariable (
|
||||||
|
OptionOrderVariable,
|
||||||
|
&gEfiGlobalVariableGuid,
|
||||||
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
||||||
|
OptionOrderSize,
|
||||||
|
OptionOrder
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (OptionOrder != NULL) {
|
||||||
|
FreePool (OptionOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update the BootOrder or DriverOrder according to the OptionType to delete OptionNumber .
|
||||||
|
|
||||||
|
@param OptionNumber Indicate the option number of load option
|
||||||
|
@param OptionType Indicate the type of load option
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER OptionType or OptionNumber is invalid.
|
||||||
|
@retval EFI_NOT_FOUND The load option cannot be found
|
||||||
|
@retval EFI_SUCCESS The load option was deleted
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerDeleteLoadOptionVariable (
|
||||||
|
IN UINTN OptionNumber,
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if ((OptionType >= LoadOptionTypeMax) || (OptionNumber >= LoadOptionNumberMax)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BmDeleteOptionVariable (
|
||||||
|
OptionType == LoadOptionTypeBoot ? L"BootOrder" : L"DriverOrder",
|
||||||
|
(UINT16) OptionNumber
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert a single character to number.
|
||||||
|
It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F'
|
||||||
|
|
||||||
|
@param Char The input char which need to convert to int.
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
BmCharToUint (
|
||||||
|
IN CHAR16 Char
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if ((Char >= L'0') && (Char <= L'9')) {
|
||||||
|
return (UINTN) (Char - L'0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Char >= L'A') && (Char <= L'F')) {
|
||||||
|
return (UINTN) (Char - L'A' + 0xA);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT (FALSE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the size of a device path in bytes.
|
||||||
|
|
||||||
|
This function returns the size, in bytes, of the device path data structure
|
||||||
|
specified by DevicePath including the end of device path node. If DevicePath
|
||||||
|
is NULL, then 0 is returned. If the length of the device path is bigger than
|
||||||
|
MaxSize, also return 0 to indicate this is an invalidate device path.
|
||||||
|
|
||||||
|
@param DevicePath A pointer to a device path data structure.
|
||||||
|
@param MaxSize Max valid device path size. If big than this size,
|
||||||
|
return error.
|
||||||
|
|
||||||
|
@retval 0 An invalid device path.
|
||||||
|
@retval Others The size of a device path in bytes.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
BmGetDevicePathSizeEx (
|
||||||
|
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||||
|
IN UINTN MaxSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Size;
|
||||||
|
UINTN NodeSize;
|
||||||
|
|
||||||
|
if (DevicePath == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Search for the end of the device path structure
|
||||||
|
//
|
||||||
|
Size = 0;
|
||||||
|
while (!IsDevicePathEnd (DevicePath)) {
|
||||||
|
NodeSize = DevicePathNodeLength (DevicePath);
|
||||||
|
if (NodeSize == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Size += NodeSize;
|
||||||
|
if (Size > MaxSize) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DevicePath = NextDevicePathNode (DevicePath);
|
||||||
|
}
|
||||||
|
Size += DevicePathNodeLength (DevicePath);
|
||||||
|
if (Size > MaxSize) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the length of a Null-terminated Unicode string. If the length is
|
||||||
|
bigger than MaxStringLen, return length 0 to indicate that this is an
|
||||||
|
invalidate string.
|
||||||
|
|
||||||
|
This function returns the number of Unicode characters in the Null-terminated
|
||||||
|
Unicode string specified by String.
|
||||||
|
|
||||||
|
If String is NULL, then ASSERT().
|
||||||
|
If String is not aligned on a 16-bit boundary, then ASSERT().
|
||||||
|
|
||||||
|
@param String A pointer to a Null-terminated Unicode string.
|
||||||
|
@param MaxStringLen Max string len in this string.
|
||||||
|
|
||||||
|
@retval 0 An invalid string.
|
||||||
|
@retval Others The length of String.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
BmStrSizeEx (
|
||||||
|
IN CONST CHAR16 *String,
|
||||||
|
IN UINTN MaxStringLen
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Length;
|
||||||
|
|
||||||
|
ASSERT (String != NULL && MaxStringLen != 0);
|
||||||
|
ASSERT (((UINTN) String & BIT0) == 0);
|
||||||
|
|
||||||
|
for (Length = 0; *String != L'\0' && MaxStringLen != Length; String++, Length+=2);
|
||||||
|
|
||||||
|
if (*String != L'\0' && MaxStringLen == Length) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Length + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Validate the EFI Boot#### variable (VendorGuid/Name)
|
||||||
|
|
||||||
|
@param Variable Boot#### variable data.
|
||||||
|
@param VariableSize Returns the size of the EFI variable that was read
|
||||||
|
|
||||||
|
@retval TRUE The variable data is correct.
|
||||||
|
@retval FALSE The variable data is corrupted.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
BmValidateOption (
|
||||||
|
UINT8 *Variable,
|
||||||
|
UINTN VariableSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT16 FilePathSize;
|
||||||
|
UINT8 *TempPtr;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||||
|
UINTN TempSize;
|
||||||
|
|
||||||
|
if (VariableSize <= sizeof (UINT16) + sizeof (UINT32)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Skip the option attribute
|
||||||
|
//
|
||||||
|
TempPtr = Variable;
|
||||||
|
TempPtr += sizeof (UINT32);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the option's device path size
|
||||||
|
//
|
||||||
|
FilePathSize = *(UINT16 *) TempPtr;
|
||||||
|
TempPtr += sizeof (UINT16);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the option's description string size
|
||||||
|
//
|
||||||
|
TempSize = BmStrSizeEx ((CHAR16 *) TempPtr, VariableSize - sizeof (UINT16) - sizeof (UINT32));
|
||||||
|
TempPtr += TempSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the option's device path
|
||||||
|
//
|
||||||
|
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
|
||||||
|
TempPtr += FilePathSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Validation boot option variable.
|
||||||
|
//
|
||||||
|
if ((FilePathSize == 0) || (TempSize == 0)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TempSize + FilePathSize + sizeof (UINT16) + sizeof (UINT32) > VariableSize) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (BOOLEAN) (BmGetDevicePathSizeEx (DevicePath, FilePathSize) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Build the Boot#### or Driver#### option from the VariableName.
|
||||||
|
|
||||||
|
@param VariableName EFI Variable name indicate if it is Boot#### or
|
||||||
|
Driver####
|
||||||
|
@param Option Return the Boot#### or Driver#### option.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Get the option just been created
|
||||||
|
@retval EFI_NOT_FOUND Failed to get the new option
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerVariableToLoadOption (
|
||||||
|
IN CHAR16 *VariableName,
|
||||||
|
IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT32 Attribute;
|
||||||
|
UINT16 FilePathSize;
|
||||||
|
UINT8 *Variable;
|
||||||
|
UINT8 *TempPtr;
|
||||||
|
UINTN VariableSize;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *FilePath;
|
||||||
|
UINT8 *OptionalData;
|
||||||
|
UINT32 OptionalDataSize;
|
||||||
|
CHAR16 *Description;
|
||||||
|
UINT8 NumOff;
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType;
|
||||||
|
UINT16 OptionNumber;
|
||||||
|
|
||||||
|
if ((VariableName == NULL) || (Option == NULL)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read the variable
|
||||||
|
//
|
||||||
|
GetEfiGlobalVariable2 (VariableName, (VOID **) &Variable, &VariableSize);
|
||||||
|
if (Variable == NULL) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Validate Boot#### variable data.
|
||||||
|
//
|
||||||
|
if (!BmValidateOption(Variable, VariableSize)) {
|
||||||
|
FreePool (Variable);
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Notes: careful defined the variable of Boot#### or
|
||||||
|
// Driver####, consider use some macro to abstract the code
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Get the option attribute
|
||||||
|
//
|
||||||
|
TempPtr = Variable;
|
||||||
|
Attribute = *(UINT32 *) Variable;
|
||||||
|
TempPtr += sizeof (UINT32);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the option's device path size
|
||||||
|
//
|
||||||
|
FilePathSize = *(UINT16 *) TempPtr;
|
||||||
|
TempPtr += sizeof (UINT16);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the option's description string
|
||||||
|
//
|
||||||
|
Description = (CHAR16 *) TempPtr;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the option's description string size
|
||||||
|
//
|
||||||
|
TempPtr += StrSize ((CHAR16 *) TempPtr);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the option's device path
|
||||||
|
//
|
||||||
|
FilePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
|
||||||
|
TempPtr += FilePathSize;
|
||||||
|
|
||||||
|
OptionalDataSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));
|
||||||
|
if (OptionalDataSize == 0) {
|
||||||
|
OptionalData = NULL;
|
||||||
|
} else {
|
||||||
|
OptionalData = TempPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*VariableName == L'B') {
|
||||||
|
OptionType = LoadOptionTypeBoot;
|
||||||
|
NumOff = (UINT8) (sizeof (L"Boot") / sizeof (CHAR16) - 1);
|
||||||
|
} else {
|
||||||
|
OptionType = LoadOptionTypeDriver;
|
||||||
|
NumOff = (UINT8) (sizeof (L"Driver") / sizeof (CHAR16) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the value from VariableName Unicode string
|
||||||
|
// since the ISO standard assumes ASCII equivalent abbreviations, we can be safe in converting this
|
||||||
|
// Unicode stream to ASCII without any loss in meaning.
|
||||||
|
//
|
||||||
|
OptionNumber = (UINT16) (BmCharToUint (VariableName[NumOff+0]) * 0x1000)
|
||||||
|
+ (UINT16) (BmCharToUint (VariableName[NumOff+1]) * 0x100)
|
||||||
|
+ (UINT16) (BmCharToUint (VariableName[NumOff+2]) * 0x10)
|
||||||
|
+ (UINT16) (BmCharToUint (VariableName[NumOff+3]) * 0x1);
|
||||||
|
|
||||||
|
Status = EfiBootManagerInitializeLoadOption (
|
||||||
|
Option,
|
||||||
|
OptionNumber,
|
||||||
|
OptionType,
|
||||||
|
Attribute,
|
||||||
|
Description,
|
||||||
|
FilePath,
|
||||||
|
OptionalData,
|
||||||
|
OptionalDataSize
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
FreePool (Variable);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns an array of load options based on the EFI variable
|
||||||
|
L"BootOrder"/L"DriverOrder" and the L"Boot####"/L"Driver####" variables impled by it.
|
||||||
|
#### is the hex value of the UINT16 in each BootOrder/DriverOrder entry.
|
||||||
|
|
||||||
|
@param LoadOptionCount Returns number of entries in the array.
|
||||||
|
@param LoadOptionType The type of the load option.
|
||||||
|
|
||||||
|
@retval NULL No load options exist.
|
||||||
|
@retval !NULL Array of load option entries.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION *
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerGetLoadOptions (
|
||||||
|
OUT UINTN *OptionCount,
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT16 *OptionOrder;
|
||||||
|
UINTN OptionOrderSize;
|
||||||
|
UINTN Index;
|
||||||
|
UINTN OptionIndex;
|
||||||
|
EFI_BOOT_MANAGER_LOAD_OPTION *Option;
|
||||||
|
CHAR16 OptionName[sizeof ("Driver####")];
|
||||||
|
UINT16 OptionNumber;
|
||||||
|
|
||||||
|
*OptionCount = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read the BootOrder, or DriverOrder variable.
|
||||||
|
//
|
||||||
|
GetEfiGlobalVariable2 (
|
||||||
|
(LoadOptionType == LoadOptionTypeBoot) ? L"BootOrder" : L"DriverOrder",
|
||||||
|
(VOID **) &OptionOrder,
|
||||||
|
&OptionOrderSize
|
||||||
|
);
|
||||||
|
if (OptionOrder == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*OptionCount = OptionOrderSize / sizeof (UINT16);
|
||||||
|
|
||||||
|
Option = AllocatePool (*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
|
||||||
|
ASSERT (Option != NULL);
|
||||||
|
|
||||||
|
OptionIndex = 0;
|
||||||
|
for (Index = 0; Index < *OptionCount; Index++) {
|
||||||
|
OptionNumber = OptionOrder[Index];
|
||||||
|
if (LoadOptionType == LoadOptionTypeBoot) {
|
||||||
|
UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionNumber);
|
||||||
|
} else {
|
||||||
|
UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = EfiBootManagerVariableToLoadOption (OptionName, &Option[OptionIndex]);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_INFO, "[Bds] %s doesn't exist - Update ****Order variable to remove the reference!!", OptionName));
|
||||||
|
EfiBootManagerDeleteLoadOptionVariable (OptionNumber, LoadOptionTypeBoot);
|
||||||
|
} else {
|
||||||
|
ASSERT (Option[OptionIndex].OptionNumber == OptionNumber);
|
||||||
|
OptionIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OptionOrder != NULL) {
|
||||||
|
FreePool (OptionOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OptionIndex < *OptionCount) {
|
||||||
|
Option = ReallocatePool (
|
||||||
|
*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),
|
||||||
|
OptionIndex * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),
|
||||||
|
Option
|
||||||
|
);
|
||||||
|
ASSERT (Option != NULL);
|
||||||
|
*OptionCount = OptionIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Option;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Free an EFI_BOOT_MANGER_LOAD_OPTION entry that was allocate by the library.
|
||||||
|
|
||||||
|
@param LoadOption Pointer to boot option to Free.
|
||||||
|
|
||||||
|
@return EFI_SUCCESS BootOption was freed
|
||||||
|
@return EFI_NOT_FOUND BootOption == NULL
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerFreeLoadOption (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (LoadOption == NULL) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LoadOption->Description != NULL) {
|
||||||
|
FreePool (LoadOption->Description);
|
||||||
|
}
|
||||||
|
if (LoadOption->FilePath != NULL) {
|
||||||
|
FreePool (LoadOption->FilePath);
|
||||||
|
}
|
||||||
|
if (LoadOption->OptionalData != NULL) {
|
||||||
|
FreePool (LoadOption->OptionalData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Free an EFI_BOOT_MANGER_LOAD_OPTION array that was allocated by
|
||||||
|
EfiBootManagerGetLoadOptions().
|
||||||
|
|
||||||
|
@param Option Pointer to boot option array to free.
|
||||||
|
@param OptionCount Number of array entries in BootOption
|
||||||
|
|
||||||
|
@return EFI_SUCCESS BootOption was freed
|
||||||
|
@return EFI_NOT_FOUND BootOption == NULL
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiBootManagerFreeLoadOptions (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION *Option,
|
||||||
|
IN UINTN OptionCount
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
if (Option == NULL) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Index = 0;Index < OptionCount; Index++) {
|
||||||
|
EfiBootManagerFreeLoadOption (&Option[Index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool (Option);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
507
MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c
Normal file
507
MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c
Normal file
@ -0,0 +1,507 @@
|
|||||||
|
/** @file
|
||||||
|
Misc library functions.
|
||||||
|
|
||||||
|
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "InternalBm.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Delete the instance in Multi which matches partly with Single instance
|
||||||
|
|
||||||
|
@param Multi A pointer to a multi-instance device path data
|
||||||
|
structure.
|
||||||
|
@param Single A pointer to a single-instance device path data
|
||||||
|
structure.
|
||||||
|
|
||||||
|
@return This function will remove the device path instances in Multi which partly
|
||||||
|
match with the Single, and return the result device path. If there is no
|
||||||
|
remaining device path as a result, this function will return NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
BmDelPartMatchInstance (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *Multi,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *Single
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *Instance;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
|
||||||
|
UINTN InstanceSize;
|
||||||
|
UINTN SingleDpSize;
|
||||||
|
|
||||||
|
NewDevicePath = NULL;
|
||||||
|
TempNewDevicePath = NULL;
|
||||||
|
|
||||||
|
if (Multi == NULL || Single == NULL) {
|
||||||
|
return Multi;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
|
||||||
|
SingleDpSize = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;
|
||||||
|
InstanceSize -= END_DEVICE_PATH_LENGTH;
|
||||||
|
|
||||||
|
while (Instance != NULL) {
|
||||||
|
|
||||||
|
if (CompareMem (Instance, Single, MIN (SingleDpSize, InstanceSize)) != 0) {
|
||||||
|
//
|
||||||
|
// Append the device path instance which does not match with Single
|
||||||
|
//
|
||||||
|
TempNewDevicePath = NewDevicePath;
|
||||||
|
NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);
|
||||||
|
if (TempNewDevicePath != NULL) {
|
||||||
|
FreePool(TempNewDevicePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreePool(Instance);
|
||||||
|
Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
|
||||||
|
InstanceSize -= END_DEVICE_PATH_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewDevicePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Function compares a device path data structure to that of all the nodes of a
|
||||||
|
second device path instance.
|
||||||
|
|
||||||
|
@param Multi A pointer to a multi-instance device path data
|
||||||
|
structure.
|
||||||
|
@param Single A pointer to a single-instance device path data
|
||||||
|
structure.
|
||||||
|
|
||||||
|
@retval TRUE If the Single device path is contained within Multi device path.
|
||||||
|
@retval FALSE The Single device path is not match within Multi device path.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
BmMatchDevicePaths (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *Multi,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *Single
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
|
||||||
|
UINTN Size;
|
||||||
|
|
||||||
|
if (Multi == NULL || Single == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DevicePath = Multi;
|
||||||
|
DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Search for the match of 'Single' in 'Multi'
|
||||||
|
//
|
||||||
|
while (DevicePathInst != NULL) {
|
||||||
|
//
|
||||||
|
// If the single device path is found in multiple device paths,
|
||||||
|
// return success
|
||||||
|
//
|
||||||
|
if (CompareMem (Single, DevicePathInst, Size) == 0) {
|
||||||
|
FreePool (DevicePathInst);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool (DevicePathInst);
|
||||||
|
DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the headers (dos, image, optional header) from an image
|
||||||
|
|
||||||
|
@param Device SimpleFileSystem device handle
|
||||||
|
@param FileName File name for the image
|
||||||
|
@param DosHeader Pointer to dos header
|
||||||
|
@param Hdr The buffer in which to return the PE32, PE32+, or TE header.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully get the machine type.
|
||||||
|
@retval EFI_NOT_FOUND The file is not found.
|
||||||
|
@retval EFI_LOAD_ERROR File is not a valid image file.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmGetImageHeader (
|
||||||
|
IN EFI_HANDLE Device,
|
||||||
|
IN CHAR16 *FileName,
|
||||||
|
OUT EFI_IMAGE_DOS_HEADER *DosHeader,
|
||||||
|
OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
|
||||||
|
EFI_FILE_HANDLE Root;
|
||||||
|
EFI_FILE_HANDLE ThisFile;
|
||||||
|
UINTN BufferSize;
|
||||||
|
UINT64 FileSize;
|
||||||
|
EFI_FILE_INFO *Info;
|
||||||
|
|
||||||
|
Root = NULL;
|
||||||
|
ThisFile = NULL;
|
||||||
|
//
|
||||||
|
// Handle the file system interface to the device
|
||||||
|
//
|
||||||
|
Status = gBS->HandleProtocol (
|
||||||
|
Device,
|
||||||
|
&gEfiSimpleFileSystemProtocolGuid,
|
||||||
|
(VOID *) &Volume
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = Volume->OpenVolume (
|
||||||
|
Volume,
|
||||||
|
&Root
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Root = NULL;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
ASSERT (Root != NULL);
|
||||||
|
Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
ASSERT (ThisFile != NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get file size
|
||||||
|
//
|
||||||
|
BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
|
||||||
|
do {
|
||||||
|
Info = NULL;
|
||||||
|
Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
Status = ThisFile->GetInfo (
|
||||||
|
ThisFile,
|
||||||
|
&gEfiFileInfoGuid,
|
||||||
|
&BufferSize,
|
||||||
|
Info
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (Status != EFI_BUFFER_TOO_SMALL) {
|
||||||
|
FreePool (Info);
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
FreePool (Info);
|
||||||
|
} while (TRUE);
|
||||||
|
|
||||||
|
FileSize = Info->FileSize;
|
||||||
|
FreePool (Info);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read dos header
|
||||||
|
//
|
||||||
|
BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);
|
||||||
|
Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader);
|
||||||
|
if (EFI_ERROR (Status) ||
|
||||||
|
BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) ||
|
||||||
|
FileSize <= DosHeader->e_lfanew ||
|
||||||
|
DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
|
||||||
|
Status = EFI_LOAD_ERROR;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Move to PE signature
|
||||||
|
//
|
||||||
|
Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Status = EFI_LOAD_ERROR;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read and check PE signature
|
||||||
|
//
|
||||||
|
BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
|
||||||
|
Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32);
|
||||||
|
if (EFI_ERROR (Status) ||
|
||||||
|
BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) ||
|
||||||
|
Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
|
||||||
|
Status = EFI_LOAD_ERROR;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check PE32 or PE32+ magic
|
||||||
|
//
|
||||||
|
if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
|
||||||
|
Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
||||||
|
Status = EFI_LOAD_ERROR;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
Done:
|
||||||
|
if (ThisFile != NULL) {
|
||||||
|
ThisFile->Close (ThisFile);
|
||||||
|
}
|
||||||
|
if (Root != NULL) {
|
||||||
|
Root->Close (Root);
|
||||||
|
}
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This routine adjust the memory information for different memory type and
|
||||||
|
save them into the variables for next boot.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmSetMemoryTypeInformationVariable (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_MEMORY_TYPE_INFORMATION *PreviousMemoryTypeInformation;
|
||||||
|
EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation;
|
||||||
|
UINTN VariableSize;
|
||||||
|
UINTN Index;
|
||||||
|
UINTN Index1;
|
||||||
|
UINT32 Previous;
|
||||||
|
UINT32 Current;
|
||||||
|
UINT32 Next;
|
||||||
|
EFI_HOB_GUID_TYPE *GuidHob;
|
||||||
|
BOOLEAN MemoryTypeInformationModified;
|
||||||
|
BOOLEAN MemoryTypeInformationVariableExists;
|
||||||
|
EFI_BOOT_MODE BootMode;
|
||||||
|
|
||||||
|
MemoryTypeInformationModified = FALSE;
|
||||||
|
MemoryTypeInformationVariableExists = FALSE;
|
||||||
|
|
||||||
|
|
||||||
|
BootMode = GetBootModeHob ();
|
||||||
|
//
|
||||||
|
// In BOOT_IN_RECOVERY_MODE, Variable region is not reliable.
|
||||||
|
//
|
||||||
|
if (BootMode == BOOT_IN_RECOVERY_MODE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Only check the the Memory Type Information variable in the boot mode
|
||||||
|
// other than BOOT_WITH_DEFAULT_SETTINGS because the Memory Type
|
||||||
|
// Information is not valid in this boot mode.
|
||||||
|
//
|
||||||
|
if (BootMode != BOOT_WITH_DEFAULT_SETTINGS) {
|
||||||
|
VariableSize = 0;
|
||||||
|
Status = gRT->GetVariable (
|
||||||
|
EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
|
||||||
|
&gEfiMemoryTypeInformationGuid,
|
||||||
|
NULL,
|
||||||
|
&VariableSize,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||||
|
MemoryTypeInformationVariableExists = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Retrieve the current memory usage statistics. If they are not found, then
|
||||||
|
// no adjustments can be made to the Memory Type Information variable.
|
||||||
|
//
|
||||||
|
Status = EfiGetSystemConfigurationTable (
|
||||||
|
&gEfiMemoryTypeInformationGuid,
|
||||||
|
(VOID **) &CurrentMemoryTypeInformation
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the Memory Type Information settings from Hob if they exist,
|
||||||
|
// PEI is responsible for getting them from variable and build a Hob to save them.
|
||||||
|
// If the previous Memory Type Information is not available, then set defaults
|
||||||
|
//
|
||||||
|
GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
|
||||||
|
if (GuidHob == NULL) {
|
||||||
|
//
|
||||||
|
// If Platform has not built Memory Type Info into the Hob, just return.
|
||||||
|
//
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
|
||||||
|
VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Use a heuristic to adjust the Memory Type Information for the next boot
|
||||||
|
//
|
||||||
|
DEBUG ((EFI_D_INFO, "Memory Previous Current Next \n"));
|
||||||
|
DEBUG ((EFI_D_INFO, " Type Pages Pages Pages \n"));
|
||||||
|
DEBUG ((EFI_D_INFO, "====== ======== ======== ========\n"));
|
||||||
|
|
||||||
|
for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
|
||||||
|
|
||||||
|
for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {
|
||||||
|
if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Previous is the number of pages pre-allocated
|
||||||
|
// Current is the number of pages actually needed
|
||||||
|
//
|
||||||
|
Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;
|
||||||
|
Current = CurrentMemoryTypeInformation[Index1].NumberOfPages;
|
||||||
|
Next = Previous;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Inconsistent Memory Reserved across bootings may lead to S4 fail
|
||||||
|
// Write next varible to 125% * current when the pre-allocated memory is:
|
||||||
|
// 1. More than 150% of needed memory and boot mode is BOOT_WITH_DEFAULT_SETTING
|
||||||
|
// 2. Less than the needed memory
|
||||||
|
//
|
||||||
|
if ((Current + (Current >> 1)) < Previous) {
|
||||||
|
if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
|
||||||
|
Next = Current + (Current >> 2);
|
||||||
|
}
|
||||||
|
} else if (Current > Previous) {
|
||||||
|
Next = Current + (Current >> 2);
|
||||||
|
}
|
||||||
|
if (Next > 0 && Next < 4) {
|
||||||
|
Next = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Next != Previous) {
|
||||||
|
PreviousMemoryTypeInformation[Index].NumberOfPages = Next;
|
||||||
|
MemoryTypeInformationModified = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, " %02x %08x %08x %08x\n", PreviousMemoryTypeInformation[Index].Type, Previous, Current, Next));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If any changes were made to the Memory Type Information settings, then set the new variable value;
|
||||||
|
// Or create the variable in first boot.
|
||||||
|
//
|
||||||
|
if (MemoryTypeInformationModified || !MemoryTypeInformationVariableExists) {
|
||||||
|
Status = BmSetVariableAndReportStatusCodeOnError (
|
||||||
|
EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
|
||||||
|
&gEfiMemoryTypeInformationGuid,
|
||||||
|
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||||
|
VariableSize,
|
||||||
|
PreviousMemoryTypeInformation
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// If the Memory Type Information settings have been modified, then reset the platform
|
||||||
|
// so the new Memory Type Information setting will be used to guarantee that an S4
|
||||||
|
// entry/resume cycle will not fail.
|
||||||
|
//
|
||||||
|
if (MemoryTypeInformationModified) {
|
||||||
|
DEBUG ((EFI_D_INFO, "Memory Type Information settings change. Warm Reset!!!\n"));
|
||||||
|
gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG ((EFI_D_ERROR, "Memory Type Information settings cannot be saved. OS S4 may fail!\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set the variable and report the error through status code upon failure.
|
||||||
|
|
||||||
|
@param VariableName A Null-terminated string that is the name of the vendor's variable.
|
||||||
|
Each VariableName is unique for each VendorGuid. VariableName must
|
||||||
|
contain 1 or more characters. If VariableName is an empty string,
|
||||||
|
then EFI_INVALID_PARAMETER is returned.
|
||||||
|
@param VendorGuid A unique identifier for the vendor.
|
||||||
|
@param Attributes Attributes bitmask to set for the variable.
|
||||||
|
@param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE,
|
||||||
|
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or
|
||||||
|
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero
|
||||||
|
causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is
|
||||||
|
set, then a SetVariable() call with a DataSize of zero will not cause any change to
|
||||||
|
the variable value (the timestamp associated with the variable may be updated however
|
||||||
|
even if no new data value is provided,see the description of the
|
||||||
|
EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not
|
||||||
|
be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated).
|
||||||
|
@param Data The contents for the variable.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
|
||||||
|
defined by the Attributes.
|
||||||
|
@retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the
|
||||||
|
DataSize exceeds the maximum allowed.
|
||||||
|
@retval EFI_INVALID_PARAMETER VariableName is an empty string.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
|
||||||
|
@retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
|
||||||
|
@retval EFI_WRITE_PROTECTED The variable in question is read-only.
|
||||||
|
@retval EFI_WRITE_PROTECTED The variable in question cannot be deleted.
|
||||||
|
@retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
|
||||||
|
or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo
|
||||||
|
does NOT pass the validation check carried out by the firmware.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmSetVariableAndReportStatusCodeOnError (
|
||||||
|
IN CHAR16 *VariableName,
|
||||||
|
IN EFI_GUID *VendorGuid,
|
||||||
|
IN UINT32 Attributes,
|
||||||
|
IN UINTN DataSize,
|
||||||
|
IN VOID *Data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EDKII_SET_VARIABLE_STATUS *SetVariableStatus;
|
||||||
|
UINTN NameSize;
|
||||||
|
|
||||||
|
Status = gRT->SetVariable (
|
||||||
|
VariableName,
|
||||||
|
VendorGuid,
|
||||||
|
Attributes,
|
||||||
|
DataSize,
|
||||||
|
Data
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
NameSize = StrSize (VariableName);
|
||||||
|
SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize);
|
||||||
|
if (SetVariableStatus != NULL) {
|
||||||
|
CopyGuid (&SetVariableStatus->Guid, VendorGuid);
|
||||||
|
SetVariableStatus->NameSize = NameSize;
|
||||||
|
SetVariableStatus->DataSize = DataSize;
|
||||||
|
SetVariableStatus->SetStatus = Status;
|
||||||
|
SetVariableStatus->Attributes = Attributes;
|
||||||
|
CopyMem (SetVariableStatus + 1, VariableName, NameSize);
|
||||||
|
CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data, DataSize);
|
||||||
|
|
||||||
|
REPORT_STATUS_CODE_EX (
|
||||||
|
EFI_ERROR_CODE,
|
||||||
|
PcdGet32 (PcdErrorCodeSetVariable),
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
&gEdkiiStatusCodeDataTypeVariableGuid,
|
||||||
|
SetVariableStatus,
|
||||||
|
sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize
|
||||||
|
);
|
||||||
|
|
||||||
|
FreePool (SetVariableStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
358
MdeModulePkg/Library/UefiBootManagerLib/BmPerformance.c
Normal file
358
MdeModulePkg/Library/UefiBootManagerLib/BmPerformance.c
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
/** @file
|
||||||
|
This file include the file which can help to get the system
|
||||||
|
performance, all the function will only include if the performance
|
||||||
|
switch is set.
|
||||||
|
|
||||||
|
Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "InternalBm.h"
|
||||||
|
|
||||||
|
PERF_HEADER mBmPerfHeader;
|
||||||
|
PERF_DATA mBmPerfData;
|
||||||
|
EFI_PHYSICAL_ADDRESS mBmAcpiLowMemoryBase = 0x0FFFFFFFFULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the short verion of PDB file name to be
|
||||||
|
used in performance data logging.
|
||||||
|
|
||||||
|
@param PdbFileName The long PDB file name.
|
||||||
|
@param GaugeString The output string to be logged by performance logger.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmGetShortPdbFileName (
|
||||||
|
IN CONST CHAR8 *PdbFileName,
|
||||||
|
OUT CHAR8 *GaugeString
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
UINTN Index1;
|
||||||
|
UINTN StartIndex;
|
||||||
|
UINTN EndIndex;
|
||||||
|
|
||||||
|
if (PdbFileName == NULL) {
|
||||||
|
AsciiStrCpy (GaugeString, " ");
|
||||||
|
} else {
|
||||||
|
StartIndex = 0;
|
||||||
|
for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
|
||||||
|
;
|
||||||
|
|
||||||
|
for (Index = 0; PdbFileName[Index] != 0; Index++) {
|
||||||
|
if (PdbFileName[Index] == '\\') {
|
||||||
|
StartIndex = Index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PdbFileName[Index] == '.') {
|
||||||
|
EndIndex = Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Index1 = 0;
|
||||||
|
for (Index = StartIndex; Index < EndIndex; Index++) {
|
||||||
|
GaugeString[Index1] = PdbFileName[Index];
|
||||||
|
Index1++;
|
||||||
|
if (Index1 == PERF_TOKEN_LENGTH - 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GaugeString[Index1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the name from the Driver handle, which can be a handle with
|
||||||
|
EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.
|
||||||
|
This name can be used in performance data logging.
|
||||||
|
|
||||||
|
@param Handle Driver handle.
|
||||||
|
@param GaugeString The output string to be logged by performance logger.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmGetNameFromHandle (
|
||||||
|
IN EFI_HANDLE Handle,
|
||||||
|
OUT CHAR8 *GaugeString
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_LOADED_IMAGE_PROTOCOL *Image;
|
||||||
|
CHAR8 *PdbFileName;
|
||||||
|
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
|
||||||
|
|
||||||
|
AsciiStrCpy (GaugeString, " ");
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get handle name from image protocol
|
||||||
|
//
|
||||||
|
Status = gBS->HandleProtocol (
|
||||||
|
Handle,
|
||||||
|
&gEfiLoadedImageProtocolGuid,
|
||||||
|
(VOID **) &Image
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
Handle,
|
||||||
|
&gEfiDriverBindingProtocolGuid,
|
||||||
|
(VOID **) &DriverBinding,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Get handle name from image protocol
|
||||||
|
//
|
||||||
|
Status = gBS->HandleProtocol (
|
||||||
|
DriverBinding->ImageHandle,
|
||||||
|
&gEfiLoadedImageProtocolGuid,
|
||||||
|
(VOID **) &Image
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
|
||||||
|
|
||||||
|
if (PdbFileName != NULL) {
|
||||||
|
BmGetShortPdbFileName (PdbFileName, GaugeString);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Writes performance data of booting into the allocated memory.
|
||||||
|
OS can process these records.
|
||||||
|
|
||||||
|
@param Event The triggered event.
|
||||||
|
@param Context Context for this event.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
BmWriteBootToOsPerformanceData (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT32 LimitCount;
|
||||||
|
EFI_HANDLE *Handles;
|
||||||
|
UINTN NoHandles;
|
||||||
|
CHAR8 GaugeString[PERF_TOKEN_LENGTH];
|
||||||
|
UINT8 *Ptr;
|
||||||
|
UINT32 Index;
|
||||||
|
UINT64 Ticker;
|
||||||
|
UINT64 Freq;
|
||||||
|
UINT32 Duration;
|
||||||
|
UINTN LogEntryKey;
|
||||||
|
CONST VOID *Handle;
|
||||||
|
CONST CHAR8 *Token;
|
||||||
|
CONST CHAR8 *Module;
|
||||||
|
UINT64 StartTicker;
|
||||||
|
UINT64 EndTicker;
|
||||||
|
UINT64 StartValue;
|
||||||
|
UINT64 EndValue;
|
||||||
|
BOOLEAN CountUp;
|
||||||
|
UINTN EntryIndex;
|
||||||
|
UINTN NumPerfEntries;
|
||||||
|
//
|
||||||
|
// List of flags indicating PerfEntry contains DXE handle
|
||||||
|
//
|
||||||
|
BOOLEAN *PerfEntriesAsDxeHandle;
|
||||||
|
UINTN VarSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Record the performance data for End of BDS
|
||||||
|
//
|
||||||
|
PERF_END(NULL, "BDS", NULL, 0);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Retrieve time stamp count as early as possible
|
||||||
|
//
|
||||||
|
Ticker = GetPerformanceCounter ();
|
||||||
|
|
||||||
|
Freq = GetPerformanceCounterProperties (&StartValue, &EndValue);
|
||||||
|
|
||||||
|
Freq = DivU64x32 (Freq, 1000);
|
||||||
|
|
||||||
|
mBmPerfHeader.CpuFreq = Freq;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Record BDS raw performance data
|
||||||
|
//
|
||||||
|
if (EndValue >= StartValue) {
|
||||||
|
mBmPerfHeader.BDSRaw = Ticker - StartValue;
|
||||||
|
CountUp = TRUE;
|
||||||
|
} else {
|
||||||
|
mBmPerfHeader.BDSRaw = StartValue - Ticker;
|
||||||
|
CountUp = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mBmAcpiLowMemoryBase == 0x0FFFFFFFF) {
|
||||||
|
VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
|
||||||
|
Status = gRT->GetVariable (
|
||||||
|
L"PerfDataMemAddr",
|
||||||
|
&gPerformanceProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&VarSize,
|
||||||
|
&mBmAcpiLowMemoryBase
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Fail to get the variable, return.
|
||||||
|
//
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Put Detailed performance data into memory
|
||||||
|
//
|
||||||
|
Handles = NULL;
|
||||||
|
Status = gBS->LocateHandleBuffer (
|
||||||
|
AllHandles,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&NoHandles,
|
||||||
|
&Handles
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ptr = (UINT8 *) ((UINT32) mBmAcpiLowMemoryBase + sizeof (PERF_HEADER));
|
||||||
|
LimitCount = (UINT32) (PERF_DATA_MAX_LENGTH - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
|
||||||
|
|
||||||
|
NumPerfEntries = 0;
|
||||||
|
LogEntryKey = 0;
|
||||||
|
while ((LogEntryKey = GetPerformanceMeasurement (
|
||||||
|
LogEntryKey,
|
||||||
|
&Handle,
|
||||||
|
&Token,
|
||||||
|
&Module,
|
||||||
|
&StartTicker,
|
||||||
|
&EndTicker)) != 0) {
|
||||||
|
NumPerfEntries++;
|
||||||
|
}
|
||||||
|
PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));
|
||||||
|
ASSERT (PerfEntriesAsDxeHandle != NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get DXE drivers performance
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < NoHandles; Index++) {
|
||||||
|
Ticker = 0;
|
||||||
|
LogEntryKey = 0;
|
||||||
|
EntryIndex = 0;
|
||||||
|
while ((LogEntryKey = GetPerformanceMeasurement (
|
||||||
|
LogEntryKey,
|
||||||
|
&Handle,
|
||||||
|
&Token,
|
||||||
|
&Module,
|
||||||
|
&StartTicker,
|
||||||
|
&EndTicker)) != 0) {
|
||||||
|
if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {
|
||||||
|
PerfEntriesAsDxeHandle[EntryIndex] = TRUE;
|
||||||
|
}
|
||||||
|
EntryIndex++;
|
||||||
|
if ((Handle == Handles[Index]) && (EndTicker != 0)) {
|
||||||
|
if (StartTicker == 1) {
|
||||||
|
StartTicker = StartValue;
|
||||||
|
}
|
||||||
|
if (EndTicker == 1) {
|
||||||
|
EndTicker = StartValue;
|
||||||
|
}
|
||||||
|
Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
|
||||||
|
|
||||||
|
if (Duration > 0) {
|
||||||
|
|
||||||
|
BmGetNameFromHandle (Handles[Index], GaugeString);
|
||||||
|
|
||||||
|
AsciiStrCpy (mBmPerfData.Token, GaugeString);
|
||||||
|
mBmPerfData.Duration = Duration;
|
||||||
|
|
||||||
|
CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));
|
||||||
|
Ptr += sizeof (PERF_DATA);
|
||||||
|
|
||||||
|
mBmPerfHeader.Count++;
|
||||||
|
if (mBmPerfHeader.Count == LimitCount) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get inserted performance data
|
||||||
|
//
|
||||||
|
LogEntryKey = 0;
|
||||||
|
EntryIndex = 0;
|
||||||
|
while ((LogEntryKey = GetPerformanceMeasurement (
|
||||||
|
LogEntryKey,
|
||||||
|
&Handle,
|
||||||
|
&Token,
|
||||||
|
&Module,
|
||||||
|
&StartTicker,
|
||||||
|
&EndTicker)) != 0) {
|
||||||
|
if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {
|
||||||
|
|
||||||
|
ZeroMem (&mBmPerfData, sizeof (PERF_DATA));
|
||||||
|
|
||||||
|
AsciiStrnCpy (mBmPerfData.Token, Token, PERF_TOKEN_LENGTH);
|
||||||
|
if (StartTicker == 1) {
|
||||||
|
StartTicker = StartValue;
|
||||||
|
}
|
||||||
|
if (EndTicker == 1) {
|
||||||
|
EndTicker = StartValue;
|
||||||
|
}
|
||||||
|
Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
|
||||||
|
|
||||||
|
mBmPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
|
||||||
|
|
||||||
|
CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));
|
||||||
|
Ptr += sizeof (PERF_DATA);
|
||||||
|
|
||||||
|
mBmPerfHeader.Count++;
|
||||||
|
if (mBmPerfHeader.Count == LimitCount) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EntryIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Done:
|
||||||
|
|
||||||
|
FreePool (Handles);
|
||||||
|
FreePool (PerfEntriesAsDxeHandle);
|
||||||
|
|
||||||
|
mBmPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Put performance data to Reserved memory
|
||||||
|
//
|
||||||
|
CopyMem (
|
||||||
|
(UINTN *) (UINTN) mBmAcpiLowMemoryBase,
|
||||||
|
&mBmPerfHeader,
|
||||||
|
sizeof (PERF_HEADER)
|
||||||
|
);
|
||||||
|
|
||||||
|
return ;
|
||||||
|
}
|
364
MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
Normal file
364
MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
/** @file
|
||||||
|
BDS library definition, include the file and data structure
|
||||||
|
|
||||||
|
Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _INTERNAL_BM_H_
|
||||||
|
#define _INTERNAL_BM_H_
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
|
||||||
|
#include <IndustryStandard/Pci.h>
|
||||||
|
#include <IndustryStandard/PeImage.h>
|
||||||
|
#include <IndustryStandard/Atapi.h>
|
||||||
|
#include <IndustryStandard/Scsi.h>
|
||||||
|
|
||||||
|
#include <Protocol/PciRootBridgeIo.h>
|
||||||
|
#include <Protocol/BlockIo.h>
|
||||||
|
#include <Protocol/LoadedImage.h>
|
||||||
|
#include <Protocol/SimpleFileSystem.h>
|
||||||
|
#include <Protocol/LoadFile.h>
|
||||||
|
#include <Protocol/DevicePath.h>
|
||||||
|
#include <Protocol/SimpleTextIn.h>
|
||||||
|
#include <Protocol/SimpleTextInEx.h>
|
||||||
|
#include <Protocol/SimpleTextOut.h>
|
||||||
|
#include <Protocol/SimpleNetwork.h>
|
||||||
|
#include <Protocol/FirmwareVolume2.h>
|
||||||
|
#include <Protocol/PciIo.h>
|
||||||
|
#include <Protocol/GraphicsOutput.h>
|
||||||
|
#include <Protocol/UsbIo.h>
|
||||||
|
#include <Protocol/DiskInfo.h>
|
||||||
|
#include <Protocol/IdeControllerInit.h>
|
||||||
|
#include <Protocol/BootLogo.h>
|
||||||
|
#include <Protocol/DriverHealth.h>
|
||||||
|
#include <Protocol/FormBrowser2.h>
|
||||||
|
|
||||||
|
#include <Guid/ZeroGuid.h>
|
||||||
|
#include <Guid/MemoryTypeInformation.h>
|
||||||
|
#include <Guid/FileInfo.h>
|
||||||
|
#include <Guid/GlobalVariable.h>
|
||||||
|
#include <Guid/Performance.h>
|
||||||
|
#include <Guid/StatusCodeDataTypeVariable.h>
|
||||||
|
|
||||||
|
#include <Library/PrintLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||||
|
#include <Library/UefiLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/DxeServicesTableLib.h>
|
||||||
|
#include <Library/HobLib.h>
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/DevicePathLib.h>
|
||||||
|
#include <Library/PerformanceLib.h>
|
||||||
|
#include <Library/PcdLib.h>
|
||||||
|
#include <Library/PeCoffGetEntryPointLib.h>
|
||||||
|
#include <Library/UefiBootManagerLib.h>
|
||||||
|
#include <Library/TimerLib.h>
|
||||||
|
#include <Library/DxeServicesLib.h>
|
||||||
|
#include <Library/ReportStatusCodeLib.h>
|
||||||
|
#include <Library/CapsuleLib.h>
|
||||||
|
#include <Library/PerformanceLib.h>
|
||||||
|
#include <Library/HiiLib.h>
|
||||||
|
|
||||||
|
#if !defined (EFI_REMOVABLE_MEDIA_FILE_NAME)
|
||||||
|
#if defined (MDE_CPU_EBC)
|
||||||
|
//
|
||||||
|
// Uefi specification only defines the default boot file name for IA32, X64
|
||||||
|
// and IPF processor, so need define boot file name for EBC architecture here.
|
||||||
|
//
|
||||||
|
#define EFI_REMOVABLE_MEDIA_FILE_NAME L"\\EFI\\BOOT\\BOOTEBC.EFI"
|
||||||
|
#else
|
||||||
|
#error "Can not determine the default boot file name for unknown processor type!"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BmAcpiFloppyBoot,
|
||||||
|
BmHardwareDeviceBoot,
|
||||||
|
BmMessageAtapiBoot,
|
||||||
|
BmMessageSataBoot,
|
||||||
|
BmMessageUsbBoot,
|
||||||
|
BmMessageScsiBoot,
|
||||||
|
BmMessageNetworkBoot,
|
||||||
|
BmMiscBoot
|
||||||
|
} BM_BOOT_TYPE;
|
||||||
|
|
||||||
|
typedef
|
||||||
|
CHAR16 *
|
||||||
|
(* BM_GET_BOOT_DESCRIPTION) (
|
||||||
|
IN EFI_HANDLE Handle
|
||||||
|
);
|
||||||
|
|
||||||
|
#define BM_HOTKEY_SIGNATURE SIGNATURE_32 ('b', 'm', 'h', 'k')
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Signature;
|
||||||
|
LIST_ENTRY Link;
|
||||||
|
|
||||||
|
BOOLEAN IsContinue;
|
||||||
|
UINT16 BootOption;
|
||||||
|
UINT8 CodeCount;
|
||||||
|
UINT8 WaitingKey;
|
||||||
|
EFI_KEY_DATA KeyData[3];
|
||||||
|
} BM_HOTKEY;
|
||||||
|
|
||||||
|
#define BM_HOTKEY_FROM_LINK(a) CR (a, BM_HOTKEY, Link, BM_HOTKEY_SIGNATURE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the image file buffer data and buffer size by its device path.
|
||||||
|
|
||||||
|
@param FilePath On input, a pointer to an allocated buffer containing the device
|
||||||
|
path of the file.
|
||||||
|
On output the pointer could be NULL when the function fails to
|
||||||
|
load the boot option, or could point to an allocated buffer containing
|
||||||
|
the device path of the file.
|
||||||
|
It could be updated by either short-form device path expanding,
|
||||||
|
or default boot file path appending.
|
||||||
|
Caller is responsible to free it when it's non-NULL.
|
||||||
|
@param FileSize A pointer to the size of the file buffer.
|
||||||
|
|
||||||
|
@retval NULL File is NULL, or FileSize is NULL. Or, the file can't be found.
|
||||||
|
@retval other The file buffer. The caller is responsible to free the memory.
|
||||||
|
**/
|
||||||
|
VOID *
|
||||||
|
BmLoadEfiBootOption (
|
||||||
|
IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
|
||||||
|
OUT UINTN *FileSize
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the Option Number that wasn't used.
|
||||||
|
|
||||||
|
@param OrderVariableName Could be L"BootOrder" or L"DriverOrder".
|
||||||
|
@param FreeOptionNumber To receive the minimal free option number.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The option number is found
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is no free option number that can be used.
|
||||||
|
@retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmGetFreeOptionNumber (
|
||||||
|
IN CHAR16 *OrderVariableName,
|
||||||
|
OUT UINT16 *FreeOptionNumber
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Writes performance data of booting into the allocated memory.
|
||||||
|
OS can process these records.
|
||||||
|
|
||||||
|
@param Event The triggered event.
|
||||||
|
@param Context Context for this event.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
BmWriteBootToOsPerformanceData (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the headers (dos, image, optional header) from an image
|
||||||
|
|
||||||
|
@param Device SimpleFileSystem device handle
|
||||||
|
@param FileName File name for the image
|
||||||
|
@param DosHeader Pointer to dos header
|
||||||
|
@param Hdr The buffer in which to return the PE32, PE32+, or TE header.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully get the machine type.
|
||||||
|
@retval EFI_NOT_FOUND The file is not found.
|
||||||
|
@retval EFI_LOAD_ERROR File is not a valid image file.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmGetImageHeader (
|
||||||
|
IN EFI_HANDLE Device,
|
||||||
|
IN CHAR16 *FileName,
|
||||||
|
OUT EFI_IMAGE_DOS_HEADER *DosHeader,
|
||||||
|
OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This routine adjust the memory information for different memory type and
|
||||||
|
save them into the variables for next boot.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmSetMemoryTypeInformationVariable (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check whether there is a instance in BlockIoDevicePath, which contain multi device path
|
||||||
|
instances, has the same partition node with HardDriveDevicePath device path
|
||||||
|
|
||||||
|
@param BlockIoDevicePath Multi device path instances which need to check
|
||||||
|
@param HardDriveDevicePath A device path which starts with a hard drive media
|
||||||
|
device path.
|
||||||
|
|
||||||
|
@retval TRUE There is a matched device path instance.
|
||||||
|
@retval FALSE There is no matched device path instance.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
BmMatchPartitionDevicePathNode (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,
|
||||||
|
IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Connect the specific Usb device which match the short form device path.
|
||||||
|
|
||||||
|
@param DevicePath A short-form device path that starts with the first
|
||||||
|
element being a USB WWID or a USB Class device
|
||||||
|
path
|
||||||
|
|
||||||
|
@return EFI_INVALID_PARAMETER DevicePath is NULL pointer.
|
||||||
|
DevicePath is not a USB device path.
|
||||||
|
|
||||||
|
@return EFI_SUCCESS Success to connect USB device
|
||||||
|
@return EFI_NOT_FOUND Fail to find handle for USB controller to connect.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmConnectUsbShortFormDevicePath (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Stop the hotkey processing.
|
||||||
|
|
||||||
|
@param Event Event pointer related to hotkey service.
|
||||||
|
@param Context Context pass to this function.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
BmStopHotkeyService (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set the variable and report the error through status code upon failure.
|
||||||
|
|
||||||
|
@param VariableName A Null-terminated string that is the name of the vendor's variable.
|
||||||
|
Each VariableName is unique for each VendorGuid. VariableName must
|
||||||
|
contain 1 or more characters. If VariableName is an empty string,
|
||||||
|
then EFI_INVALID_PARAMETER is returned.
|
||||||
|
@param VendorGuid A unique identifier for the vendor.
|
||||||
|
@param Attributes Attributes bitmask to set for the variable.
|
||||||
|
@param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE,
|
||||||
|
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or
|
||||||
|
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero
|
||||||
|
causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is
|
||||||
|
set, then a SetVariable() call with a DataSize of zero will not cause any change to
|
||||||
|
the variable value (the timestamp associated with the variable may be updated however
|
||||||
|
even if no new data value is provided,see the description of the
|
||||||
|
EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not
|
||||||
|
be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated).
|
||||||
|
@param Data The contents for the variable.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
|
||||||
|
defined by the Attributes.
|
||||||
|
@retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the
|
||||||
|
DataSize exceeds the maximum allowed.
|
||||||
|
@retval EFI_INVALID_PARAMETER VariableName is an empty string.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
|
||||||
|
@retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
|
||||||
|
@retval EFI_WRITE_PROTECTED The variable in question is read-only.
|
||||||
|
@retval EFI_WRITE_PROTECTED The variable in question cannot be deleted.
|
||||||
|
@retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
|
||||||
|
or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo
|
||||||
|
does NOT pass the validation check carried out by the firmware.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmSetVariableAndReportStatusCodeOnError (
|
||||||
|
IN CHAR16 *VariableName,
|
||||||
|
IN EFI_GUID *VendorGuid,
|
||||||
|
IN UINT32 Attributes,
|
||||||
|
IN UINTN DataSize,
|
||||||
|
IN VOID *Data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Function compares a device path data structure to that of all the nodes of a
|
||||||
|
second device path instance.
|
||||||
|
|
||||||
|
@param Multi A pointer to a multi-instance device path data
|
||||||
|
structure.
|
||||||
|
@param Single A pointer to a single-instance device path data
|
||||||
|
structure.
|
||||||
|
|
||||||
|
@retval TRUE If the Single device path is contained within Multi device path.
|
||||||
|
@retval FALSE The Single device path is not match within Multi device path.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
BmMatchDevicePaths (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *Multi,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *Single
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Delete the instance in Multi which matches partly with Single instance
|
||||||
|
|
||||||
|
@param Multi A pointer to a multi-instance device path data
|
||||||
|
structure.
|
||||||
|
@param Single A pointer to a single-instance device path data
|
||||||
|
structure.
|
||||||
|
|
||||||
|
@return This function will remove the device path instances in Multi which partly
|
||||||
|
match with the Single, and return the result device path. If there is no
|
||||||
|
remaining device path as a result, this function will return NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
BmDelPartMatchInstance (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *Multi,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *Single
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the index of the load option in the load option array.
|
||||||
|
|
||||||
|
The function consider two load options are equal when the
|
||||||
|
OptionType, Attributes, Description, FilePath and OptionalData are equal.
|
||||||
|
|
||||||
|
@param Key Pointer to the load option to be found.
|
||||||
|
@param Array Pointer to the array of load options to be found.
|
||||||
|
@param Count Number of entries in the Array.
|
||||||
|
|
||||||
|
@retval -1 Key wasn't found in the Array.
|
||||||
|
@retval 0 ~ Count-1 The index of the Key in the Array.
|
||||||
|
**/
|
||||||
|
INTN
|
||||||
|
BmFindLoadOption (
|
||||||
|
IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
|
||||||
|
IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
|
||||||
|
IN UINTN Count
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Repair all the controllers according to the Driver Health status queried.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmRepairAllControllers (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif // _INTERNAL_BM_H_
|
110
MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
Normal file
110
MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
## @file
|
||||||
|
# Define and produce general Boot Manager related interfaces.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
|
# are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
# which accompanies this distribution. The full text of the license may be found at
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
#
|
||||||
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = UefiBootManagerLib
|
||||||
|
FILE_GUID = 8D4752BC-595E-49a2-B4AF-F3F57B601DE9
|
||||||
|
MODULE_TYPE = DXE_DRIVER
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
LIBRARY_CLASS = UefiBootManagerLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||||
|
#
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
BmPerformance.c
|
||||||
|
BmConnect.c
|
||||||
|
BmMisc.c
|
||||||
|
BmConsole.c
|
||||||
|
BmBoot.c
|
||||||
|
BmLoadOption.c
|
||||||
|
BmHotkey.c
|
||||||
|
BmDriverHealth.c
|
||||||
|
InternalBm.h
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
HobLib
|
||||||
|
PcdLib
|
||||||
|
BaseLib
|
||||||
|
UefiLib
|
||||||
|
TimerLib
|
||||||
|
DebugLib
|
||||||
|
PrintLib
|
||||||
|
BaseMemoryLib
|
||||||
|
DevicePathLib
|
||||||
|
PerformanceLib
|
||||||
|
PeCoffGetEntryPointLib
|
||||||
|
UefiBootServicesTableLib
|
||||||
|
UefiRuntimeServicesTableLib
|
||||||
|
DxeServicesTableLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
DxeServicesLib
|
||||||
|
ReportStatusCodeLib
|
||||||
|
PerformanceLib
|
||||||
|
HiiLib
|
||||||
|
BaseSortLib
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEfiMemoryTypeInformationGuid ## CONSUMES ## GUID (The identifier of memory type information type in system table)
|
||||||
|
## CONSUMES ## GUID HOB (The hob holding memory type information)
|
||||||
|
gEfiGlobalVariableGuid ## SOMETIMES_PRODUCES ## Variable:L"BootCurrent" (The boot option of current boot)
|
||||||
|
## SOMETIMES_CONSUMES ## Variable:L"BootXX" (Boot option variable)
|
||||||
|
## CONSUMES ## Variable:L"Timeout" (The time out value in second of showing progress bar)
|
||||||
|
## SOMETIMES_CONSUMES ## Variable:L"BootOrder" (The boot option array)
|
||||||
|
## SOMETIMES_CONSUMES ## Variable:L"DriverOrder" (The driver order list)
|
||||||
|
## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device)
|
||||||
|
## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device)
|
||||||
|
## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device)
|
||||||
|
gEfiFileInfoGuid ## CONSUMES ## GUID
|
||||||
|
gPerformanceProtocolGuid ## SOMETIMES_PRODUCES ## Variable:L"PerfDataMemAddr" (The ACPI address of performance data)
|
||||||
|
gEdkiiStatusCodeDataTypeVariableGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gEfiDiskInfoAhciInterfaceGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gEfiDiskInfoIdeInterfaceGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gEfiDiskInfoScsiInterfaceGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gZeroGuid ## CONSUMES ## GUID
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
|
||||||
|
gEfiSimpleFileSystemProtocolGuid ## CONSUMES
|
||||||
|
gEfiLoadFileProtocolGuid ## CONSUMES
|
||||||
|
gEfiSimpleTextOutProtocolGuid ## CONSUMES
|
||||||
|
gEfiPciIoProtocolGuid ## CONSUMES
|
||||||
|
gEfiLoadedImageProtocolGuid ## CONSUMES
|
||||||
|
gEfiSimpleNetworkProtocolGuid ## CONSUMES
|
||||||
|
gEfiSimpleTextInProtocolGuid ## CONSUMES
|
||||||
|
gEfiBlockIoProtocolGuid ## CONSUMES
|
||||||
|
gEfiFirmwareVolume2ProtocolGuid ## CONSUMES
|
||||||
|
gEfiDevicePathProtocolGuid ## CONSUMES
|
||||||
|
gEfiBootLogoProtocolGuid ## CONSUMES
|
||||||
|
gEfiSimpleTextInputExProtocolGuid ## CONSUMES
|
||||||
|
gEfiGraphicsOutputProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
gEfiDiskInfoProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
gEfiDriverHealthProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange ## SOMETIMES_CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderLoad ## SOMETIMES_CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderStart ## SOMETIMES_CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable ## SOMETIMES_CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdDriverHealthConfigureForm ## SOMETIMES_CONSUMES
|
||||||
|
|
@ -105,6 +105,9 @@
|
|||||||
## @libraryclass Provides sorting functions
|
## @libraryclass Provides sorting functions
|
||||||
SortLib|Include/Library/SortLib.h
|
SortLib|Include/Library/SortLib.h
|
||||||
|
|
||||||
|
## @libraryclass Provides core boot manager functions
|
||||||
|
UefiBootManagerLib|Include/Library/UefiBootManagerLib.h
|
||||||
|
|
||||||
[Guids]
|
[Guids]
|
||||||
## MdeModule package token space guid
|
## MdeModule package token space guid
|
||||||
# Include/Guid/MdeModulePkgTokenSpace.h
|
# Include/Guid/MdeModulePkgTokenSpace.h
|
||||||
@ -922,7 +925,16 @@
|
|||||||
## Serial Port Extended Transmit FIFO Size. The default is 64 bytes.
|
## Serial Port Extended Transmit FIFO Size. The default is 64 bytes.
|
||||||
# @Prompt Serial Port Extended Transmit FIFO Size in Bytes
|
# @Prompt Serial Port Extended Transmit FIFO Size in Bytes
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialExtendedTxFifoSize|64|UINT32|0x00010068
|
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.
|
## The number of bytes between registers in serial device. The default is 1 byte.
|
||||||
# @Prompt Serial Port Register Stride in Bytes
|
# @Prompt Serial Port Register Stride in Bytes
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1|UINT32|0x0001006B
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1|UINT32|0x0001006B
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
|
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
|
||||||
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
|
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
|
||||||
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
|
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
|
||||||
|
BaseSortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
|
||||||
#
|
#
|
||||||
# UEFI & PI
|
# UEFI & PI
|
||||||
#
|
#
|
||||||
@ -267,6 +268,7 @@
|
|||||||
MdeModulePkg/Library/PlatformHookLibSerialPortPpi/PlatformHookLibSerialPortPpi.inf
|
MdeModulePkg/Library/PlatformHookLibSerialPortPpi/PlatformHookLibSerialPortPpi.inf
|
||||||
MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
|
MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
|
||||||
MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
|
MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
|
||||||
|
MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
|
||||||
|
|
||||||
MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
|
MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
|
||||||
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
|
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
|
||||||
|
Reference in New Issue
Block a user