MdeModulePkg: Fix EOL to be DOS format.
authorRuiyu Ni <ruiyu.ni@intel.com>
Wed, 13 May 2015 02:23:44 +0000 (02:23 +0000)
committerniruiyu <niruiyu@Edk2>
Wed, 13 May 2015 02:23:44 +0000 (02:23 +0000)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17421 6f19259b-4bc3-4df7-8a09-765794883524

12 files changed:
MdeModulePkg/Include/Library/UefiBootManagerLib.h
MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
MdeModulePkg/Library/UefiBootManagerLib/BmConnect.c
MdeModulePkg/Library/UefiBootManagerLib/BmConsole.c
MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c
MdeModulePkg/Library/UefiBootManagerLib/BmHotkey.c
MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c
MdeModulePkg/Library/UefiBootManagerLib/BmPerformance.c
MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf

index 2ec8089..886229e 100644 (file)
-/** @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 {
-  LoadOptionTypeDriver,
-  LoadOptionTypeSysPrep,
-  LoadOptionTypeBoot,
-  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
-  EFI_GUID                          VendorGuid;
-
-  //
-  // 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####/SysPrep#### and the 
-  BootOrder/DriverOrder/SysPrepOrder 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/SysPrepOrder.
-
-  @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 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.
-  @retval EFI_SECURITY_VIOLATION The user has no permission to start UEFI device 
-                                 drivers on the DevicePath.
-**/
-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.
-
-  @retval EFI_DEVICE_ERROR         All the consoles were not connected due to an error.
-  @retval EFI_SUCCESS              Success connect any one instance of the console
-                                   device path base on the variable ConVarName.
-**/
-EFI_STATUS
-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
-  );
-
-/**
-  Process (load and execute) the load option.
-
-  @param LoadOption  Pointer to the load option.
-
-  @retval EFI_INVALID_PARAMETER  The load option type is invalid, 
-                                 or the load option file path doesn't point to a valid file.
-  @retval EFI_UNSUPPORTED        The load option type is of LoadOptionTypeBoot.
-  @retval EFI_SUCCESS            The load option is inactive, or successfully loaded and executed.
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerProcessLoadOption (
-  EFI_BOOT_MANAGER_LOAD_OPTION       *LoadOption
-  );
-#endif
+/** @file\r
+  Provide Boot Manager related library APIs.\r
+\r
+Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef _UEFI_BOOT_MANAGER_LIB_H_\r
+#define _UEFI_BOOT_MANAGER_LIB_H_\r
+\r
+#include <Protocol/DriverHealth.h>\r
+#include <Library/SortLib.h>\r
+\r
+//\r
+// Boot Manager load option library functions.\r
+//\r
+\r
+//\r
+// Load Option Type\r
+//\r
+typedef enum {\r
+  LoadOptionTypeDriver,\r
+  LoadOptionTypeSysPrep,\r
+  LoadOptionTypeBoot,\r
+  LoadOptionTypeMax\r
+} EFI_BOOT_MANAGER_LOAD_OPTION_TYPE;\r
+\r
+typedef enum {\r
+  LoadOptionNumberMax = 0x10000,\r
+  LoadOptionNumberUnassigned = LoadOptionNumberMax\r
+} EFI_BOOT_MANAGER_LOAD_OPTION_NUMBER;\r
+\r
+//\r
+// Common structure definition for DriverOption and BootOption\r
+//\r
+typedef struct {\r
+  //\r
+  // Data read from UEFI NV variables\r
+  //\r
+  UINTN                             OptionNumber;       // #### numerical value, could be LoadOptionNumberUnassigned\r
+  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType;         // LoadOptionTypeBoot or LoadOptionTypeDriver\r
+  UINT32                            Attributes;         // Load Option Attributes\r
+  CHAR16                            *Description;       // Load Option Description\r
+  EFI_DEVICE_PATH_PROTOCOL          *FilePath;          // Load Option Device Path\r
+  UINT8                             *OptionalData;      // Load Option optional data to pass into image\r
+  UINT32                            OptionalDataSize;   // Load Option size of OptionalData\r
+  EFI_GUID                          VendorGuid;\r
+\r
+  //\r
+  // Used at runtime\r
+  //\r
+  EFI_STATUS                        Status;             // Status returned from boot attempt gBS->StartImage ()\r
+  CHAR16                            *ExitData;          // Exit data returned from gBS->StartImage () \r
+  UINTN                             ExitDataSize;       // Size of ExitData\r
+} EFI_BOOT_MANAGER_LOAD_OPTION;\r
+\r
+/**\r
+  Returns an array of load options based on the EFI variable\r
+  L"BootOrder"/L"DriverOrder" and the L"Boot####"/L"Driver####" variables impled by it.\r
+  #### is the hex value of the UINT16 in each BootOrder/DriverOrder entry. \r
+\r
+  @param  LoadOptionCount   Returns number of entries in the array.\r
+  @param  LoadOptionType    The type of the load option.\r
+\r
+  @retval NULL  No load options exist.\r
+  @retval !NULL Array of load option entries.\r
+\r
+**/\r
+EFI_BOOT_MANAGER_LOAD_OPTION *\r
+EFIAPI\r
+EfiBootManagerGetLoadOptions (\r
+  OUT UINTN                            *LoadOptionCount,\r
+  IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType\r
+  );\r
+\r
+/**\r
+  Free an array of load options returned from EfiBootManagerGetLoadOptions().\r
+\r
+  @param  LoadOptions      Pointer to the array of load options to free.\r
+  @param  LoadOptionCount  Number of array entries in LoadOptions.\r
+\r
+  @return EFI_SUCCESS           LoadOptions was freed.\r
+  @return EFI_INVALID_PARAMETER LoadOptions is NULL.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerFreeLoadOptions (\r
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION  *LoadOptions,\r
+  IN  UINTN                         LoadOptionCount\r
+  );\r
+\r
+/**\r
+  Initialize a load option.\r
+\r
+  @param Option           Pointer to the load option to be initialized.\r
+  @param OptionNumber     Option number of the load option.\r
+  @param OptionType       Type of the load option.\r
+  @param Attributes       Attributes of the load option.\r
+  @param Description      Description of the load option.\r
+  @param FilePath         Device path of the load option.\r
+  @param OptionalData     Optional data of the load option.\r
+  @param OptionalDataSize Size of the optional data of the load option.\r
+\r
+  @retval EFI_SUCCESS           The load option was initialized successfully.\r
+  @retval EFI_INVALID_PARAMETER Option, Description or FilePath is NULL.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerInitializeLoadOption (\r
+  IN OUT EFI_BOOT_MANAGER_LOAD_OPTION   *Option,\r
+  IN  UINTN                             OptionNumber,\r
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,\r
+  IN  UINT32                            Attributes,\r
+  IN  CHAR16                            *Description,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL          *FilePath,\r
+  IN  UINT8                             *OptionalData,\r
+  IN  UINT32                            OptionalDataSize\r
+  );\r
+\r
+/**\r
+  Free a load option created by EfiBootManagerInitializeLoadOption()\r
+  or EfiBootManagerVariableToLoadOption().\r
+\r
+  @param  LoadOption   Pointer to the load option to free.\r
+  CONCERN: Check Boot#### instead of BootOrder, optimize, spec clarify\r
+  @return EFI_SUCCESS           LoadOption was freed.\r
+  @return EFI_INVALID_PARAMETER LoadOption is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerFreeLoadOption (\r
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION  *LoadOption\r
+  );\r
+\r
+/**\r
+  Initialize the load option from the VariableName.\r
+\r
+  @param  VariableName          EFI Variable name which could be Boot#### or\r
+                                Driver####\r
+  @param  LoadOption            Pointer to the load option to be initialized\r
+\r
+  @retval EFI_SUCCESS           The option was created\r
+  @retval EFI_INVALID_PARAMETER VariableName or LoadOption is NULL.\r
+  @retval EFI_NOT_FOUND         The variable specified by VariableName cannot be found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerVariableToLoadOption (\r
+  IN CHAR16                           *VariableName,\r
+  IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption\r
+  );\r
+\r
+/**\r
+  Create the Boot#### or Driver#### variable from the load option.\r
+  \r
+  @param  LoadOption      Pointer to the load option.\r
+\r
+  @retval EFI_SUCCESS     The variable was created.\r
+  @retval Others          Error status returned by RT->SetVariable.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerLoadOptionToVariable (\r
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION     *LoadOption\r
+  );\r
+\r
+/**\r
+  This function will update the Boot####/Driver####/SysPrep#### and the \r
+  BootOrder/DriverOrder/SysPrepOrder to add a new load option.\r
+\r
+  @param  Option        Pointer to load option to add.\r
+  @param  Position      Position of the new load option to put in the BootOrder/DriverOrder/SysPrepOrder.\r
+\r
+  @retval EFI_SUCCESS   The load option has been successfully added.\r
+  @retval Others        Error status returned by RT->SetVariable.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerAddLoadOptionVariable (\r
+  IN EFI_BOOT_MANAGER_LOAD_OPTION  *Option,\r
+  IN UINTN                         Position\r
+  );\r
+\r
+/**\r
+  Delete the load option according to the OptionNumber and OptionType.\r
+  \r
+  Only the BootOrder/DriverOrder is updated to remove the reference of the OptionNumber.\r
+  \r
+  @param  OptionNumber        Option number of the load option.\r
+  @param  OptionType          Type of the load option.\r
+\r
+  @retval EFI_NOT_FOUND       The load option cannot be found.\r
+  @retval EFI_SUCCESS         The load option was deleted.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerDeleteLoadOptionVariable (\r
+  IN UINTN                              OptionNumber,\r
+  IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE  OptionType\r
+  );\r
+\r
+/**\r
+  Sort the load options. The DriverOrder/BootOrder variables will be re-created to \r
+  reflect the new order.\r
+\r
+  @param OptionType        The type of the load option.\r
+  @param Comparator        The comparator function pointer.\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerSortLoadOptionVariable (\r
+  IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,\r
+  IN SORT_COMPARE                      CompareFunction\r
+  );\r
+\r
+//\r
+// Boot Manager hot key library functions.\r
+//\r
+\r
+#pragma pack(1)\r
+///\r
+/// EFI Key Option.\r
+///\r
+typedef struct {\r
+  ///\r
+  /// Specifies options about how the key will be processed.\r
+  ///\r
+  EFI_BOOT_KEY_DATA  KeyData;\r
+  ///\r
+  /// The CRC-32 which should match the CRC-32 of the entire EFI_LOAD_OPTION to\r
+  /// which BootOption refers. If the CRC-32s do not match this value, then this key\r
+  /// option is ignored.\r
+  ///\r
+  UINT32             BootOptionCrc;\r
+  ///\r
+  /// The Boot#### option which will be invoked if this key is pressed and the boot option\r
+  /// is active (LOAD_OPTION_ACTIVE is set).\r
+  ///\r
+  UINT16             BootOption;\r
+  ///\r
+  /// The key codes to compare against those returned by the\r
+  /// EFI_SIMPLE_TEXT_INPUT and EFI_SIMPLE_TEXT_INPUT_EX protocols.\r
+  /// The number of key codes (0-3) is specified by the EFI_KEY_CODE_COUNT field in KeyOptions.\r
+  ///\r
+  EFI_INPUT_KEY      Keys[3];\r
+  UINT16             OptionNumber;\r
+} EFI_BOOT_MANAGER_KEY_OPTION;\r
+#pragma pack()\r
+\r
+/**\r
+  Start the hot key service so that the key press can trigger the boot option.\r
+\r
+  @param HotkeyTriggered  Return the waitable event and it will be signaled \r
+                          when a valid hot key is pressed.\r
+\r
+  @retval EFI_SUCCESS     The hot key service is started.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerStartHotkeyService (\r
+  IN EFI_EVENT      *HotkeyTriggered\r
+  );\r
+\r
+//\r
+// Modifier for EfiBootManagerAddKeyOptionVariable and EfiBootManagerDeleteKeyOptionVariable\r
+//\r
+#define EFI_BOOT_MANAGER_SHIFT_PRESSED    0x00000001\r
+#define EFI_BOOT_MANAGER_CONTROL_PRESSED  0x00000002\r
+#define EFI_BOOT_MANAGER_ALT_PRESSED      0x00000004\r
+#define EFI_BOOT_MANAGER_LOGO_PRESSED     0x00000008\r
+#define EFI_BOOT_MANAGER_MENU_KEY_PRESSED 0x00000010\r
+#define EFI_BOOT_MANAGER_SYS_REQ_PRESSED  0x00000020\r
+\r
+/**\r
+  Add the key option.\r
+  It adds the key option variable and the key option takes affect immediately.\r
+\r
+  @param AddedOption      Return the added key option.\r
+  @param BootOptionNumber The boot option number for the key option.\r
+  @param Modifier         Key shift state.\r
+  @param ...              Parameter list of pointer of EFI_INPUT_KEY.\r
+\r
+  @retval EFI_SUCCESS         The key option is added.\r
+  @retval EFI_ALREADY_STARTED The hot key is already used by certain key option.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerAddKeyOptionVariable (\r
+  OUT EFI_BOOT_MANAGER_KEY_OPTION *AddedOption,   OPTIONAL\r
+  IN UINT16                       BootOptionNumber,\r
+  IN UINT32                       Modifier,\r
+  ...\r
+  );\r
+\r
+/**\r
+  Delete the Key Option variable and unregister the hot key\r
+\r
+  @param DeletedOption  Return the deleted key options.\r
+  @param Modifier       Key shift state.\r
+  @param ...            Parameter list of pointer of EFI_INPUT_KEY.\r
+\r
+  @retval EFI_SUCCESS   The key option is deleted.\r
+  @retval EFI_NOT_FOUND The key option cannot be found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerDeleteKeyOptionVariable (\r
+  IN EFI_BOOT_MANAGER_KEY_OPTION *DeletedOption, OPTIONAL\r
+  IN UINT32                      Modifier,\r
+  ...\r
+  );\r
+\r
+/**\r
+  Register the key option to exit the waiting of the Boot Manager timeout.\r
+  Platform should ensure that the continue key option isn't conflict with\r
+  other boot key options.\r
+\r
+  @param Modifier     Key shift state.\r
+  @param  ...         Parameter list of pointer of EFI_INPUT_KEY.\r
+\r
+  @retval EFI_SUCCESS         Successfully register the continue key option.\r
+  @retval EFI_ALREADY_STARTED The continue key option is already registered.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerRegisterContinueKeyOption (\r
+  IN UINT32           Modifier,\r
+  ...\r
+  );\r
+\r
+/**\r
+  Try to boot the boot option triggered by hot key.\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerHotkeyBoot (\r
+  VOID\r
+  );\r
+//\r
+// Boot Manager boot library functions.\r
+//\r
+\r
+/**\r
+  The function creates boot options for all possible bootable medias in the following order:\r
+  1. Removable BlockIo            - The boot option only points to the removable media\r
+                                    device, like USB key, DVD, Floppy etc.\r
+  2. Fixed BlockIo                - The boot option only points to a Fixed blockIo device,\r
+                                    like HardDisk.\r
+  3. Non-BlockIo SimpleFileSystem - The boot option points to a device supporting\r
+                                    SimpleFileSystem Protocol, but not supporting BlockIo\r
+                                    protocol.\r
+  4. LoadFile                     - The boot option points to the media supporting \r
+                                    LoadFile protocol.\r
+  Reference: UEFI Spec chapter 3.3 Boot Option Variables Default Boot Behavior\r
+\r
+  The function won't delete the boot option not added by itself.\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerRefreshAllBootOption (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Attempt to boot the EFI boot option. This routine sets L"BootCurent" and\r
+  signals the EFI ready to boot event. If the device path for the option starts\r
+  with a BBS device path a legacy boot is attempted. Short form device paths are\r
+  also supported via this rountine. A device path starting with \r
+  MEDIA_HARDDRIVE_DP, MSG_USB_WWID_DP, MSG_USB_CLASS_DP gets expaned out\r
+  to find the first device that matches. If the BootOption Device Path \r
+  fails the removable media boot algorithm is attempted (\EFI\BOOTIA32.EFI,\r
+  \EFI\BOOTX64.EFI,... only one file type is tried per processor type)\r
+\r
+  @param  BootOption    Boot Option to try and boot.\r
+                        On return, BootOption->Status contains the boot status:\r
+                        EFI_SUCCESS     BootOption was booted\r
+                        EFI_UNSUPPORTED BootOption isn't supported.\r
+                        EFI_NOT_FOUND   The BootOption was not found on the system\r
+                        Others          BootOption failed with this error status\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerBoot (\r
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption\r
+  );\r
+\r
+/**\r
+  Return the Boot Manager Menu.\r
\r
+  @param BootOption    Return the Boot Manager Menu.\r
+\r
+  @retval EFI_SUCCESS   The Boot Manager Menu is successfully returned.\r
+  @retval EFI_NOT_FOUND The Boot Manager Menu is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerGetBootManagerMenu (\r
+  EFI_BOOT_MANAGER_LOAD_OPTION *BootOption\r
+  );\r
+\r
+/**\r
+  The function enumerates all the legacy boot options, creates them and \r
+  registers them in the BootOrder variable.\r
+**/\r
+typedef\r
+VOID\r
+(EFIAPI *EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION) (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  The function boots a legacy boot option.\r
+**/\r
+typedef\r
+VOID\r
+(EFIAPI *EFI_BOOT_MANAGER_LEGACY_BOOT) (\r
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption\r
+  );\r
+\r
+/**\r
+  The function registers the legacy boot support capabilities.\r
+\r
+  @param RefreshLegacyBootOption The function pointer to create all the legacy boot options.\r
+  @param LegacyBoot              The function pointer to boot the legacy boot option.\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerRegisterLegacyBootSupport (\r
+  EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION   RefreshLegacyBootOption,\r
+  EFI_BOOT_MANAGER_LEGACY_BOOT                  LegacyBoot\r
+  );\r
+\r
+\r
+//\r
+// Boot Manager connect and disconnect library functions\r
+//\r
+\r
+/**\r
+  This function will connect all the system driver to controller\r
+  first, and then special connect the default console, this make\r
+  sure all the system controller available and the platform default\r
+  console connected.\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerConnectAll (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function will create all handles associate with every device\r
+  path node. If the handle associate with one device path node can not\r
+  be created successfully, then still give chance to do the dispatch,\r
+  which load the missing drivers if possible.\r
+\r
+  @param  DevicePathToConnect   The device path which will be connected, it can be\r
+                                a multi-instance device path\r
+  @param  MatchingHandle        Return the controller handle closest to the DevicePathToConnect\r
+\r
+  @retval EFI_SUCCESS            All handles associate with every device path node\r
+                                 have been created.\r
+  @retval EFI_OUT_OF_RESOURCES   There is no resource to create new handles.\r
+  @retval EFI_NOT_FOUND          Create the handle associate with one device path\r
+                                 node failed.\r
+  @retval EFI_SECURITY_VIOLATION The user has no permission to start UEFI device \r
+                                 drivers on the DevicePath.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerConnectDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePathToConnect,\r
+  OUT EFI_HANDLE                *MatchingHandle          OPTIONAL\r
+  );\r
+\r
+/**\r
+  This function will disconnect all current system handles. \r
+  \r
+  gBS->DisconnectController() is invoked for each handle exists in system handle buffer.\r
+  If handle is a bus type handle, all childrens also are disconnected recursively by\r
+  gBS->DisconnectController().\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerDisconnectAll (\r
+  VOID\r
+  );\r
+\r
+\r
+//\r
+// Boot Manager console library functions\r
+//\r
+\r
+typedef enum {\r
+  ConIn,\r
+  ConOut,\r
+  ErrOut,\r
+  ConInDev,\r
+  ConOutDev,\r
+  ErrOutDev,\r
+  ConsoleTypeMax\r
+} CONSOLE_TYPE;\r
+\r
+/**\r
+  This function will connect all the console devices base on the console\r
+  device variable ConIn, ConOut and ErrOut.\r
+\r
+  @retval EFI_DEVICE_ERROR         All the consoles were not connected due to an error.\r
+  @retval EFI_SUCCESS              Success connect any one instance of the console\r
+                                   device path base on the variable ConVarName.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerConnectAllDefaultConsoles (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function updates the console variable based on ConVarName. It can\r
+  add or remove one specific console device path from the variable\r
+\r
+  @param  ConsoleType              ConIn, ConOut, ErrOut, ConInDev, ConOutDev or ErrOutDev.\r
+  @param  CustomizedConDevicePath  The console device path to be added to\r
+                                   the console variable. Cannot be multi-instance.\r
+  @param  ExclusiveDevicePath      The console device path to be removed\r
+                                   from the console variable. Cannot be multi-instance.\r
+\r
+  @retval EFI_UNSUPPORTED          The added device path is the same as a removed one.\r
+  @retval EFI_SUCCESS              Successfully added or removed the device path from the\r
+                                   console variable.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerUpdateConsoleVariable (\r
+  IN  CONSOLE_TYPE              ConsoleType,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *CustomizedConDevicePath,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *ExclusiveDevicePath\r
+  );\r
+\r
+/**\r
+  Connect the console device base on the variable ConVarName, if\r
+  device path of the ConVarName is multi-instance device path, if\r
+  anyone of the instances is connected success, then this function\r
+  will return success.\r
+\r
+  @param  ConsoleType              ConIn, ConOut or ErrOut.\r
+\r
+  @retval EFI_NOT_FOUND            There is not any console devices connected\r
+                                   success\r
+  @retval EFI_SUCCESS              Success connect any one instance of the console\r
+                                   device path base on the variable ConVarName.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerConnectConsoleVariable (\r
+  IN  CONSOLE_TYPE              ConsoleType\r
+  );\r
+\r
+/**\r
+  Query all the children of VideoController and return the device paths of all the \r
+  children that support GraphicsOutput protocol.\r
+\r
+  @param VideoController       PCI handle of video controller.\r
+\r
+  @return  Device paths of all the children that support GraphicsOutput protocol.\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+EFIAPI\r
+EfiBootManagerGetGopDevicePath (\r
+  IN  EFI_HANDLE               VideoController\r
+  );\r
+\r
+/**\r
+  Connect the platform active active video controller.\r
+\r
+  @param VideoController       PCI handle of video controller.\r
+\r
+  @retval EFI_NOT_FOUND There is no active video controller.\r
+  @retval EFI_SUCCESS   The video controller is connected.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerConnectVideoController (\r
+  EFI_HANDLE                 VideoController  OPTIONAL\r
+  );\r
+\r
+//\r
+// Boot Manager driver health library functions.\r
+//\r
+\r
+typedef struct {\r
+  EFI_DRIVER_HEALTH_PROTOCOL      *DriverHealth;\r
+\r
+  ///\r
+  /// Driver relative handles\r
+  ///\r
+  EFI_HANDLE                      DriverHealthHandle;\r
+  EFI_HANDLE                      ControllerHandle;\r
+  EFI_HANDLE                      ChildHandle;\r
+\r
+  ///\r
+  /// Driver health messages of the specify Driver \r
+  ///\r
+  EFI_DRIVER_HEALTH_HII_MESSAGE   *MessageList;\r
+\r
+  ///\r
+  /// HII relative handles\r
+  ///\r
+  EFI_HII_HANDLE                  HiiHandle;\r
+\r
+  ///\r
+  /// Driver Health status\r
+  ///\r
+  EFI_DRIVER_HEALTH_STATUS        HealthStatus;\r
+} EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO;\r
+\r
+/**\r
+  Return all the Driver Health information.\r
+\r
+  When the cumulative health status of all the controllers managed by the\r
+  driver who produces the EFI_DRIVER_HEALTH_PROTOCOL is healthy, only one\r
+  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry is created for such\r
+  EFI_DRIVER_HEALTH_PROTOCOL instance.\r
+  Otherwise, every controller creates one EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO\r
+  entry. Additionally every child controller creates one\r
+  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry if the driver is a bus driver.\r
+\r
+  @param Count      Return the count of the Driver Health information.\r
+\r
+  @retval NULL      No Driver Health information is returned.\r
+  @retval !NULL     Pointer to the Driver Health information array.\r
+**/\r
+EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *\r
+EFIAPI\r
+EfiBootManagerGetDriverHealthInfo (\r
+  UINTN    *Count\r
+  );\r
+\r
+/**\r
+  Free the Driver Health information array.\r
+\r
+  @param DriverHealthInfo       Pointer to array of the Driver Health information.\r
+  @param Count                  Count of the array.\r
+\r
+  @retval EFI_SUCCESS           The array is freed.\r
+  @retval EFI_INVALID_PARAMETER The array is NULL.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerFreeDriverHealthInfo (\r
+  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO  *DriverHealthInfo,\r
+  UINTN                                Count\r
+  );\r
+\r
+/**\r
+  Process (load and execute) the load option.\r
+\r
+  @param LoadOption  Pointer to the load option.\r
+\r
+  @retval EFI_INVALID_PARAMETER  The load option type is invalid, \r
+                                 or the load option file path doesn't point to a valid file.\r
+  @retval EFI_UNSUPPORTED        The load option type is of LoadOptionTypeBoot.\r
+  @retval EFI_SUCCESS            The load option is inactive, or successfully loaded and executed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerProcessLoadOption (\r
+  EFI_BOOT_MANAGER_LOAD_OPTION       *LoadOption\r
+  );\r
+#endif\r
index e23b4d0..9d3633b 100644 (file)
@@ -1,7 +1,7 @@
 ##  @file\r
 #   Library used for sorting routines.\r
 #\r
-#  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved. <BR>
+#  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved. <BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -19,7 +19,7 @@
   FILE_GUID                      = 03F3331B-F12D-494f-BF37-E55A657F2497\r
   MODULE_TYPE                    = UEFI_DRIVER\r
   VERSION_STRING                 = 1.0\r
-  LIBRARY_CLASS                  = SortLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
+  LIBRARY_CLASS                  = SortLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER\r
 \r
 #\r
 #  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
@@ -37,5 +37,3 @@
   BaseLib\r
   BaseMemoryLib\r
   DebugLib\r
-\r
-\r
index ede5250..efac6d5 100644 (file)
-/** @file
-  Library functions which relates with booting.
-
-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"
-
-#define VENDOR_IDENTIFICATION_OFFSET     3
-#define VENDOR_IDENTIFICATION_LENGTH     8
-#define PRODUCT_IDENTIFICATION_OFFSET    11
-#define PRODUCT_IDENTIFICATION_LENGTH    16
-
-CONST UINT16 mBmUsbLangId    = 0x0409; // English
-CHAR16       mBmUefiPrefix[] = L"UEFI ";
-
-EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION  mBmRefreshLegacyBootOption = NULL;
-EFI_BOOT_MANAGER_LEGACY_BOOT                 mBmLegacyBoot              = NULL;
-
-///
-/// This GUID is used for an EFI Variable that stores the front device pathes
-/// for a partial device path that starts with the HD node.
-///
-EFI_GUID mBmHardDriveBootVariableGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x08, 0xe2, 0x0e, 0x90, 0x6c, 0xb6, 0xde } };
-EFI_GUID mBmAutoCreateBootOptionGuid  = { 0x8108ac4e, 0x9f11, 0x4d59, { 0x85, 0x0e, 0xe2, 0x1a, 0x52, 0x2c, 0x59, 0xb2 } };
-
-/**
-  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
-  )
-{
-  mBmRefreshLegacyBootOption = RefreshLegacyBootOption;
-  mBmLegacyBoot              = LegacyBoot;
-}
-
-/**
-  For a bootable Device path, return its boot type.
-
-  @param  DevicePath                   The bootable device Path to check
-
-  @retval AcpiFloppyBoot               If given device path contains ACPI_DEVICE_PATH type device path node
-                                       which HID is floppy device.
-  @retval MessageAtapiBoot             If given device path contains MESSAGING_DEVICE_PATH type device path node
-                                       and its last device path node's subtype is MSG_ATAPI_DP.
-  @retval MessageSataBoot              If given device path contains MESSAGING_DEVICE_PATH type device path node
-                                       and its last device path node's subtype is MSG_SATA_DP.
-  @retval MessageScsiBoot              If given device path contains MESSAGING_DEVICE_PATH type device path node
-                                       and its last device path node's subtype is MSG_SCSI_DP.
-  @retval MessageUsbBoot               If given device path contains MESSAGING_DEVICE_PATH type device path node
-                                       and its last device path node's subtype is MSG_USB_DP.
-  @retval MessageNetworkBoot           If given device path contains MESSAGING_DEVICE_PATH type device path node
-                                       and its last device path node's subtype is MSG_MAC_ADDR_DP, MSG_VLAN_DP,
-                                       MSG_IPv4_DP or MSG_IPv6_DP.
-  @retval UnsupportedBoot              If tiven device path doesn't match the above condition, it's not supported.
-
-**/
-BM_BOOT_TYPE
-BmDevicePathType (
-  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
-  )
-{
-  EFI_DEVICE_PATH_PROTOCOL      *Node;
-  EFI_DEVICE_PATH_PROTOCOL      *NextNode;
-
-  ASSERT (DevicePath != NULL);
-
-  for (Node = DevicePath; !IsDevicePathEndType (Node); Node = NextDevicePathNode (Node)) {
-    switch (DevicePathType (Node)) {
-
-      case ACPI_DEVICE_PATH:
-        if (EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *) Node)->HID) == 0x0604) {
-          return BmAcpiFloppyBoot;
-        }
-        break;
-
-      case HARDWARE_DEVICE_PATH:
-        if (DevicePathSubType (Node) == HW_CONTROLLER_DP) {
-          return BmHardwareDeviceBoot;
-        }
-        break;
-
-      case MESSAGING_DEVICE_PATH:
-        //
-        // Skip LUN device node
-        //
-        NextNode = Node;
-        do {
-          NextNode = NextDevicePathNode (NextNode);
-        } while (
-            (DevicePathType (NextNode) == MESSAGING_DEVICE_PATH) &&
-            (DevicePathSubType(NextNode) == MSG_DEVICE_LOGICAL_UNIT_DP)
-            );
-
-        //
-        // If the device path not only point to driver device, it is not a messaging device path,
-        //
-        if (!IsDevicePathEndType (NextNode)) {
-          break;
-        }
-
-        switch (DevicePathSubType (Node)) {
-        case MSG_ATAPI_DP:
-          return BmMessageAtapiBoot;
-          break;
-
-        case MSG_SATA_DP:
-          return BmMessageSataBoot;
-          break;
-
-        case MSG_USB_DP:
-          return BmMessageUsbBoot;
-          break;
-
-        case MSG_SCSI_DP:
-          return BmMessageScsiBoot;
-          break;
-
-        case MSG_MAC_ADDR_DP:
-        case MSG_VLAN_DP:
-        case MSG_IPv4_DP:
-        case MSG_IPv6_DP:
-          return BmMessageNetworkBoot;
-          break;
-        }
-    }
-  }
-
-  return BmMiscBoot;
-}
-
-/**
-  Find the boot option in the NV storage and return the option number.
-
-  @param OptionToFind  Boot option to be checked.
-
-  @return   The option number of the found boot option.
-
-**/
-UINTN
-BmFindBootOptionInVariable (
-  IN  EFI_BOOT_MANAGER_LOAD_OPTION             *OptionToFind
-  )
-{
-  EFI_STATUS                   Status;
-  EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
-  UINTN                        OptionNumber;
-  CHAR16                       OptionName[BM_OPTION_NAME_LEN];
-  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
-  UINTN                        BootOptionCount;
-  UINTN                        Index;
-  
-  OptionNumber = LoadOptionNumberUnassigned;
-
-  //
-  // Try to match the variable exactly if the option number is assigned
-  //
-  if (OptionToFind->OptionNumber != LoadOptionNumberUnassigned) {
-    UnicodeSPrint (
-      OptionName, sizeof (OptionName), L"%s%04x",
-      mBmLoadOptionName[OptionToFind->OptionType], OptionToFind->OptionNumber
-      );
-    Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption);
-
-    if (!EFI_ERROR (Status)) {
-      ASSERT (OptionToFind->OptionNumber == BootOption.OptionNumber);
-      if ((OptionToFind->Attributes == BootOption.Attributes) &&
-          (StrCmp (OptionToFind->Description, BootOption.Description) == 0) &&
-          (CompareMem (OptionToFind->FilePath, BootOption.FilePath, GetDevicePathSize (OptionToFind->FilePath)) == 0) &&
-          (OptionToFind->OptionalDataSize == BootOption.OptionalDataSize) &&
-          (CompareMem (OptionToFind->OptionalData, BootOption.OptionalData, OptionToFind->OptionalDataSize) == 0)
-         ) {
-        OptionNumber = OptionToFind->OptionNumber;
-      }
-      EfiBootManagerFreeLoadOption (&BootOption);
-    }
-  }
-
-  //
-  // The option number assigned is either incorrect or unassigned.
-  //
-  if (OptionNumber == LoadOptionNumberUnassigned) {
-    BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
-
-    Index = BmFindLoadOption (OptionToFind, BootOptions, BootOptionCount);
-    if (Index != -1) {
-      OptionNumber = BootOptions[Index].OptionNumber;
-    }
-
-    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
-  }
-
-  return OptionNumber;
-}
-
-/**
-  Get the file buffer using a Memory Mapped Device Path.
-
-  FV address may change across reboot. This routine promises the FV file device path is right.
-
-  @param  DevicePath   The Memory Mapped Device Path to get the file buffer.
-  @param  FullPath     Receive the updated FV Device Path pointint to the file.
-  @param  FileSize     Receive the file buffer size.
-
-  @return  The file buffer.
-**/
-VOID *
-BmGetFileBufferByMemmapFv (
-  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath,
-  OUT EFI_DEVICE_PATH_PROTOCOL     **FullPath,
-  OUT UINTN                        *FileSize
-  )
-{
-  EFI_STATUS                    Status;
-  UINTN                         Index;
-  EFI_DEVICE_PATH_PROTOCOL      *FvFileNode;
-  EFI_HANDLE                    FvHandle;
-  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
-  UINT32                        AuthenticationStatus;
-  UINTN                         FvHandleCount;
-  EFI_HANDLE                    *FvHandles;
-  EFI_DEVICE_PATH_PROTOCOL      *NewDevicePath;
-  VOID                          *FileBuffer;
-  
-  FvFileNode = DevicePath;
-  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &FvFileNode, &FvHandle);
-  if (!EFI_ERROR (Status)) {
-    FileBuffer = GetFileBufferByFilePath (TRUE, DevicePath, FileSize, &AuthenticationStatus);
-    if (FileBuffer != NULL) {
-      *FullPath = DuplicateDevicePath (DevicePath);
-    }
-    return FileBuffer;
-  }
-
-  FvFileNode = NextDevicePathNode (DevicePath);
-
-  //
-  // Firstly find the FV file in current FV
-  //
-  gBS->HandleProtocol (
-         gImageHandle,
-         &gEfiLoadedImageProtocolGuid,
-         (VOID **) &LoadedImage
-         );
-  NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (LoadedImage->DeviceHandle), FvFileNode);
-  FileBuffer = BmGetFileBufferByMemmapFv (NewDevicePath, FullPath, FileSize);
-  FreePool (NewDevicePath);
-
-  if (FileBuffer != NULL) {
-    return FileBuffer;
-  }
-
-  //
-  // Secondly find the FV file in all other FVs
-  //
-  gBS->LocateHandleBuffer (
-         ByProtocol,
-         &gEfiFirmwareVolume2ProtocolGuid,
-         NULL,
-         &FvHandleCount,
-         &FvHandles
-         );
-  for (Index = 0; (Index < FvHandleCount) && (FileBuffer == NULL); Index++) {
-    if (FvHandles[Index] == LoadedImage->DeviceHandle) {
-      //
-      // Skip current FV
-      //
-      continue;
-    }
-    NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (FvHandles[Index]), FvFileNode);
-    FileBuffer = BmGetFileBufferByMemmapFv (NewDevicePath, FullPath, FileSize);
-    FreePool (NewDevicePath);
-  }
-  
-  if (FvHandles != NULL) {
-    FreePool (FvHandles);
-  }
-  return FileBuffer;
-}
-
-/**
-  Check if it's a Memory Mapped FV Device Path.
-  
-  The function doesn't garentee the device path points to existing FV file.
-
-  @param  DevicePath     Input device path.
-
-  @retval TRUE   The device path is a Memory Mapped FV Device Path.
-  @retval FALSE  The device path is NOT a Memory Mapped FV Device Path.
-**/
-BOOLEAN
-BmIsMemmapFvFilePath (
-  IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath
-  )
-{
-  EFI_DEVICE_PATH_PROTOCOL   *FileNode;
-
-  if ((DevicePathType (DevicePath) == HARDWARE_DEVICE_PATH) && (DevicePathSubType (DevicePath) == HW_MEMMAP_DP)) {
-    FileNode = NextDevicePathNode (DevicePath);
-    if ((DevicePathType (FileNode) == MEDIA_DEVICE_PATH) && (DevicePathSubType (FileNode) == MEDIA_PIWG_FW_FILE_DP)) {
-      return IsDevicePathEnd (NextDevicePathNode (FileNode));
-    }
-  }
-
-  return FALSE;
-}
-
-/**
-  Check whether a USB device match the specified USB Class device path. This
-  function follows "Load Option Processing" behavior in UEFI specification.
-
-  @param UsbIo       USB I/O protocol associated with the USB device.
-  @param UsbClass    The USB Class device path to match.
-
-  @retval TRUE       The USB device match the USB Class device path.
-  @retval FALSE      The USB device does not match the USB Class device path.
-
-**/
-BOOLEAN
-BmMatchUsbClass (
-  IN EFI_USB_IO_PROTOCOL        *UsbIo,
-  IN USB_CLASS_DEVICE_PATH      *UsbClass
-  )
-{
-  EFI_STATUS                    Status;
-  EFI_USB_DEVICE_DESCRIPTOR     DevDesc;
-  EFI_USB_INTERFACE_DESCRIPTOR  IfDesc;
-  UINT8                         DeviceClass;
-  UINT8                         DeviceSubClass;
-  UINT8                         DeviceProtocol;
-
-  if ((DevicePathType (UsbClass) != MESSAGING_DEVICE_PATH) ||
-      (DevicePathSubType (UsbClass) != MSG_USB_CLASS_DP)){
-    return FALSE;
-  }
-
-  //
-  // Check Vendor Id and Product Id.
-  //
-  Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);
-  if (EFI_ERROR (Status)) {
-    return FALSE;
-  }
-
-  if ((UsbClass->VendorId != 0xffff) &&
-      (UsbClass->VendorId != DevDesc.IdVendor)) {
-    return FALSE;
-  }
-
-  if ((UsbClass->ProductId != 0xffff) &&
-      (UsbClass->ProductId != DevDesc.IdProduct)) {
-    return FALSE;
-  }
-
-  DeviceClass    = DevDesc.DeviceClass;
-  DeviceSubClass = DevDesc.DeviceSubClass;
-  DeviceProtocol = DevDesc.DeviceProtocol;
-  if (DeviceClass == 0) {
-    //
-    // If Class in Device Descriptor is set to 0, use the Class, SubClass and
-    // Protocol in Interface Descriptor instead.
-    //
-    Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);
-    if (EFI_ERROR (Status)) {
-      return FALSE;
-    }
-
-    DeviceClass    = IfDesc.InterfaceClass;
-    DeviceSubClass = IfDesc.InterfaceSubClass;
-    DeviceProtocol = IfDesc.InterfaceProtocol;
-  }
-
-  //
-  // Check Class, SubClass and Protocol.
-  //
-  if ((UsbClass->DeviceClass != 0xff) &&
-      (UsbClass->DeviceClass != DeviceClass)) {
-    return FALSE;
-  }
-
-  if ((UsbClass->DeviceSubClass != 0xff) &&
-      (UsbClass->DeviceSubClass != DeviceSubClass)) {
-    return FALSE;
-  }
-
-  if ((UsbClass->DeviceProtocol != 0xff) &&
-      (UsbClass->DeviceProtocol != DeviceProtocol)) {
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-/**
-  Eliminate the extra spaces in the Str to one space.
-
-  @param    Str     Input string info.
-**/
-VOID
-BmEliminateExtraSpaces (
-  IN CHAR16                    *Str
-  )
-{
-  UINTN                        Index;
-  UINTN                        ActualIndex;
-
-  for (Index = 0, ActualIndex = 0; Str[Index] != L'\0'; Index++) {
-    if ((Str[Index] != L' ') || ((ActualIndex > 0) && (Str[ActualIndex - 1] != L' '))) {
-      Str[ActualIndex++] = Str[Index];
-    }
-  }
-  Str[ActualIndex] = L'\0';
-}
-
-/**
-  Try to get the controller's ATA/ATAPI description.
-
-  @param Handle                Controller handle.
-
-  @return  The description string.
-**/
-CHAR16 *
-BmGetDescriptionFromDiskInfo (
-  IN EFI_HANDLE                Handle
-  )
-{
-  UINTN                        Index;
-  EFI_STATUS                   Status;
-  EFI_DISK_INFO_PROTOCOL       *DiskInfo;
-  UINT32                       BufferSize;
-  EFI_ATAPI_IDENTIFY_DATA      IdentifyData;
-  EFI_SCSI_INQUIRY_DATA        InquiryData;
-  CHAR16                       *Description;
-  UINTN                        Length;
-  CONST UINTN                  ModelNameLength    = 40;
-  CONST UINTN                  SerialNumberLength = 20;
-  CHAR8                        *StrPtr;
-  UINT8                        Temp;
-
-  Description  = NULL;
-
-  Status = gBS->HandleProtocol (
-                  Handle,
-                  &gEfiDiskInfoProtocolGuid,
-                  (VOID **) &DiskInfo
-                  );
-  if (EFI_ERROR (Status)) {
-    return NULL;
-  }
-
-  if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoAhciInterfaceGuid) || 
-      CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) {
-    BufferSize   = sizeof (EFI_ATAPI_IDENTIFY_DATA);
-    Status = DiskInfo->Identify (
-                         DiskInfo,
-                         &IdentifyData,
-                         &BufferSize
-                         );
-    if (!EFI_ERROR (Status)) {
-      Description = AllocateZeroPool ((ModelNameLength + SerialNumberLength + 2) * sizeof (CHAR16));
-      ASSERT (Description != NULL);
-      for (Index = 0; Index + 1 < ModelNameLength; Index += 2) {
-        Description[Index]     = (CHAR16) IdentifyData.ModelName[Index + 1];
-        Description[Index + 1] = (CHAR16) IdentifyData.ModelName[Index];
-      }
-
-      Length = Index;
-      Description[Length++] = L' ';
-
-      for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) {
-        Description[Length + Index]     = (CHAR16) IdentifyData.SerialNo[Index + 1];
-        Description[Length + Index + 1] = (CHAR16) IdentifyData.SerialNo[Index];
-      }
-      Length += Index;
-      Description[Length++] = L'\0';
-      ASSERT (Length == ModelNameLength + SerialNumberLength + 2);
-
-      BmEliminateExtraSpaces (Description);
-    }
-  } else if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoScsiInterfaceGuid)) {
-    BufferSize   = sizeof (EFI_SCSI_INQUIRY_DATA);
-    Status = DiskInfo->Inquiry (
-                         DiskInfo,
-                         &InquiryData,
-                         &BufferSize
-                         );
-    if (!EFI_ERROR (Status)) {
-      Description = AllocateZeroPool ((VENDOR_IDENTIFICATION_LENGTH + PRODUCT_IDENTIFICATION_LENGTH + 2) * sizeof (CHAR16));
-      ASSERT (Description != NULL);
-
-      //
-      // Per SCSI spec, EFI_SCSI_INQUIRY_DATA.Reserved_5_95[3 - 10] save the Verdor identification
-      // EFI_SCSI_INQUIRY_DATA.Reserved_5_95[11 - 26] save the product identification, 
-      // Here combine the vendor identification and product identification to the description.
-      //
-      StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[VENDOR_IDENTIFICATION_OFFSET]);
-      Temp = StrPtr[VENDOR_IDENTIFICATION_LENGTH];
-      StrPtr[VENDOR_IDENTIFICATION_LENGTH] = '\0';
-      AsciiStrToUnicodeStr (StrPtr, Description);
-      StrPtr[VENDOR_IDENTIFICATION_LENGTH] = Temp;
-
-      //
-      // Add one space at the middle of vendor information and product information.
-      //
-      Description[VENDOR_IDENTIFICATION_LENGTH] = L' ';
-
-      StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[PRODUCT_IDENTIFICATION_OFFSET]);
-      StrPtr[PRODUCT_IDENTIFICATION_LENGTH] = '\0';
-      AsciiStrToUnicodeStr (StrPtr, Description + VENDOR_IDENTIFICATION_LENGTH + 1);
-
-      BmEliminateExtraSpaces (Description);
-    }
-  }
-
-  return Description;
-}
-
-/**
-  Try to get the controller's USB description.
-
-  @param Handle                Controller handle.
-
-  @return  The description string.
-**/
-CHAR16 *
-BmGetUsbDescription (
-  IN EFI_HANDLE                Handle
-  )
-{
-  EFI_STATUS                   Status;
-  EFI_USB_IO_PROTOCOL          *UsbIo;
-  CHAR16                       NullChar;
-  CHAR16                       *Manufacturer;
-  CHAR16                       *Product;
-  CHAR16                       *SerialNumber;
-  CHAR16                       *Description;
-  EFI_USB_DEVICE_DESCRIPTOR    DevDesc;
-
-  Status = gBS->HandleProtocol (
-                  Handle,
-                  &gEfiUsbIoProtocolGuid,
-                  (VOID **) &UsbIo
-                  );
-  if (EFI_ERROR (Status)) {
-    return NULL;
-  }
-
-  NullChar = L'\0';
-
-  Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);
-  if (EFI_ERROR (Status)) {
-    return NULL;
-  }
-
-  Status = UsbIo->UsbGetStringDescriptor (
-                    UsbIo,
-                    mBmUsbLangId,
-                    DevDesc.StrManufacturer,
-                    &Manufacturer
-                    );
-  if (EFI_ERROR (Status)) {
-    Manufacturer = &NullChar;
-  }
-  
-  Status = UsbIo->UsbGetStringDescriptor (
-                    UsbIo,
-                    mBmUsbLangId,
-                    DevDesc.StrProduct,
-                    &Product
-                    );
-  if (EFI_ERROR (Status)) {
-    Product = &NullChar;
-  }
-  
-  Status = UsbIo->UsbGetStringDescriptor (
-                    UsbIo,
-                    mBmUsbLangId,
-                    DevDesc.StrSerialNumber,
-                    &SerialNumber
-                    );
-  if (EFI_ERROR (Status)) {
-    SerialNumber = &NullChar;
-  }
-
-  if ((Manufacturer == &NullChar) &&
-      (Product == &NullChar) &&
-      (SerialNumber == &NullChar)
-      ) {
-    return NULL;
-  }
-
-  Description = AllocateZeroPool (StrSize (Manufacturer) + StrSize (Product) + StrSize (SerialNumber));
-  ASSERT (Description != NULL);
-  StrCat (Description, Manufacturer);
-  StrCat (Description, L" ");
-
-  StrCat (Description, Product);  
-  StrCat (Description, L" ");
-
-  StrCat (Description, SerialNumber);
-
-  if (Manufacturer != &NullChar) {
-    FreePool (Manufacturer);
-  }
-  if (Product != &NullChar) {
-    FreePool (Product);
-  }
-  if (SerialNumber != &NullChar) {
-    FreePool (SerialNumber);
-  }
-
-  BmEliminateExtraSpaces (Description);
-
-  return Description;
-}
-
-/**
-  Return the boot description for the controller based on the type.
-
-  @param Handle                Controller handle.
-
-  @return  The description string.
-**/
-CHAR16 *
-BmGetMiscDescription (
-  IN EFI_HANDLE                  Handle
-  )
-{
-  EFI_STATUS                     Status;
-  CHAR16                         *Description;
-  EFI_BLOCK_IO_PROTOCOL          *BlockIo;
-
-  switch (BmDevicePathType (DevicePathFromHandle (Handle))) {
-  case BmAcpiFloppyBoot:
-    Description = L"Floppy";
-    break;
-
-  case BmMessageAtapiBoot:
-  case BmMessageSataBoot:
-    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
-    ASSERT_EFI_ERROR (Status);
-    //
-    // Assume a removable SATA device should be the DVD/CD device
-    //
-    Description = BlockIo->Media->RemovableMedia ? L"DVD/CDROM" : L"Hard Drive";
-    break;
-
-  case BmMessageUsbBoot:
-    Description = L"USB Device";
-    break;
-
-  case BmMessageScsiBoot:
-    Description = L"SCSI Device";
-    break;
-
-  case BmHardwareDeviceBoot:
-    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
-    if (!EFI_ERROR (Status)) {
-      Description = BlockIo->Media->RemovableMedia ? L"Removable Disk" : L"Hard Drive";
-    } else {
-      Description = L"Misc Device";
-    }
-    break;
-
-  default:
-    Description = L"Misc Device";
-    break;
-  }
-
-  return AllocateCopyPool (StrSize (Description), Description);
-}
-
-BM_GET_BOOT_DESCRIPTION mBmGetBootDescription[] = {
-  BmGetUsbDescription,
-  BmGetDescriptionFromDiskInfo,
-  BmGetMiscDescription
-};
-
-/**
-  Check whether a USB device match the specified USB WWID device path. This
-  function follows "Load Option Processing" behavior in UEFI specification.
-
-  @param UsbIo       USB I/O protocol associated with the USB device.
-  @param UsbWwid     The USB WWID device path to match.
-
-  @retval TRUE       The USB device match the USB WWID device path.
-  @retval FALSE      The USB device does not match the USB WWID device path.
-
-**/
-BOOLEAN
-BmMatchUsbWwid (
-  IN EFI_USB_IO_PROTOCOL        *UsbIo,
-  IN USB_WWID_DEVICE_PATH       *UsbWwid
-  )
-{
-  EFI_STATUS                   Status;
-  EFI_USB_DEVICE_DESCRIPTOR    DevDesc;
-  EFI_USB_INTERFACE_DESCRIPTOR IfDesc;
-  UINT16                       *LangIdTable;
-  UINT16                       TableSize;
-  UINT16                       Index;
-  CHAR16                       *CompareStr;
-  UINTN                        CompareLen;
-  CHAR16                       *SerialNumberStr;
-  UINTN                        Length;
-
-  if ((DevicePathType (UsbWwid) != MESSAGING_DEVICE_PATH) ||
-      (DevicePathSubType (UsbWwid) != MSG_USB_WWID_DP)) {
-    return FALSE;
-  }
-
-  //
-  // Check Vendor Id and Product Id.
-  //
-  Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);
-  if (EFI_ERROR (Status)) {
-    return FALSE;
-  }
-  if ((DevDesc.IdVendor != UsbWwid->VendorId) ||
-      (DevDesc.IdProduct != UsbWwid->ProductId)) {
-    return FALSE;
-  }
-
-  //
-  // Check Interface Number.
-  //
-  Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);
-  if (EFI_ERROR (Status)) {
-    return FALSE;
-  }
-  if (IfDesc.InterfaceNumber != UsbWwid->InterfaceNumber) {
-    return FALSE;
-  }
-
-  //
-  // Check Serial Number.
-  //
-  if (DevDesc.StrSerialNumber == 0) {
-    return FALSE;
-  }
-
-  //
-  // Get all supported languages.
-  //
-  TableSize = 0;
-  LangIdTable = NULL;
-  Status = UsbIo->UsbGetSupportedLanguages (UsbIo, &LangIdTable, &TableSize);
-  if (EFI_ERROR (Status) || (TableSize == 0) || (LangIdTable == NULL)) {
-    return FALSE;
-  }
-
-  //
-  // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.
-  //
-  CompareStr = (CHAR16 *) (UINTN) (UsbWwid + 1);
-  CompareLen = (DevicePathNodeLength (UsbWwid) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16);
-  if (CompareStr[CompareLen - 1] == L'\0') {
-    CompareLen--;
-  }
-
-  //
-  // Compare serial number in each supported language.
-  //
-  for (Index = 0; Index < TableSize / sizeof (UINT16); Index++) {
-    SerialNumberStr = NULL;
-    Status = UsbIo->UsbGetStringDescriptor (
-                      UsbIo,
-                      LangIdTable[Index],
-                      DevDesc.StrSerialNumber,
-                      &SerialNumberStr
-                      );
-    if (EFI_ERROR (Status) || (SerialNumberStr == NULL)) {
-      continue;
-    }
-
-    Length = StrLen (SerialNumberStr);
-    if ((Length >= CompareLen) &&
-        (CompareMem (SerialNumberStr + Length - CompareLen, CompareStr, CompareLen * sizeof (CHAR16)) == 0)) {
-      FreePool (SerialNumberStr);
-      return TRUE;
-    }
-
-    FreePool (SerialNumberStr);
-  }
-
-  return FALSE;
-}
-
-/**
-  Find a USB device which match the specified short-form device path start with 
-  USB Class or USB WWID device path. If ParentDevicePath is NULL, this function
-  will search in all USB devices of the platform. If ParentDevicePath is not NULL,
-  this function will only search in its child devices.
-
-  @param DevicePath           The device path that contains USB Class or USB WWID device path.
-  @param ParentDevicePathSize The length of the device path before the USB Class or 
-                              USB WWID device path.
-  @param UsbIoHandleCount     A pointer to the count of the returned USB IO handles.
-
-  @retval NULL       The matched USB IO handles cannot be found.
-  @retval other      The matched USB IO handles.
-
-**/
-EFI_HANDLE *
-BmFindUsbDevice (
-  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
-  IN  UINTN                     ParentDevicePathSize,
-  OUT UINTN                     *UsbIoHandleCount
-  )
-{
-  EFI_STATUS                Status;
-  EFI_HANDLE                *UsbIoHandles;
-  EFI_DEVICE_PATH_PROTOCOL  *UsbIoDevicePath;
-  EFI_USB_IO_PROTOCOL       *UsbIo;
-  UINTN                     Index;
-  UINTN                     UsbIoDevicePathSize;
-  BOOLEAN                   Matched;
-
-  ASSERT (UsbIoHandleCount != NULL);  
-
-  //
-  // Get all UsbIo Handles.
-  //
-  Status = gBS->LocateHandleBuffer (
-                  ByProtocol,
-                  &gEfiUsbIoProtocolGuid,
-                  NULL,
-                  UsbIoHandleCount,
-                  &UsbIoHandles
-                  );
-  if (EFI_ERROR (Status)) {
-    *UsbIoHandleCount = 0;
-    UsbIoHandles      = NULL;
-  }
-
-  for (Index = 0; Index < *UsbIoHandleCount; ) {
-    //
-    // Get the Usb IO interface.
-    //
-    Status = gBS->HandleProtocol(
-                    UsbIoHandles[Index],
-                    &gEfiUsbIoProtocolGuid,
-                    (VOID **) &UsbIo
-                    );
-    UsbIoDevicePath = DevicePathFromHandle (UsbIoHandles[Index]);
-    Matched         = FALSE;
-    if (!EFI_ERROR (Status) && (UsbIoDevicePath != NULL)) {
-      UsbIoDevicePathSize = GetDevicePathSize (UsbIoDevicePath) - END_DEVICE_PATH_LENGTH;
-
-      //
-      // Compare starting part of UsbIoHandle's device path with ParentDevicePath.
-      //
-      if (CompareMem (UsbIoDevicePath, DevicePath, ParentDevicePathSize) == 0) {
-        if (BmMatchUsbClass (UsbIo, (USB_CLASS_DEVICE_PATH *) ((UINTN) DevicePath + ParentDevicePathSize)) ||
-            BmMatchUsbWwid (UsbIo, (USB_WWID_DEVICE_PATH *) ((UINTN) DevicePath + ParentDevicePathSize))) {
-          Matched = TRUE;
-        }
-      }
-    }
-
-    if (!Matched) {
-      (*UsbIoHandleCount) --;
-      CopyMem (&UsbIoHandles[Index], &UsbIoHandles[Index + 1], (*UsbIoHandleCount - Index) * sizeof (EFI_HANDLE));
-    } else {
-      Index++;
-    }
-  }
-
-  return UsbIoHandles;
-}
-
-/**
-  Expand USB Class or USB WWID device path node to be full device path of a USB
-  device in platform.
-
-  This function support following 4 cases:
-  1) Boot Option device path starts with a USB Class or USB WWID device path,
-     and there is no Media FilePath device path in the end.
-     In this case, it will follow Removable Media Boot Behavior.
-  2) Boot Option device path starts with a USB Class or USB WWID device path,
-     and ended with Media FilePath device path.
-  3) Boot Option device path starts with a full device path to a USB Host Controller,
-     contains a USB Class or USB WWID device path node, while not ended with Media
-     FilePath device path. In this case, it will follow Removable Media Boot Behavior.
-  4) Boot Option device path starts with a full device path to a USB Host Controller,
-     contains a USB Class or USB WWID device path node, and ended with Media
-     FilePath device path.
-
-  @param FilePath      The device path pointing to a load option.
-                       It could be a short-form device path.
-  @param FullPath      Return the full device path of the load option after
-                       short-form device path expanding.
-                       Caller is responsible to free it.
-  @param FileSize      Return the load option size.
-  @param ShortformNode Pointer to the USB short-form device path node in the FilePath buffer.
-
-  @return The load option buffer. Caller is responsible to free the memory.
-**/
-VOID *
-BmExpandUsbDevicePath (
-  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
-  OUT EFI_DEVICE_PATH_PROTOCOL  **FullPath,
-  OUT UINTN                     *FileSize,
-  IN EFI_DEVICE_PATH_PROTOCOL   *ShortformNode
-  )
-{
-  UINTN                             ParentDevicePathSize;
-  EFI_DEVICE_PATH_PROTOCOL          *RemainingDevicePath;
-  EFI_DEVICE_PATH_PROTOCOL          *FullDevicePath;
-  EFI_HANDLE                        *Handles;
-  UINTN                             HandleCount;
-  UINTN                             Index;
-  VOID                              *FileBuffer;
-
-  ParentDevicePathSize = (UINTN) ShortformNode - (UINTN) FilePath;
-  RemainingDevicePath = NextDevicePathNode (ShortformNode);
-  FileBuffer = NULL;
-  Handles = BmFindUsbDevice (FilePath, ParentDevicePathSize, &HandleCount);
-
-  for (Index = 0; (Index < HandleCount) && (FileBuffer == NULL); Index++) {
-    FullDevicePath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), RemainingDevicePath);
-    FileBuffer = BmGetLoadOptionBuffer (FullDevicePath, FullPath, FileSize);
-    FreePool (FullDevicePath);
-  }
-
-  if (Handles != NULL) {
-    FreePool (Handles);
-  }
-
-  return FileBuffer;
-}
-
-/**
-  Save the partition DevicePath to the CachedDevicePath as the first instance.
-
-  @param CachedDevicePath  The device path cache.
-  @param DevicePath        The partition device path to be cached.
-**/
-VOID
-BmCachePartitionDevicePath (
-  IN OUT EFI_DEVICE_PATH_PROTOCOL **CachedDevicePath,
-  IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
-  )
-{
-  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
-  UINTN                           Count;
-  
-  if (BmMatchDevicePaths (*CachedDevicePath, DevicePath)) {
-    TempDevicePath = *CachedDevicePath;
-    *CachedDevicePath = BmDelPartMatchInstance (*CachedDevicePath, DevicePath);
-    FreePool (TempDevicePath);
-  }
-
-  if (*CachedDevicePath == NULL) {
-    *CachedDevicePath = DuplicateDevicePath (DevicePath);
-    return;
-  }
-
-  TempDevicePath = *CachedDevicePath;
-  *CachedDevicePath = AppendDevicePathInstance (DevicePath, *CachedDevicePath);
-  if (TempDevicePath != NULL) {
-    FreePool (TempDevicePath);
-  }
-
-  //
-  // Here limit the device path instance number to 12, which is max number for a system support 3 IDE controller
-  // If the user try to boot many OS in different HDs or partitions, in theory, the 'HDDP' variable maybe become larger and larger.
-  //
-  Count = 0;
-  TempDevicePath = *CachedDevicePath;
-  while (!IsDevicePathEnd (TempDevicePath)) {
-    TempDevicePath = NextDevicePathNode (TempDevicePath);
-    //
-    // Parse one instance
-    //
-    while (!IsDevicePathEndType (TempDevicePath)) {
-      TempDevicePath = NextDevicePathNode (TempDevicePath);
-    }
-    Count++;
-    //
-    // If the CachedDevicePath variable contain too much instance, only remain 12 instances.
-    //
-    if (Count == 12) {
-      SetDevicePathEndNode (TempDevicePath);
-      break;
-    }
-  }
-}
-
-/**
-  Expand a device path that starts with a hard drive media device path node to be a
-  full device path that includes the full hardware path to the device. We need
-  to do this so it can be booted. As an optimization the front match (the part point
-  to the partition node. E.g. ACPI() /PCI()/ATA()/Partition() ) is saved in a variable
-  so a connect all is not required on every boot. All successful history device path
-  which point to partition node (the front part) will be saved.
-
-  @param FilePath      The device path pointing to a load option.
-                       It could be a short-form device path.
-  @param FullPath      Return the full device path of the load option after
-                       short-form device path expanding.
-                       Caller is responsible to free it.
-  @param FileSize      Return the load option size.
-
-  @return The load option buffer. Caller is responsible to free the memory.
-**/
-VOID *
-BmExpandPartitionDevicePath (
-  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
-  OUT EFI_DEVICE_PATH_PROTOCOL  **FullPath,
-  OUT UINTN                     *FileSize
-  )
-{
-  EFI_STATUS                Status;
-  UINTN                     BlockIoHandleCount;
-  EFI_HANDLE                *BlockIoBuffer;
-  VOID                      *FileBuffer;
-  EFI_DEVICE_PATH_PROTOCOL  *BlockIoDevicePath;
-  UINTN                     Index;
-  EFI_DEVICE_PATH_PROTOCOL  *CachedDevicePath;
-  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;
-  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
-  UINTN                     CachedDevicePathSize;
-  BOOLEAN                   NeedAdjust;
-  EFI_DEVICE_PATH_PROTOCOL  *Instance;
-  UINTN                     Size;
-
-  FileBuffer = NULL;
-  //
-  // Check if there is prestore 'HDDP' variable.
-  // If exist, search the front path which point to partition node in the variable instants.
-  // If fail to find or 'HDDP' not exist, reconnect all and search in all system
-  //
-  GetVariable2 (L"HDDP", &mBmHardDriveBootVariableGuid, (VOID **) &CachedDevicePath, &CachedDevicePathSize);
-
-  //
-  // Delete the invalid 'HDDP' variable.
-  //
-  if ((CachedDevicePath != NULL) && !IsDevicePathValid (CachedDevicePath, CachedDevicePathSize)) {
-    FreePool (CachedDevicePath);
-    CachedDevicePath = NULL;
-    Status = gRT->SetVariable (
-                    L"HDDP",
-                    &mBmHardDriveBootVariableGuid,
-                    0,
-                    0,
-                    NULL
-                    );
-    ASSERT_EFI_ERROR (Status);
-  }
-
-  if (CachedDevicePath != NULL) {
-    TempNewDevicePath = CachedDevicePath;
-    NeedAdjust = FALSE;
-    do {
-      //
-      // Check every instance of the variable
-      // First, check whether the instance contain the partition node, which is needed for distinguishing  multi
-      // partial partition boot option. Second, check whether the instance could be connected.
-      //
-      Instance  = GetNextDevicePathInstance (&TempNewDevicePath, &Size);
-      if (BmMatchPartitionDevicePathNode (Instance, (HARDDRIVE_DEVICE_PATH *) FilePath)) {
-        //
-        // Connect the device path instance, the device path point to hard drive media device path node
-        // e.g. ACPI() /PCI()/ATA()/Partition()
-        //
-        Status = EfiBootManagerConnectDevicePath (Instance, NULL);
-        if (!EFI_ERROR (Status)) {
-          TempDevicePath = AppendDevicePath (Instance, NextDevicePathNode (FilePath));
-          FileBuffer = BmGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);
-          FreePool (TempDevicePath);
-
-          if (FileBuffer != NULL) {
-            //
-            // Adjust the 'HDDP' instances sequence if the matched one is not first one.
-            //
-            if (NeedAdjust) {
-              BmCachePartitionDevicePath (&CachedDevicePath, Instance);
-              //
-              // Save the matching Device Path so we don't need to do a connect all next time
-              // Failing to save only impacts performance next time expanding the short-form device path
-              //
-              Status = gRT->SetVariable (
-                L"HDDP",
-                &mBmHardDriveBootVariableGuid,
-                EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
-                GetDevicePathSize (CachedDevicePath),
-                CachedDevicePath
-                );
-            }
-
-            FreePool (Instance);
-            FreePool (CachedDevicePath);
-            return FileBuffer;
-          }
-        }
-      }
-      //
-      // Come here means the first instance is not matched
-      //
-      NeedAdjust = TRUE;
-      FreePool(Instance);
-    } while (TempNewDevicePath != NULL);
-  }
-
-  //
-  // If we get here we fail to find or 'HDDP' not exist, and now we need
-  // to search all devices in the system for a matched partition
-  //
-  EfiBootManagerConnectAll ();
-  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);
-  if (EFI_ERROR (Status)) {
-    BlockIoHandleCount = 0;
-    BlockIoBuffer      = NULL;
-  }
-  //
-  // Loop through all the device handles that support the BLOCK_IO Protocol
-  //
-  for (Index = 0; Index < BlockIoHandleCount; Index++) {
-    BlockIoDevicePath = DevicePathFromHandle (BlockIoBuffer[Index]);
-    if (BlockIoDevicePath == NULL) {
-      continue;
-    }
-
-    if (BmMatchPartitionDevicePathNode (BlockIoDevicePath, (HARDDRIVE_DEVICE_PATH *) FilePath)) {
-      //
-      // Find the matched partition device path
-      //
-      TempDevicePath = AppendDevicePath (BlockIoDevicePath, NextDevicePathNode (FilePath));
-      FileBuffer = BmGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);
-      FreePool (TempDevicePath);
-
-      if (FileBuffer != NULL) {
-        BmCachePartitionDevicePath (&CachedDevicePath, BlockIoDevicePath);
-
-        //
-        // Save the matching Device Path so we don't need to do a connect all next time
-        // Failing to save only impacts performance next time expanding the short-form device path
-        //
-        Status = gRT->SetVariable (
-                        L"HDDP",
-                        &mBmHardDriveBootVariableGuid,
-                        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
-                        GetDevicePathSize (CachedDevicePath),
-                        CachedDevicePath
-                        );
-
-        break;
-      }
-    }
-  }
-
-  if (CachedDevicePath != NULL) {
-    FreePool (CachedDevicePath);
-  }
-  if (BlockIoBuffer != NULL) {
-    FreePool (BlockIoBuffer);
-  }
-  return FileBuffer;
-}
-
-/**
-  Expand the media device path which points to a BlockIo or SimpleFileSystem instance
-  by appending EFI_REMOVABLE_MEDIA_FILE_NAME.
-
-  @param DevicePath  The media device path pointing to a BlockIo or SimpleFileSystem instance.
-  @param FullPath    Return the full device path pointing to the load option.
-  @param FileSize    Return the size of the load option.
-
-  @return  The load option buffer.
-**/
-VOID *
-BmExpandMediaDevicePath (
-  IN  EFI_DEVICE_PATH_PROTOCOL        *DevicePath,
-  OUT EFI_DEVICE_PATH_PROTOCOL        **FullPath,
-  OUT UINTN                           *FileSize
-  )
-{
-  EFI_STATUS                          Status;
-  EFI_HANDLE                          Handle;
-  EFI_BLOCK_IO_PROTOCOL               *BlockIo;
-  VOID                                *Buffer;
-  EFI_DEVICE_PATH_PROTOCOL            *TempDevicePath;
-  UINTN                               Size;
-  UINTN                               TempSize;
-  EFI_HANDLE                          *SimpleFileSystemHandles;
-  UINTN                               NumberSimpleFileSystemHandles;
-  UINTN                               Index;
-  VOID                                *FileBuffer;
-  UINT32                              AuthenticationStatus;
-
-  //
-  // Check whether the device is connected
-  //
-  TempDevicePath = DevicePath;
-  Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &TempDevicePath, &Handle);
-  if (!EFI_ERROR (Status)) {
-    ASSERT (IsDevicePathEnd (TempDevicePath));
-
-    TempDevicePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);
-    FileBuffer = GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize, &AuthenticationStatus);
-    if (FileBuffer == NULL) {
-      FreePool (TempDevicePath);
-      TempDevicePath = NULL;
-    }
-    *FullPath = TempDevicePath;
-    return FileBuffer;
-  }
-
-  //
-  // For device boot option only pointing to the removable device handle, 
-  // should make sure all its children handles (its child partion or media handles) are created and connected. 
-  //
-  gBS->ConnectController (Handle, NULL, NULL, TRUE);
-
-  //
-  // Issue a dummy read to the device to check for media change.
-  // When the removable media is changed, any Block IO read/write will
-  // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is
-  // returned. After the Block IO protocol is reinstalled, subsequent
-  // Block IO read/write will success.
-  //
-  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);
-  ASSERT_EFI_ERROR (Status);
-  Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
-  ASSERT_EFI_ERROR (Status);
-  Buffer = AllocatePool (BlockIo->Media->BlockSize);
-  if (Buffer != NULL) {
-    BlockIo->ReadBlocks (
-      BlockIo,
-      BlockIo->Media->MediaId,
-      0,
-      BlockIo->Media->BlockSize,
-      Buffer
-      );
-    FreePool (Buffer);
-  }
-
-  //
-  // Detect the the default boot file from removable Media
-  //
-  FileBuffer = NULL;
-  *FullPath = NULL;
-  Size = GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH;
-  gBS->LocateHandleBuffer (
-         ByProtocol,
-         &gEfiSimpleFileSystemProtocolGuid,
-         NULL,
-         &NumberSimpleFileSystemHandles,
-         &SimpleFileSystemHandles
-         );
-  for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
-    //
-    // Get the device path size of SimpleFileSystem handle
-    //
-    TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
-    TempSize = GetDevicePathSize (TempDevicePath) - END_DEVICE_PATH_LENGTH;
-    //
-    // Check whether the device path of boot option is part of the SimpleFileSystem handle's device path
-    //
-    if ((Size <= TempSize) && (CompareMem (TempDevicePath, DevicePath, Size) == 0)) {
-      TempDevicePath = FileDevicePath (SimpleFileSystemHandles[Index], EFI_REMOVABLE_MEDIA_FILE_NAME);
-      FileBuffer = GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize, &AuthenticationStatus);
-      if (FileBuffer != NULL) {
-        *FullPath = TempDevicePath;
-        break;
-      }
-      FreePool (TempDevicePath);
-    }
-  }
-
-  if (SimpleFileSystemHandles != NULL) {
-    FreePool (SimpleFileSystemHandles);
-  }
-
-  return FileBuffer;
-}
-
-/**
-  Get the load option by its device path.
-
-  @param FilePath  The device path pointing to a load option.
-                   It could be a short-form device path.
-  @param FullPath  Return the full device path of the load option after
-                   short-form device path expanding.
-                   Caller is responsible to free it.
-  @param FileSize  Return the load option size.
-
-  @return The load option buffer. Caller is responsible to free the memory.
-**/
-VOID *
-BmGetLoadOptionBuffer (
-  IN  EFI_DEVICE_PATH_PROTOCOL          *FilePath,
-  OUT EFI_DEVICE_PATH_PROTOCOL          **FullPath,
-  OUT UINTN                             *FileSize
-  )
-{
-  EFI_HANDLE                      Handle;
-  VOID                            *FileBuffer;
-  UINT32                          AuthenticationStatus;
-  EFI_DEVICE_PATH_PROTOCOL        *Node;
-  EFI_STATUS                      Status;
-
-  ASSERT ((FilePath != NULL) && (FullPath != NULL) && (FileSize != NULL));
-
-  EfiBootManagerConnectDevicePath (FilePath, NULL);
-
-  *FullPath  = NULL;
-  *FileSize  = 0;
-  FileBuffer = NULL;
-
-  //
-  // Boot from media device by adding a default file name \EFI\BOOT\BOOT{machine type short-name}.EFI
-  //
-  Node = FilePath;
-  Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &Node, &Handle);
-  if (EFI_ERROR (Status)) {
-    Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &Node, &Handle);
-  }
-
-  if (!EFI_ERROR (Status) && IsDevicePathEnd (Node)) {
-    return BmExpandMediaDevicePath (FilePath, FullPath, FileSize);
-  }
-
-  //
-  // Expand the short-form device path to full device path
-  //
-  if ((DevicePathType (FilePath) == MEDIA_DEVICE_PATH) &&
-      (DevicePathSubType (FilePath) == MEDIA_HARDDRIVE_DP)) {
-    //
-    // Expand the Harddrive device path
-    //
-    return BmExpandPartitionDevicePath (FilePath, FullPath, FileSize);
-  } else {
-    for (Node = FilePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
-      if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) &&
-          ((DevicePathSubType (Node) == MSG_USB_CLASS_DP) || (DevicePathSubType (Node) == MSG_USB_WWID_DP))) {
-        break;
-      }
-    }
-
-    if (!IsDevicePathEnd (Node)) {
-      //
-      // Expand the USB WWID/Class device path
-      //
-      FileBuffer = BmExpandUsbDevicePath (FilePath, FullPath, FileSize, Node);
-      if ((FileBuffer == NULL) && (FilePath == Node)) {
-        //
-        // Boot Option device path starts with USB Class or USB WWID device path.
-        // For Boot Option device path which doesn't begin with the USB Class or
-        // USB WWID device path, it's not needed to connect again here.
-        //
-        BmConnectUsbShortFormDevicePath (FilePath);
-        FileBuffer = BmExpandUsbDevicePath (FilePath, FullPath, FileSize, Node);
-      }
-      return FileBuffer;
-    }
-  }
-
-  //
-  // Fix up the boot option path if it points to a FV in memory map style of device path
-  //
-  if (BmIsMemmapFvFilePath (FilePath)) {
-    return BmGetFileBufferByMemmapFv (FilePath, FullPath, FileSize);
-  }
-
-  //
-  // Directly reads the load option when it doesn't reside in simple file system instance (LoadFile/LoadFile2),
-  //   or it directly points to a file in simple file system instance.
-  //
-  FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, &AuthenticationStatus);
-  if (FileBuffer != NULL) {
-    *FullPath = DuplicateDevicePath (FilePath);
-  }
-
-  return FileBuffer;
-}
-
-/**
-  Attempt to boot the EFI boot option. This routine sets L"BootCurent" and
-  also 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 via the registered 
-  gLegacyBoot function. 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 A BBS device path was found with no valid callback
-                                        registered via EfiBootManagerInitialize().
-                        EFI_NOT_FOUND   The BootOption was not found on the system
-                        !EFI_SUCCESS    BootOption failed with this error status
-
-**/
-VOID
-EFIAPI
-EfiBootManagerBoot (
-  IN  EFI_BOOT_MANAGER_LOAD_OPTION             *BootOption
-  )
-{
-  EFI_STATUS                Status;
-  EFI_HANDLE                ImageHandle;
-  EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
-  UINT16                    Uint16;
-  UINTN                     OptionNumber;
-  UINTN                     OriginalOptionNumber;
-  EFI_DEVICE_PATH_PROTOCOL  *FilePath;
-  EFI_DEVICE_PATH_PROTOCOL  *Node;
-  EFI_HANDLE                FvHandle;
-  VOID                      *FileBuffer;
-  UINTN                     FileSize;
-  EFI_BOOT_LOGO_PROTOCOL    *BootLogo;
-  EFI_EVENT                 LegacyBootEvent;
-
-  if (BootOption == NULL) {
-    return;
-  }
-
-  if (BootOption->FilePath == NULL || BootOption->OptionType != LoadOptionTypeBoot) {
-    BootOption->Status = EFI_INVALID_PARAMETER;
-    return;
-  }
-
-  //
-  // 1. Create Boot#### for a temporary boot if there is no match Boot#### (i.e. a boot by selected a EFI Shell using "Boot From File")
-  //
-  OptionNumber = BmFindBootOptionInVariable (BootOption);
-  if (OptionNumber == LoadOptionNumberUnassigned) {
-    Status = BmGetFreeOptionNumber (LoadOptionTypeBoot, &Uint16);
-    if (!EFI_ERROR (Status)) {
-      //
-      // Save the BootOption->OptionNumber to restore later
-      //
-      OptionNumber             = Uint16;
-      OriginalOptionNumber     = BootOption->OptionNumber;
-      BootOption->OptionNumber = OptionNumber;
-      Status = EfiBootManagerLoadOptionToVariable (BootOption);
-      BootOption->OptionNumber = OriginalOptionNumber;
-    }
-
-    if (EFI_ERROR (Status)) {
-      DEBUG ((EFI_D_ERROR, "[Bds] Failed to create Boot#### for a temporary boot - %r!\n", Status));
-      BootOption->Status = Status;
-      return ;
-    }
-  }
-
-  //
-  // 2. Set BootCurrent
-  //
-  Uint16 = (UINT16) OptionNumber;
-  BmSetVariableAndReportStatusCodeOnError (
-    L"BootCurrent",
-    &gEfiGlobalVariableGuid,
-    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
-    sizeof (UINT16),
-    &Uint16
-    );
-
-  //
-  // 3. Signal the EVT_SIGNAL_READY_TO_BOOT event when we are about to load and execute
-  //    the boot option.
-  //
-  Node   = BootOption->FilePath;
-  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &FvHandle);
-  if (!EFI_ERROR (Status) && CompareGuid (
-        EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) Node),
-        PcdGetPtr (PcdBootManagerMenuFile)
-        )) {
-    DEBUG ((EFI_D_INFO, "[Bds] Booting Boot Manager Menu.\n"));
-    BmStopHotkeyService (NULL, NULL);
-  } else {
-    EfiSignalEventReadyToBoot();
-    //
-    // Report Status Code to indicate ReadyToBoot was signalled
-    //
-    REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT));
-    //
-    // 4. Repair system through DriverHealth protocol
-    //
-    BmRepairAllControllers ();
-  }
-
-  PERF_START_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);
-
-  //
-  // 5. Load EFI boot option to ImageHandle
-  //
-  ImageHandle = NULL;
-  if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) {
-    Status     = EFI_NOT_FOUND;
-    FileBuffer = BmGetLoadOptionBuffer (BootOption->FilePath, &FilePath, &FileSize);
-    DEBUG_CODE (
-      if (FileBuffer != NULL && CompareMem (BootOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {
-        DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));
-        BmPrintDp (BootOption->FilePath);
-        DEBUG ((EFI_D_INFO, " -> "));
-        BmPrintDp (FilePath);
-        DEBUG ((EFI_D_INFO, "\n"));
-      }
-    );
-    if (BmIsLoadOptionPeHeaderValid (BootOption->OptionType, FileBuffer, FileSize)) {
-      REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));
-      Status = gBS->LoadImage (
-                      TRUE,
-                      gImageHandle,
-                      FilePath,
-                      FileBuffer,
-                      FileSize,
-                      &ImageHandle
-                      );
-    }
-    if (FileBuffer != NULL) {
-      FreePool (FileBuffer);
-    }
-    if (FilePath != NULL) {
-      FreePool (FilePath);
-    }
-
-    if (EFI_ERROR (Status)) {
-      //
-      // Report Status Code to indicate that the failure to load boot option
-      //
-      REPORT_STATUS_CODE (
-        EFI_ERROR_CODE | EFI_ERROR_MINOR,
-        (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR)
-        );
-      BootOption->Status = Status;
-      return;
-    }
-  }
-
-  //
-  // 6. Adjust the different type memory page number just before booting
-  //    and save the updated info into the variable for next boot to use
-  //
-  if ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT) {
-    if (PcdGetBool (PcdResetOnMemoryTypeInformationChange)) {
-      BmSetMemoryTypeInformationVariable ();
-    }
-  }
-
-  DEBUG_CODE_BEGIN();
-    if (BootOption->Description == NULL) {
-      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting from unknown device path\n"));
-    } else {
-      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting %s\n", BootOption->Description));
-    }
-  DEBUG_CODE_END();
-
-  //
-  // Check to see if we should legacy BOOT. If yes then do the legacy boot
-  // Write boot to OS performance data for Legacy boot
-  //
-  if ((DevicePathType (BootOption->FilePath) == BBS_DEVICE_PATH) && (DevicePathSubType (BootOption->FilePath) == BBS_BBS_DP)) {
-    if (mBmLegacyBoot != NULL) {
-      //
-      // Write boot to OS performance data for legacy boot.
-      //
-      PERF_CODE (
-        //
-        // Create an event to be signalled when Legacy Boot occurs to write performance data.
-        //
-        Status = EfiCreateEventLegacyBootEx(
-                   TPL_NOTIFY,
-                   BmWriteBootToOsPerformanceData,
-                   NULL, 
-                   &LegacyBootEvent
-                   );
-        ASSERT_EFI_ERROR (Status);
-      );
-
-      mBmLegacyBoot (BootOption);
-    } else {
-      BootOption->Status = EFI_UNSUPPORTED;
-    }
-
-    PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);
-    return;
-  }
-  //
-  // Provide the image with its load options
-  //
-  Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
-  ASSERT_EFI_ERROR (Status);
-
-  ImageInfo->LoadOptionsSize  = BootOption->OptionalDataSize;
-  ImageInfo->LoadOptions      = BootOption->OptionalData;
-
-  //
-  // Clean to NULL because the image is loaded directly from the firmwares boot manager.
-  //
-  ImageInfo->ParentHandle = NULL;
-
-  //
-  // Before calling the image, enable the Watchdog Timer for 5 minutes period
-  //
-  gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
-
-  //
-  // Write boot to OS performance data for UEFI boot
-  //
-  PERF_CODE (
-    BmWriteBootToOsPerformanceData (NULL, NULL);
-  );
-
-  REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderStart));
-
-  Status = gBS->StartImage (ImageHandle, &BootOption->ExitDataSize, &BootOption->ExitData);
-  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", Status));
-  BootOption->Status = Status;
-  if (EFI_ERROR (Status)) {
-    //
-    // Report Status Code to indicate that boot failure
-    //
-    REPORT_STATUS_CODE (
-      EFI_ERROR_CODE | EFI_ERROR_MINOR,
-      (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED)
-      );
-  }
-  PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);
-
-  //
-  // Clear the Watchdog Timer after the image returns
-  //
-  gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
-
-  //
-  // Set Logo status invalid after trying one boot option
-  //
-  BootLogo = NULL;
-  Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
-  if (!EFI_ERROR (Status) && (BootLogo != NULL)) {
-    Status = BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);
-    ASSERT_EFI_ERROR (Status);
-  }
-
-  //
-  // Clear Boot Current
-  //
-  Status = gRT->SetVariable (
-                  L"BootCurrent",
-                  &gEfiGlobalVariableGuid,
-                  0,
-                  0,
-                  NULL
-                  );
-  //
-  // Deleting variable with current variable implementation shouldn't fail.
-  // When BootXXXX (e.g.: BootManagerMenu) boots BootYYYY, exiting BootYYYY causes BootCurrent deleted,
-  // exiting BootXXXX causes deleting BootCurrent returns EFI_NOT_FOUND.
-  //
-  ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);
-}
-
-/**
-  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
-  )
-{
-  HARDDRIVE_DEVICE_PATH     *Node;
-
-  if ((BlockIoDevicePath == NULL) || (HardDriveDevicePath == NULL)) {
-    return FALSE;
-  }
-
-  //
-  // find the partition device path node
-  //
-  while (!IsDevicePathEnd (BlockIoDevicePath)) {
-    if ((DevicePathType (BlockIoDevicePath) == MEDIA_DEVICE_PATH) &&
-        (DevicePathSubType (BlockIoDevicePath) == MEDIA_HARDDRIVE_DP)
-        ) {
-      break;
-    }
-
-    BlockIoDevicePath = NextDevicePathNode (BlockIoDevicePath);
-  }
-
-  if (IsDevicePathEnd (BlockIoDevicePath)) {
-    return FALSE;
-  }
-
-  //
-  // See if the harddrive device path in blockio matches the orig Hard Drive Node
-  //
-  Node = (HARDDRIVE_DEVICE_PATH *) BlockIoDevicePath;
-
-  //
-  // Match Signature and PartitionNumber.
-  // Unused bytes in Signature are initiaized with zeros.
-  //
-  return (BOOLEAN) (
-    (Node->PartitionNumber == HardDriveDevicePath->PartitionNumber) &&
-    (Node->MBRType == HardDriveDevicePath->MBRType) &&
-    (Node->SignatureType == HardDriveDevicePath->SignatureType) &&
-    (CompareMem (Node->Signature, HardDriveDevicePath->Signature, sizeof (Node->Signature)) == 0)
-    );
-}
-
-/**
-  Emuerate 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
-
-  @param BootOptionCount   Return the boot option count which has been found.
-
-  @retval   Pointer to the boot option array.
-**/
-EFI_BOOT_MANAGER_LOAD_OPTION *
-BmEnumerateBootOptions (
-  UINTN                                 *BootOptionCount
-  )
-{
-  EFI_STATUS                            Status;
-  EFI_BOOT_MANAGER_LOAD_OPTION          *BootOptions;
-  UINT16                                NonBlockNumber;
-  UINTN                                 HandleCount;
-  EFI_HANDLE                            *Handles;
-  EFI_BLOCK_IO_PROTOCOL                 *BlkIo;
-  UINTN                                 Removable;
-  UINTN                                 Index;
-  UINTN                                 FunctionIndex;
-  CHAR16                                *Temp;
-  CHAR16                                *DescriptionPtr;
-  CHAR16                                Description[30];
-
-  ASSERT (BootOptionCount != NULL);
-
-  *BootOptionCount = 0;
-  BootOptions      = NULL;
-
-  //
-  // Parse removable block io followed by fixed block io
-  //
-  gBS->LocateHandleBuffer (
-         ByProtocol,
-         &gEfiBlockIoProtocolGuid,
-         NULL,
-         &HandleCount,
-         &Handles
-         );
-
-  for (Removable = 0; Removable < 2; Removable++) {
-    for (Index = 0; Index < HandleCount; Index++) {
-      Status = gBS->HandleProtocol (
-                      Handles[Index],
-                      &gEfiBlockIoProtocolGuid,
-                      (VOID **) &BlkIo
-                      );
-      if (EFI_ERROR (Status)) {
-        continue;
-      }
-
-      //
-      // Skip the logical partitions
-      //
-      if (BlkIo->Media->LogicalPartition) {
-        continue;
-      }
-
-      //
-      // Skip the fixed block io then the removable block io
-      //
-      if (BlkIo->Media->RemovableMedia == ((Removable == 0) ? FALSE : TRUE)) {
-        continue;
-      }
-
-      DescriptionPtr = NULL;
-      for (FunctionIndex = 0; FunctionIndex < sizeof (mBmGetBootDescription) / sizeof (mBmGetBootDescription[0]); FunctionIndex++) {
-        DescriptionPtr = mBmGetBootDescription[FunctionIndex] (Handles[Index]);
-        if (DescriptionPtr != NULL) {
-          break;
-        }
-      }
-
-      if (DescriptionPtr == NULL) {
-        continue;
-      }
-
-      //
-      // Avoid description confusion between UEFI & Legacy boot option by adding "UEFI " prefix
-      //
-      Temp = AllocatePool (StrSize (DescriptionPtr) + sizeof (mBmUefiPrefix)); 
-      ASSERT (Temp != NULL);
-      StrCpy (Temp, mBmUefiPrefix);
-      StrCat (Temp, DescriptionPtr);
-      FreePool (DescriptionPtr);
-      DescriptionPtr = Temp;
-
-      BootOptions = ReallocatePool (
-                      sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),
-                      sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),
-                      BootOptions
-                      );
-      ASSERT (BootOptions != NULL);
-
-      Status = EfiBootManagerInitializeLoadOption (
-                 &BootOptions[(*BootOptionCount)++],
-                 LoadOptionNumberUnassigned,
-                 LoadOptionTypeBoot,
-                 LOAD_OPTION_ACTIVE,
-                 DescriptionPtr,
-                 DevicePathFromHandle (Handles[Index]),
-                 NULL,
-                 0
-                 );
-      ASSERT_EFI_ERROR (Status);
-
-      FreePool (DescriptionPtr);
-    }
-  }
-
-  if (HandleCount != 0) {
-    FreePool (Handles);
-  }
-
-  //
-  // Parse simple file system not based on block io
-  //
-  NonBlockNumber = 0;
-  gBS->LocateHandleBuffer (
-         ByProtocol,
-         &gEfiSimpleFileSystemProtocolGuid,
-         NULL,
-         &HandleCount,
-         &Handles
-         );
-  for (Index = 0; Index < HandleCount; Index++) {
-    Status = gBS->HandleProtocol (
-                    Handles[Index],
-                    &gEfiBlockIoProtocolGuid,
-                    (VOID **) &BlkIo
-                    );
-     if (!EFI_ERROR (Status)) {
-      //
-      //  Skip if the file system handle supports a BlkIo protocol, which we've handled in above
-      //
-      continue;
-    }
-    UnicodeSPrint (Description, sizeof (Description), NonBlockNumber > 0 ? L"%s %d" : L"%s", L"UEFI Non-Block Boot Device", NonBlockNumber);
-    
-    BootOptions = ReallocatePool (
-                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),
-                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),
-                    BootOptions
-                    );
-    ASSERT (BootOptions != NULL);
-
-    Status = EfiBootManagerInitializeLoadOption (
-               &BootOptions[(*BootOptionCount)++],
-               LoadOptionNumberUnassigned,
-               LoadOptionTypeBoot,
-               LOAD_OPTION_ACTIVE,
-               Description,
-               DevicePathFromHandle (Handles[Index]),
-               NULL,
-               0
-               );
-    ASSERT_EFI_ERROR (Status);
-  }
-
-  if (HandleCount != 0) {
-    FreePool (Handles);
-  }
-
-  //
-  // Parse load file, assuming UEFI Network boot option
-  //
-  gBS->LocateHandleBuffer (
-         ByProtocol,
-         &gEfiLoadFileProtocolGuid,
-         NULL,
-         &HandleCount,
-         &Handles
-         );
-  for (Index = 0; Index < HandleCount; Index++) {
-
-    UnicodeSPrint (Description, sizeof (Description), Index > 0 ? L"%s %d" : L"%s", L"UEFI Network", Index);
-
-    BootOptions = ReallocatePool (
-                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),
-                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),
-                    BootOptions
-                    );
-    ASSERT (BootOptions != NULL);
-
-    Status = EfiBootManagerInitializeLoadOption (
-               &BootOptions[(*BootOptionCount)++],
-               LoadOptionNumberUnassigned,
-               LoadOptionTypeBoot,
-               LOAD_OPTION_ACTIVE,
-               Description,
-               DevicePathFromHandle (Handles[Index]),
-               NULL,
-               0
-               );
-    ASSERT_EFI_ERROR (Status);
-  }
-
-  if (HandleCount != 0) {
-    FreePool (Handles);
-  }
-
-  return BootOptions;
-}
-
-/**
-  The function enumerates all boot options, creates them and registers them in the BootOrder variable.
-**/
-VOID
-EFIAPI
-EfiBootManagerRefreshAllBootOption (
-  VOID
-  )
-{
-  EFI_STATUS                    Status;
-  EFI_BOOT_MANAGER_LOAD_OPTION  *NvBootOptions;
-  UINTN                         NvBootOptionCount;
-  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions;
-  UINTN                         BootOptionCount;
-  UINTN                         Index;
-
-  //
-  // Optionally refresh the legacy boot option
-  //
-  if (mBmRefreshLegacyBootOption != NULL) {
-    mBmRefreshLegacyBootOption ();
-  }
-
-  BootOptions   = BmEnumerateBootOptions (&BootOptionCount);
-  NvBootOptions = EfiBootManagerGetLoadOptions (&NvBootOptionCount, LoadOptionTypeBoot);
-
-  //
-  // Mark the boot option as added by BDS by setting OptionalData to a special GUID
-  //
-  for (Index = 0; Index < BootOptionCount; Index++) {
-    BootOptions[Index].OptionalData     = AllocateCopyPool (sizeof (EFI_GUID), &mBmAutoCreateBootOptionGuid);
-    BootOptions[Index].OptionalDataSize = sizeof (EFI_GUID);
-  }
-
-  //
-  // Remove invalid EFI boot options from NV
-  //
-  for (Index = 0; Index < NvBootOptionCount; Index++) {
-    if (((DevicePathType (NvBootOptions[Index].FilePath) != BBS_DEVICE_PATH) || 
-         (DevicePathSubType (NvBootOptions[Index].FilePath) != BBS_BBS_DP)
-        ) &&
-        (NvBootOptions[Index].OptionalDataSize == sizeof (EFI_GUID)) &&
-        CompareGuid ((EFI_GUID *) NvBootOptions[Index].OptionalData, &mBmAutoCreateBootOptionGuid)
-       ) {
-      //
-      // Only check those added by BDS
-      // so that the boot options added by end-user or OS installer won't be deleted
-      //
-      if (BmFindLoadOption (&NvBootOptions[Index], BootOptions, BootOptionCount) == (UINTN) -1) {
-        Status = EfiBootManagerDeleteLoadOptionVariable (NvBootOptions[Index].OptionNumber, LoadOptionTypeBoot);
-        //
-        // Deleting variable with current variable implementation shouldn't fail.
-        //
-        ASSERT_EFI_ERROR (Status);
-      }
-    }
-  }
-
-  //
-  // Add new EFI boot options to NV
-  //
-  for (Index = 0; Index < BootOptionCount; Index++) {
-    if (BmFindLoadOption (&BootOptions[Index], NvBootOptions, NvBootOptionCount) == (UINTN) -1) {
-      EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1);
-      //
-      // Try best to add the boot options so continue upon failure.
-      //
-    }
-  }
-
-  EfiBootManagerFreeLoadOptions (BootOptions,   BootOptionCount);
-  EfiBootManagerFreeLoadOptions (NvBootOptions, NvBootOptionCount);
-}
-
-/**
-  This function is called to create the boot option for the Boot Manager Menu.
-
-  The Boot Manager Menu is shown after successfully booting a boot option.
-  Assume the BootManagerMenuFile is in the same FV as the module links to this library.
-
-  @param  BootOption    Return the boot option of the Boot Manager Menu
-
-  @retval EFI_SUCCESS   Successfully register the Boot Manager Menu.
-  @retval Status        Return status of gRT->SetVariable (). BootOption still points
-                        to the Boot Manager Menu even the Status is not EFI_SUCCESS.
-**/
-EFI_STATUS
-BmRegisterBootManagerMenu (
-  OUT EFI_BOOT_MANAGER_LOAD_OPTION   *BootOption
-  )
-{
-  EFI_STATUS                         Status;
-  CHAR16                             *Description;
-  UINTN                              DescriptionLength;
-  EFI_DEVICE_PATH_PROTOCOL           *DevicePath;
-  EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;
-  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;
-
-  Status = GetSectionFromFv (
-             PcdGetPtr (PcdBootManagerMenuFile),
-             EFI_SECTION_USER_INTERFACE,
-             0,
-             (VOID **) &Description,
-             &DescriptionLength
-             );
-  if (EFI_ERROR (Status)) {
-    Description = NULL;
-  }
-
-  EfiInitializeFwVolDevicepathNode (&FileNode, PcdGetPtr (PcdBootManagerMenuFile));
-  Status = gBS->HandleProtocol (
-                  gImageHandle,
-                  &gEfiLoadedImageProtocolGuid,
-                  (VOID **) &LoadedImage
-                  );
-  ASSERT_EFI_ERROR (Status);
-  DevicePath = AppendDevicePathNode (
-                 DevicePathFromHandle (LoadedImage->DeviceHandle),
-                 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
-                 );
-  ASSERT (DevicePath != NULL);
-
-  Status = EfiBootManagerInitializeLoadOption (
-             BootOption,
-             LoadOptionNumberUnassigned,
-             LoadOptionTypeBoot,
-             LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDEN,
-             (Description != NULL) ? Description : L"Boot Manager Menu",
-             DevicePath,
-             NULL,
-             0
-             );
-  ASSERT_EFI_ERROR (Status);
-  FreePool (DevicePath);
-  if (Description != NULL) {
-    FreePool (Description);
-  }
-
-  DEBUG_CODE (
-    EFI_BOOT_MANAGER_LOAD_OPTION    *BootOptions;
-    UINTN                           BootOptionCount;
-
-    BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
-    ASSERT (BmFindLoadOption (BootOption, BootOptions, BootOptionCount) == -1);
-    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
-    );
-
-  return EfiBootManagerAddLoadOptionVariable (BootOption, 0);
-}
-
-/**
-  Return the boot option corresponding to the Boot Manager Menu.
-  It may automatically create one if the boot option hasn't been created yet.
-  
-  @param BootOption    Return the Boot Manager Menu.
-
-  @retval EFI_SUCCESS   The Boot Manager Menu is successfully returned.
-  @retval Status        Return status of gRT->SetVariable (). BootOption still points
-                        to the Boot Manager Menu even the Status is not EFI_SUCCESS.
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerGetBootManagerMenu (
-  EFI_BOOT_MANAGER_LOAD_OPTION *BootOption
-  )
-{
-  EFI_STATUS                   Status;
-  UINTN                        BootOptionCount;
-  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
-  UINTN                        Index;
-  EFI_DEVICE_PATH_PROTOCOL     *Node;
-  EFI_HANDLE                   FvHandle;
-  
-  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
-
-  for (Index = 0; Index < BootOptionCount; Index++) {
-    Node   = BootOptions[Index].FilePath;
-    Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &FvHandle);
-    if (!EFI_ERROR (Status)) {
-      if (CompareGuid (
-            EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) Node),
-            PcdGetPtr (PcdBootManagerMenuFile)
-            )
-          ) {        
-        Status = EfiBootManagerInitializeLoadOption (
-                   BootOption,
-                   BootOptions[Index].OptionNumber,
-                   BootOptions[Index].OptionType,
-                   BootOptions[Index].Attributes,
-                   BootOptions[Index].Description,
-                   BootOptions[Index].FilePath,
-                   BootOptions[Index].OptionalData,
-                   BootOptions[Index].OptionalDataSize
-                   );
-        ASSERT_EFI_ERROR (Status);
-        break;
-      }
-    }
-  }
-
-  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
-
-  //
-  // Automatically create the Boot#### for Boot Manager Menu when not found.
-  //
-  if (Index == BootOptionCount) {
-    return BmRegisterBootManagerMenu (BootOption);
-  } else {
-    return EFI_SUCCESS;
-  }
-}
-
+/** @file\r
+  Library functions which relates with booting.\r
+\r
+Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBm.h"\r
+\r
+#define VENDOR_IDENTIFICATION_OFFSET     3\r
+#define VENDOR_IDENTIFICATION_LENGTH     8\r
+#define PRODUCT_IDENTIFICATION_OFFSET    11\r
+#define PRODUCT_IDENTIFICATION_LENGTH    16\r
+\r
+CONST UINT16 mBmUsbLangId    = 0x0409; // English\r
+CHAR16       mBmUefiPrefix[] = L"UEFI ";\r
+\r
+EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION  mBmRefreshLegacyBootOption = NULL;\r
+EFI_BOOT_MANAGER_LEGACY_BOOT                 mBmLegacyBoot              = NULL;\r
+\r
+///\r
+/// This GUID is used for an EFI Variable that stores the front device pathes\r
+/// for a partial device path that starts with the HD node.\r
+///\r
+EFI_GUID mBmHardDriveBootVariableGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x08, 0xe2, 0x0e, 0x90, 0x6c, 0xb6, 0xde } };\r
+EFI_GUID mBmAutoCreateBootOptionGuid  = { 0x8108ac4e, 0x9f11, 0x4d59, { 0x85, 0x0e, 0xe2, 0x1a, 0x52, 0x2c, 0x59, 0xb2 } };\r
+\r
+/**\r
+  The function registers the legacy boot support capabilities.\r
+\r
+  @param RefreshLegacyBootOption The function pointer to create all the legacy boot options.\r
+  @param LegacyBoot              The function pointer to boot the legacy boot option.\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerRegisterLegacyBootSupport (\r
+  EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION   RefreshLegacyBootOption,\r
+  EFI_BOOT_MANAGER_LEGACY_BOOT                  LegacyBoot\r
+  )\r
+{\r
+  mBmRefreshLegacyBootOption = RefreshLegacyBootOption;\r
+  mBmLegacyBoot              = LegacyBoot;\r
+}\r
+\r
+/**\r
+  For a bootable Device path, return its boot type.\r
+\r
+  @param  DevicePath                   The bootable device Path to check\r
+\r
+  @retval AcpiFloppyBoot               If given device path contains ACPI_DEVICE_PATH type device path node\r
+                                       which HID is floppy device.\r
+  @retval MessageAtapiBoot             If given device path contains MESSAGING_DEVICE_PATH type device path node\r
+                                       and its last device path node's subtype is MSG_ATAPI_DP.\r
+  @retval MessageSataBoot              If given device path contains MESSAGING_DEVICE_PATH type device path node\r
+                                       and its last device path node's subtype is MSG_SATA_DP.\r
+  @retval MessageScsiBoot              If given device path contains MESSAGING_DEVICE_PATH type device path node\r
+                                       and its last device path node's subtype is MSG_SCSI_DP.\r
+  @retval MessageUsbBoot               If given device path contains MESSAGING_DEVICE_PATH type device path node\r
+                                       and its last device path node's subtype is MSG_USB_DP.\r
+  @retval MessageNetworkBoot           If given device path contains MESSAGING_DEVICE_PATH type device path node\r
+                                       and its last device path node's subtype is MSG_MAC_ADDR_DP, MSG_VLAN_DP,\r
+                                       MSG_IPv4_DP or MSG_IPv6_DP.\r
+  @retval UnsupportedBoot              If tiven device path doesn't match the above condition, it's not supported.\r
+\r
+**/\r
+BM_BOOT_TYPE\r
+BmDevicePathType (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL      *Node;\r
+  EFI_DEVICE_PATH_PROTOCOL      *NextNode;\r
+\r
+  ASSERT (DevicePath != NULL);\r
+\r
+  for (Node = DevicePath; !IsDevicePathEndType (Node); Node = NextDevicePathNode (Node)) {\r
+    switch (DevicePathType (Node)) {\r
+\r
+      case ACPI_DEVICE_PATH:\r
+        if (EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *) Node)->HID) == 0x0604) {\r
+          return BmAcpiFloppyBoot;\r
+        }\r
+        break;\r
+\r
+      case HARDWARE_DEVICE_PATH:\r
+        if (DevicePathSubType (Node) == HW_CONTROLLER_DP) {\r
+          return BmHardwareDeviceBoot;\r
+        }\r
+        break;\r
+\r
+      case MESSAGING_DEVICE_PATH:\r
+        //\r
+        // Skip LUN device node\r
+        //\r
+        NextNode = Node;\r
+        do {\r
+          NextNode = NextDevicePathNode (NextNode);\r
+        } while (\r
+            (DevicePathType (NextNode) == MESSAGING_DEVICE_PATH) &&\r
+            (DevicePathSubType(NextNode) == MSG_DEVICE_LOGICAL_UNIT_DP)\r
+            );\r
+\r
+        //\r
+        // If the device path not only point to driver device, it is not a messaging device path,\r
+        //\r
+        if (!IsDevicePathEndType (NextNode)) {\r
+          break;\r
+        }\r
+\r
+        switch (DevicePathSubType (Node)) {\r
+        case MSG_ATAPI_DP:\r
+          return BmMessageAtapiBoot;\r
+          break;\r
+\r
+        case MSG_SATA_DP:\r
+          return BmMessageSataBoot;\r
+          break;\r
+\r
+        case MSG_USB_DP:\r
+          return BmMessageUsbBoot;\r
+          break;\r
+\r
+        case MSG_SCSI_DP:\r
+          return BmMessageScsiBoot;\r
+          break;\r
+\r
+        case MSG_MAC_ADDR_DP:\r
+        case MSG_VLAN_DP:\r
+        case MSG_IPv4_DP:\r
+        case MSG_IPv6_DP:\r
+          return BmMessageNetworkBoot;\r
+          break;\r
+        }\r
+    }\r
+  }\r
+\r
+  return BmMiscBoot;\r
+}\r
+\r
+/**\r
+  Find the boot option in the NV storage and return the option number.\r
+\r
+  @param OptionToFind  Boot option to be checked.\r
+\r
+  @return   The option number of the found boot option.\r
+\r
+**/\r
+UINTN\r
+BmFindBootOptionInVariable (\r
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION             *OptionToFind\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
+  UINTN                        OptionNumber;\r
+  CHAR16                       OptionName[BM_OPTION_NAME_LEN];\r
+  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
+  UINTN                        BootOptionCount;\r
+  UINTN                        Index;\r
+  \r
+  OptionNumber = LoadOptionNumberUnassigned;\r
+\r
+  //\r
+  // Try to match the variable exactly if the option number is assigned\r
+  //\r
+  if (OptionToFind->OptionNumber != LoadOptionNumberUnassigned) {\r
+    UnicodeSPrint (\r
+      OptionName, sizeof (OptionName), L"%s%04x",\r
+      mBmLoadOptionName[OptionToFind->OptionType], OptionToFind->OptionNumber\r
+      );\r
+    Status = EfiBootManagerVariableToLoadOption (OptionName, &BootOption);\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      ASSERT (OptionToFind->OptionNumber == BootOption.OptionNumber);\r
+      if ((OptionToFind->Attributes == BootOption.Attributes) &&\r
+          (StrCmp (OptionToFind->Description, BootOption.Description) == 0) &&\r
+          (CompareMem (OptionToFind->FilePath, BootOption.FilePath, GetDevicePathSize (OptionToFind->FilePath)) == 0) &&\r
+          (OptionToFind->OptionalDataSize == BootOption.OptionalDataSize) &&\r
+          (CompareMem (OptionToFind->OptionalData, BootOption.OptionalData, OptionToFind->OptionalDataSize) == 0)\r
+         ) {\r
+        OptionNumber = OptionToFind->OptionNumber;\r
+      }\r
+      EfiBootManagerFreeLoadOption (&BootOption);\r
+    }\r
+  }\r
+\r
+  //\r
+  // The option number assigned is either incorrect or unassigned.\r
+  //\r
+  if (OptionNumber == LoadOptionNumberUnassigned) {\r
+    BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
+\r
+    Index = BmFindLoadOption (OptionToFind, BootOptions, BootOptionCount);\r
+    if (Index != -1) {\r
+      OptionNumber = BootOptions[Index].OptionNumber;\r
+    }\r
+\r
+    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
+  }\r
+\r
+  return OptionNumber;\r
+}\r
+\r
+/**\r
+  Get the file buffer using a Memory Mapped Device Path.\r
+\r
+  FV address may change across reboot. This routine promises the FV file device path is right.\r
+\r
+  @param  DevicePath   The Memory Mapped Device Path to get the file buffer.\r
+  @param  FullPath     Receive the updated FV Device Path pointint to the file.\r
+  @param  FileSize     Receive the file buffer size.\r
+\r
+  @return  The file buffer.\r
+**/\r
+VOID *\r
+BmGetFileBufferByMemmapFv (\r
+  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL     **FullPath,\r
+  OUT UINTN                        *FileSize\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Index;\r
+  EFI_DEVICE_PATH_PROTOCOL      *FvFileNode;\r
+  EFI_HANDLE                    FvHandle;\r
+  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;\r
+  UINT32                        AuthenticationStatus;\r
+  UINTN                         FvHandleCount;\r
+  EFI_HANDLE                    *FvHandles;\r
+  EFI_DEVICE_PATH_PROTOCOL      *NewDevicePath;\r
+  VOID                          *FileBuffer;\r
+  \r
+  FvFileNode = DevicePath;\r
+  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &FvFileNode, &FvHandle);\r
+  if (!EFI_ERROR (Status)) {\r
+    FileBuffer = GetFileBufferByFilePath (TRUE, DevicePath, FileSize, &AuthenticationStatus);\r
+    if (FileBuffer != NULL) {\r
+      *FullPath = DuplicateDevicePath (DevicePath);\r
+    }\r
+    return FileBuffer;\r
+  }\r
+\r
+  FvFileNode = NextDevicePathNode (DevicePath);\r
+\r
+  //\r
+  // Firstly find the FV file in current FV\r
+  //\r
+  gBS->HandleProtocol (\r
+         gImageHandle,\r
+         &gEfiLoadedImageProtocolGuid,\r
+         (VOID **) &LoadedImage\r
+         );\r
+  NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (LoadedImage->DeviceHandle), FvFileNode);\r
+  FileBuffer = BmGetFileBufferByMemmapFv (NewDevicePath, FullPath, FileSize);\r
+  FreePool (NewDevicePath);\r
+\r
+  if (FileBuffer != NULL) {\r
+    return FileBuffer;\r
+  }\r
+\r
+  //\r
+  // Secondly find the FV file in all other FVs\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+         ByProtocol,\r
+         &gEfiFirmwareVolume2ProtocolGuid,\r
+         NULL,\r
+         &FvHandleCount,\r
+         &FvHandles\r
+         );\r
+  for (Index = 0; (Index < FvHandleCount) && (FileBuffer == NULL); Index++) {\r
+    if (FvHandles[Index] == LoadedImage->DeviceHandle) {\r
+      //\r
+      // Skip current FV\r
+      //\r
+      continue;\r
+    }\r
+    NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (FvHandles[Index]), FvFileNode);\r
+    FileBuffer = BmGetFileBufferByMemmapFv (NewDevicePath, FullPath, FileSize);\r
+    FreePool (NewDevicePath);\r
+  }\r
+  \r
+  if (FvHandles != NULL) {\r
+    FreePool (FvHandles);\r
+  }\r
+  return FileBuffer;\r
+}\r
+\r
+/**\r
+  Check if it's a Memory Mapped FV Device Path.\r
+  \r
+  The function doesn't garentee the device path points to existing FV file.\r
+\r
+  @param  DevicePath     Input device path.\r
+\r
+  @retval TRUE   The device path is a Memory Mapped FV Device Path.\r
+  @retval FALSE  The device path is NOT a Memory Mapped FV Device Path.\r
+**/\r
+BOOLEAN\r
+BmIsMemmapFvFilePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL   *FileNode;\r
+\r
+  if ((DevicePathType (DevicePath) == HARDWARE_DEVICE_PATH) && (DevicePathSubType (DevicePath) == HW_MEMMAP_DP)) {\r
+    FileNode = NextDevicePathNode (DevicePath);\r
+    if ((DevicePathType (FileNode) == MEDIA_DEVICE_PATH) && (DevicePathSubType (FileNode) == MEDIA_PIWG_FW_FILE_DP)) {\r
+      return IsDevicePathEnd (NextDevicePathNode (FileNode));\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Check whether a USB device match the specified USB Class device path. This\r
+  function follows "Load Option Processing" behavior in UEFI specification.\r
+\r
+  @param UsbIo       USB I/O protocol associated with the USB device.\r
+  @param UsbClass    The USB Class device path to match.\r
+\r
+  @retval TRUE       The USB device match the USB Class device path.\r
+  @retval FALSE      The USB device does not match the USB Class device path.\r
+\r
+**/\r
+BOOLEAN\r
+BmMatchUsbClass (\r
+  IN EFI_USB_IO_PROTOCOL        *UsbIo,\r
+  IN USB_CLASS_DEVICE_PATH      *UsbClass\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_USB_DEVICE_DESCRIPTOR     DevDesc;\r
+  EFI_USB_INTERFACE_DESCRIPTOR  IfDesc;\r
+  UINT8                         DeviceClass;\r
+  UINT8                         DeviceSubClass;\r
+  UINT8                         DeviceProtocol;\r
+\r
+  if ((DevicePathType (UsbClass) != MESSAGING_DEVICE_PATH) ||\r
+      (DevicePathSubType (UsbClass) != MSG_USB_CLASS_DP)){\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check Vendor Id and Product Id.\r
+  //\r
+  Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((UsbClass->VendorId != 0xffff) &&\r
+      (UsbClass->VendorId != DevDesc.IdVendor)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((UsbClass->ProductId != 0xffff) &&\r
+      (UsbClass->ProductId != DevDesc.IdProduct)) {\r
+    return FALSE;\r
+  }\r
+\r
+  DeviceClass    = DevDesc.DeviceClass;\r
+  DeviceSubClass = DevDesc.DeviceSubClass;\r
+  DeviceProtocol = DevDesc.DeviceProtocol;\r
+  if (DeviceClass == 0) {\r
+    //\r
+    // If Class in Device Descriptor is set to 0, use the Class, SubClass and\r
+    // Protocol in Interface Descriptor instead.\r
+    //\r
+    Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);\r
+    if (EFI_ERROR (Status)) {\r
+      return FALSE;\r
+    }\r
+\r
+    DeviceClass    = IfDesc.InterfaceClass;\r
+    DeviceSubClass = IfDesc.InterfaceSubClass;\r
+    DeviceProtocol = IfDesc.InterfaceProtocol;\r
+  }\r
+\r
+  //\r
+  // Check Class, SubClass and Protocol.\r
+  //\r
+  if ((UsbClass->DeviceClass != 0xff) &&\r
+      (UsbClass->DeviceClass != DeviceClass)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((UsbClass->DeviceSubClass != 0xff) &&\r
+      (UsbClass->DeviceSubClass != DeviceSubClass)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((UsbClass->DeviceProtocol != 0xff) &&\r
+      (UsbClass->DeviceProtocol != DeviceProtocol)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Eliminate the extra spaces in the Str to one space.\r
+\r
+  @param    Str     Input string info.\r
+**/\r
+VOID\r
+BmEliminateExtraSpaces (\r
+  IN CHAR16                    *Str\r
+  )\r
+{\r
+  UINTN                        Index;\r
+  UINTN                        ActualIndex;\r
+\r
+  for (Index = 0, ActualIndex = 0; Str[Index] != L'\0'; Index++) {\r
+    if ((Str[Index] != L' ') || ((ActualIndex > 0) && (Str[ActualIndex - 1] != L' '))) {\r
+      Str[ActualIndex++] = Str[Index];\r
+    }\r
+  }\r
+  Str[ActualIndex] = L'\0';\r
+}\r
+\r
+/**\r
+  Try to get the controller's ATA/ATAPI description.\r
+\r
+  @param Handle                Controller handle.\r
+\r
+  @return  The description string.\r
+**/\r
+CHAR16 *\r
+BmGetDescriptionFromDiskInfo (\r
+  IN EFI_HANDLE                Handle\r
+  )\r
+{\r
+  UINTN                        Index;\r
+  EFI_STATUS                   Status;\r
+  EFI_DISK_INFO_PROTOCOL       *DiskInfo;\r
+  UINT32                       BufferSize;\r
+  EFI_ATAPI_IDENTIFY_DATA      IdentifyData;\r
+  EFI_SCSI_INQUIRY_DATA        InquiryData;\r
+  CHAR16                       *Description;\r
+  UINTN                        Length;\r
+  CONST UINTN                  ModelNameLength    = 40;\r
+  CONST UINTN                  SerialNumberLength = 20;\r
+  CHAR8                        *StrPtr;\r
+  UINT8                        Temp;\r
+\r
+  Description  = NULL;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiDiskInfoProtocolGuid,\r
+                  (VOID **) &DiskInfo\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoAhciInterfaceGuid) || \r
+      CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) {\r
+    BufferSize   = sizeof (EFI_ATAPI_IDENTIFY_DATA);\r
+    Status = DiskInfo->Identify (\r
+                         DiskInfo,\r
+                         &IdentifyData,\r
+                         &BufferSize\r
+                         );\r
+    if (!EFI_ERROR (Status)) {\r
+      Description = AllocateZeroPool ((ModelNameLength + SerialNumberLength + 2) * sizeof (CHAR16));\r
+      ASSERT (Description != NULL);\r
+      for (Index = 0; Index + 1 < ModelNameLength; Index += 2) {\r
+        Description[Index]     = (CHAR16) IdentifyData.ModelName[Index + 1];\r
+        Description[Index + 1] = (CHAR16) IdentifyData.ModelName[Index];\r
+      }\r
+\r
+      Length = Index;\r
+      Description[Length++] = L' ';\r
+\r
+      for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) {\r
+        Description[Length + Index]     = (CHAR16) IdentifyData.SerialNo[Index + 1];\r
+        Description[Length + Index + 1] = (CHAR16) IdentifyData.SerialNo[Index];\r
+      }\r
+      Length += Index;\r
+      Description[Length++] = L'\0';\r
+      ASSERT (Length == ModelNameLength + SerialNumberLength + 2);\r
+\r
+      BmEliminateExtraSpaces (Description);\r
+    }\r
+  } else if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoScsiInterfaceGuid)) {\r
+    BufferSize   = sizeof (EFI_SCSI_INQUIRY_DATA);\r
+    Status = DiskInfo->Inquiry (\r
+                         DiskInfo,\r
+                         &InquiryData,\r
+                         &BufferSize\r
+                         );\r
+    if (!EFI_ERROR (Status)) {\r
+      Description = AllocateZeroPool ((VENDOR_IDENTIFICATION_LENGTH + PRODUCT_IDENTIFICATION_LENGTH + 2) * sizeof (CHAR16));\r
+      ASSERT (Description != NULL);\r
+\r
+      //\r
+      // Per SCSI spec, EFI_SCSI_INQUIRY_DATA.Reserved_5_95[3 - 10] save the Verdor identification\r
+      // EFI_SCSI_INQUIRY_DATA.Reserved_5_95[11 - 26] save the product identification, \r
+      // Here combine the vendor identification and product identification to the description.\r
+      //\r
+      StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[VENDOR_IDENTIFICATION_OFFSET]);\r
+      Temp = StrPtr[VENDOR_IDENTIFICATION_LENGTH];\r
+      StrPtr[VENDOR_IDENTIFICATION_LENGTH] = '\0';\r
+      AsciiStrToUnicodeStr (StrPtr, Description);\r
+      StrPtr[VENDOR_IDENTIFICATION_LENGTH] = Temp;\r
+\r
+      //\r
+      // Add one space at the middle of vendor information and product information.\r
+      //\r
+      Description[VENDOR_IDENTIFICATION_LENGTH] = L' ';\r
+\r
+      StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[PRODUCT_IDENTIFICATION_OFFSET]);\r
+      StrPtr[PRODUCT_IDENTIFICATION_LENGTH] = '\0';\r
+      AsciiStrToUnicodeStr (StrPtr, Description + VENDOR_IDENTIFICATION_LENGTH + 1);\r
+\r
+      BmEliminateExtraSpaces (Description);\r
+    }\r
+  }\r
+\r
+  return Description;\r
+}\r
+\r
+/**\r
+  Try to get the controller's USB description.\r
+\r
+  @param Handle                Controller handle.\r
+\r
+  @return  The description string.\r
+**/\r
+CHAR16 *\r
+BmGetUsbDescription (\r
+  IN EFI_HANDLE                Handle\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_USB_IO_PROTOCOL          *UsbIo;\r
+  CHAR16                       NullChar;\r
+  CHAR16                       *Manufacturer;\r
+  CHAR16                       *Product;\r
+  CHAR16                       *SerialNumber;\r
+  CHAR16                       *Description;\r
+  EFI_USB_DEVICE_DESCRIPTOR    DevDesc;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiUsbIoProtocolGuid,\r
+                  (VOID **) &UsbIo\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  NullChar = L'\0';\r
+\r
+  Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  Status = UsbIo->UsbGetStringDescriptor (\r
+                    UsbIo,\r
+                    mBmUsbLangId,\r
+                    DevDesc.StrManufacturer,\r
+                    &Manufacturer\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    Manufacturer = &NullChar;\r
+  }\r
+  \r
+  Status = UsbIo->UsbGetStringDescriptor (\r
+                    UsbIo,\r
+                    mBmUsbLangId,\r
+                    DevDesc.StrProduct,\r
+                    &Product\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    Product = &NullChar;\r
+  }\r
+  \r
+  Status = UsbIo->UsbGetStringDescriptor (\r
+                    UsbIo,\r
+                    mBmUsbLangId,\r
+                    DevDesc.StrSerialNumber,\r
+                    &SerialNumber\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    SerialNumber = &NullChar;\r
+  }\r
+\r
+  if ((Manufacturer == &NullChar) &&\r
+      (Product == &NullChar) &&\r
+      (SerialNumber == &NullChar)\r
+      ) {\r
+    return NULL;\r
+  }\r
+\r
+  Description = AllocateZeroPool (StrSize (Manufacturer) + StrSize (Product) + StrSize (SerialNumber));\r
+  ASSERT (Description != NULL);\r
+  StrCat (Description, Manufacturer);\r
+  StrCat (Description, L" ");\r
+\r
+  StrCat (Description, Product);  \r
+  StrCat (Description, L" ");\r
+\r
+  StrCat (Description, SerialNumber);\r
+\r
+  if (Manufacturer != &NullChar) {\r
+    FreePool (Manufacturer);\r
+  }\r
+  if (Product != &NullChar) {\r
+    FreePool (Product);\r
+  }\r
+  if (SerialNumber != &NullChar) {\r
+    FreePool (SerialNumber);\r
+  }\r
+\r
+  BmEliminateExtraSpaces (Description);\r
+\r
+  return Description;\r
+}\r
+\r
+/**\r
+  Return the boot description for the controller based on the type.\r
+\r
+  @param Handle                Controller handle.\r
+\r
+  @return  The description string.\r
+**/\r
+CHAR16 *\r
+BmGetMiscDescription (\r
+  IN EFI_HANDLE                  Handle\r
+  )\r
+{\r
+  EFI_STATUS                     Status;\r
+  CHAR16                         *Description;\r
+  EFI_BLOCK_IO_PROTOCOL          *BlockIo;\r
+\r
+  switch (BmDevicePathType (DevicePathFromHandle (Handle))) {\r
+  case BmAcpiFloppyBoot:\r
+    Description = L"Floppy";\r
+    break;\r
+\r
+  case BmMessageAtapiBoot:\r
+  case BmMessageSataBoot:\r
+    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+    ASSERT_EFI_ERROR (Status);\r
+    //\r
+    // Assume a removable SATA device should be the DVD/CD device\r
+    //\r
+    Description = BlockIo->Media->RemovableMedia ? L"DVD/CDROM" : L"Hard Drive";\r
+    break;\r
+\r
+  case BmMessageUsbBoot:\r
+    Description = L"USB Device";\r
+    break;\r
+\r
+  case BmMessageScsiBoot:\r
+    Description = L"SCSI Device";\r
+    break;\r
+\r
+  case BmHardwareDeviceBoot:\r
+    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+    if (!EFI_ERROR (Status)) {\r
+      Description = BlockIo->Media->RemovableMedia ? L"Removable Disk" : L"Hard Drive";\r
+    } else {\r
+      Description = L"Misc Device";\r
+    }\r
+    break;\r
+\r
+  default:\r
+    Description = L"Misc Device";\r
+    break;\r
+  }\r
+\r
+  return AllocateCopyPool (StrSize (Description), Description);\r
+}\r
+\r
+BM_GET_BOOT_DESCRIPTION mBmGetBootDescription[] = {\r
+  BmGetUsbDescription,\r
+  BmGetDescriptionFromDiskInfo,\r
+  BmGetMiscDescription\r
+};\r
+\r
+/**\r
+  Check whether a USB device match the specified USB WWID device path. This\r
+  function follows "Load Option Processing" behavior in UEFI specification.\r
+\r
+  @param UsbIo       USB I/O protocol associated with the USB device.\r
+  @param UsbWwid     The USB WWID device path to match.\r
+\r
+  @retval TRUE       The USB device match the USB WWID device path.\r
+  @retval FALSE      The USB device does not match the USB WWID device path.\r
+\r
+**/\r
+BOOLEAN\r
+BmMatchUsbWwid (\r
+  IN EFI_USB_IO_PROTOCOL        *UsbIo,\r
+  IN USB_WWID_DEVICE_PATH       *UsbWwid\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_USB_DEVICE_DESCRIPTOR    DevDesc;\r
+  EFI_USB_INTERFACE_DESCRIPTOR IfDesc;\r
+  UINT16                       *LangIdTable;\r
+  UINT16                       TableSize;\r
+  UINT16                       Index;\r
+  CHAR16                       *CompareStr;\r
+  UINTN                        CompareLen;\r
+  CHAR16                       *SerialNumberStr;\r
+  UINTN                        Length;\r
+\r
+  if ((DevicePathType (UsbWwid) != MESSAGING_DEVICE_PATH) ||\r
+      (DevicePathSubType (UsbWwid) != MSG_USB_WWID_DP)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check Vendor Id and Product Id.\r
+  //\r
+  Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+  if ((DevDesc.IdVendor != UsbWwid->VendorId) ||\r
+      (DevDesc.IdProduct != UsbWwid->ProductId)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check Interface Number.\r
+  //\r
+  Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+  if (IfDesc.InterfaceNumber != UsbWwid->InterfaceNumber) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check Serial Number.\r
+  //\r
+  if (DevDesc.StrSerialNumber == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Get all supported languages.\r
+  //\r
+  TableSize = 0;\r
+  LangIdTable = NULL;\r
+  Status = UsbIo->UsbGetSupportedLanguages (UsbIo, &LangIdTable, &TableSize);\r
+  if (EFI_ERROR (Status) || (TableSize == 0) || (LangIdTable == NULL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.\r
+  //\r
+  CompareStr = (CHAR16 *) (UINTN) (UsbWwid + 1);\r
+  CompareLen = (DevicePathNodeLength (UsbWwid) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16);\r
+  if (CompareStr[CompareLen - 1] == L'\0') {\r
+    CompareLen--;\r
+  }\r
+\r
+  //\r
+  // Compare serial number in each supported language.\r
+  //\r
+  for (Index = 0; Index < TableSize / sizeof (UINT16); Index++) {\r
+    SerialNumberStr = NULL;\r
+    Status = UsbIo->UsbGetStringDescriptor (\r
+                      UsbIo,\r
+                      LangIdTable[Index],\r
+                      DevDesc.StrSerialNumber,\r
+                      &SerialNumberStr\r
+                      );\r
+    if (EFI_ERROR (Status) || (SerialNumberStr == NULL)) {\r
+      continue;\r
+    }\r
+\r
+    Length = StrLen (SerialNumberStr);\r
+    if ((Length >= CompareLen) &&\r
+        (CompareMem (SerialNumberStr + Length - CompareLen, CompareStr, CompareLen * sizeof (CHAR16)) == 0)) {\r
+      FreePool (SerialNumberStr);\r
+      return TRUE;\r
+    }\r
+\r
+    FreePool (SerialNumberStr);\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Find a USB device which match the specified short-form device path start with \r
+  USB Class or USB WWID device path. If ParentDevicePath is NULL, this function\r
+  will search in all USB devices of the platform. If ParentDevicePath is not NULL,\r
+  this function will only search in its child devices.\r
+\r
+  @param DevicePath           The device path that contains USB Class or USB WWID device path.\r
+  @param ParentDevicePathSize The length of the device path before the USB Class or \r
+                              USB WWID device path.\r
+  @param UsbIoHandleCount     A pointer to the count of the returned USB IO handles.\r
+\r
+  @retval NULL       The matched USB IO handles cannot be found.\r
+  @retval other      The matched USB IO handles.\r
+\r
+**/\r
+EFI_HANDLE *\r
+BmFindUsbDevice (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  IN  UINTN                     ParentDevicePathSize,\r
+  OUT UINTN                     *UsbIoHandleCount\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_HANDLE                *UsbIoHandles;\r
+  EFI_DEVICE_PATH_PROTOCOL  *UsbIoDevicePath;\r
+  EFI_USB_IO_PROTOCOL       *UsbIo;\r
+  UINTN                     Index;\r
+  UINTN                     UsbIoDevicePathSize;\r
+  BOOLEAN                   Matched;\r
+\r
+  ASSERT (UsbIoHandleCount != NULL);  \r
+\r
+  //\r
+  // Get all UsbIo Handles.\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiUsbIoProtocolGuid,\r
+                  NULL,\r
+                  UsbIoHandleCount,\r
+                  &UsbIoHandles\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    *UsbIoHandleCount = 0;\r
+    UsbIoHandles      = NULL;\r
+  }\r
+\r
+  for (Index = 0; Index < *UsbIoHandleCount; ) {\r
+    //\r
+    // Get the Usb IO interface.\r
+    //\r
+    Status = gBS->HandleProtocol(\r
+                    UsbIoHandles[Index],\r
+                    &gEfiUsbIoProtocolGuid,\r
+                    (VOID **) &UsbIo\r
+                    );\r
+    UsbIoDevicePath = DevicePathFromHandle (UsbIoHandles[Index]);\r
+    Matched         = FALSE;\r
+    if (!EFI_ERROR (Status) && (UsbIoDevicePath != NULL)) {\r
+      UsbIoDevicePathSize = GetDevicePathSize (UsbIoDevicePath) - END_DEVICE_PATH_LENGTH;\r
+\r
+      //\r
+      // Compare starting part of UsbIoHandle's device path with ParentDevicePath.\r
+      //\r
+      if (CompareMem (UsbIoDevicePath, DevicePath, ParentDevicePathSize) == 0) {\r
+        if (BmMatchUsbClass (UsbIo, (USB_CLASS_DEVICE_PATH *) ((UINTN) DevicePath + ParentDevicePathSize)) ||\r
+            BmMatchUsbWwid (UsbIo, (USB_WWID_DEVICE_PATH *) ((UINTN) DevicePath + ParentDevicePathSize))) {\r
+          Matched = TRUE;\r
+        }\r
+      }\r
+    }\r
+\r
+    if (!Matched) {\r
+      (*UsbIoHandleCount) --;\r
+      CopyMem (&UsbIoHandles[Index], &UsbIoHandles[Index + 1], (*UsbIoHandleCount - Index) * sizeof (EFI_HANDLE));\r
+    } else {\r
+      Index++;\r
+    }\r
+  }\r
+\r
+  return UsbIoHandles;\r
+}\r
+\r
+/**\r
+  Expand USB Class or USB WWID device path node to be full device path of a USB\r
+  device in platform.\r
+\r
+  This function support following 4 cases:\r
+  1) Boot Option device path starts with a USB Class or USB WWID device path,\r
+     and there is no Media FilePath device path in the end.\r
+     In this case, it will follow Removable Media Boot Behavior.\r
+  2) Boot Option device path starts with a USB Class or USB WWID device path,\r
+     and ended with Media FilePath device path.\r
+  3) Boot Option device path starts with a full device path to a USB Host Controller,\r
+     contains a USB Class or USB WWID device path node, while not ended with Media\r
+     FilePath device path. In this case, it will follow Removable Media Boot Behavior.\r
+  4) Boot Option device path starts with a full device path to a USB Host Controller,\r
+     contains a USB Class or USB WWID device path node, and ended with Media\r
+     FilePath device path.\r
+\r
+  @param FilePath      The device path pointing to a load option.\r
+                       It could be a short-form device path.\r
+  @param FullPath      Return the full device path of the load option after\r
+                       short-form device path expanding.\r
+                       Caller is responsible to free it.\r
+  @param FileSize      Return the load option size.\r
+  @param ShortformNode Pointer to the USB short-form device path node in the FilePath buffer.\r
+\r
+  @return The load option buffer. Caller is responsible to free the memory.\r
+**/\r
+VOID *\r
+BmExpandUsbDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL  **FullPath,\r
+  OUT UINTN                     *FileSize,\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *ShortformNode\r
+  )\r
+{\r
+  UINTN                             ParentDevicePathSize;\r
+  EFI_DEVICE_PATH_PROTOCOL          *RemainingDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL          *FullDevicePath;\r
+  EFI_HANDLE                        *Handles;\r
+  UINTN                             HandleCount;\r
+  UINTN                             Index;\r
+  VOID                              *FileBuffer;\r
+\r
+  ParentDevicePathSize = (UINTN) ShortformNode - (UINTN) FilePath;\r
+  RemainingDevicePath = NextDevicePathNode (ShortformNode);\r
+  FileBuffer = NULL;\r
+  Handles = BmFindUsbDevice (FilePath, ParentDevicePathSize, &HandleCount);\r
+\r
+  for (Index = 0; (Index < HandleCount) && (FileBuffer == NULL); Index++) {\r
+    FullDevicePath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), RemainingDevicePath);\r
+    FileBuffer = BmGetLoadOptionBuffer (FullDevicePath, FullPath, FileSize);\r
+    FreePool (FullDevicePath);\r
+  }\r
+\r
+  if (Handles != NULL) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  return FileBuffer;\r
+}\r
+\r
+/**\r
+  Save the partition DevicePath to the CachedDevicePath as the first instance.\r
+\r
+  @param CachedDevicePath  The device path cache.\r
+  @param DevicePath        The partition device path to be cached.\r
+**/\r
+VOID\r
+BmCachePartitionDevicePath (\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL **CachedDevicePath,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;\r
+  UINTN                           Count;\r
+  \r
+  if (BmMatchDevicePaths (*CachedDevicePath, DevicePath)) {\r
+    TempDevicePath = *CachedDevicePath;\r
+    *CachedDevicePath = BmDelPartMatchInstance (*CachedDevicePath, DevicePath);\r
+    FreePool (TempDevicePath);\r
+  }\r
+\r
+  if (*CachedDevicePath == NULL) {\r
+    *CachedDevicePath = DuplicateDevicePath (DevicePath);\r
+    return;\r
+  }\r
+\r
+  TempDevicePath = *CachedDevicePath;\r
+  *CachedDevicePath = AppendDevicePathInstance (DevicePath, *CachedDevicePath);\r
+  if (TempDevicePath != NULL) {\r
+    FreePool (TempDevicePath);\r
+  }\r
+\r
+  //\r
+  // Here limit the device path instance number to 12, which is max number for a system support 3 IDE controller\r
+  // If the user try to boot many OS in different HDs or partitions, in theory, the 'HDDP' variable maybe become larger and larger.\r
+  //\r
+  Count = 0;\r
+  TempDevicePath = *CachedDevicePath;\r
+  while (!IsDevicePathEnd (TempDevicePath)) {\r
+    TempDevicePath = NextDevicePathNode (TempDevicePath);\r
+    //\r
+    // Parse one instance\r
+    //\r
+    while (!IsDevicePathEndType (TempDevicePath)) {\r
+      TempDevicePath = NextDevicePathNode (TempDevicePath);\r
+    }\r
+    Count++;\r
+    //\r
+    // If the CachedDevicePath variable contain too much instance, only remain 12 instances.\r
+    //\r
+    if (Count == 12) {\r
+      SetDevicePathEndNode (TempDevicePath);\r
+      break;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Expand a device path that starts with a hard drive media device path node to be a\r
+  full device path that includes the full hardware path to the device. We need\r
+  to do this so it can be booted. As an optimization the front match (the part point\r
+  to the partition node. E.g. ACPI() /PCI()/ATA()/Partition() ) is saved in a variable\r
+  so a connect all is not required on every boot. All successful history device path\r
+  which point to partition node (the front part) will be saved.\r
+\r
+  @param FilePath      The device path pointing to a load option.\r
+                       It could be a short-form device path.\r
+  @param FullPath      Return the full device path of the load option after\r
+                       short-form device path expanding.\r
+                       Caller is responsible to free it.\r
+  @param FileSize      Return the load option size.\r
+\r
+  @return The load option buffer. Caller is responsible to free the memory.\r
+**/\r
+VOID *\r
+BmExpandPartitionDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL  **FullPath,\r
+  OUT UINTN                     *FileSize\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINTN                     BlockIoHandleCount;\r
+  EFI_HANDLE                *BlockIoBuffer;\r
+  VOID                      *FileBuffer;\r
+  EFI_DEVICE_PATH_PROTOCOL  *BlockIoDevicePath;\r
+  UINTN                     Index;\r
+  EFI_DEVICE_PATH_PROTOCOL  *CachedDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;\r
+  UINTN                     CachedDevicePathSize;\r
+  BOOLEAN                   NeedAdjust;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;\r
+  UINTN                     Size;\r
+\r
+  FileBuffer = NULL;\r
+  //\r
+  // Check if there is prestore 'HDDP' variable.\r
+  // If exist, search the front path which point to partition node in the variable instants.\r
+  // If fail to find or 'HDDP' not exist, reconnect all and search in all system\r
+  //\r
+  GetVariable2 (L"HDDP", &mBmHardDriveBootVariableGuid, (VOID **) &CachedDevicePath, &CachedDevicePathSize);\r
+\r
+  //\r
+  // Delete the invalid 'HDDP' variable.\r
+  //\r
+  if ((CachedDevicePath != NULL) && !IsDevicePathValid (CachedDevicePath, CachedDevicePathSize)) {\r
+    FreePool (CachedDevicePath);\r
+    CachedDevicePath = NULL;\r
+    Status = gRT->SetVariable (\r
+                    L"HDDP",\r
+                    &mBmHardDriveBootVariableGuid,\r
+                    0,\r
+                    0,\r
+                    NULL\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  if (CachedDevicePath != NULL) {\r
+    TempNewDevicePath = CachedDevicePath;\r
+    NeedAdjust = FALSE;\r
+    do {\r
+      //\r
+      // Check every instance of the variable\r
+      // First, check whether the instance contain the partition node, which is needed for distinguishing  multi\r
+      // partial partition boot option. Second, check whether the instance could be connected.\r
+      //\r
+      Instance  = GetNextDevicePathInstance (&TempNewDevicePath, &Size);\r
+      if (BmMatchPartitionDevicePathNode (Instance, (HARDDRIVE_DEVICE_PATH *) FilePath)) {\r
+        //\r
+        // Connect the device path instance, the device path point to hard drive media device path node\r
+        // e.g. ACPI() /PCI()/ATA()/Partition()\r
+        //\r
+        Status = EfiBootManagerConnectDevicePath (Instance, NULL);\r
+        if (!EFI_ERROR (Status)) {\r
+          TempDevicePath = AppendDevicePath (Instance, NextDevicePathNode (FilePath));\r
+          FileBuffer = BmGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);\r
+          FreePool (TempDevicePath);\r
+\r
+          if (FileBuffer != NULL) {\r
+            //\r
+            // Adjust the 'HDDP' instances sequence if the matched one is not first one.\r
+            //\r
+            if (NeedAdjust) {\r
+              BmCachePartitionDevicePath (&CachedDevicePath, Instance);\r
+              //\r
+              // Save the matching Device Path so we don't need to do a connect all next time\r
+              // Failing to save only impacts performance next time expanding the short-form device path\r
+              //\r
+              Status = gRT->SetVariable (\r
+                L"HDDP",\r
+                &mBmHardDriveBootVariableGuid,\r
+                EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                GetDevicePathSize (CachedDevicePath),\r
+                CachedDevicePath\r
+                );\r
+            }\r
+\r
+            FreePool (Instance);\r
+            FreePool (CachedDevicePath);\r
+            return FileBuffer;\r
+          }\r
+        }\r
+      }\r
+      //\r
+      // Come here means the first instance is not matched\r
+      //\r
+      NeedAdjust = TRUE;\r
+      FreePool(Instance);\r
+    } while (TempNewDevicePath != NULL);\r
+  }\r
+\r
+  //\r
+  // If we get here we fail to find or 'HDDP' not exist, and now we need\r
+  // to search all devices in the system for a matched partition\r
+  //\r
+  EfiBootManagerConnectAll ();\r
+  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    BlockIoHandleCount = 0;\r
+    BlockIoBuffer      = NULL;\r
+  }\r
+  //\r
+  // Loop through all the device handles that support the BLOCK_IO Protocol\r
+  //\r
+  for (Index = 0; Index < BlockIoHandleCount; Index++) {\r
+    BlockIoDevicePath = DevicePathFromHandle (BlockIoBuffer[Index]);\r
+    if (BlockIoDevicePath == NULL) {\r
+      continue;\r
+    }\r
+\r
+    if (BmMatchPartitionDevicePathNode (BlockIoDevicePath, (HARDDRIVE_DEVICE_PATH *) FilePath)) {\r
+      //\r
+      // Find the matched partition device path\r
+      //\r
+      TempDevicePath = AppendDevicePath (BlockIoDevicePath, NextDevicePathNode (FilePath));\r
+      FileBuffer = BmGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);\r
+      FreePool (TempDevicePath);\r
+\r
+      if (FileBuffer != NULL) {\r
+        BmCachePartitionDevicePath (&CachedDevicePath, BlockIoDevicePath);\r
+\r
+        //\r
+        // Save the matching Device Path so we don't need to do a connect all next time\r
+        // Failing to save only impacts performance next time expanding the short-form device path\r
+        //\r
+        Status = gRT->SetVariable (\r
+                        L"HDDP",\r
+                        &mBmHardDriveBootVariableGuid,\r
+                        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                        GetDevicePathSize (CachedDevicePath),\r
+                        CachedDevicePath\r
+                        );\r
+\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (CachedDevicePath != NULL) {\r
+    FreePool (CachedDevicePath);\r
+  }\r
+  if (BlockIoBuffer != NULL) {\r
+    FreePool (BlockIoBuffer);\r
+  }\r
+  return FileBuffer;\r
+}\r
+\r
+/**\r
+  Expand the media device path which points to a BlockIo or SimpleFileSystem instance\r
+  by appending EFI_REMOVABLE_MEDIA_FILE_NAME.\r
+\r
+  @param DevicePath  The media device path pointing to a BlockIo or SimpleFileSystem instance.\r
+  @param FullPath    Return the full device path pointing to the load option.\r
+  @param FileSize    Return the size of the load option.\r
+\r
+  @return  The load option buffer.\r
+**/\r
+VOID *\r
+BmExpandMediaDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL        *DevicePath,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL        **FullPath,\r
+  OUT UINTN                           *FileSize\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  EFI_HANDLE                          Handle;\r
+  EFI_BLOCK_IO_PROTOCOL               *BlockIo;\r
+  VOID                                *Buffer;\r
+  EFI_DEVICE_PATH_PROTOCOL            *TempDevicePath;\r
+  UINTN                               Size;\r
+  UINTN                               TempSize;\r
+  EFI_HANDLE                          *SimpleFileSystemHandles;\r
+  UINTN                               NumberSimpleFileSystemHandles;\r
+  UINTN                               Index;\r
+  VOID                                *FileBuffer;\r
+  UINT32                              AuthenticationStatus;\r
+\r
+  //\r
+  // Check whether the device is connected\r
+  //\r
+  TempDevicePath = DevicePath;\r
+  Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &TempDevicePath, &Handle);\r
+  if (!EFI_ERROR (Status)) {\r
+    ASSERT (IsDevicePathEnd (TempDevicePath));\r
+\r
+    TempDevicePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
+    FileBuffer = GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize, &AuthenticationStatus);\r
+    if (FileBuffer == NULL) {\r
+      FreePool (TempDevicePath);\r
+      TempDevicePath = NULL;\r
+    }\r
+    *FullPath = TempDevicePath;\r
+    return FileBuffer;\r
+  }\r
+\r
+  //\r
+  // For device boot option only pointing to the removable device handle, \r
+  // should make sure all its children handles (its child partion or media handles) are created and connected. \r
+  //\r
+  gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
+\r
+  //\r
+  // Issue a dummy read to the device to check for media change.\r
+  // When the removable media is changed, any Block IO read/write will\r
+  // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is\r
+  // returned. After the Block IO protocol is reinstalled, subsequent\r
+  // Block IO read/write will success.\r
+  //\r
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
+  ASSERT_EFI_ERROR (Status);\r
+  Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+  ASSERT_EFI_ERROR (Status);\r
+  Buffer = AllocatePool (BlockIo->Media->BlockSize);\r
+  if (Buffer != NULL) {\r
+    BlockIo->ReadBlocks (\r
+      BlockIo,\r
+      BlockIo->Media->MediaId,\r
+      0,\r
+      BlockIo->Media->BlockSize,\r
+      Buffer\r
+      );\r
+    FreePool (Buffer);\r
+  }\r
+\r
+  //\r
+  // Detect the the default boot file from removable Media\r
+  //\r
+  FileBuffer = NULL;\r
+  *FullPath = NULL;\r
+  Size = GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH;\r
+  gBS->LocateHandleBuffer (\r
+         ByProtocol,\r
+         &gEfiSimpleFileSystemProtocolGuid,\r
+         NULL,\r
+         &NumberSimpleFileSystemHandles,\r
+         &SimpleFileSystemHandles\r
+         );\r
+  for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {\r
+    //\r
+    // Get the device path size of SimpleFileSystem handle\r
+    //\r
+    TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);\r
+    TempSize = GetDevicePathSize (TempDevicePath) - END_DEVICE_PATH_LENGTH;\r
+    //\r
+    // Check whether the device path of boot option is part of the SimpleFileSystem handle's device path\r
+    //\r
+    if ((Size <= TempSize) && (CompareMem (TempDevicePath, DevicePath, Size) == 0)) {\r
+      TempDevicePath = FileDevicePath (SimpleFileSystemHandles[Index], EFI_REMOVABLE_MEDIA_FILE_NAME);\r
+      FileBuffer = GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize, &AuthenticationStatus);\r
+      if (FileBuffer != NULL) {\r
+        *FullPath = TempDevicePath;\r
+        break;\r
+      }\r
+      FreePool (TempDevicePath);\r
+    }\r
+  }\r
+\r
+  if (SimpleFileSystemHandles != NULL) {\r
+    FreePool (SimpleFileSystemHandles);\r
+  }\r
+\r
+  return FileBuffer;\r
+}\r
+\r
+/**\r
+  Get the load option by its device path.\r
+\r
+  @param FilePath  The device path pointing to a load option.\r
+                   It could be a short-form device path.\r
+  @param FullPath  Return the full device path of the load option after\r
+                   short-form device path expanding.\r
+                   Caller is responsible to free it.\r
+  @param FileSize  Return the load option size.\r
+\r
+  @return The load option buffer. Caller is responsible to free the memory.\r
+**/\r
+VOID *\r
+BmGetLoadOptionBuffer (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL          *FilePath,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL          **FullPath,\r
+  OUT UINTN                             *FileSize\r
+  )\r
+{\r
+  EFI_HANDLE                      Handle;\r
+  VOID                            *FileBuffer;\r
+  UINT32                          AuthenticationStatus;\r
+  EFI_DEVICE_PATH_PROTOCOL        *Node;\r
+  EFI_STATUS                      Status;\r
+\r
+  ASSERT ((FilePath != NULL) && (FullPath != NULL) && (FileSize != NULL));\r
+\r
+  EfiBootManagerConnectDevicePath (FilePath, NULL);\r
+\r
+  *FullPath  = NULL;\r
+  *FileSize  = 0;\r
+  FileBuffer = NULL;\r
+\r
+  //\r
+  // Boot from media device by adding a default file name \EFI\BOOT\BOOT{machine type short-name}.EFI\r
+  //\r
+  Node = FilePath;\r
+  Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &Node, &Handle);\r
+  if (EFI_ERROR (Status)) {\r
+    Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &Node, &Handle);\r
+  }\r
+\r
+  if (!EFI_ERROR (Status) && IsDevicePathEnd (Node)) {\r
+    return BmExpandMediaDevicePath (FilePath, FullPath, FileSize);\r
+  }\r
+\r
+  //\r
+  // Expand the short-form device path to full device path\r
+  //\r
+  if ((DevicePathType (FilePath) == MEDIA_DEVICE_PATH) &&\r
+      (DevicePathSubType (FilePath) == MEDIA_HARDDRIVE_DP)) {\r
+    //\r
+    // Expand the Harddrive device path\r
+    //\r
+    return BmExpandPartitionDevicePath (FilePath, FullPath, FileSize);\r
+  } else {\r
+    for (Node = FilePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {\r
+      if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) &&\r
+          ((DevicePathSubType (Node) == MSG_USB_CLASS_DP) || (DevicePathSubType (Node) == MSG_USB_WWID_DP))) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (!IsDevicePathEnd (Node)) {\r
+      //\r
+      // Expand the USB WWID/Class device path\r
+      //\r
+      FileBuffer = BmExpandUsbDevicePath (FilePath, FullPath, FileSize, Node);\r
+      if ((FileBuffer == NULL) && (FilePath == Node)) {\r
+        //\r
+        // Boot Option device path starts with USB Class or USB WWID device path.\r
+        // For Boot Option device path which doesn't begin with the USB Class or\r
+        // USB WWID device path, it's not needed to connect again here.\r
+        //\r
+        BmConnectUsbShortFormDevicePath (FilePath);\r
+        FileBuffer = BmExpandUsbDevicePath (FilePath, FullPath, FileSize, Node);\r
+      }\r
+      return FileBuffer;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Fix up the boot option path if it points to a FV in memory map style of device path\r
+  //\r
+  if (BmIsMemmapFvFilePath (FilePath)) {\r
+    return BmGetFileBufferByMemmapFv (FilePath, FullPath, FileSize);\r
+  }\r
+\r
+  //\r
+  // Directly reads the load option when it doesn't reside in simple file system instance (LoadFile/LoadFile2),\r
+  //   or it directly points to a file in simple file system instance.\r
+  //\r
+  FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, &AuthenticationStatus);\r
+  if (FileBuffer != NULL) {\r
+    *FullPath = DuplicateDevicePath (FilePath);\r
+  }\r
+\r
+  return FileBuffer;\r
+}\r
+\r
+/**\r
+  Attempt to boot the EFI boot option. This routine sets L"BootCurent" and\r
+  also signals the EFI ready to boot event. If the device path for the option\r
+  starts with a BBS device path a legacy boot is attempted via the registered \r
+  gLegacyBoot function. Short form device paths are also supported via this \r
+  rountine. A device path starting with MEDIA_HARDDRIVE_DP, MSG_USB_WWID_DP,\r
+  MSG_USB_CLASS_DP gets expaned out to find the first device that matches.\r
+  If the BootOption Device Path fails the removable media boot algorithm \r
+  is attempted (\EFI\BOOTIA32.EFI, \EFI\BOOTX64.EFI,... only one file type \r
+  is tried per processor type)\r
+\r
+  @param  BootOption    Boot Option to try and boot.\r
+                        On return, BootOption->Status contains the boot status.\r
+                        EFI_SUCCESS     BootOption was booted\r
+                        EFI_UNSUPPORTED A BBS device path was found with no valid callback\r
+                                        registered via EfiBootManagerInitialize().\r
+                        EFI_NOT_FOUND   The BootOption was not found on the system\r
+                        !EFI_SUCCESS    BootOption failed with this error status\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerBoot (\r
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION             *BootOption\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_HANDLE                ImageHandle;\r
+  EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
+  UINT16                    Uint16;\r
+  UINTN                     OptionNumber;\r
+  UINTN                     OriginalOptionNumber;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FilePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  EFI_HANDLE                FvHandle;\r
+  VOID                      *FileBuffer;\r
+  UINTN                     FileSize;\r
+  EFI_BOOT_LOGO_PROTOCOL    *BootLogo;\r
+  EFI_EVENT                 LegacyBootEvent;\r
+\r
+  if (BootOption == NULL) {\r
+    return;\r
+  }\r
+\r
+  if (BootOption->FilePath == NULL || BootOption->OptionType != LoadOptionTypeBoot) {\r
+    BootOption->Status = EFI_INVALID_PARAMETER;\r
+    return;\r
+  }\r
+\r
+  //\r
+  // 1. Create Boot#### for a temporary boot if there is no match Boot#### (i.e. a boot by selected a EFI Shell using "Boot From File")\r
+  //\r
+  OptionNumber = BmFindBootOptionInVariable (BootOption);\r
+  if (OptionNumber == LoadOptionNumberUnassigned) {\r
+    Status = BmGetFreeOptionNumber (LoadOptionTypeBoot, &Uint16);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Save the BootOption->OptionNumber to restore later\r
+      //\r
+      OptionNumber             = Uint16;\r
+      OriginalOptionNumber     = BootOption->OptionNumber;\r
+      BootOption->OptionNumber = OptionNumber;\r
+      Status = EfiBootManagerLoadOptionToVariable (BootOption);\r
+      BootOption->OptionNumber = OriginalOptionNumber;\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "[Bds] Failed to create Boot#### for a temporary boot - %r!\n", Status));\r
+      BootOption->Status = Status;\r
+      return ;\r
+    }\r
+  }\r
+\r
+  //\r
+  // 2. Set BootCurrent\r
+  //\r
+  Uint16 = (UINT16) OptionNumber;\r
+  BmSetVariableAndReportStatusCodeOnError (\r
+    L"BootCurrent",\r
+    &gEfiGlobalVariableGuid,\r
+    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+    sizeof (UINT16),\r
+    &Uint16\r
+    );\r
+\r
+  //\r
+  // 3. Signal the EVT_SIGNAL_READY_TO_BOOT event when we are about to load and execute\r
+  //    the boot option.\r
+  //\r
+  Node   = BootOption->FilePath;\r
+  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &FvHandle);\r
+  if (!EFI_ERROR (Status) && CompareGuid (\r
+        EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) Node),\r
+        PcdGetPtr (PcdBootManagerMenuFile)\r
+        )) {\r
+    DEBUG ((EFI_D_INFO, "[Bds] Booting Boot Manager Menu.\n"));\r
+    BmStopHotkeyService (NULL, NULL);\r
+  } else {\r
+    EfiSignalEventReadyToBoot();\r
+    //\r
+    // Report Status Code to indicate ReadyToBoot was signalled\r
+    //\r
+    REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT));\r
+    //\r
+    // 4. Repair system through DriverHealth protocol\r
+    //\r
+    BmRepairAllControllers ();\r
+  }\r
+\r
+  PERF_START_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);\r
+\r
+  //\r
+  // 5. Load EFI boot option to ImageHandle\r
+  //\r
+  ImageHandle = NULL;\r
+  if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) {\r
+    Status     = EFI_NOT_FOUND;\r
+    FileBuffer = BmGetLoadOptionBuffer (BootOption->FilePath, &FilePath, &FileSize);\r
+    DEBUG_CODE (\r
+      if (FileBuffer != NULL && CompareMem (BootOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {\r
+        DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));\r
+        BmPrintDp (BootOption->FilePath);\r
+        DEBUG ((EFI_D_INFO, " -> "));\r
+        BmPrintDp (FilePath);\r
+        DEBUG ((EFI_D_INFO, "\n"));\r
+      }\r
+    );\r
+    if (BmIsLoadOptionPeHeaderValid (BootOption->OptionType, FileBuffer, FileSize)) {\r
+      REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));\r
+      Status = gBS->LoadImage (\r
+                      TRUE,\r
+                      gImageHandle,\r
+                      FilePath,\r
+                      FileBuffer,\r
+                      FileSize,\r
+                      &ImageHandle\r
+                      );\r
+    }\r
+    if (FileBuffer != NULL) {\r
+      FreePool (FileBuffer);\r
+    }\r
+    if (FilePath != NULL) {\r
+      FreePool (FilePath);\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Report Status Code to indicate that the failure to load boot option\r
+      //\r
+      REPORT_STATUS_CODE (\r
+        EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+        (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR)\r
+        );\r
+      BootOption->Status = Status;\r
+      return;\r
+    }\r
+  }\r
+\r
+  //\r
+  // 6. Adjust the different type memory page number just before booting\r
+  //    and save the updated info into the variable for next boot to use\r
+  //\r
+  if ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT) {\r
+    if (PcdGetBool (PcdResetOnMemoryTypeInformationChange)) {\r
+      BmSetMemoryTypeInformationVariable ();\r
+    }\r
+  }\r
+\r
+  DEBUG_CODE_BEGIN();\r
+    if (BootOption->Description == NULL) {\r
+      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting from unknown device path\n"));\r
+    } else {\r
+      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting %s\n", BootOption->Description));\r
+    }\r
+  DEBUG_CODE_END();\r
+\r
+  //\r
+  // Check to see if we should legacy BOOT. If yes then do the legacy boot\r
+  // Write boot to OS performance data for Legacy boot\r
+  //\r
+  if ((DevicePathType (BootOption->FilePath) == BBS_DEVICE_PATH) && (DevicePathSubType (BootOption->FilePath) == BBS_BBS_DP)) {\r
+    if (mBmLegacyBoot != NULL) {\r
+      //\r
+      // Write boot to OS performance data for legacy boot.\r
+      //\r
+      PERF_CODE (\r
+        //\r
+        // Create an event to be signalled when Legacy Boot occurs to write performance data.\r
+        //\r
+        Status = EfiCreateEventLegacyBootEx(\r
+                   TPL_NOTIFY,\r
+                   BmWriteBootToOsPerformanceData,\r
+                   NULL, \r
+                   &LegacyBootEvent\r
+                   );\r
+        ASSERT_EFI_ERROR (Status);\r
+      );\r
+\r
+      mBmLegacyBoot (BootOption);\r
+    } else {\r
+      BootOption->Status = EFI_UNSUPPORTED;\r
+    }\r
+\r
+    PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);\r
+    return;\r
+  }\r
\r
+  //\r
+  // Provide the image with its load options\r
+  //\r
+  Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  ImageInfo->LoadOptionsSize  = BootOption->OptionalDataSize;\r
+  ImageInfo->LoadOptions      = BootOption->OptionalData;\r
+\r
+  //\r
+  // Clean to NULL because the image is loaded directly from the firmwares boot manager.\r
+  //\r
+  ImageInfo->ParentHandle = NULL;\r
+\r
+  //\r
+  // Before calling the image, enable the Watchdog Timer for 5 minutes period\r
+  //\r
+  gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
+\r
+  //\r
+  // Write boot to OS performance data for UEFI boot\r
+  //\r
+  PERF_CODE (\r
+    BmWriteBootToOsPerformanceData (NULL, NULL);\r
+  );\r
+\r
+  REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderStart));\r
+\r
+  Status = gBS->StartImage (ImageHandle, &BootOption->ExitDataSize, &BootOption->ExitData);\r
+  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", Status));\r
+  BootOption->Status = Status;\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Report Status Code to indicate that boot failure\r
+    //\r
+    REPORT_STATUS_CODE (\r
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+      (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED)\r
+      );\r
+  }\r
+  PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);\r
+\r
+  //\r
+  // Clear the Watchdog Timer after the image returns\r
+  //\r
+  gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
+\r
+  //\r
+  // Set Logo status invalid after trying one boot option\r
+  //\r
+  BootLogo = NULL;\r
+  Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);\r
+  if (!EFI_ERROR (Status) && (BootLogo != NULL)) {\r
+    Status = BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  //\r
+  // Clear Boot Current\r
+  //\r
+  Status = gRT->SetVariable (\r
+                  L"BootCurrent",\r
+                  &gEfiGlobalVariableGuid,\r
+                  0,\r
+                  0,\r
+                  NULL\r
+                  );\r
+  //\r
+  // Deleting variable with current variable implementation shouldn't fail.\r
+  // When BootXXXX (e.g.: BootManagerMenu) boots BootYYYY, exiting BootYYYY causes BootCurrent deleted,\r
+  // exiting BootXXXX causes deleting BootCurrent returns EFI_NOT_FOUND.\r
+  //\r
+  ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);\r
+}\r
+\r
+/**\r
+  Check whether there is a instance in BlockIoDevicePath, which contain multi device path\r
+  instances, has the same partition node with HardDriveDevicePath device path\r
+\r
+  @param  BlockIoDevicePath      Multi device path instances which need to check\r
+  @param  HardDriveDevicePath    A device path which starts with a hard drive media\r
+                                 device path.\r
+\r
+  @retval TRUE                   There is a matched device path instance.\r
+  @retval FALSE                  There is no matched device path instance.\r
+\r
+**/\r
+BOOLEAN\r
+BmMatchPartitionDevicePathNode (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL   *BlockIoDevicePath,\r
+  IN  HARDDRIVE_DEVICE_PATH      *HardDriveDevicePath\r
+  )\r
+{\r
+  HARDDRIVE_DEVICE_PATH     *Node;\r
+\r
+  if ((BlockIoDevicePath == NULL) || (HardDriveDevicePath == NULL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // find the partition device path node\r
+  //\r
+  while (!IsDevicePathEnd (BlockIoDevicePath)) {\r
+    if ((DevicePathType (BlockIoDevicePath) == MEDIA_DEVICE_PATH) &&\r
+        (DevicePathSubType (BlockIoDevicePath) == MEDIA_HARDDRIVE_DP)\r
+        ) {\r
+      break;\r
+    }\r
+\r
+    BlockIoDevicePath = NextDevicePathNode (BlockIoDevicePath);\r
+  }\r
+\r
+  if (IsDevicePathEnd (BlockIoDevicePath)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // See if the harddrive device path in blockio matches the orig Hard Drive Node\r
+  //\r
+  Node = (HARDDRIVE_DEVICE_PATH *) BlockIoDevicePath;\r
+\r
+  //\r
+  // Match Signature and PartitionNumber.\r
+  // Unused bytes in Signature are initiaized with zeros.\r
+  //\r
+  return (BOOLEAN) (\r
+    (Node->PartitionNumber == HardDriveDevicePath->PartitionNumber) &&\r
+    (Node->MBRType == HardDriveDevicePath->MBRType) &&\r
+    (Node->SignatureType == HardDriveDevicePath->SignatureType) &&\r
+    (CompareMem (Node->Signature, HardDriveDevicePath->Signature, sizeof (Node->Signature)) == 0)\r
+    );\r
+}\r
+\r
+/**\r
+  Emuerate all possible bootable medias in the following order:\r
+  1. Removable BlockIo            - The boot option only points to the removable media\r
+                                    device, like USB key, DVD, Floppy etc.\r
+  2. Fixed BlockIo                - The boot option only points to a Fixed blockIo device,\r
+                                    like HardDisk.\r
+  3. Non-BlockIo SimpleFileSystem - The boot option points to a device supporting\r
+                                    SimpleFileSystem Protocol, but not supporting BlockIo\r
+                                    protocol.\r
+  4. LoadFile                     - The boot option points to the media supporting \r
+                                    LoadFile protocol.\r
+  Reference: UEFI Spec chapter 3.3 Boot Option Variables Default Boot Behavior\r
+\r
+  @param BootOptionCount   Return the boot option count which has been found.\r
+\r
+  @retval   Pointer to the boot option array.\r
+**/\r
+EFI_BOOT_MANAGER_LOAD_OPTION *\r
+BmEnumerateBootOptions (\r
+  UINTN                                 *BootOptionCount\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION          *BootOptions;\r
+  UINT16                                NonBlockNumber;\r
+  UINTN                                 HandleCount;\r
+  EFI_HANDLE                            *Handles;\r
+  EFI_BLOCK_IO_PROTOCOL                 *BlkIo;\r
+  UINTN                                 Removable;\r
+  UINTN                                 Index;\r
+  UINTN                                 FunctionIndex;\r
+  CHAR16                                *Temp;\r
+  CHAR16                                *DescriptionPtr;\r
+  CHAR16                                Description[30];\r
+\r
+  ASSERT (BootOptionCount != NULL);\r
+\r
+  *BootOptionCount = 0;\r
+  BootOptions      = NULL;\r
+\r
+  //\r
+  // Parse removable block io followed by fixed block io\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+         ByProtocol,\r
+         &gEfiBlockIoProtocolGuid,\r
+         NULL,\r
+         &HandleCount,\r
+         &Handles\r
+         );\r
+\r
+  for (Removable = 0; Removable < 2; Removable++) {\r
+    for (Index = 0; Index < HandleCount; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      Handles[Index],\r
+                      &gEfiBlockIoProtocolGuid,\r
+                      (VOID **) &BlkIo\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Skip the logical partitions\r
+      //\r
+      if (BlkIo->Media->LogicalPartition) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Skip the fixed block io then the removable block io\r
+      //\r
+      if (BlkIo->Media->RemovableMedia == ((Removable == 0) ? FALSE : TRUE)) {\r
+        continue;\r
+      }\r
+\r
+      DescriptionPtr = NULL;\r
+      for (FunctionIndex = 0; FunctionIndex < sizeof (mBmGetBootDescription) / sizeof (mBmGetBootDescription[0]); FunctionIndex++) {\r
+        DescriptionPtr = mBmGetBootDescription[FunctionIndex] (Handles[Index]);\r
+        if (DescriptionPtr != NULL) {\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (DescriptionPtr == NULL) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Avoid description confusion between UEFI & Legacy boot option by adding "UEFI " prefix\r
+      //\r
+      Temp = AllocatePool (StrSize (DescriptionPtr) + sizeof (mBmUefiPrefix)); \r
+      ASSERT (Temp != NULL);\r
+      StrCpy (Temp, mBmUefiPrefix);\r
+      StrCat (Temp, DescriptionPtr);\r
+      FreePool (DescriptionPtr);\r
+      DescriptionPtr = Temp;\r
+\r
+      BootOptions = ReallocatePool (\r
+                      sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),\r
+                      sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),\r
+                      BootOptions\r
+                      );\r
+      ASSERT (BootOptions != NULL);\r
+\r
+      Status = EfiBootManagerInitializeLoadOption (\r
+                 &BootOptions[(*BootOptionCount)++],\r
+                 LoadOptionNumberUnassigned,\r
+                 LoadOptionTypeBoot,\r
+                 LOAD_OPTION_ACTIVE,\r
+                 DescriptionPtr,\r
+                 DevicePathFromHandle (Handles[Index]),\r
+                 NULL,\r
+                 0\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      FreePool (DescriptionPtr);\r
+    }\r
+  }\r
+\r
+  if (HandleCount != 0) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  //\r
+  // Parse simple file system not based on block io\r
+  //\r
+  NonBlockNumber = 0;\r
+  gBS->LocateHandleBuffer (\r
+         ByProtocol,\r
+         &gEfiSimpleFileSystemProtocolGuid,\r
+         NULL,\r
+         &HandleCount,\r
+         &Handles\r
+         );\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Status = gBS->HandleProtocol (\r
+                    Handles[Index],\r
+                    &gEfiBlockIoProtocolGuid,\r
+                    (VOID **) &BlkIo\r
+                    );\r
+     if (!EFI_ERROR (Status)) {\r
+      //\r
+      //  Skip if the file system handle supports a BlkIo protocol, which we've handled in above\r
+      //\r
+      continue;\r
+    }\r
+    UnicodeSPrint (Description, sizeof (Description), NonBlockNumber > 0 ? L"%s %d" : L"%s", L"UEFI Non-Block Boot Device", NonBlockNumber);\r
+    \r
+    BootOptions = ReallocatePool (\r
+                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),\r
+                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),\r
+                    BootOptions\r
+                    );\r
+    ASSERT (BootOptions != NULL);\r
+\r
+    Status = EfiBootManagerInitializeLoadOption (\r
+               &BootOptions[(*BootOptionCount)++],\r
+               LoadOptionNumberUnassigned,\r
+               LoadOptionTypeBoot,\r
+               LOAD_OPTION_ACTIVE,\r
+               Description,\r
+               DevicePathFromHandle (Handles[Index]),\r
+               NULL,\r
+               0\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  if (HandleCount != 0) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  //\r
+  // Parse load file, assuming UEFI Network boot option\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+         ByProtocol,\r
+         &gEfiLoadFileProtocolGuid,\r
+         NULL,\r
+         &HandleCount,\r
+         &Handles\r
+         );\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+\r
+    UnicodeSPrint (Description, sizeof (Description), Index > 0 ? L"%s %d" : L"%s", L"UEFI Network", Index);\r
+\r
+    BootOptions = ReallocatePool (\r
+                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),\r
+                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),\r
+                    BootOptions\r
+                    );\r
+    ASSERT (BootOptions != NULL);\r
+\r
+    Status = EfiBootManagerInitializeLoadOption (\r
+               &BootOptions[(*BootOptionCount)++],\r
+               LoadOptionNumberUnassigned,\r
+               LoadOptionTypeBoot,\r
+               LOAD_OPTION_ACTIVE,\r
+               Description,\r
+               DevicePathFromHandle (Handles[Index]),\r
+               NULL,\r
+               0\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  if (HandleCount != 0) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  return BootOptions;\r
+}\r
+\r
+/**\r
+  The function enumerates all boot options, creates them and registers them in the BootOrder variable.\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerRefreshAllBootOption (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION  *NvBootOptions;\r
+  UINTN                         NvBootOptionCount;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions;\r
+  UINTN                         BootOptionCount;\r
+  UINTN                         Index;\r
+\r
+  //\r
+  // Optionally refresh the legacy boot option\r
+  //\r
+  if (mBmRefreshLegacyBootOption != NULL) {\r
+    mBmRefreshLegacyBootOption ();\r
+  }\r
+\r
+  BootOptions   = BmEnumerateBootOptions (&BootOptionCount);\r
+  NvBootOptions = EfiBootManagerGetLoadOptions (&NvBootOptionCount, LoadOptionTypeBoot);\r
+\r
+  //\r
+  // Mark the boot option as added by BDS by setting OptionalData to a special GUID\r
+  //\r
+  for (Index = 0; Index < BootOptionCount; Index++) {\r
+    BootOptions[Index].OptionalData     = AllocateCopyPool (sizeof (EFI_GUID), &mBmAutoCreateBootOptionGuid);\r
+    BootOptions[Index].OptionalDataSize = sizeof (EFI_GUID);\r
+  }\r
+\r
+  //\r
+  // Remove invalid EFI boot options from NV\r
+  //\r
+  for (Index = 0; Index < NvBootOptionCount; Index++) {\r
+    if (((DevicePathType (NvBootOptions[Index].FilePath) != BBS_DEVICE_PATH) || \r
+         (DevicePathSubType (NvBootOptions[Index].FilePath) != BBS_BBS_DP)\r
+        ) &&\r
+        (NvBootOptions[Index].OptionalDataSize == sizeof (EFI_GUID)) &&\r
+        CompareGuid ((EFI_GUID *) NvBootOptions[Index].OptionalData, &mBmAutoCreateBootOptionGuid)\r
+       ) {\r
+      //\r
+      // Only check those added by BDS\r
+      // so that the boot options added by end-user or OS installer won't be deleted\r
+      //\r
+      if (BmFindLoadOption (&NvBootOptions[Index], BootOptions, BootOptionCount) == (UINTN) -1) {\r
+        Status = EfiBootManagerDeleteLoadOptionVariable (NvBootOptions[Index].OptionNumber, LoadOptionTypeBoot);\r
+        //\r
+        // Deleting variable with current variable implementation shouldn't fail.\r
+        //\r
+        ASSERT_EFI_ERROR (Status);\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Add new EFI boot options to NV\r
+  //\r
+  for (Index = 0; Index < BootOptionCount; Index++) {\r
+    if (BmFindLoadOption (&BootOptions[Index], NvBootOptions, NvBootOptionCount) == (UINTN) -1) {\r
+      EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1);\r
+      //\r
+      // Try best to add the boot options so continue upon failure.\r
+      //\r
+    }\r
+  }\r
+\r
+  EfiBootManagerFreeLoadOptions (BootOptions,   BootOptionCount);\r
+  EfiBootManagerFreeLoadOptions (NvBootOptions, NvBootOptionCount);\r
+}\r
+\r
+/**\r
+  This function is called to create the boot option for the Boot Manager Menu.\r
+\r
+  The Boot Manager Menu is shown after successfully booting a boot option.\r
+  Assume the BootManagerMenuFile is in the same FV as the module links to this library.\r
+\r
+  @param  BootOption    Return the boot option of the Boot Manager Menu\r
+\r
+  @retval EFI_SUCCESS   Successfully register the Boot Manager Menu.\r
+  @retval Status        Return status of gRT->SetVariable (). BootOption still points\r
+                        to the Boot Manager Menu even the Status is not EFI_SUCCESS.\r
+**/\r
+EFI_STATUS\r
+BmRegisterBootManagerMenu (\r
+  OUT EFI_BOOT_MANAGER_LOAD_OPTION   *BootOption\r
+  )\r
+{\r
+  EFI_STATUS                         Status;\r
+  CHAR16                             *Description;\r
+  UINTN                              DescriptionLength;\r
+  EFI_DEVICE_PATH_PROTOCOL           *DevicePath;\r
+  EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;\r
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;\r
+\r
+  Status = GetSectionFromFv (\r
+             PcdGetPtr (PcdBootManagerMenuFile),\r
+             EFI_SECTION_USER_INTERFACE,\r
+             0,\r
+             (VOID **) &Description,\r
+             &DescriptionLength\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Description = NULL;\r
+  }\r
+\r
+  EfiInitializeFwVolDevicepathNode (&FileNode, PcdGetPtr (PcdBootManagerMenuFile));\r
+  Status = gBS->HandleProtocol (\r
+                  gImageHandle,\r
+                  &gEfiLoadedImageProtocolGuid,\r
+                  (VOID **) &LoadedImage\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  DevicePath = AppendDevicePathNode (\r
+                 DevicePathFromHandle (LoadedImage->DeviceHandle),\r
+                 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
+                 );\r
+  ASSERT (DevicePath != NULL);\r
+\r
+  Status = EfiBootManagerInitializeLoadOption (\r
+             BootOption,\r
+             LoadOptionNumberUnassigned,\r
+             LoadOptionTypeBoot,\r
+             LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDEN,\r
+             (Description != NULL) ? Description : L"Boot Manager Menu",\r
+             DevicePath,\r
+             NULL,\r
+             0\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+  FreePool (DevicePath);\r
+  if (Description != NULL) {\r
+    FreePool (Description);\r
+  }\r
+\r
+  DEBUG_CODE (\r
+    EFI_BOOT_MANAGER_LOAD_OPTION    *BootOptions;\r
+    UINTN                           BootOptionCount;\r
+\r
+    BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
+    ASSERT (BmFindLoadOption (BootOption, BootOptions, BootOptionCount) == -1);\r
+    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
+    );\r
+\r
+  return EfiBootManagerAddLoadOptionVariable (BootOption, 0);\r
+}\r
+\r
+/**\r
+  Return the boot option corresponding to the Boot Manager Menu.\r
+  It may automatically create one if the boot option hasn't been created yet.\r
+  \r
+  @param BootOption    Return the Boot Manager Menu.\r
+\r
+  @retval EFI_SUCCESS   The Boot Manager Menu is successfully returned.\r
+  @retval Status        Return status of gRT->SetVariable (). BootOption still points\r
+                        to the Boot Manager Menu even the Status is not EFI_SUCCESS.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerGetBootManagerMenu (\r
+  EFI_BOOT_MANAGER_LOAD_OPTION *BootOption\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  UINTN                        BootOptionCount;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
+  UINTN                        Index;\r
+  EFI_DEVICE_PATH_PROTOCOL     *Node;\r
+  EFI_HANDLE                   FvHandle;\r
+  \r
+  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
+\r
+  for (Index = 0; Index < BootOptionCount; Index++) {\r
+    Node   = BootOptions[Index].FilePath;\r
+    Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &FvHandle);\r
+    if (!EFI_ERROR (Status)) {\r
+      if (CompareGuid (\r
+            EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) Node),\r
+            PcdGetPtr (PcdBootManagerMenuFile)\r
+            )\r
+          ) {        \r
+        Status = EfiBootManagerInitializeLoadOption (\r
+                   BootOption,\r
+                   BootOptions[Index].OptionNumber,\r
+                   BootOptions[Index].OptionType,\r
+                   BootOptions[Index].Attributes,\r
+                   BootOptions[Index].Description,\r
+                   BootOptions[Index].FilePath,\r
+                   BootOptions[Index].OptionalData,\r
+                   BootOptions[Index].OptionalDataSize\r
+                   );\r
+        ASSERT_EFI_ERROR (Status);\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
+\r
+  //\r
+  // Automatically create the Boot#### for Boot Manager Menu when not found.\r
+  //\r
+  if (Index == BootOptionCount) {\r
+    return BmRegisterBootManagerMenu (BootOption);\r
+  } else {\r
+    return EFI_SUCCESS;\r
+  }\r
+}\r
+\r
index 9e3a683..b1c94ad 100644 (file)
-/** @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.
-  @retval EFI_SECURITY_VIOLATION The user has no permission to start UEFI device 
-                                 drivers on the DevicePath.
-**/
-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.
-        //
-        // If ConnectController fails to find a driver, 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
-        //
-        Status = gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
-        if (Status == EFI_NOT_FOUND) {
-          Status = EFI_SUCCESS;
-        }
-        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;
-}
+/** @file\r
+  Library functions which relate with connecting the device.\r
+\r
+Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBm.h"\r
+\r
+/**\r
+  Connect all the drivers to all the controllers.\r
+\r
+  This function makes sure all the current system drivers manage the correspoinding\r
+  controllers if have. And at the same time, makes sure all the system controllers\r
+  have driver to manage it if have.\r
+**/\r
+VOID\r
+BmConnectAllDriversToAllControllers (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       HandleCount;\r
+  EFI_HANDLE  *HandleBuffer;\r
+  UINTN       Index;\r
+\r
+  do {\r
+    //\r
+    // Connect All EFI 1.10 drivers following EFI 1.10 algorithm\r
+    //\r
+    gBS->LocateHandleBuffer (\r
+           AllHandles,\r
+           NULL,\r
+           NULL,\r
+           &HandleCount,\r
+           &HandleBuffer\r
+           );\r
+\r
+    for (Index = 0; Index < HandleCount; Index++) {\r
+      gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
+    }\r
+\r
+    if (HandleBuffer != NULL) {\r
+      FreePool (HandleBuffer);\r
+    }\r
+\r
+    //\r
+    // Check to see if it's possible to dispatch an more DXE drivers.\r
+    // The above code may have made new DXE drivers show up.\r
+    // If any new driver is dispatched (Status == EFI_SUCCESS) and we will try\r
+    // the connect again.\r
+    //\r
+    Status = gDS->Dispatch ();\r
+\r
+  } while (!EFI_ERROR (Status));\r
+}\r
+\r
+/**\r
+  This function will connect all the system driver to controller\r
+  first, and then special connect the default console, this make\r
+  sure all the system controller available and the platform default\r
+  console connected.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerConnectAll (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Connect the platform console first\r
+  //\r
+  EfiBootManagerConnectAllDefaultConsoles ();\r
+\r
+  //\r
+  // Generic way to connect all the drivers\r
+  //\r
+  BmConnectAllDriversToAllControllers ();\r
+\r
+  //\r
+  // Here we have the assumption that we have already had\r
+  // platform default console\r
+  //\r
+  EfiBootManagerConnectAllDefaultConsoles ();\r
+}\r
+\r
+/**\r
+  This function will create all handles associate with every device\r
+  path node. If the handle associate with one device path node can not\r
+  be created successfully, then still give chance to do the dispatch,\r
+  which load the missing drivers if possible.\r
+\r
+  @param  DevicePathToConnect   The device path which will be connected, it can be\r
+                                a multi-instance device path\r
+  @param  MatchingHandle        Return the controller handle closest to the DevicePathToConnect\r
+\r
+  @retval EFI_SUCCESS            All handles associate with every device path node\r
+                                 have been created.\r
+  @retval EFI_OUT_OF_RESOURCES   There is no resource to create new handles.\r
+  @retval EFI_NOT_FOUND          Create the handle associate with one device path\r
+                                 node failed.\r
+  @retval EFI_SECURITY_VIOLATION The user has no permission to start UEFI device \r
+                                 drivers on the DevicePath.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerConnectDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePathToConnect,\r
+  OUT EFI_HANDLE                *MatchingHandle          OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;\r
+  EFI_HANDLE                Handle;\r
+  EFI_HANDLE                PreviousHandle;\r
+  EFI_TPL                   CurrentTpl;\r
+\r
+  if (DevicePathToConnect == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  CurrentTpl = EfiGetCurrentTpl ();\r
+  //\r
+  // Start the real work of connect with RemainingDevicePath\r
+  //\r
+  PreviousHandle = NULL;\r
+  do {\r
+    //\r
+    // Find the handle that best matches the Device Path. If it is only a\r
+    // partial match the remaining part of the device path is returned in\r
+    // RemainingDevicePath.\r
+    //\r
+    RemainingDevicePath = DevicePathToConnect;\r
+    Status              = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);\r
+    if (!EFI_ERROR (Status)) {\r
+      if (Handle == PreviousHandle) {\r
+        //\r
+        // If no forward progress is made try invoking the Dispatcher.\r
+        // A new FV may have been added to the system an new drivers\r
+        // may now be found.\r
+        // Status == EFI_SUCCESS means a driver was dispatched\r
+        // Status == EFI_NOT_FOUND means no new drivers were dispatched\r
+        //\r
+        if (CurrentTpl == TPL_APPLICATION) {\r
+          Status = gDS->Dispatch ();\r
+        } else {\r
+          //\r
+          // Always return EFI_NOT_FOUND here\r
+          // to prevent dead loop when control handle is found but connection failded case\r
+          //\r
+          Status = EFI_NOT_FOUND;\r
+        }\r
+      }\r
+\r
+\r
+      if (!EFI_ERROR (Status)) {\r
+        PreviousHandle = Handle;\r
+        //\r
+        // Connect all drivers that apply to Handle and RemainingDevicePath,\r
+        // the Recursive flag is FALSE so only one level will be expanded.\r
+        //\r
+        // If ConnectController fails to find a driver, then still give the chance to \r
+        // do dispatch, because partial RemainingDevicePath may be in the new FV\r
+        //\r
+        // 1. If the connect fail, RemainingDevicepath and handle will not\r
+        //    change, so next time will do the dispatch, then dispatch's status\r
+        //    will take effect\r
+        // 2. If the connect success, the RemainingDevicepath and handle will\r
+        //    change, then avoid the dispatch, we have chance to continue the\r
+        //    next connection\r
+        //\r
+        Status = gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);\r
+        if (Status == EFI_NOT_FOUND) {\r
+          Status = EFI_SUCCESS;\r
+        }\r
+        if (MatchingHandle != NULL) {\r
+          *MatchingHandle = Handle;\r
+        }\r
+      }\r
+    }\r
+    //\r
+    // Loop until RemainingDevicePath is an empty device path\r
+    //\r
+  } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));\r
+\r
+  ASSERT (EFI_ERROR (Status) || IsDevicePathEnd (RemainingDevicePath));\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function will disconnect all current system handles. \r
+  \r
+  gBS->DisconnectController() is invoked for each handle exists in system handle buffer.\r
+  If handle is a bus type handle, all childrens also are disconnected recursively by\r
+  gBS->DisconnectController().\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerDisconnectAll (\r
+  VOID\r
+  )\r
+{\r
+  UINTN       HandleCount;\r
+  EFI_HANDLE  *HandleBuffer;\r
+  UINTN       Index;\r
+\r
+  //\r
+  // Disconnect all\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+         AllHandles,\r
+         NULL,\r
+         NULL,\r
+         &HandleCount,\r
+         &HandleBuffer\r
+         );\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);\r
+  }\r
+\r
+  if (HandleBuffer != NULL) {\r
+    FreePool (HandleBuffer);\r
+  }\r
+}\r
+\r
+/**\r
+  Connect the specific Usb device which match the short form device path,\r
+  and whose bus is determined by Host Controller (Uhci or Ehci).\r
+\r
+  @param  DevicePath             A short-form device path that starts with the first\r
+                                 element being a USB WWID or a USB Class device\r
+                                 path\r
+\r
+  @return EFI_INVALID_PARAMETER  DevicePath is NULL pointer.\r
+                                 DevicePath is not a USB device path.\r
+\r
+  @return EFI_SUCCESS            Success to connect USB device\r
+  @return EFI_NOT_FOUND          Fail to find handle for USB controller to connect.\r
+\r
+**/\r
+EFI_STATUS\r
+BmConnectUsbShortFormDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  EFI_HANDLE                            *Handles;\r
+  UINTN                                 HandleCount;\r
+  UINTN                                 Index;\r
+  EFI_PCI_IO_PROTOCOL                   *PciIo;\r
+  UINT8                                 Class[3];\r
+  BOOLEAN                               AtLeastOneConnected;\r
+\r
+  //\r
+  // Check the passed in parameters\r
+  //\r
+  if (DevicePath == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||\r
+      ((DevicePathSubType (DevicePath) != MSG_USB_CLASS_DP) && (DevicePathSubType (DevicePath) != MSG_USB_WWID_DP))\r
+     ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Find the usb host controller firstly, then connect with the remaining device path\r
+  //\r
+  AtLeastOneConnected = FALSE;\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  NULL,\r
+                  &HandleCount,\r
+                  &Handles\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index = 0; Index < HandleCount; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      Handles[Index],\r
+                      &gEfiPciIoProtocolGuid,\r
+                      (VOID **) &PciIo\r
+                      );\r
+      if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Check whether the Pci device is the wanted usb host controller\r
+        //\r
+        Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);\r
+        if (!EFI_ERROR (Status) &&\r
+            ((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))\r
+           ) {\r
+          Status = gBS->ConnectController (\r
+                          Handles[Index],\r
+                          NULL,\r
+                          DevicePath,\r
+                          FALSE\r
+                          );\r
+          if (!EFI_ERROR(Status)) {\r
+            AtLeastOneConnected = TRUE;\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    if (Handles != NULL) {\r
+      FreePool (Handles);\r
+    }\r
+  }\r
+\r
+  return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;\r
+}\r
index 4f5c8b0..86b4fac 100644 (file)
-/** @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.
-
-  @retval EFI_DEVICE_ERROR         All the consoles were not connected due to an error.
-  @retval EFI_SUCCESS              Success connect any one instance of the console
-                                   device path base on the variable ConVarName.
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerConnectAllDefaultConsoles (
-  VOID
-  )
-{
-  EFI_STATUS                Status;
-  BOOLEAN                   OneConnected;
-  BOOLEAN                   SystemTableUpdated;
-
-  OneConnected = FALSE;
-
-  Status = EfiBootManagerConnectConsoleVariable (ConOut);
-  if (!EFI_ERROR (Status)) {
-    OneConnected = TRUE;
-  }
-  PERF_START (NULL, "ConOutReady", "BDS", 1);
-  PERF_END   (NULL, "ConOutReady", "BDS", 0);
-
-  
-  Status = EfiBootManagerConnectConsoleVariable (ConIn);
-  if (!EFI_ERROR (Status)) {
-    OneConnected = TRUE;
-  }
-  PERF_START (NULL, "ConInReady", "BDS", 1);
-  PERF_END   (NULL, "ConInReady", "BDS", 0);
-
-  Status = EfiBootManagerConnectConsoleVariable (ErrOut);
-  if (!EFI_ERROR (Status)) {
-    OneConnected = TRUE;
-  }
-  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
-          );
-  }
-
-  return OneConnected ? EFI_SUCCESS : EFI_DEVICE_ERROR;
-}
+/** @file\r
+  Library functions which contain all the code to connect console device.\r
+\r
+Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBm.h"\r
+\r
+CHAR16       *mConVarName[] = {\r
+  L"ConIn",\r
+  L"ConOut",\r
+  L"ErrOut",\r
+  L"ConInDev",\r
+  L"ConOutDev",\r
+  L"ErrOutDev"\r
+};\r
+\r
+/**\r
+  Search out the video controller.\r
+\r
+  @return  PCI device path of the video controller.\r
+**/\r
+EFI_HANDLE\r
+BmGetVideoController (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINTN                     RootBridgeHandleCount;\r
+  EFI_HANDLE                *RootBridgeHandleBuffer;\r
+  UINTN                     HandleCount;\r
+  EFI_HANDLE                *HandleBuffer;\r
+  UINTN                     RootBridgeIndex;\r
+  UINTN                     Index;\r
+  EFI_HANDLE                VideoController;\r
+  EFI_PCI_IO_PROTOCOL       *PciIo;\r
+  PCI_TYPE00                Pci;\r
+\r
+  //\r
+  // Make all the PCI_IO protocols show up\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  NULL,\r
+                  &RootBridgeHandleCount,\r
+                  &RootBridgeHandleBuffer\r
+                  );\r
+  if (EFI_ERROR (Status) || (RootBridgeHandleCount == 0)) {\r
+    return NULL;\r
+  }\r
+\r
+  VideoController = NULL;\r
+  for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {\r
+    gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);\r
+\r
+    //\r
+    // Start to check all the pci io to find the first video controller\r
+    //\r
+    Status = gBS->LocateHandleBuffer (\r
+                    ByProtocol,\r
+                    &gEfiPciIoProtocolGuid,\r
+                    NULL,\r
+                    &HandleCount,\r
+                    &HandleBuffer\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    for (Index = 0; Index < HandleCount; Index++) {\r
+      Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo);\r
+      if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Check for all video controller\r
+        //\r
+        Status = PciIo->Pci.Read (\r
+                          PciIo,\r
+                          EfiPciIoWidthUint32,\r
+                          0,\r
+                          sizeof (Pci) / sizeof (UINT32),\r
+                          &Pci\r
+                          );\r
+        if (!EFI_ERROR (Status) && IS_PCI_VGA (&Pci)) {\r
+          // TODO: use IS_PCI_DISPLAY??\r
+          VideoController = HandleBuffer[Index];\r
+          break;\r
+        }\r
+      }\r
+    }\r
+    FreePool (HandleBuffer);\r
+\r
+    if (VideoController != NULL) {\r
+      break;\r
+    }\r
+  }\r
+  FreePool (RootBridgeHandleBuffer);\r
+  \r
+  return VideoController;\r
+}\r
+\r
+/**\r
+  Query all the children of VideoController and return the device paths of all the \r
+  children that support GraphicsOutput protocol.\r
+\r
+  @param VideoController       PCI handle of video controller.\r
+\r
+  @return  Device paths of all the children that support GraphicsOutput protocol.\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+EFIAPI\r
+EfiBootManagerGetGopDevicePath (\r
+  IN  EFI_HANDLE                       VideoController\r
+  )\r
+{\r
+  UINTN                                Index;\r
+  EFI_STATUS                           Status;\r
+  EFI_GUID                             **ProtocolBuffer;\r
+  UINTN                                ProtocolBufferCount;\r
+  UINTN                                ProtocolIndex;\r
+  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY  *OpenInfoBuffer;\r
+  UINTN                                EntryCount;\r
+  EFI_DEVICE_PATH_PROTOCOL             *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL             *Next;\r
+  EFI_DEVICE_PATH_PROTOCOL             *Previous;\r
+  EFI_DEVICE_PATH_PROTOCOL             *TempDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL             *GopPool;\r
+  EFI_DEVICE_PATH_PROTOCOL             *ReturnDevicePath;\r
+\r
+\r
+  Status = gBS->ProtocolsPerHandle (\r
+                  VideoController,\r
+                  &ProtocolBuffer,\r
+                  &ProtocolBufferCount\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  GopPool = NULL;\r
+\r
+  for (ProtocolIndex = 0; ProtocolIndex < ProtocolBufferCount; ProtocolIndex++) {\r
+    Status = gBS->OpenProtocolInformation (\r
+                    VideoController,\r
+                    ProtocolBuffer[ProtocolIndex],\r
+                    &OpenInfoBuffer,\r
+                    &EntryCount\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    for (Index = 0; Index < EntryCount; Index++) {\r
+      //\r
+      // Query all the children\r
+      //\r
+      if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
+        Status = gBS->OpenProtocol (\r
+                        OpenInfoBuffer[Index].ControllerHandle,\r
+                        &gEfiDevicePathProtocolGuid,\r
+                        (VOID **) &DevicePath,\r
+                        NULL,\r
+                        NULL,\r
+                        EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                        );\r
+        if (EFI_ERROR (Status)) {\r
+          continue;\r
+        }\r
+\r
+        Previous = NULL;\r
+        for (Next = DevicePath; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {\r
+          Previous = Next;\r
+        }\r
+        ASSERT (Previous != NULL);\r
+\r
+        if (DevicePathType (Previous) == ACPI_DEVICE_PATH && DevicePathSubType (Previous) == ACPI_ADR_DP) {\r
+          Status = gBS->OpenProtocol (\r
+                          OpenInfoBuffer[Index].ControllerHandle,\r
+                          &gEfiGraphicsOutputProtocolGuid,\r
+                          NULL,\r
+                          NULL,\r
+                          NULL,\r
+                          EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                          );\r
+          if (!EFI_ERROR (Status)) {\r
+            //\r
+            // Append the device path to GOP pool when there is GOP protocol installed.\r
+            //\r
+            TempDevicePath = GopPool;\r
+            GopPool = AppendDevicePathInstance (GopPool, DevicePath);\r
+            gBS->FreePool (TempDevicePath);\r
+          }\r
+        }\r
+\r
+        if (DevicePathType (Previous) == HARDWARE_DEVICE_PATH && DevicePathSubType (Previous) == HW_CONTROLLER_DP) {\r
+          //\r
+          // Recursively look for GOP child in this frame buffer handle\r
+          //\r
+          DEBUG ((EFI_D_INFO, "[Bds] Looking for GOP child deeper ... \n"));\r
+          TempDevicePath = GopPool;\r
+          ReturnDevicePath = EfiBootManagerGetGopDevicePath (OpenInfoBuffer[Index].ControllerHandle);\r
+          GopPool = AppendDevicePathInstance (GopPool, ReturnDevicePath);\r
+          gBS->FreePool (ReturnDevicePath);\r
+          gBS->FreePool (TempDevicePath);\r
+        }\r
+      }\r
+    }\r
+\r
+    FreePool (OpenInfoBuffer);\r
+  }\r
+\r
+  FreePool (ProtocolBuffer);\r
+\r
+  return GopPool;\r
+}\r
+\r
+/**\r
+  Connect the platform active active video controller.\r
+\r
+  @param VideoController       PCI handle of video controller.\r
+\r
+  @retval EFI_NOT_FOUND There is no active video controller.\r
+  @retval EFI_SUCCESS   The video controller is connected.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerConnectVideoController (\r
+  EFI_HANDLE                 VideoController  OPTIONAL\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL   *Gop;\r
+  \r
+  if (VideoController == NULL) {\r
+    //\r
+    // Get the platform vga device\r
+    //\r
+    VideoController = BmGetVideoController ();\r
+  }\r
\r
+  if (VideoController == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Try to connect the PCI device path, so that GOP dirver could start on this \r
+  // device and create child handles with GraphicsOutput Protocol installed\r
+  // on them, then we get device paths of these child handles and select \r
+  // them as possible console device.\r
+  //\r
+  gBS->ConnectController (VideoController, NULL, NULL, FALSE);\r
+\r
+  Gop = EfiBootManagerGetGopDevicePath (VideoController);\r
+  if (Gop == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  EfiBootManagerUpdateConsoleVariable (ConOut, Gop, NULL);\r
+  FreePool (Gop);\r
+\r
+  //\r
+  // Necessary for ConPlatform and ConSplitter driver to start up again after ConOut is updated.\r
+  //\r
+  return gBS->ConnectController (VideoController, NULL, NULL, TRUE);\r
+}\r
+\r
+/**\r
+  Fill console handle in System Table if there are no valid console handle in.\r
+\r
+  Firstly, check the validation of console handle in System Table. If it is invalid,\r
+  update it by the first console device handle from EFI console variable. \r
+\r
+  @param  VarName            The name of the EFI console variable.\r
+  @param  ConsoleGuid        Specified Console protocol GUID.\r
+  @param  ConsoleHandle      On IN,  console handle in System Table to be checked. \r
+                             On OUT, new console handle in system table.\r
+  @param  ProtocolInterface  On IN,  console protocol on console handle in System Table to be checked. \r
+                             On OUT, new console protocol on new console handle in system table.\r
+\r
+  @retval TRUE               System Table has been updated.\r
+  @retval FALSE              System Table hasn't been updated.\r
+\r
+**/\r
+BOOLEAN \r
+BmUpdateSystemTableConsole (\r
+  IN     CHAR16                   *VarName,\r
+  IN     EFI_GUID                 *ConsoleGuid,\r
+  IN OUT EFI_HANDLE               *ConsoleHandle,\r
+  IN OUT VOID                     **ProtocolInterface\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  UINTN                           DevicePathSize;\r
+  EFI_DEVICE_PATH_PROTOCOL        *FullDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL        *VarConsole;\r
+  EFI_DEVICE_PATH_PROTOCOL        *Instance;\r
+  VOID                            *Interface;\r
+  EFI_HANDLE                      NewHandle;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
+\r
+  ASSERT (VarName != NULL);\r
+  ASSERT (ConsoleHandle != NULL);\r
+  ASSERT (ConsoleGuid != NULL);\r
+  ASSERT (ProtocolInterface != NULL);\r
+\r
+  if (*ConsoleHandle != NULL) {\r
+    Status = gBS->HandleProtocol (\r
+                   *ConsoleHandle,\r
+                   ConsoleGuid,\r
+                   &Interface\r
+                   );\r
+    if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) {\r
+      //\r
+      // If ConsoleHandle is valid and console protocol on this handle also\r
+      // also matched, just return.\r
+      //\r
+      return FALSE;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Get all possible consoles device path from EFI variable\r
+  //\r
+  GetEfiGlobalVariable2 (VarName, (VOID **) &VarConsole, NULL);\r
+  if (VarConsole == NULL) {\r
+    //\r
+    // If there is no any console device, just return.\r
+    //\r
+    return FALSE;\r
+  }\r
+\r
+  FullDevicePath = VarConsole;\r
+\r
+  do {\r
+    //\r
+    // Check every instance of the console variable\r
+    //\r
+    Instance  = GetNextDevicePathInstance (&VarConsole, &DevicePathSize);\r
+    if (Instance == NULL) {\r
+      DEBUG ((EFI_D_ERROR, "[Bds] No valid console instance is found for %s!\n", VarName));\r
+      // We should not ASSERT when all the console devices are removed.\r
+      // ASSERT_EFI_ERROR (EFI_NOT_FOUND);\r
+      FreePool (FullDevicePath);\r
+      return FALSE;\r
+    }\r
+    \r
+    //\r
+    // Find console device handle by device path instance\r
+    //\r
+    Status = gBS->LocateDevicePath (\r
+                    ConsoleGuid,\r
+                    &Instance,\r
+                    &NewHandle\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Get the console protocol on this console device handle\r
+      //\r
+      Status = gBS->HandleProtocol (\r
+                      NewHandle,\r
+                      ConsoleGuid,\r
+                      &Interface\r
+                      );\r
+      if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Update new console handle in System Table.\r
+        //\r
+        *ConsoleHandle     = NewHandle;\r
+        *ProtocolInterface = Interface;\r
+        if (CompareGuid (ConsoleGuid, &gEfiSimpleTextOutProtocolGuid)) {\r
+          //\r
+          // If it is console out device, set console mode 80x25 if current mode is invalid.\r
+          //\r
+          TextOut = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *) Interface;\r
+          if (TextOut->Mode->Mode == -1) {\r
+            TextOut->SetMode (TextOut, 0);\r
+          }\r
+        }\r
+        return TRUE;\r
+      }\r
+    }\r
+\r
+  } while (Instance != NULL);\r
+\r
+  //\r
+  // No any available console devcie found.\r
+  //\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  This function updates the console variable based on ConVarName. It can\r
+  add or remove one specific console device path from the variable\r
+\r
+  @param  ConsoleType              ConIn, ConOut, ErrOut, ConInDev, ConOutDev or ErrOutDev.\r
+  @param  CustomizedConDevicePath  The console device path to be added to\r
+                                   the console variable. Cannot be multi-instance.\r
+  @param  ExclusiveDevicePath      The console device path to be removed\r
+                                   from the console variable. Cannot be multi-instance.\r
+\r
+  @retval EFI_UNSUPPORTED          The added device path is the same as a removed one.\r
+  @retval EFI_SUCCESS              Successfully added or removed the device path from the\r
+                                   console variable.\r
+  @retval others                   Return status of RT->SetVariable().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerUpdateConsoleVariable (\r
+  IN  CONSOLE_TYPE              ConsoleType,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *CustomizedConDevicePath,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *ExclusiveDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *VarConsole;\r
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;\r
+\r
+  if (ConsoleType >= sizeof (mConVarName) / sizeof (mConVarName[0])) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Notes: check the device path point, here should check\r
+  // with compare memory\r
+  //\r
+  if (CustomizedConDevicePath == ExclusiveDevicePath) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Delete the ExclusiveDevicePath from current default console\r
+  //\r
+  GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **) &VarConsole, NULL);\r
+  //\r
+  // Initialize NewDevicePath\r
+  //\r
+  NewDevicePath = VarConsole;\r
+\r
+  //\r
+  // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.\r
+  // In the end, NewDevicePath is the final device path.\r
+  //\r
+  if (ExclusiveDevicePath != NULL && VarConsole != NULL) {\r
+      NewDevicePath = BmDelPartMatchInstance (VarConsole, ExclusiveDevicePath);\r
+  }\r
+  //\r
+  // Try to append customized device path to NewDevicePath.\r
+  //\r
+  if (CustomizedConDevicePath != NULL) {\r
+    if (!BmMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {\r
+      //\r
+      // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.\r
+      //\r
+      NewDevicePath = BmDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);\r
+      //\r
+      // In the first check, the default console variable will be _ModuleEntryPoint,\r
+      // just append current customized device path\r
+      //\r
+      TempNewDevicePath = NewDevicePath;\r
+      NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);\r
+      if (TempNewDevicePath != NULL) {\r
+        FreePool(TempNewDevicePath);\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Finally, Update the variable of the default console by NewDevicePath\r
+  //\r
+  Status = gRT->SetVariable (\r
+                  mConVarName[ConsoleType],\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS\r
+                                                  | ((ConsoleType < ConInDev) ? EFI_VARIABLE_NON_VOLATILE : 0),\r
+                  GetDevicePathSize (NewDevicePath),\r
+                  NewDevicePath\r
+                  );\r
+\r
+  if (VarConsole == NewDevicePath) {\r
+    if (VarConsole != NULL) {\r
+      FreePool(VarConsole);\r
+    }\r
+  } else {\r
+    if (VarConsole != NULL) {\r
+      FreePool(VarConsole);\r
+    }\r
+    if (NewDevicePath != NULL) {\r
+      FreePool(NewDevicePath);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Connect the console device base on the variable ConsoleType.\r
+\r
+  @param  ConsoleType              ConIn, ConOut or ErrOut.\r
+\r
+  @retval EFI_NOT_FOUND            There is not any console devices connected\r
+                                   success\r
+  @retval EFI_SUCCESS              Success connect any one instance of the console\r
+                                   device path base on the variable ConVarName.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerConnectConsoleVariable (\r
+  IN  CONSOLE_TYPE              ConsoleType\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *StartDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Next;\r
+  EFI_DEVICE_PATH_PROTOCOL  *CopyOfDevicePath;\r
+  UINTN                     Size;\r
+  BOOLEAN                   DeviceExist;\r
+  EFI_HANDLE                Handle;\r
+\r
+  if ((ConsoleType != ConIn) && (ConsoleType != ConOut) && (ConsoleType != ErrOut)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status      = EFI_SUCCESS;\r
+  DeviceExist = FALSE;\r
+  Handle      = NULL;\r
+\r
+  //\r
+  // Check if the console variable exist\r
+  //\r
+  GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **) &StartDevicePath, NULL);\r
+  if (StartDevicePath == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  CopyOfDevicePath = StartDevicePath;\r
+  do {\r
+    //\r
+    // Check every instance of the console variable\r
+    //\r
+    Instance  = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);\r
+    if (Instance == NULL) {\r
+      FreePool (StartDevicePath);\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+    \r
+    Next      = Instance;\r
+    while (!IsDevicePathEndType (Next)) {\r
+      Next = NextDevicePathNode (Next);\r
+    }\r
+\r
+    SetDevicePathEndNode (Next);\r
+    //\r
+    // Connect the USB console\r
+    // USB console device path is a short-form device path that \r
+    //  starts with the first element being a USB WWID\r
+    //  or a USB Class device path\r
+    //\r
+    if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&\r
+        ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) || (DevicePathSubType (Instance) == MSG_USB_WWID_DP))\r
+       ) {\r
+      Status = BmConnectUsbShortFormDevicePath (Instance);\r
+      if (!EFI_ERROR (Status)) {\r
+        DeviceExist = TRUE;\r
+      }\r
+    } else {\r
+      for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {\r
+        if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) {\r
+          break;\r
+        } else if (DevicePathType (Next) == HARDWARE_DEVICE_PATH && \r
+                   DevicePathSubType (Next) == HW_CONTROLLER_DP &&\r
+                   DevicePathType (NextDevicePathNode (Next)) == ACPI_DEVICE_PATH &&\r
+                   DevicePathSubType (NextDevicePathNode (Next)) == ACPI_ADR_DP\r
+                   ) {\r
+          break;\r
+        }\r
+      }\r
+      if (!IsDevicePathEnd (Next)) {\r
+        //\r
+        // For GOP device path, start the video driver with NULL remaining device path\r
+        //\r
+        SetDevicePathEndNode (Next);\r
+        Status = EfiBootManagerConnectDevicePath (Instance, &Handle);\r
+        if (!EFI_ERROR (Status)) {\r
+          gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
+        }\r
+      } else {\r
+        Status = EfiBootManagerConnectDevicePath (Instance, NULL);\r
+      }\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Delete the instance from the console varialbe\r
+        //\r
+        EfiBootManagerUpdateConsoleVariable (ConsoleType, NULL, Instance);\r
+      } else {\r
+        DeviceExist = TRUE;\r
+      }\r
+    }\r
+    FreePool(Instance);\r
+  } while (CopyOfDevicePath != NULL);\r
+\r
+  FreePool (StartDevicePath);\r
+\r
+  if (!DeviceExist) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function will search every input/output device in current system,\r
+  and make every input/output device as potential console device.\r
+**/\r
+VOID\r
+EFIAPI\r
+EfiBootManagerConnectAllConsoles (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                     Index;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ConDevicePath;\r
+  UINTN                     HandleCount;\r
+  EFI_HANDLE                *HandleBuffer;\r
+\r
+  Index         = 0;\r
+  HandleCount   = 0;\r
+  HandleBuffer  = NULL;\r
+  ConDevicePath = NULL;\r
+\r
+  //\r
+  // Update all the console variables\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+          ByProtocol,\r
+          &gEfiSimpleTextInProtocolGuid,\r
+          NULL,\r
+          &HandleCount,\r
+          &HandleBuffer\r
+          );\r
+\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    gBS->HandleProtocol (\r
+            HandleBuffer[Index],\r
+            &gEfiDevicePathProtocolGuid,\r
+            (VOID **) &ConDevicePath\r
+            );\r
+    EfiBootManagerUpdateConsoleVariable (ConIn, ConDevicePath, NULL);\r
+  }\r
+\r
+  if (HandleBuffer != NULL) {\r
+    FreePool(HandleBuffer);\r
+    HandleBuffer = NULL;\r
+  }\r
+\r
+  gBS->LocateHandleBuffer (\r
+          ByProtocol,\r
+          &gEfiSimpleTextOutProtocolGuid,\r
+          NULL,\r
+          &HandleCount,\r
+          &HandleBuffer\r
+          );\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    gBS->HandleProtocol (\r
+            HandleBuffer[Index],\r
+            &gEfiDevicePathProtocolGuid,\r
+            (VOID **) &ConDevicePath\r
+            );\r
+    EfiBootManagerUpdateConsoleVariable (ConOut, ConDevicePath, NULL);\r
+    EfiBootManagerUpdateConsoleVariable (ErrOut, ConDevicePath, NULL);\r
+  }\r
+\r
+  if (HandleBuffer != NULL) {\r
+    FreePool(HandleBuffer);\r
+  }\r
+\r
+  //\r
+  // Connect all console variables\r
+  //\r
+  EfiBootManagerConnectAllDefaultConsoles ();\r
+}\r
+\r
+\r
+/**\r
+  This function will connect all the console devices base on the console\r
+  device variable ConIn, ConOut and ErrOut.\r
+\r
+  @retval EFI_DEVICE_ERROR         All the consoles were not connected due to an error.\r
+  @retval EFI_SUCCESS              Success connect any one instance of the console\r
+                                   device path base on the variable ConVarName.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerConnectAllDefaultConsoles (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  BOOLEAN                   OneConnected;