diff --git a/MdeModulePkg/Include/Library/UefiBootManagerLib.h b/MdeModulePkg/Include/Library/UefiBootManagerLib.h
index 2ec80894ad..886229ed9e 100644
--- a/MdeModulePkg/Include/Library/UefiBootManagerLib.h
+++ b/MdeModulePkg/Include/Library/UefiBootManagerLib.h
@@ -1,681 +1,681 @@
-/** @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
+  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
diff --git a/MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf b/MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
index e23b4d073b..9d3633b9b6 100644
--- a/MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
+++ b/MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
@@ -1,7 +1,7 @@
 ##  @file
 #   Library used for sorting routines.
 #
-#  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved. <BR>
+#  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved. <BR>
 #
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD License
@@ -19,7 +19,7 @@
   FILE_GUID                      = 03F3331B-F12D-494f-BF37-E55A657F2497
   MODULE_TYPE                    = UEFI_DRIVER
   VERSION_STRING                 = 1.0
-  LIBRARY_CLASS                  = SortLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
+  LIBRARY_CLASS                  = SortLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
 
 #
 #  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
@@ -37,5 +37,3 @@
   BaseLib
   BaseMemoryLib
   DebugLib
-
-
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
index ede5250851..efac6d5bea 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
@@ -1,2160 +1,2160 @@
-/** @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
+  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;
+  }
+}
+
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmConnect.c b/MdeModulePkg/Library/UefiBootManagerLib/BmConnect.c
index 9e3a683e25..b1c94ad9d9 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmConnect.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmConnect.c
@@ -1,321 +1,321 @@
-/** @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
+  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;
+}
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmConsole.c b/MdeModulePkg/Library/UefiBootManagerLib/BmConsole.c
index 4f5c8b04c2..86b4fac424 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmConsole.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmConsole.c
@@ -1,764 +1,764 @@
-/** @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
+  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;
+}
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c b/MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c
index 2b5257394e..d197816fa1 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c
@@ -1,578 +1,578 @@
-/** @file
-  Library functions which relates with driver health.
-
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "InternalBm.h"
-
-GLOBAL_REMOVE_IF_UNREFERENCED
-  CHAR16 *mBmHealthStatusText[] = {
-    L"Healthy",
-    L"Repair Required",
-    L"Configuration Required",
-    L"Failed",
-    L"Reconnect Required",
-    L"Reboot Required"
-    };
-
-/**
-  Return the controller name.
-
-  @param DriverHealthHandle  The handle on which the Driver Health protocol instance is retrieved.
-  @param ControllerHandle    The handle of a controller that the driver specified by DriverBindingHandle is managing.
-                             This handle specifies the controller whose name is to be returned.
-  @param ChildHandle         The handle of the child controller to retrieve the name of. This is an
-                             optional parameter that may be NULL. It will be NULL for device drivers.
-                             It will also be NULL for bus drivers that attempt to retrieve the name
-                             of the bus controller. It will not be NULL for a bus driver that attempts
-                             to retrieve the name of a child controller.
-
-  @return A pointer to the Unicode string to return. This Unicode string is the name of the controller
-          specified by ControllerHandle and ChildHandle.
-**/
-CHAR16 *
-BmGetControllerName (
-  IN  EFI_HANDLE                   DriverHealthHandle,
-  IN  EFI_HANDLE                   ControllerHandle,
-  IN  EFI_HANDLE                   ChildHandle
-  )
-{
-  EFI_STATUS                       Status;
-  CHAR16                           *ControllerName;
-  CHAR8                            *LanguageVariable;
-  CHAR8                            *BestLanguage;
-  BOOLEAN                          Iso639Language;
-  EFI_COMPONENT_NAME_PROTOCOL      *ComponentName;
-
-  ControllerName = NULL;
-
-  //
-  // Locate Component Name (2) protocol on the driver binging handle.
-  //
-  Iso639Language = FALSE;
-  Status = gBS->HandleProtocol (
-                 DriverHealthHandle,
-                 &gEfiComponentName2ProtocolGuid,
-                 (VOID **) &ComponentName
-                 );
-  if (EFI_ERROR (Status)) {
-    Status = gBS->HandleProtocol (
-                    DriverHealthHandle,
-                    &gEfiComponentNameProtocolGuid,
-                    (VOID **) &ComponentName
-                    );
-    if (!EFI_ERROR (Status)) {
-      Iso639Language = TRUE;
-    }
-  }
-
-  if (!EFI_ERROR (Status)) {
-    LanguageVariable = GetEfiGlobalVariable (Iso639Language ? L"Lang" : L"PlatformLang");
-    BestLanguage     = GetBestLanguage(
-                         ComponentName->SupportedLanguages,
-                         Iso639Language,
-                         (LanguageVariable != NULL) ? LanguageVariable : "",
-                         Iso639Language ? "eng" : "en-US",
-                         NULL
-                         );
-    if (LanguageVariable != NULL) {
-      FreePool (LanguageVariable);
-    }
-
-    Status = ComponentName->GetControllerName (
-                              ComponentName,
-                              ControllerHandle, 
-                              ChildHandle,
-                              BestLanguage,
-                              &ControllerName
-                              );
-  }
-
-  if (!EFI_ERROR (Status)) {
-    return AllocateCopyPool (StrSize (ControllerName), ControllerName);
-  } else {
-    return ConvertDevicePathToText (
-             DevicePathFromHandle (ChildHandle != NULL ? ChildHandle : ControllerHandle),
-             FALSE,
-             FALSE
-             );
-  }
-}
-
-/**
-  Display a set of messages returned by the GetHealthStatus () service of the EFI Driver Health Protocol
-
-  @param DriverHealthInfo  Pointer to the Driver Health information entry.
-**/
-VOID
-BmDisplayMessages (
-  IN  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo
-  )
-{
-  UINTN                            Index;
-  EFI_STRING                       String;
-  CHAR16                           *ControllerName;
-
-  if (DriverHealthInfo->MessageList == NULL ||
-      DriverHealthInfo->MessageList[0].HiiHandle == NULL) {
-    return;
-  }
-
-  ControllerName = BmGetControllerName (
-                     DriverHealthInfo->DriverHealthHandle,
-                     DriverHealthInfo->ControllerHandle, 
-                     DriverHealthInfo->ChildHandle
-                     );
-
-  DEBUG ((EFI_D_INFO, "Controller: %s\n", ControllerName));
-  Print (L"Controller: %s\n", ControllerName);
-  for (Index = 0; DriverHealthInfo->MessageList[Index].HiiHandle != NULL; Index++) {
-    String = HiiGetString (
-               DriverHealthInfo->MessageList[Index].HiiHandle,
-               DriverHealthInfo->MessageList[Index].StringId,
-               NULL
-               );
-    if (String != NULL) {
-      Print (L"  %s\n", String);
-      DEBUG ((EFI_D_INFO, "  %s\n", String));
-      FreePool (String);
-    }
-  }
-
-  if (ControllerName != NULL) {
-    FreePool (ControllerName);
-  }
-}
-
-/**
-  The repair notify function.
-  @param Value  A value between 0 and Limit that identifies the current progress
-                of the repair operation.
-  @param Limit  The maximum value of Value for the current repair operation.
-                If Limit is 0, then the completion progress is indeterminate.
-                For example, a driver that wants to specify progress in percent
-                would use a Limit value of 100.
-
-  @retval EFI_SUCCESS  Successfully return from the notify function.
-**/
-EFI_STATUS
-EFIAPI
-BmRepairNotify (
-  IN UINTN        Value,
-  IN UINTN        Limit
-  )
-{
-  DEBUG ((EFI_D_INFO, "[BDS]RepairNotify: %d/%d\n", Value, Limit));
-  Print (L"[BDS]RepairNotify: %d/%d\n", Value, Limit);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Collect the Driver Health status of a single controller.
-  
-  @param DriverHealthInfo        A pointer to the array containing all of the platform driver health information.
-  @param Count                   Return the updated array count.
-  @param DriverHealthHandle      The handle on which the Driver Health protocol instance is retrieved.
-  @param ControllerHandle        The handle of the controller..
-  @param ChildHandle             The handle of the child controller to retrieve the health
-                                 status on.  This is an optional parameter that may be NULL.
-
-  @retval Status                 The status returned from GetHealthStatus.
-  @retval EFI_ABORTED            The health status is healthy so no further query is needed.
-
-**/
-EFI_STATUS
-BmGetSingleControllerHealthStatus (
-  IN OUT EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO **DriverHealthInfo,
-  IN OUT UINTN                               *Count,
-  IN  EFI_HANDLE                             DriverHealthHandle,
-  IN  EFI_HANDLE                             ControllerHandle,  OPTIONAL
-  IN  EFI_HANDLE                             ChildHandle        OPTIONAL
-  )
-{
-  EFI_STATUS                     Status;
-  EFI_DRIVER_HEALTH_PROTOCOL     *DriverHealth;
-  EFI_DRIVER_HEALTH_HII_MESSAGE  *MessageList;
-  EFI_HII_HANDLE                 FormHiiHandle;
-  EFI_DRIVER_HEALTH_STATUS       HealthStatus;
-
-  ASSERT (DriverHealthHandle != NULL);
-  //
-  // Retrieve the Driver Health Protocol from DriverHandle
-  //
-  Status = gBS->HandleProtocol (
-                  DriverHealthHandle,
-                  &gEfiDriverHealthProtocolGuid,
-                  (VOID **) &DriverHealth
-                  );
-  ASSERT_EFI_ERROR (Status);
-  
-
-  if (ControllerHandle == NULL) {
-    //
-    // If ControllerHandle is NULL, the return the cumulative health status of the driver
-    //
-    Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, &HealthStatus, NULL, NULL);
-    if (!EFI_ERROR (Status) && HealthStatus == EfiDriverHealthStatusHealthy) {
-      *DriverHealthInfo = ReallocatePool (
-                            (*Count)     * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
-                            (*Count + 1) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
-                            *DriverHealthInfo
-                            );
-      ASSERT (*DriverHealthInfo != NULL);
-
-      (*DriverHealthInfo)[*Count].DriverHealthHandle = DriverHealthHandle;
-      (*DriverHealthInfo)[*Count].DriverHealth       = DriverHealth;
-      (*DriverHealthInfo)[*Count].HealthStatus       = HealthStatus;
-
-      *Count = *Count + 1;
-
-      Status = EFI_ABORTED;
-    }
-    return Status;
-  }
-
-  MessageList   = NULL;
-  FormHiiHandle = NULL;
-
-  //
-  // Collect the health status with the optional HII message list
-  //
-  Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, &HealthStatus, &MessageList, &FormHiiHandle);
-  if (!EFI_ERROR (Status)) {
-    *DriverHealthInfo = ReallocatePool (
-                          (*Count)     * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
-                          (*Count + 1) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
-                          *DriverHealthInfo
-                          );
-    ASSERT (*DriverHealthInfo != NULL);
-    (*DriverHealthInfo)[*Count].DriverHealth       = DriverHealth;
-    (*DriverHealthInfo)[*Count].DriverHealthHandle = DriverHealthHandle;
-    (*DriverHealthInfo)[*Count].ControllerHandle   = ControllerHandle;
-    (*DriverHealthInfo)[*Count].ChildHandle        = ChildHandle;
-    (*DriverHealthInfo)[*Count].HiiHandle          = FormHiiHandle;
-    (*DriverHealthInfo)[*Count].MessageList        = MessageList;
-    (*DriverHealthInfo)[*Count].HealthStatus       = HealthStatus;
-
-    *Count = *Count + 1;
-  }
-
-  return Status;
-}
-
-/**
-  Return all the Driver Health information.
-
-  When the cumulative health status of all the controllers managed by the
-  driver who produces the EFI_DRIVER_HEALTH_PROTOCOL is healthy, only one
-  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry is created for such
-  EFI_DRIVER_HEALTH_PROTOCOL instance.
-  Otherwise, every controller creates one EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO
-  entry. Additionally every child controller creates one
-  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry if the driver is a bus driver.
-
-  @param Count      Return the count of the Driver Health information.
-
-  @retval NULL      No Driver Health information is returned.
-  @retval !NULL     Pointer to the Driver Health information array.
-**/
-EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *
-EFIAPI
-EfiBootManagerGetDriverHealthInfo (
-  UINTN                      *Count
-  )
-{
-  EFI_STATUS                 Status;
-  UINTN                      NumHandles;
-  EFI_HANDLE                 *DriverHealthHandles;
-  EFI_DRIVER_HEALTH_STATUS   HealthStatus;
-  UINTN                      DriverHealthIndex;
-  EFI_HANDLE                 *Handles;
-  UINTN                      HandleCount;
-  UINTN                      ControllerIndex;
-  UINTN                      ChildIndex;
-  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO  *DriverHealthInfo;
-
-  //
-  // Initialize local variables
-  //
-  *Count                  = 0;
-  DriverHealthInfo        = NULL;
-  Handles                 = NULL;
-  DriverHealthHandles     = NULL;
-  NumHandles              = 0;
-  HandleCount             = 0;
-
-  HealthStatus = EfiDriverHealthStatusHealthy;
-
-  Status = gBS->LocateHandleBuffer (
-                  ByProtocol,
-                  &gEfiDriverHealthProtocolGuid,
-                  NULL,
-                  &NumHandles,
-                  &DriverHealthHandles
-                  );
-
-  if (Status == EFI_NOT_FOUND || NumHandles == 0) {
-    //
-    // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
-    //
-    return NULL;
-  }
-
-  ASSERT_EFI_ERROR (Status);
-  ASSERT (DriverHealthHandles != NULL);
-
-  //
-  // Check the health status of all controllers in the platform
-  // Start by looping through all the Driver Health Protocol handles in the handle database
-  //
-  for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) {
-    //
-    // Get the cumulative health status of the driver
-    //
-    Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], NULL, NULL);
-    if (EFI_ERROR (Status)) {
-      continue;
-    }
-
-    //
-    // See if the list of all handles in the handle database has been retrieved
-    //
-    //
-    if (Handles == NULL) {
-      //
-      // Retrieve the list of all handles from the handle database
-      //
-      Status = gBS->LocateHandleBuffer (
-        AllHandles,
-        NULL,
-        NULL,
-        &HandleCount,
-        &Handles
-        );
-      ASSERT_EFI_ERROR (Status);
-    }
-    //
-    // Loop through all the controller handles in the handle database
-    //
-    for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) {
-      Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL);
-      if (EFI_ERROR (Status)) {
-        continue;
-      }
-
-      //
-      // Loop through all the child handles in the handle database
-      //
-      for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) {
-        Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex]);
-        if (EFI_ERROR (Status)) {
-          continue;
-        }
-      }
-    }
-  }
-
-  Status = EFI_SUCCESS;
-
-  if (Handles != NULL) {
-    FreePool (Handles);
-  }
-  if (DriverHealthHandles != NULL) {
-    FreePool (DriverHealthHandles);
-  }
-
-  return DriverHealthInfo;
-}
-
-/**
-  Free the Driver Health information array.
-
-  @param DriverHealthInfo       Pointer to array of the Driver Health information.
-  @param Count                  Count of the array.
-
-  @retval EFI_SUCCESS           The array is freed.
-  @retval EFI_INVALID_PARAMETER The array is NULL.
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerFreeDriverHealthInfo (
-  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo,
-  UINTN                               Count
-  )
-{
-  UINTN                               Index;
-
-  for (Index = 0; Index < Count; Index++) {
-    if (DriverHealthInfo[Index].MessageList != NULL) {
-      FreePool (DriverHealthInfo[Index].MessageList);
-    }
-  }
-  return gBS->FreePool (DriverHealthInfo);
-}
-
-/**
-  Repair all the controllers according to the Driver Health status queried.
-**/
-VOID
-BmRepairAllControllers (
-  VOID
-  )
-{
-  EFI_STATUS                          Status;
-  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo;
-  EFI_DRIVER_HEALTH_STATUS            HealthStatus;
-  UINTN                               Count;
-  UINTN                               Index;
-  BOOLEAN                             RepairRequired;
-  BOOLEAN                             ConfigurationRequired;
-  BOOLEAN                             ReconnectRequired;
-  BOOLEAN                             RebootRequired;
-  EFI_HII_HANDLE                      *HiiHandles;
-  EFI_FORM_BROWSER2_PROTOCOL          *FormBrowser2;
-
-  //
-  // Configure PcdDriverHealthConfigureForm to ZeroGuid to disable driver health check.
-  //
-  if (CompareGuid (PcdGetPtr (PcdDriverHealthConfigureForm), &gZeroGuid)) {
-    return;
-  }
-
-  Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
-  ASSERT_EFI_ERROR (Status);
-
-  do {
-    RepairRequired        = FALSE;
-    ConfigurationRequired = FALSE;
-
-    //
-    // Deal with Repair Required
-    //
-    DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
-    for (Index = 0; Index < Count; Index++) {
-      if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusConfigurationRequired) {
-        ConfigurationRequired = TRUE;
-      }
-      
-      if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusRepairRequired) {
-        RepairRequired        = TRUE;
-
-        BmDisplayMessages (&DriverHealthInfo[Index]);
-
-        Status = DriverHealthInfo[Index].DriverHealth->Repair (
-                                                         DriverHealthInfo[Index].DriverHealth,
-                                                         DriverHealthInfo[Index].ControllerHandle,
-                                                         DriverHealthInfo[Index].ChildHandle,
-                                                         BmRepairNotify
-                                                         );
-        if (!EFI_ERROR (Status) && !ConfigurationRequired) {
-          Status = DriverHealthInfo[Index].DriverHealth->GetHealthStatus (
-                                                           DriverHealthInfo[Index].DriverHealth,
-                                                           DriverHealthInfo[Index].ControllerHandle,
-                                                           DriverHealthInfo[Index].ChildHandle,
-                                                           &HealthStatus,
-                                                           NULL,
-                                                           NULL
-                                                           );
-          if (!EFI_ERROR (Status) && (HealthStatus == EfiDriverHealthStatusConfigurationRequired)) {
-            ConfigurationRequired = TRUE;
-          }
-        }
-      }
-    }
-
-    if (ConfigurationRequired) {
-      HiiHandles = HiiGetHiiHandles (NULL);
-      if (HiiHandles != NULL) {
-        for (Index = 0; HiiHandles[Index] != NULL; Index++) {
-          Status = FormBrowser2->SendForm (
-                                   FormBrowser2,
-                                   &HiiHandles[Index],
-                                   1,
-                                   PcdGetPtr (PcdDriverHealthConfigureForm),
-                                   0,
-                                   NULL,
-                                   NULL
-                                   );
-          if (!EFI_ERROR (Status)) {
-            break;
-          }
-        }
-        FreePool (HiiHandles);
-      }
-    }
-  
-    EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
-  } while (RepairRequired || ConfigurationRequired);
-
-  RebootRequired    = FALSE;
-  ReconnectRequired = FALSE;
-  DriverHealthInfo  = EfiBootManagerGetDriverHealthInfo (&Count);
-  for (Index = 0; Index < Count; Index++) {
-
-    BmDisplayMessages (&DriverHealthInfo[Index]);
-
-    if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusReconnectRequired) {
-      Status = gBS->DisconnectController (DriverHealthInfo[Index].ControllerHandle, NULL, NULL);
-      if (EFI_ERROR (Status)) {
-        //
-        // Disconnect failed. Need to promote reconnect to a reboot.
-        //
-        RebootRequired    = TRUE;
-      } else {
-        gBS->ConnectController (DriverHealthInfo[Index].ControllerHandle, NULL, NULL, TRUE);
-        ReconnectRequired = TRUE;
-      }
-    }
-
-    if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusRebootRequired) {
-      RebootRequired      = TRUE;
-    }
-  }
-  EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
-
-
-  if (ReconnectRequired) {
-    BmRepairAllControllers ();
-  }
-
-  DEBUG_CODE (
-    CHAR16 *ControllerName;
-
-    DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
-    for (Index = 0; Index < Count; Index++) {
-      ControllerName = BmGetControllerName (
-                         DriverHealthInfo[Index].DriverHealthHandle,
-                         DriverHealthInfo[Index].ControllerHandle,
-                         DriverHealthInfo[Index].ChildHandle
-                         );
-      DEBUG ((
-        EFI_D_INFO,
-        "%02d: %s - %s\n",
-        Index,
-        ControllerName,
-        mBmHealthStatusText[DriverHealthInfo[Index].HealthStatus]
-        ));
-      if (ControllerName != NULL) {
-        FreePool (ControllerName);
-      }
-    }
-    EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
-    );
-
-  if (RebootRequired) {
-    DEBUG ((EFI_D_INFO, "[BDS] One of the Driver Health instances requires rebooting.\n"));
-    gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
-  }
-}
+/** @file
+  Library functions which relates with driver health.
+
+Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "InternalBm.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+  CHAR16 *mBmHealthStatusText[] = {
+    L"Healthy",
+    L"Repair Required",
+    L"Configuration Required",
+    L"Failed",
+    L"Reconnect Required",
+    L"Reboot Required"
+    };
+
+/**
+  Return the controller name.
+
+  @param DriverHealthHandle  The handle on which the Driver Health protocol instance is retrieved.
+  @param ControllerHandle    The handle of a controller that the driver specified by DriverBindingHandle is managing.
+                             This handle specifies the controller whose name is to be returned.
+  @param ChildHandle         The handle of the child controller to retrieve the name of. This is an
+                             optional parameter that may be NULL. It will be NULL for device drivers.
+                             It will also be NULL for bus drivers that attempt to retrieve the name
+                             of the bus controller. It will not be NULL for a bus driver that attempts
+                             to retrieve the name of a child controller.
+
+  @return A pointer to the Unicode string to return. This Unicode string is the name of the controller
+          specified by ControllerHandle and ChildHandle.
+**/
+CHAR16 *
+BmGetControllerName (
+  IN  EFI_HANDLE                   DriverHealthHandle,
+  IN  EFI_HANDLE                   ControllerHandle,
+  IN  EFI_HANDLE                   ChildHandle
+  )
+{
+  EFI_STATUS                       Status;
+  CHAR16                           *ControllerName;
+  CHAR8                            *LanguageVariable;
+  CHAR8                            *BestLanguage;
+  BOOLEAN                          Iso639Language;
+  EFI_COMPONENT_NAME_PROTOCOL      *ComponentName;
+
+  ControllerName = NULL;
+
+  //
+  // Locate Component Name (2) protocol on the driver binging handle.
+  //
+  Iso639Language = FALSE;
+  Status = gBS->HandleProtocol (
+                 DriverHealthHandle,
+                 &gEfiComponentName2ProtocolGuid,
+                 (VOID **) &ComponentName
+                 );
+  if (EFI_ERROR (Status)) {
+    Status = gBS->HandleProtocol (
+                    DriverHealthHandle,
+                    &gEfiComponentNameProtocolGuid,
+                    (VOID **) &ComponentName
+                    );
+    if (!EFI_ERROR (Status)) {
+      Iso639Language = TRUE;
+    }
+  }
+
+  if (!EFI_ERROR (Status)) {
+    LanguageVariable = GetEfiGlobalVariable (Iso639Language ? L"Lang" : L"PlatformLang");
+    BestLanguage     = GetBestLanguage(
+                         ComponentName->SupportedLanguages,
+                         Iso639Language,
+                         (LanguageVariable != NULL) ? LanguageVariable : "",
+                         Iso639Language ? "eng" : "en-US",
+                         NULL
+                         );
+    if (LanguageVariable != NULL) {
+      FreePool (LanguageVariable);
+    }
+
+    Status = ComponentName->GetControllerName (
+                              ComponentName,
+                              ControllerHandle, 
+                              ChildHandle,
+                              BestLanguage,
+                              &ControllerName
+                              );
+  }
+
+  if (!EFI_ERROR (Status)) {
+    return AllocateCopyPool (StrSize (ControllerName), ControllerName);
+  } else {
+    return ConvertDevicePathToText (
+             DevicePathFromHandle (ChildHandle != NULL ? ChildHandle : ControllerHandle),
+             FALSE,
+             FALSE
+             );
+  }
+}
+
+/**
+  Display a set of messages returned by the GetHealthStatus () service of the EFI Driver Health Protocol
+
+  @param DriverHealthInfo  Pointer to the Driver Health information entry.
+**/
+VOID
+BmDisplayMessages (
+  IN  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo
+  )
+{
+  UINTN                            Index;
+  EFI_STRING                       String;
+  CHAR16                           *ControllerName;
+
+  if (DriverHealthInfo->MessageList == NULL ||
+      DriverHealthInfo->MessageList[0].HiiHandle == NULL) {
+    return;
+  }
+
+  ControllerName = BmGetControllerName (
+                     DriverHealthInfo->DriverHealthHandle,
+                     DriverHealthInfo->ControllerHandle, 
+                     DriverHealthInfo->ChildHandle
+                     );
+
+  DEBUG ((EFI_D_INFO, "Controller: %s\n", ControllerName));
+  Print (L"Controller: %s\n", ControllerName);
+  for (Index = 0; DriverHealthInfo->MessageList[Index].HiiHandle != NULL; Index++) {
+    String = HiiGetString (
+               DriverHealthInfo->MessageList[Index].HiiHandle,
+               DriverHealthInfo->MessageList[Index].StringId,
+               NULL
+               );
+    if (String != NULL) {
+      Print (L"  %s\n", String);
+      DEBUG ((EFI_D_INFO, "  %s\n", String));
+      FreePool (String);
+    }
+  }
+
+  if (ControllerName != NULL) {
+    FreePool (ControllerName);
+  }
+}
+
+/**
+  The repair notify function.
+  @param Value  A value between 0 and Limit that identifies the current progress
+                of the repair operation.
+  @param Limit  The maximum value of Value for the current repair operation.
+                If Limit is 0, then the completion progress is indeterminate.
+                For example, a driver that wants to specify progress in percent
+                would use a Limit value of 100.
+
+  @retval EFI_SUCCESS  Successfully return from the notify function.
+**/
+EFI_STATUS
+EFIAPI
+BmRepairNotify (
+  IN UINTN        Value,
+  IN UINTN        Limit
+  )
+{
+  DEBUG ((EFI_D_INFO, "[BDS]RepairNotify: %d/%d\n", Value, Limit));
+  Print (L"[BDS]RepairNotify: %d/%d\n", Value, Limit);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Collect the Driver Health status of a single controller.
+  
+  @param DriverHealthInfo        A pointer to the array containing all of the platform driver health information.
+  @param Count                   Return the updated array count.
+  @param DriverHealthHandle      The handle on which the Driver Health protocol instance is retrieved.
+  @param ControllerHandle        The handle of the controller..
+  @param ChildHandle             The handle of the child controller to retrieve the health
+                                 status on.  This is an optional parameter that may be NULL.
+
+  @retval Status                 The status returned from GetHealthStatus.
+  @retval EFI_ABORTED            The health status is healthy so no further query is needed.
+
+**/
+EFI_STATUS
+BmGetSingleControllerHealthStatus (
+  IN OUT EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO **DriverHealthInfo,
+  IN OUT UINTN                               *Count,
+  IN  EFI_HANDLE                             DriverHealthHandle,
+  IN  EFI_HANDLE                             ControllerHandle,  OPTIONAL
+  IN  EFI_HANDLE                             ChildHandle        OPTIONAL
+  )
+{
+  EFI_STATUS                     Status;
+  EFI_DRIVER_HEALTH_PROTOCOL     *DriverHealth;
+  EFI_DRIVER_HEALTH_HII_MESSAGE  *MessageList;
+  EFI_HII_HANDLE                 FormHiiHandle;
+  EFI_DRIVER_HEALTH_STATUS       HealthStatus;
+
+  ASSERT (DriverHealthHandle != NULL);
+  //
+  // Retrieve the Driver Health Protocol from DriverHandle
+  //
+  Status = gBS->HandleProtocol (
+                  DriverHealthHandle,
+                  &gEfiDriverHealthProtocolGuid,
+                  (VOID **) &DriverHealth
+                  );
+  ASSERT_EFI_ERROR (Status);
+  
+
+  if (ControllerHandle == NULL) {
+    //
+    // If ControllerHandle is NULL, the return the cumulative health status of the driver
+    //
+    Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, &HealthStatus, NULL, NULL);
+    if (!EFI_ERROR (Status) && HealthStatus == EfiDriverHealthStatusHealthy) {
+      *DriverHealthInfo = ReallocatePool (
+                            (*Count)     * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
+                            (*Count + 1) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
+                            *DriverHealthInfo
+                            );
+      ASSERT (*DriverHealthInfo != NULL);
+
+      (*DriverHealthInfo)[*Count].DriverHealthHandle = DriverHealthHandle;
+      (*DriverHealthInfo)[*Count].DriverHealth       = DriverHealth;
+      (*DriverHealthInfo)[*Count].HealthStatus       = HealthStatus;
+
+      *Count = *Count + 1;
+
+      Status = EFI_ABORTED;
+    }
+    return Status;
+  }
+
+  MessageList   = NULL;
+  FormHiiHandle = NULL;
+
+  //
+  // Collect the health status with the optional HII message list
+  //
+  Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, &HealthStatus, &MessageList, &FormHiiHandle);
+  if (!EFI_ERROR (Status)) {
+    *DriverHealthInfo = ReallocatePool (
+                          (*Count)     * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
+                          (*Count + 1) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
+                          *DriverHealthInfo
+                          );
+    ASSERT (*DriverHealthInfo != NULL);
+    (*DriverHealthInfo)[*Count].DriverHealth       = DriverHealth;
+    (*DriverHealthInfo)[*Count].DriverHealthHandle = DriverHealthHandle;
+    (*DriverHealthInfo)[*Count].ControllerHandle   = ControllerHandle;
+    (*DriverHealthInfo)[*Count].ChildHandle        = ChildHandle;
+    (*DriverHealthInfo)[*Count].HiiHandle          = FormHiiHandle;
+    (*DriverHealthInfo)[*Count].MessageList        = MessageList;
+    (*DriverHealthInfo)[*Count].HealthStatus       = HealthStatus;
+
+    *Count = *Count + 1;
+  }
+
+  return Status;
+}
+
+/**
+  Return all the Driver Health information.
+
+  When the cumulative health status of all the controllers managed by the
+  driver who produces the EFI_DRIVER_HEALTH_PROTOCOL is healthy, only one
+  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry is created for such
+  EFI_DRIVER_HEALTH_PROTOCOL instance.
+  Otherwise, every controller creates one EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO
+  entry. Additionally every child controller creates one
+  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry if the driver is a bus driver.
+
+  @param Count      Return the count of the Driver Health information.
+
+  @retval NULL      No Driver Health information is returned.
+  @retval !NULL     Pointer to the Driver Health information array.
+**/
+EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *
+EFIAPI
+EfiBootManagerGetDriverHealthInfo (
+  UINTN                      *Count
+  )
+{
+  EFI_STATUS                 Status;
+  UINTN                      NumHandles;
+  EFI_HANDLE                 *DriverHealthHandles;
+  EFI_DRIVER_HEALTH_STATUS   HealthStatus;
+  UINTN                      DriverHealthIndex;
+  EFI_HANDLE                 *Handles;
+  UINTN                      HandleCount;
+  UINTN                      ControllerIndex;
+  UINTN                      ChildIndex;
+  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO  *DriverHealthInfo;
+
+  //
+  // Initialize local variables
+  //
+  *Count                  = 0;
+  DriverHealthInfo        = NULL;
+  Handles                 = NULL;
+  DriverHealthHandles     = NULL;
+  NumHandles              = 0;
+  HandleCount             = 0;
+
+  HealthStatus = EfiDriverHealthStatusHealthy;
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiDriverHealthProtocolGuid,
+                  NULL,
+                  &NumHandles,
+                  &DriverHealthHandles
+                  );
+
+  if (Status == EFI_NOT_FOUND || NumHandles == 0) {
+    //
+    // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
+    //
+    return NULL;
+  }
+
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (DriverHealthHandles != NULL);
+
+  //
+  // Check the health status of all controllers in the platform
+  // Start by looping through all the Driver Health Protocol handles in the handle database
+  //
+  for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) {
+    //
+    // Get the cumulative health status of the driver
+    //
+    Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], NULL, NULL);
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    //
+    // See if the list of all handles in the handle database has been retrieved
+    //
+    //
+    if (Handles == NULL) {
+      //
+      // Retrieve the list of all handles from the handle database
+      //
+      Status = gBS->LocateHandleBuffer (
+        AllHandles,
+        NULL,
+        NULL,
+        &HandleCount,
+        &Handles
+        );
+      ASSERT_EFI_ERROR (Status);
+    }
+    //
+    // Loop through all the controller handles in the handle database
+    //
+    for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) {
+      Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL);
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+
+      //
+      // Loop through all the child handles in the handle database
+      //
+      for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) {
+        Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex]);
+        if (EFI_ERROR (Status)) {
+          continue;
+        }
+      }
+    }
+  }
+
+  Status = EFI_SUCCESS;
+
+  if (Handles != NULL) {
+    FreePool (Handles);
+  }
+  if (DriverHealthHandles != NULL) {
+    FreePool (DriverHealthHandles);
+  }
+
+  return DriverHealthInfo;
+}
+
+/**
+  Free the Driver Health information array.
+
+  @param DriverHealthInfo       Pointer to array of the Driver Health information.
+  @param Count                  Count of the array.
+
+  @retval EFI_SUCCESS           The array is freed.
+  @retval EFI_INVALID_PARAMETER The array is NULL.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerFreeDriverHealthInfo (
+  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo,
+  UINTN                               Count
+  )
+{
+  UINTN                               Index;
+
+  for (Index = 0; Index < Count; Index++) {
+    if (DriverHealthInfo[Index].MessageList != NULL) {
+      FreePool (DriverHealthInfo[Index].MessageList);
+    }
+  }
+  return gBS->FreePool (DriverHealthInfo);
+}
+
+/**
+  Repair all the controllers according to the Driver Health status queried.
+**/
+VOID
+BmRepairAllControllers (
+  VOID
+  )
+{
+  EFI_STATUS                          Status;
+  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo;
+  EFI_DRIVER_HEALTH_STATUS            HealthStatus;
+  UINTN                               Count;
+  UINTN                               Index;
+  BOOLEAN                             RepairRequired;
+  BOOLEAN                             ConfigurationRequired;
+  BOOLEAN                             ReconnectRequired;
+  BOOLEAN                             RebootRequired;
+  EFI_HII_HANDLE                      *HiiHandles;
+  EFI_FORM_BROWSER2_PROTOCOL          *FormBrowser2;
+
+  //
+  // Configure PcdDriverHealthConfigureForm to ZeroGuid to disable driver health check.
+  //
+  if (CompareGuid (PcdGetPtr (PcdDriverHealthConfigureForm), &gZeroGuid)) {
+    return;
+  }
+
+  Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
+  ASSERT_EFI_ERROR (Status);
+
+  do {
+    RepairRequired        = FALSE;
+    ConfigurationRequired = FALSE;
+
+    //
+    // Deal with Repair Required
+    //
+    DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
+    for (Index = 0; Index < Count; Index++) {
+      if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusConfigurationRequired) {
+        ConfigurationRequired = TRUE;
+      }
+      
+      if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusRepairRequired) {
+        RepairRequired        = TRUE;
+
+        BmDisplayMessages (&DriverHealthInfo[Index]);
+
+        Status = DriverHealthInfo[Index].DriverHealth->Repair (
+                                                         DriverHealthInfo[Index].DriverHealth,
+                                                         DriverHealthInfo[Index].ControllerHandle,
+                                                         DriverHealthInfo[Index].ChildHandle,
+                                                         BmRepairNotify
+                                                         );
+        if (!EFI_ERROR (Status) && !ConfigurationRequired) {
+          Status = DriverHealthInfo[Index].DriverHealth->GetHealthStatus (
+                                                           DriverHealthInfo[Index].DriverHealth,
+                                                           DriverHealthInfo[Index].ControllerHandle,
+                                                           DriverHealthInfo[Index].ChildHandle,
+                                                           &HealthStatus,
+                                                           NULL,
+                                                           NULL
+                                                           );
+          if (!EFI_ERROR (Status) && (HealthStatus == EfiDriverHealthStatusConfigurationRequired)) {
+            ConfigurationRequired = TRUE;
+          }
+        }
+      }
+    }
+
+    if (ConfigurationRequired) {
+      HiiHandles = HiiGetHiiHandles (NULL);
+      if (HiiHandles != NULL) {
+        for (Index = 0; HiiHandles[Index] != NULL; Index++) {
+          Status = FormBrowser2->SendForm (
+                                   FormBrowser2,
+                                   &HiiHandles[Index],
+                                   1,
+                                   PcdGetPtr (PcdDriverHealthConfigureForm),
+                                   0,
+                                   NULL,
+                                   NULL
+                                   );
+          if (!EFI_ERROR (Status)) {
+            break;
+          }
+        }
+        FreePool (HiiHandles);
+      }
+    }
+  
+    EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
+  } while (RepairRequired || ConfigurationRequired);
+
+  RebootRequired    = FALSE;
+  ReconnectRequired = FALSE;
+  DriverHealthInfo  = EfiBootManagerGetDriverHealthInfo (&Count);
+  for (Index = 0; Index < Count; Index++) {
+
+    BmDisplayMessages (&DriverHealthInfo[Index]);
+
+    if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusReconnectRequired) {
+      Status = gBS->DisconnectController (DriverHealthInfo[Index].ControllerHandle, NULL, NULL);
+      if (EFI_ERROR (Status)) {
+        //
+        // Disconnect failed. Need to promote reconnect to a reboot.
+        //
+        RebootRequired    = TRUE;
+      } else {
+        gBS->ConnectController (DriverHealthInfo[Index].ControllerHandle, NULL, NULL, TRUE);
+        ReconnectRequired = TRUE;
+      }
+    }
+
+    if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusRebootRequired) {
+      RebootRequired      = TRUE;
+    }
+  }
+  EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
+
+
+  if (ReconnectRequired) {
+    BmRepairAllControllers ();
+  }
+
+  DEBUG_CODE (
+    CHAR16 *ControllerName;
+
+    DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
+    for (Index = 0; Index < Count; Index++) {
+      ControllerName = BmGetControllerName (
+                         DriverHealthInfo[Index].DriverHealthHandle,
+                         DriverHealthInfo[Index].ControllerHandle,
+                         DriverHealthInfo[Index].ChildHandle
+                         );
+      DEBUG ((
+        EFI_D_INFO,
+        "%02d: %s - %s\n",
+        Index,
+        ControllerName,
+        mBmHealthStatusText[DriverHealthInfo[Index].HealthStatus]
+        ));
+      if (ControllerName != NULL) {
+        FreePool (ControllerName);
+      }
+    }
+    EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
+    );
+
+  if (RebootRequired) {
+    DEBUG ((EFI_D_INFO, "[BDS] One of the Driver Health instances requires rebooting.\n"));
+    gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+  }
+}
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmHotkey.c b/MdeModulePkg/Library/UefiBootManagerLib/BmHotkey.c
index 6a770f940c..8d398fb4c6 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmHotkey.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmHotkey.c
@@ -1,1101 +1,1101 @@
-/** @file
-  Hotkey library functions.
-
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "InternalBm.h"
-
-//
-// Lock for linked list
-//
-EFI_LOCK                     mBmHotkeyLock            = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
-LIST_ENTRY                   mBmHotkeyList            = INITIALIZE_LIST_HEAD_VARIABLE (mBmHotkeyList);
-EFI_EVENT                    mBmHotkeyTriggered       = NULL;
-BOOLEAN                      mBmHotkeyServiceStarted  = FALSE;
-UINTN                        mBmHotkeySupportCount    = 0;
-
-//
-// Set OptionNumber as unassigned value to indicate the option isn't initialized
-//
-EFI_BOOT_MANAGER_LOAD_OPTION mBmHotkeyBootOption      = { LoadOptionNumberUnassigned };
-
-EFI_BOOT_MANAGER_KEY_OPTION  *mBmContinueKeyOption    = NULL;
-VOID                         *mBmTxtInExRegistration  = NULL;
-
-/**
-
-  Check whether the input key option is valid.
-
-  @param   KeyOption               Input key option info.
-
-  @retval  TRUE               Input key option is valid.
-  @retval  FALSE              Input key option is not valid.
-**/
-BOOLEAN
-BmIsKeyOptionValid (
-  IN EFI_BOOT_MANAGER_KEY_OPTION     *KeyOption
-)
-{
-  UINT16   OptionName[sizeof (L"Boot####")];
-  UINT8    *BootOption;
-  UINTN    BootOptionSize;
-  UINT32   Crc;
-
-  //
-  // Check whether corresponding Boot Option exist
-  //
-  UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", KeyOption->BootOption);
-  GetEfiGlobalVariable2 (OptionName, (VOID **) &BootOption, &BootOptionSize);
-
-  if (BootOption == NULL) {
-    return FALSE;
-  }
-
-  //
-  // Check CRC for Boot Option
-  //
-  gBS->CalculateCrc32 (BootOption, BootOptionSize, &Crc);
-  FreePool (BootOption);
-
-  return (BOOLEAN) (KeyOption->BootOptionCrc == Crc);
-}
-
-/**
-
-  Check whether the input variable is an key option variable.
-
-  @param   Name               Input variable name.
-  @param   Guid               Input variable guid.
-  @param   OptionNumber       The option number of this key option variable.
-
-  @retval  TRUE               Input variable is a key option variable.
-  @retval  FALSE              Input variable is not a key option variable.
-**/
-BOOLEAN
-BmIsKeyOptionVariable (
-  CHAR16        *Name,
-  EFI_GUID      *Guid,
-  UINT16        *OptionNumber
-  )
-{
-  UINTN         Index;
-  
-  if (!CompareGuid (Guid, &gEfiGlobalVariableGuid) ||
-      (StrSize (Name) != sizeof (L"Key####")) ||
-      (StrnCmp (Name, L"Key", 3) != 0)
-     ) {
-    return FALSE;
-  }
-
-  *OptionNumber = 0;
-  for (Index = 3; Index < 7; Index++) {
-    if ((Name[Index] >= L'0') && (Name[Index] <= L'9')) {
-      *OptionNumber = *OptionNumber * 16 + Name[Index] - L'0';
-    } else if ((Name[Index] >= L'A') && (Name[Index] <= L'F')) {
-      *OptionNumber = *OptionNumber * 16 + Name[Index] - L'A' + 10;
-    } else {
-      return FALSE;
-    }
-  }
-
-  return TRUE;
-}
-
-/**
-  Return the buffer size of the EFI_BOOT_MANAGER_KEY_OPTION data.
-
-  @param   KeyOption            The input key option info.
-
-  @retval  The buffer size of the key option data.
-**/
-UINTN
-BmSizeOfKeyOption (
-  EFI_BOOT_MANAGER_KEY_OPTION  *KeyOption
-  )
-{
-  return OFFSET_OF (EFI_BOOT_MANAGER_KEY_OPTION, Keys)
-    + KeyOption->KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY);
-}
-
-/**
-  Return the array of key options.
-
-  @param Count  Return the number of key options.
-
-  @retval NULL  No key option.
-  @retval Other Pointer to the key options.
-**/
-EFI_BOOT_MANAGER_KEY_OPTION *
-BmGetKeyOptions (
-  OUT UINTN     *Count
-  )
-{
-  EFI_STATUS                  Status;
-  UINTN                       Index;
-  CHAR16                      *Name;
-  EFI_GUID                    Guid;
-  UINTN                       NameSize;
-  UINTN                       NewNameSize;
-  EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;
-  EFI_BOOT_MANAGER_KEY_OPTION *KeyOption;
-  UINT16                      OptionNumber;
-
-  if (Count == NULL) {
-    return NULL;
-  }
-
-  *Count     = 0;
-  KeyOptions = NULL;
-
-  NameSize = sizeof (CHAR16);
-  Name     = AllocateZeroPool (NameSize);
-  ASSERT (Name != NULL);
-  while (TRUE) {
-    NewNameSize = NameSize;
-    Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
-    if (Status == EFI_BUFFER_TOO_SMALL) {
-      Name = ReallocatePool (NameSize, NewNameSize, Name);
-      ASSERT (Name != NULL);
-      Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
-      NameSize = NewNameSize;
-    }
-
-    if (Status == EFI_NOT_FOUND) {
-      break;
-    }
-    ASSERT_EFI_ERROR (Status);
-
-    if (BmIsKeyOptionVariable (Name ,&Guid, &OptionNumber)) {
-      GetEfiGlobalVariable2 (Name, (VOID**) &KeyOption, NULL);
-      ASSERT (KeyOption != NULL);
-      if (BmIsKeyOptionValid (KeyOption)) {
-        KeyOptions = ReallocatePool (
-                       *Count * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),
-                       (*Count + 1) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),
-                       KeyOptions
-                       );
-        ASSERT (KeyOptions != NULL);
-        //
-        // Insert the key option in order
-        //
-        for (Index = 0; Index < *Count; Index++) {
-          if (OptionNumber < KeyOptions[Index].OptionNumber) {
-            break;
-          }
-        }
-        CopyMem (&KeyOptions[Index + 1], &KeyOptions[Index], (*Count - Index) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
-        CopyMem (&KeyOptions[Index], KeyOption, BmSizeOfKeyOption (KeyOption));
-        KeyOptions[Index].OptionNumber = OptionNumber;
-        (*Count)++;
-      }
-      FreePool (KeyOption);
-    }
-  }
-
-  FreePool (Name);
-
-  return KeyOptions;
-}
-
-/**
-  Callback function for event.
-  
-  @param    Event          Event for this callback function.
-  @param    Context        Context pass to this function.
-**/
-VOID
-EFIAPI
-BmEmptyFunction (
-  IN EFI_EVENT                Event,
-  IN VOID                     *Context
-  )
-{
-}
-
-/**
-  Check whether the bit is set in the value.
-
-  @param   Value            The value need to be check.
-  @param   Bit              The bit filed need to be check.
-
-  @retval  TRUE             The bit is set.
-  @retval  FALSE            The bit is not set.
-**/
-BOOLEAN
-BmBitSet (
-  IN UINT32   Value,
-  IN UINT32   Bit
-  )
-{
-  return (BOOLEAN) ((Value & Bit) != 0);
-}
-
-/**
-  Initialize the KeyData and Key[] in the EFI_BOOT_MANAGER_KEY_OPTION.
-
-  @param  Modifier   Input key info.
-  @param  Args       Va_list info.
-  @param  KeyOption  Key info which need to update.
-
-  @retval  EFI_SUCCESS             Succeed to initialize the KeyData and Key[].
-  @return  EFI_INVALID_PARAMETER   Input parameter error.
-**/
-EFI_STATUS
-BmInitializeKeyFields (
-  IN UINT32                       Modifier,
-  IN VA_LIST                      Args,
-  OUT EFI_BOOT_MANAGER_KEY_OPTION *KeyOption
-  )
-{
-  EFI_INPUT_KEY                   *Key;
-
-  if (KeyOption == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  Key = NULL;
-  while (KeyOption->KeyData.Options.InputKeyCount < sizeof (KeyOption->Keys) / sizeof (KeyOption->Keys[0])) {
-    Key = VA_ARG (Args, EFI_INPUT_KEY *);
-    if (Key == NULL) {
-      break;
-    }
-    CopyMem (
-      &KeyOption->Keys[KeyOption->KeyData.Options.InputKeyCount],
-      Key,
-      sizeof (EFI_INPUT_KEY)
-      );
-    KeyOption->KeyData.Options.InputKeyCount++;
-  }
-
-  if (Key != NULL) {
-    //
-    // Too many keys
-    //
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if ((Modifier & ~(EFI_BOOT_MANAGER_SHIFT_PRESSED
-                 | EFI_BOOT_MANAGER_CONTROL_PRESSED
-                 | EFI_BOOT_MANAGER_ALT_PRESSED
-                 | EFI_BOOT_MANAGER_LOGO_PRESSED
-                 | EFI_BOOT_MANAGER_MENU_KEY_PRESSED
-                 | EFI_BOOT_MANAGER_SYS_REQ_PRESSED
-                 )) != 0) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (BmBitSet (Modifier, EFI_BOOT_MANAGER_SHIFT_PRESSED)) {
-    KeyOption->KeyData.Options.ShiftPressed = 1;
-  }
-  if (BmBitSet (Modifier, EFI_BOOT_MANAGER_CONTROL_PRESSED)) {
-    KeyOption->KeyData.Options.ControlPressed = 1;
-  }
-  if (BmBitSet (Modifier, EFI_BOOT_MANAGER_ALT_PRESSED)) {
-    KeyOption->KeyData.Options.AltPressed = 1;
-  }
-  if (BmBitSet (Modifier, EFI_BOOT_MANAGER_LOGO_PRESSED)) {
-    KeyOption->KeyData.Options.LogoPressed = 1;
-  }
-  if (BmBitSet (Modifier, EFI_BOOT_MANAGER_MENU_KEY_PRESSED)) {
-    KeyOption->KeyData.Options.MenuPressed = 1;
-  }
-  if (BmBitSet (Modifier, EFI_BOOT_MANAGER_SYS_REQ_PRESSED)) {
-    KeyOption->KeyData.Options.SysReqPressed = 1;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Try to boot the boot option triggered by hot key.
-**/
-VOID
-EFIAPI
-EfiBootManagerHotkeyBoot (
-  VOID
-  )
-{
-  if (mBmHotkeyBootOption.OptionNumber != LoadOptionNumberUnassigned) {
-    EfiBootManagerBoot (&mBmHotkeyBootOption);
-    EfiBootManagerFreeLoadOption (&mBmHotkeyBootOption);
-    mBmHotkeyBootOption.OptionNumber = LoadOptionNumberUnassigned;
-  }
-}
-
-/**
-  This is the common notification function for HotKeys, it will be registered
-  with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.
-
-  @param KeyData         A pointer to a buffer that is filled in with the keystroke
-                         information for the key that was pressed.
-
-  @retval  EFI_SUCCESS   KeyData is successfully processed.
-  @return  EFI_NOT_FOUND Fail to find boot option variable.
-**/
-EFI_STATUS
-EFIAPI
-BmHotkeyCallback (
-  IN EFI_KEY_DATA     *KeyData
-)
-{
-  LIST_ENTRY                    *Link;
-  BM_HOTKEY                     *Hotkey;
-  CHAR16                        OptionName[sizeof ("Boot####")];
-  EFI_STATUS                    Status;
-  EFI_KEY_DATA                  *HotkeyData;
-
-  if (mBmHotkeyBootOption.OptionNumber != LoadOptionNumberUnassigned) {
-    //
-    // Do not process sequential hotkey stroke until the current boot option returns
-    //
-    return EFI_SUCCESS;
-  }
-
-  DEBUG ((EFI_D_INFO, "[Bds]BmHotkeyCallback: %04x:%04x\n", KeyData->Key.ScanCode, KeyData->Key.UnicodeChar));
-
-  EfiAcquireLock (&mBmHotkeyLock);
-  for ( Link = GetFirstNode (&mBmHotkeyList)
-      ; !IsNull (&mBmHotkeyList, Link)
-      ; Link = GetNextNode (&mBmHotkeyList, Link)
-      ) {
-    Hotkey = BM_HOTKEY_FROM_LINK (Link);
-
-    //
-    // Is this Key Stroke we are waiting for?
-    //
-    ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));
-    HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];
-    if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&
-        (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&
-        (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? 
-          (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE
-        )
-       ) {
-
-      //
-      // Receive an expecting key stroke, transit to next waiting state
-      //
-      Hotkey->WaitingKey++;
-
-      if (Hotkey->WaitingKey == Hotkey->CodeCount) {
-        //
-        // Reset to initial waiting state
-        //
-        Hotkey->WaitingKey = 0;
-        //
-        // Received the whole key stroke sequence
-        //
-        Status = gBS->SignalEvent (mBmHotkeyTriggered);
-        ASSERT_EFI_ERROR (Status);
-
-        if (!Hotkey->IsContinue) {
-          //
-          // Launch its BootOption
-          //
-          UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", Hotkey->BootOption);
-          Status = EfiBootManagerVariableToLoadOption (OptionName, &mBmHotkeyBootOption);
-          DEBUG ((EFI_D_INFO, "[Bds]Hotkey for %s pressed - %r\n", OptionName, Status));
-          if (EFI_ERROR (Status)) {
-            mBmHotkeyBootOption.OptionNumber = LoadOptionNumberUnassigned;
-          }
-        } else {
-          DEBUG ((EFI_D_INFO, "[Bds]Continue key pressed!\n"));
-        }
-      }
-    } else {
-      //
-      // Receive an unexpected key stroke, reset to initial waiting state
-      //
-      Hotkey->WaitingKey = 0;
-    }
-
-  }
-  EfiReleaseLock (&mBmHotkeyLock);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Unregister hotkey notify list.
-
-  @param    Hotkey                Hotkey list.
-
-  @retval   EFI_SUCCESS           Unregister hotkey notify success.
-  @retval   Others                Unregister hotkey notify failed.
-**/
-EFI_STATUS
-BmUnregisterHotkeyNotify (
-  IN BM_HOTKEY                          *Hotkey
-  )
-{
-  EFI_STATUS                            Status;
-  UINTN                                 Index;
-  UINTN                                 KeyIndex;
-  EFI_HANDLE                            *Handles;
-  UINTN                                 HandleCount;
-  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL     *TxtInEx;
-  VOID                                  *NotifyHandle;
-
-  gBS->LocateHandleBuffer (
-          ByProtocol,
-          &gEfiSimpleTextInputExProtocolGuid,
-          NULL,
-          &HandleCount,
-          &Handles
-          );
-  for (Index = 0; Index < HandleCount; Index++) {
-    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);
-    ASSERT_EFI_ERROR (Status);
-    for (KeyIndex = 0; KeyIndex < Hotkey->CodeCount; KeyIndex++) {
-      Status = TxtInEx->RegisterKeyNotify (
-                          TxtInEx,
-                          &Hotkey->KeyData[KeyIndex],
-                          BmHotkeyCallback,
-                          &NotifyHandle
-                          );
-      if (!EFI_ERROR (Status)) {
-        Status = TxtInEx->UnregisterKeyNotify (TxtInEx, NotifyHandle);
-        DEBUG ((EFI_D_INFO, "[Bds]UnregisterKeyNotify: %04x/%04x %r\n", Hotkey->KeyData[KeyIndex].Key.ScanCode, Hotkey->KeyData[KeyIndex].Key.UnicodeChar, Status));
-      }
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Register hotkey notify list.
-
-  @param    TxtInEx               Pointer to EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL protocol.
-  @param    Hotkey                Hotkey list.
-
-  @retval   EFI_SUCCESS           Register hotkey notify success.
-  @retval   Others                Register hotkey notify failed.
-**/
-EFI_STATUS
-BmRegisterHotkeyNotify (
-  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *TxtInEx,
-  IN BM_HOTKEY                          *Hotkey
-  )
-{
-  EFI_STATUS                            Status;
-  UINTN                                 Index;
-  VOID                                  *NotifyHandle;
-
-  for (Index = 0; Index < Hotkey->CodeCount; Index++) {
-    Status = TxtInEx->RegisterKeyNotify (
-                        TxtInEx,
-                        &Hotkey->KeyData[Index],
-                        BmHotkeyCallback,
-                        &NotifyHandle
-                        );
-    DEBUG ((
-      EFI_D_INFO,
-      "[Bds]RegisterKeyNotify: %04x/%04x %08x/%02x %r\n",
-      Hotkey->KeyData[Index].Key.ScanCode,
-      Hotkey->KeyData[Index].Key.UnicodeChar,
-      Hotkey->KeyData[Index].KeyState.KeyShiftState,
-      Hotkey->KeyData[Index].KeyState.KeyToggleState,
-      Status
-      ));
-    if (EFI_ERROR (Status)) {
-      //
-      // some of the hotkey registry failed
-      // do not unregister all in case we have both CTRL-ALT-P and CTRL-ALT-P-R
-      //
-      break;
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Generate key shift state base on the input key option info.
-
-  @param    Depth                 Which key is checked.
-  @param    KeyOption             Input key option info.
-  @param    KeyShiftState         Input key shift state.
-  @param    KeyShiftStates        Return possible key shift state array.
-  @param    KeyShiftStateCount    Possible key shift state count.
-**/
-VOID
-BmGenerateKeyShiftState (
-  IN UINTN                             Depth,
-  IN EFI_BOOT_MANAGER_KEY_OPTION       *KeyOption,
-  IN UINT32                            KeyShiftState,
-  IN UINT32                            *KeyShiftStates,
-  IN UINTN                             *KeyShiftStateCount
-  )
-{
-  switch (Depth) {
-  case 0:
-    if (KeyOption->KeyData.Options.ShiftPressed) {
-      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_SHIFT_PRESSED, KeyShiftStates, KeyShiftStateCount);
-      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_SHIFT_PRESSED,  KeyShiftStates, KeyShiftStateCount);
-    } else {
-      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);
-    }
-    break;
-
-  case 1:
-    if (KeyOption->KeyData.Options.ControlPressed) {
-      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_CONTROL_PRESSED, KeyShiftStates, KeyShiftStateCount);
-      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_CONTROL_PRESSED,  KeyShiftStates, KeyShiftStateCount);
-    } else {
-      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);
-    }
-    break;
-
-  case 2:
-    if (KeyOption->KeyData.Options.AltPressed) {
-      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_ALT_PRESSED, KeyShiftStates, KeyShiftStateCount);
-      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_ALT_PRESSED,  KeyShiftStates, KeyShiftStateCount);
-    } else {
-      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);
-    }
-    break;
-  case  3:
-    if (KeyOption->KeyData.Options.LogoPressed) {
-      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_LOGO_PRESSED, KeyShiftStates, KeyShiftStateCount);
-      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_LOGO_PRESSED,  KeyShiftStates, KeyShiftStateCount);
-    } else {
-      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);
-    }
-    break;
-  case 4:
-    if (KeyOption->KeyData.Options.MenuPressed) {
-      KeyShiftState |= EFI_MENU_KEY_PRESSED;
-    }
-    if (KeyOption->KeyData.Options.SysReqPressed) {
-      KeyShiftState |= EFI_SYS_REQ_PRESSED;
-    }
-    KeyShiftStates[*KeyShiftStateCount] = KeyShiftState;
-    (*KeyShiftStateCount)++;
-    break;
-  }
-}
-
-/**
-  Add it to hot key database, register it to existing TxtInEx.
-  New TxtInEx will be automatically registered with all the hot key in dababase
-
-  @param    KeyOption  Input key option info.
-**/
-EFI_STATUS
-BmProcessKeyOption (
-  IN EFI_BOOT_MANAGER_KEY_OPTION       *KeyOption
-  )
-{
-  EFI_STATUS                           Status;
-  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL    *TxtInEx;
-  EFI_HANDLE                           *Handles;
-  UINTN                                HandleCount;
-  UINTN                                HandleIndex;
-  UINTN                                Index;
-  BM_HOTKEY                            *Hotkey;
-  UINTN                                KeyIndex;
-  //
-  // 16 is enough to enumerate all the possible combination of LEFT_XXX and RIGHT_XXX
-  //
-  UINT32                               KeyShiftStates[16];
-  UINTN                                KeyShiftStateCount;
-
-  if (KeyOption->KeyData.Options.InputKeyCount > mBmHotkeySupportCount) {
-    return EFI_UNSUPPORTED;
-  }
-
-  KeyShiftStateCount = 0;
-  BmGenerateKeyShiftState (0, KeyOption, EFI_SHIFT_STATE_VALID, KeyShiftStates, &KeyShiftStateCount);
-  ASSERT (KeyShiftStateCount <= sizeof (KeyShiftStates) / sizeof (KeyShiftStates[0]));
-
-  EfiAcquireLock (&mBmHotkeyLock);
-
-  for (Index = 0; Index < KeyShiftStateCount; Index++) {
-    Hotkey = AllocateZeroPool (sizeof (BM_HOTKEY));
-    ASSERT (Hotkey != NULL);
-
-    Hotkey->Signature  = BM_HOTKEY_SIGNATURE;
-    Hotkey->BootOption = KeyOption->BootOption;
-    Hotkey->IsContinue = (BOOLEAN) (KeyOption == mBmContinueKeyOption);
-    Hotkey->CodeCount  = (UINT8) KeyOption->KeyData.Options.InputKeyCount;
-
-    for (KeyIndex = 0; KeyIndex < Hotkey->CodeCount; KeyIndex++) {
-      CopyMem (&Hotkey->KeyData[KeyIndex].Key, &KeyOption->Keys[KeyIndex], sizeof (EFI_INPUT_KEY));
-      Hotkey->KeyData[KeyIndex].KeyState.KeyShiftState = KeyShiftStates[Index];
-    }
-    InsertTailList (&mBmHotkeyList, &Hotkey->Link);
-
-    gBS->LocateHandleBuffer (
-            ByProtocol,
-            &gEfiSimpleTextInputExProtocolGuid,
-            NULL,
-            &HandleCount,
-            &Handles
-            );
-    for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
-      Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);
-      ASSERT_EFI_ERROR (Status);
-      BmRegisterHotkeyNotify (TxtInEx, Hotkey);
-    }
-  }
-
-  EfiReleaseLock (&mBmHotkeyLock);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Callback function for SimpleTextInEx protocol install events
-
-  @param Event           the event that is signaled.
-  @param Context         not used here.
-
-**/
-VOID
-EFIAPI
-BmTxtInExCallback (
-  IN EFI_EVENT    Event,
-  IN VOID         *Context
-  )
-{
-  EFI_STATUS                         Status;
-  UINTN                              BufferSize;
-  EFI_HANDLE                         Handle;
-  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *TxtInEx;
-  LIST_ENTRY                         *Link;
-
-  while (TRUE) {
-    BufferSize = sizeof (EFI_HANDLE);
-    Status = gBS->LocateHandle (
-                    ByRegisterNotify,
-                    NULL,
-                    mBmTxtInExRegistration,
-                    &BufferSize,
-                    &Handle
-                    );
-    if (EFI_ERROR (Status)) {
-      //
-      // If no more notification events exist
-      //
-      return ;
-    }
-
-    Status = gBS->HandleProtocol (
-                    Handle,
-                    &gEfiSimpleTextInputExProtocolGuid,
-                    (VOID **) &TxtInEx
-                    );
-    ASSERT_EFI_ERROR (Status);
-
-    //
-    // Register the hot key notification for the existing items in the list
-    //
-    EfiAcquireLock (&mBmHotkeyLock);
-    for (Link = GetFirstNode (&mBmHotkeyList); !IsNull (&mBmHotkeyList, Link); Link = GetNextNode (&mBmHotkeyList, Link)) {
-      BmRegisterHotkeyNotify (TxtInEx, BM_HOTKEY_FROM_LINK (Link));
-    }
-    EfiReleaseLock (&mBmHotkeyLock);
-  }
-}
-
-/**
-  Free the key options returned from BmGetKeyOptions.
-
-  @param KeyOptions     Pointer to the key options.
-  @param KeyOptionCount Number of the key options.
-
-  @retval EFI_SUCCESS   The key options are freed.
-  @retval EFI_NOT_FOUND KeyOptions is NULL.
-**/
-EFI_STATUS
-BmFreeKeyOptions (
-  IN EFI_BOOT_MANAGER_KEY_OPTION    *KeyOptions,
-  IN UINTN                          KeyOptionCount
-  )
-{
-  if (KeyOptions != NULL) {
-    FreePool (KeyOptions);
-    return EFI_SUCCESS;
-  } else {
-    return EFI_NOT_FOUND;
-  }
-}
-
-/**
-  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,
-  ...
-  )
-{
-  EFI_STATUS                   Status;
-  EFI_BOOT_MANAGER_KEY_OPTION  KeyOption;
-  VA_LIST                      Args;
-  
-  if (mBmContinueKeyOption != NULL) {
-    return EFI_ALREADY_STARTED;
-  }
-
-  ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
-  VA_START (Args, Modifier);
-  Status = BmInitializeKeyFields (Modifier, Args, &KeyOption);
-  VA_END (Args);
-
-  if (!EFI_ERROR (Status)) {
-    mBmContinueKeyOption = AllocateCopyPool (sizeof (EFI_BOOT_MANAGER_KEY_OPTION), &KeyOption);
-    ASSERT (mBmContinueKeyOption != NULL);
-    if (mBmHotkeyServiceStarted) {
-      BmProcessKeyOption (mBmContinueKeyOption);
-    }
-  }
-
-  return Status;
-}
-
-/**
-  Stop the hotkey processing.
-  
-  @param    Event          Event pointer related to hotkey service.
-  @param    Context        Context pass to this function.
-**/
-VOID
-EFIAPI
-BmStopHotkeyService (
-  IN EFI_EVENT    Event,
-  IN VOID         *Context
-  )
-{
-  LIST_ENTRY            *Link;
-  BM_HOTKEY             *Hotkey;
-
-  DEBUG ((EFI_D_INFO, "[Bds]Stop Hotkey Service!\n"));
-  gBS->CloseEvent (Event);
-
-  EfiAcquireLock (&mBmHotkeyLock);
-  for (Link = GetFirstNode (&mBmHotkeyList); !IsNull (&mBmHotkeyList, Link); ) {
-    Hotkey = BM_HOTKEY_FROM_LINK (Link);
-    BmUnregisterHotkeyNotify (Hotkey);
-    Link   = RemoveEntryList (Link);
-    FreePool (Hotkey);
-  }
-  EfiReleaseLock (&mBmHotkeyLock);
-}
-
-/**
-  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
-  )
-{
-  EFI_STATUS                   Status;
-  EFI_BOOT_MANAGER_KEY_OPTION  *KeyOptions;
-  UINTN                        KeyOptionCount;
-  UINTN                        Index;
-  EFI_EVENT                    Event;
-  UINT32                       *BootOptionSupport;
-
-  Status = GetEfiGlobalVariable2 (EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME, (VOID **) &BootOptionSupport, NULL);
-  ASSERT (BootOptionSupport != NULL);
-
-  if ((*BootOptionSupport & EFI_BOOT_OPTION_SUPPORT_KEY)  != 0) {
-    mBmHotkeySupportCount = ((*BootOptionSupport & EFI_BOOT_OPTION_SUPPORT_COUNT) >> LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT));
-  }
-  FreePool (BootOptionSupport);
-
-  if (mBmHotkeySupportCount == 0) {
-    DEBUG ((EFI_D_INFO, "Bds: BootOptionSupport NV variable forbids starting the hotkey service.\n"));
-    return EFI_UNSUPPORTED;
-  }
-
-  Status = gBS->CreateEvent (
-                  EVT_NOTIFY_WAIT,
-                  TPL_CALLBACK,
-                  BmEmptyFunction,
-                  NULL,
-                  &mBmHotkeyTriggered
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  if (HotkeyTriggered != NULL) {
-    *HotkeyTriggered = mBmHotkeyTriggered;
-  }
-
-  KeyOptions = BmGetKeyOptions (&KeyOptionCount);
-  for (Index = 0; Index < KeyOptionCount; Index ++) {
-    BmProcessKeyOption (&KeyOptions[Index]);
-  }
-  BmFreeKeyOptions (KeyOptions, KeyOptionCount);
-
-  if (mBmContinueKeyOption != NULL) {
-    BmProcessKeyOption (mBmContinueKeyOption);
-  }
-
-  EfiCreateProtocolNotifyEvent (
-    &gEfiSimpleTextInputExProtocolGuid,
-    TPL_CALLBACK,
-    BmTxtInExCallback,
-    NULL,
-    &mBmTxtInExRegistration
-    );
-
-  Status = EfiCreateEventReadyToBootEx (
-             TPL_CALLBACK,
-             BmStopHotkeyService,
-             NULL,
-             &Event
-             );
-  ASSERT_EFI_ERROR (Status);
-
-
-  mBmHotkeyServiceStarted = TRUE;
-  return Status;
-}
-
-/**
-  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,
-  ...
-  )
-{
-  EFI_STATUS                     Status;
-  VA_LIST                        Args;
-  VOID                           *BootOption;
-  UINTN                          BootOptionSize;
-  CHAR16                         BootOptionName[sizeof (L"Boot####")];
-  EFI_BOOT_MANAGER_KEY_OPTION    KeyOption;
-  EFI_BOOT_MANAGER_KEY_OPTION    *KeyOptions;
-  UINTN                          KeyOptionCount;
-  UINTN                          Index;
-  UINTN                          KeyOptionNumber;
-  CHAR16                         KeyOptionName[sizeof (L"Key####")];
-
-  UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", BootOptionNumber);
-  GetEfiGlobalVariable2 (BootOptionName, &BootOption, &BootOptionSize);
-
-  if (BootOption == NULL) {
-    return EFI_NOT_FOUND;
-  }
-
-  ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
-  KeyOption.BootOption = BootOptionNumber;
-  Status = gBS->CalculateCrc32 (BootOption, BootOptionSize, &KeyOption.BootOptionCrc);
-  ASSERT_EFI_ERROR (Status);
-  FreePool (BootOption);
-
-  VA_START (Args, Modifier);
-  Status = BmInitializeKeyFields (Modifier, Args, &KeyOption);
-  VA_END (Args);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  KeyOptionNumber = LoadOptionNumberUnassigned;
-  //
-  // Check if the hot key sequence was defined already
-  //
-  KeyOptions = BmGetKeyOptions (&KeyOptionCount);
-  for (Index = 0; Index < KeyOptionCount; Index++) {
-    if ((KeyOptions[Index].KeyData.PackedValue == KeyOption.KeyData.PackedValue) &&
-      (CompareMem (KeyOptions[Index].Keys, KeyOption.Keys, KeyOption.KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY)) == 0)) {
-      break;
-    }
-
-    if ((KeyOptionNumber == LoadOptionNumberUnassigned) &&
-        (KeyOptions[Index].OptionNumber > Index)
-       ){
-      KeyOptionNumber = Index;
-    }
-  }
-  BmFreeKeyOptions (KeyOptions, KeyOptionCount);
-
-  if (Index < KeyOptionCount) {
-    return EFI_ALREADY_STARTED;
-  }
-
-  if (KeyOptionNumber == LoadOptionNumberUnassigned) {
-    KeyOptionNumber = KeyOptionCount;
-  }
-
-  UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptionNumber);
-
-  Status = gRT->SetVariable (
-                  KeyOptionName,
-                  &gEfiGlobalVariableGuid,
-                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
-                  BmSizeOfKeyOption (&KeyOption),
-                  &KeyOption
-                  );
-  if (!EFI_ERROR (Status)) {
-    //
-    // Return the Key Option in case needed by caller
-    //
-    if (AddedOption != NULL) {
-      CopyMem (AddedOption, &KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
-    }
-
-    //
-    // Register the newly added hot key
-    // Calling this function before EfiBootManagerStartHotkeyService doesn't
-    // need to call BmProcessKeyOption
-    //
-    if (mBmHotkeyServiceStarted) {
-      BmProcessKeyOption (&KeyOption);
-    }
-  }
-
-  return Status;
-}
-
-/**
-  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,
-  ...
-  )
-{
-  EFI_STATUS                     Status;
-  UINTN                          Index;
-  VA_LIST                        Args;
-  EFI_BOOT_MANAGER_KEY_OPTION    KeyOption;
-  EFI_BOOT_MANAGER_KEY_OPTION    *KeyOptions;
-  UINTN                          KeyOptionCount;
-  LIST_ENTRY                     *Link;
-  BM_HOTKEY                      *Hotkey;
-  UINT32                         ShiftState;
-  BOOLEAN                        Match;
-  CHAR16                         KeyOptionName[sizeof (L"Key####")];
-
-  ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
-  VA_START (Args, Modifier);
-  Status = BmInitializeKeyFields (Modifier, Args, &KeyOption);
-  VA_END (Args);
-
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  EfiAcquireLock (&mBmHotkeyLock);
-  //
-  // Delete the key option from active hot key list
-  // Could have multiple entries when modifier isn't 0 because we map the ShiftPressed to RIGHT_SHIFT and RIGHT_SHIFT
-  //
-  for (Link = GetFirstNode (&mBmHotkeyList); !IsNull (&mBmHotkeyList, Link); ) {
-    Hotkey = BM_HOTKEY_FROM_LINK (Link);
-    Match  = (BOOLEAN) (Hotkey->CodeCount == KeyOption.KeyData.Options.InputKeyCount);
-
-    for (Index = 0; Match && (Index < Hotkey->CodeCount); Index++) {
-      ShiftState = Hotkey->KeyData[Index].KeyState.KeyShiftState;
-      if (
-        (BmBitSet (ShiftState, EFI_RIGHT_SHIFT_PRESSED | EFI_LEFT_SHIFT_PRESSED) != KeyOption.KeyData.Options.ShiftPressed) ||
-        (BmBitSet (ShiftState, EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED) != KeyOption.KeyData.Options.ControlPressed) ||
-        (BmBitSet (ShiftState, EFI_RIGHT_ALT_PRESSED | EFI_LEFT_ALT_PRESSED) != KeyOption.KeyData.Options.AltPressed) ||
-        (BmBitSet (ShiftState, EFI_RIGHT_LOGO_PRESSED | EFI_LEFT_LOGO_PRESSED) != KeyOption.KeyData.Options.LogoPressed) ||
-        (BmBitSet (ShiftState, EFI_MENU_KEY_PRESSED) != KeyOption.KeyData.Options.MenuPressed) ||
-        (BmBitSet (ShiftState, EFI_SYS_REQ_PRESSED) != KeyOption.KeyData.Options.SysReqPressed) ||
-        (CompareMem (&Hotkey->KeyData[Index].Key, &KeyOption.Keys[Index], sizeof (EFI_INPUT_KEY)) != 0)
-        ) {
-        //
-        // Break when any field doesn't match
-        //
-        Match = FALSE;
-        break;
-      }
-    }
-
-    if (Match) {
-      Link = RemoveEntryList (Link);
-      FreePool (Hotkey);
-    } else {
-      Link = GetNextNode (&mBmHotkeyList, Link);
-    }
-  }
-
-  //
-  // Delete the key option from the variable
-  //
-  Status     = EFI_NOT_FOUND;
-  KeyOptions = BmGetKeyOptions (&KeyOptionCount);
-  for (Index = 0; Index < KeyOptionCount; Index++) {
-    if ((KeyOptions[Index].KeyData.PackedValue == KeyOption.KeyData.PackedValue) &&
-        (CompareMem (
-           KeyOptions[Index].Keys, KeyOption.Keys,
-           KeyOption.KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY)) == 0)
-       ) {
-      UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptions[Index].OptionNumber);
-      Status = gRT->SetVariable (
-                 KeyOptionName,
-                 &gEfiGlobalVariableGuid,
-                 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
-                 0,
-                 NULL
-                 );
-      //
-      // Return the deleted key option in case needed by caller
-      //
-      if (DeletedOption != NULL) {
-        CopyMem (DeletedOption, &KeyOptions[Index], sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
-      }
-      break;
-    }
-  }
-  BmFreeKeyOptions (KeyOptions, KeyOptionCount);
-
-  EfiReleaseLock (&mBmHotkeyLock);
-
-  return Status;
-}
+/** @file
+  Hotkey library functions.
+
+Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "InternalBm.h"
+
+//
+// Lock for linked list
+//
+EFI_LOCK                     mBmHotkeyLock            = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
+LIST_ENTRY                   mBmHotkeyList            = INITIALIZE_LIST_HEAD_VARIABLE (mBmHotkeyList);
+EFI_EVENT                    mBmHotkeyTriggered       = NULL;
+BOOLEAN                      mBmHotkeyServiceStarted  = FALSE;
+UINTN                        mBmHotkeySupportCount    = 0;
+
+//
+// Set OptionNumber as unassigned value to indicate the option isn't initialized
+//
+EFI_BOOT_MANAGER_LOAD_OPTION mBmHotkeyBootOption      = { LoadOptionNumberUnassigned };
+
+EFI_BOOT_MANAGER_KEY_OPTION  *mBmContinueKeyOption    = NULL;
+VOID                         *mBmTxtInExRegistration  = NULL;
+
+/**
+
+  Check whether the input key option is valid.
+
+  @param   KeyOption               Input key option info.
+
+  @retval  TRUE               Input key option is valid.
+  @retval  FALSE              Input key option is not valid.
+**/
+BOOLEAN
+BmIsKeyOptionValid (
+  IN EFI_BOOT_MANAGER_KEY_OPTION     *KeyOption
+)
+{
+  UINT16   OptionName[sizeof (L"Boot####")];
+  UINT8    *BootOption;
+  UINTN    BootOptionSize;
+  UINT32   Crc;
+
+  //
+  // Check whether corresponding Boot Option exist
+  //
+  UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", KeyOption->BootOption);
+  GetEfiGlobalVariable2 (OptionName, (VOID **) &BootOption, &BootOptionSize);
+
+  if (BootOption == NULL) {
+    return FALSE;
+  }
+
+  //
+  // Check CRC for Boot Option
+  //
+  gBS->CalculateCrc32 (BootOption, BootOptionSize, &Crc);
+  FreePool (BootOption);
+
+  return (BOOLEAN) (KeyOption->BootOptionCrc == Crc);
+}
+
+/**
+
+  Check whether the input variable is an key option variable.
+
+  @param   Name               Input variable name.
+  @param   Guid               Input variable guid.
+  @param   OptionNumber       The option number of this key option variable.
+
+  @retval  TRUE               Input variable is a key option variable.
+  @retval  FALSE              Input variable is not a key option variable.
+**/
+BOOLEAN
+BmIsKeyOptionVariable (
+  CHAR16        *Name,
+  EFI_GUID      *Guid,
+  UINT16        *OptionNumber
+  )
+{
+  UINTN         Index;
+  
+  if (!CompareGuid (Guid, &gEfiGlobalVariableGuid) ||
+      (StrSize (Name) != sizeof (L"Key####")) ||
+      (StrnCmp (Name, L"Key", 3) != 0)
+     ) {
+    return FALSE;
+  }
+
+  *OptionNumber = 0;
+  for (Index = 3; Index < 7; Index++) {
+    if ((Name[Index] >= L'0') && (Name[Index] <= L'9')) {
+      *OptionNumber = *OptionNumber * 16 + Name[Index] - L'0';
+    } else if ((Name[Index] >= L'A') && (Name[Index] <= L'F')) {
+      *OptionNumber = *OptionNumber * 16 + Name[Index] - L'A' + 10;
+    } else {
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+/**
+  Return the buffer size of the EFI_BOOT_MANAGER_KEY_OPTION data.
+
+  @param   KeyOption            The input key option info.
+
+  @retval  The buffer size of the key option data.
+**/
+UINTN
+BmSizeOfKeyOption (
+  EFI_BOOT_MANAGER_KEY_OPTION  *KeyOption
+  )
+{
+  return OFFSET_OF (EFI_BOOT_MANAGER_KEY_OPTION, Keys)
+    + KeyOption->KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY);
+}
+
+/**
+  Return the array of key options.
+
+  @param Count  Return the number of key options.
+
+  @retval NULL  No key option.
+  @retval Other Pointer to the key options.
+**/
+EFI_BOOT_MANAGER_KEY_OPTION *
+BmGetKeyOptions (
+  OUT UINTN     *Count
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       Index;
+  CHAR16                      *Name;
+  EFI_GUID                    Guid;
+  UINTN                       NameSize;
+  UINTN                       NewNameSize;
+  EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;
+  EFI_BOOT_MANAGER_KEY_OPTION *KeyOption;
+  UINT16                      OptionNumber;
+
+  if (Count == NULL) {
+    return NULL;
+  }
+
+  *Count     = 0;
+  KeyOptions = NULL;
+
+  NameSize = sizeof (CHAR16);
+  Name     = AllocateZeroPool (NameSize);
+  ASSERT (Name != NULL);
+  while (TRUE) {
+    NewNameSize = NameSize;
+    Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
+    if (Status == EFI_BUFFER_TOO_SMALL) {
+      Name = ReallocatePool (NameSize, NewNameSize, Name);
+      ASSERT (Name != NULL);
+      Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
+      NameSize = NewNameSize;
+    }
+
+    if (Status == EFI_NOT_FOUND) {
+      break;
+    }
+    ASSERT_EFI_ERROR (Status);
+
+    if (BmIsKeyOptionVariable (Name ,&Guid, &OptionNumber)) {
+      GetEfiGlobalVariable2 (Name, (VOID**) &KeyOption, NULL);
+      ASSERT (KeyOption != NULL);
+      if (BmIsKeyOptionValid (KeyOption)) {
+        KeyOptions = ReallocatePool (
+                       *Count * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),
+                       (*Count + 1) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),
+                       KeyOptions
+                       );
+        ASSERT (KeyOptions != NULL);
+        //
+        // Insert the key option in order
+        //
+        for (Index = 0; Index < *Count; Index++) {
+          if (OptionNumber < KeyOptions[Index].OptionNumber) {
+            break;
+          }
+        }
+        CopyMem (&KeyOptions[Index + 1], &KeyOptions[Index], (*Count - Index) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
+        CopyMem (&KeyOptions[Index], KeyOption, BmSizeOfKeyOption (KeyOption));
+        KeyOptions[Index].OptionNumber = OptionNumber;
+        (*Count)++;
+      }
+      FreePool (KeyOption);
+    }
+  }
+
+  FreePool (Name);
+
+  return KeyOptions;
+}
+
+/**
+  Callback function for event.
+  
+  @param    Event          Event for this callback function.
+  @param    Context        Context pass to this function.
+**/
+VOID
+EFIAPI
+BmEmptyFunction (
+  IN EFI_EVENT                Event,
+  IN VOID                     *Context
+  )
+{
+}
+
+/**
+  Check whether the bit is set in the value.
+
+  @param   Value            The value need to be check.
+  @param   Bit              The bit filed need to be check.
+
+  @retval  TRUE             The bit is set.
+  @retval  FALSE            The bit is not set.
+**/
+BOOLEAN
+BmBitSet (
+  IN UINT32   Value,
+  IN UINT32   Bit
+  )
+{
+  return (BOOLEAN) ((Value & Bit) != 0);
+}
+
+/**
+  Initialize the KeyData and Key[] in the EFI_BOOT_MANAGER_KEY_OPTION.
+
+  @param  Modifier   Input key info.
+  @param  Args       Va_list info.
+  @param  KeyOption  Key info which need to update.
+
+  @retval  EFI_SUCCESS             Succeed to initialize the KeyData and Key[].
+  @return  EFI_INVALID_PARAMETER   Input parameter error.
+**/
+EFI_STATUS
+BmInitializeKeyFields (
+  IN UINT32                       Modifier,
+  IN VA_LIST                      Args,
+  OUT EFI_BOOT_MANAGER_KEY_OPTION *KeyOption
+  )
+{
+  EFI_INPUT_KEY                   *Key;
+
+  if (KeyOption == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Key = NULL;
+  while (KeyOption->KeyData.Options.InputKeyCount < sizeof (KeyOption->Keys) / sizeof (KeyOption->Keys[0])) {
+    Key = VA_ARG (Args, EFI_INPUT_KEY *);
+    if (Key == NULL) {
+      break;
+    }
+    CopyMem (
+      &KeyOption->Keys[KeyOption->KeyData.Options.InputKeyCount],
+      Key,
+      sizeof (EFI_INPUT_KEY)
+      );
+    KeyOption->KeyData.Options.InputKeyCount++;
+  }
+
+  if (Key != NULL) {
+    //
+    // Too many keys
+    //
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((Modifier & ~(EFI_BOOT_MANAGER_SHIFT_PRESSED
+                 | EFI_BOOT_MANAGER_CONTROL_PRESSED
+                 | EFI_BOOT_MANAGER_ALT_PRESSED
+                 | EFI_BOOT_MANAGER_LOGO_PRESSED
+                 | EFI_BOOT_MANAGER_MENU_KEY_PRESSED
+                 | EFI_BOOT_MANAGER_SYS_REQ_PRESSED
+                 )) != 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BmBitSet (Modifier, EFI_BOOT_MANAGER_SHIFT_PRESSED)) {
+    KeyOption->KeyData.Options.ShiftPressed = 1;
+  }
+  if (BmBitSet (Modifier, EFI_BOOT_MANAGER_CONTROL_PRESSED)) {
+    KeyOption->KeyData.Options.ControlPressed = 1;
+  }
+  if (BmBitSet (Modifier, EFI_BOOT_MANAGER_ALT_PRESSED)) {
+    KeyOption->KeyData.Options.AltPressed = 1;
+  }
+  if (BmBitSet (Modifier, EFI_BOOT_MANAGER_LOGO_PRESSED)) {
+    KeyOption->KeyData.Options.LogoPressed = 1;
+  }
+  if (BmBitSet (Modifier, EFI_BOOT_MANAGER_MENU_KEY_PRESSED)) {
+    KeyOption->KeyData.Options.MenuPressed = 1;
+  }
+  if (BmBitSet (Modifier, EFI_BOOT_MANAGER_SYS_REQ_PRESSED)) {
+    KeyOption->KeyData.Options.SysReqPressed = 1;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Try to boot the boot option triggered by hot key.
+**/
+VOID
+EFIAPI
+EfiBootManagerHotkeyBoot (
+  VOID
+  )
+{
+  if (mBmHotkeyBootOption.OptionNumber != LoadOptionNumberUnassigned) {
+    EfiBootManagerBoot (&mBmHotkeyBootOption);
+    EfiBootManagerFreeLoadOption (&mBmHotkeyBootOption);
+    mBmHotkeyBootOption.OptionNumber = LoadOptionNumberUnassigned;
+  }
+}
+
+/**
+  This is the common notification function for HotKeys, it will be registered
+  with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.
+
+  @param KeyData         A pointer to a buffer that is filled in with the keystroke
+                         information for the key that was pressed.
+
+  @retval  EFI_SUCCESS   KeyData is successfully processed.
+  @return  EFI_NOT_FOUND Fail to find boot option variable.
+**/
+EFI_STATUS
+EFIAPI
+BmHotkeyCallback (
+  IN EFI_KEY_DATA     *KeyData
+)
+{
+  LIST_ENTRY                    *Link;
+  BM_HOTKEY                     *Hotkey;
+  CHAR16                        OptionName[sizeof ("Boot####")];
+  EFI_STATUS                    Status;
+  EFI_KEY_DATA                  *HotkeyData;
+
+  if (mBmHotkeyBootOption.OptionNumber != LoadOptionNumberUnassigned) {
+    //
+    // Do not process sequential hotkey stroke until the current boot option returns
+    //
+    return EFI_SUCCESS;
+  }
+
+  DEBUG ((EFI_D_INFO, "[Bds]BmHotkeyCallback: %04x:%04x\n", KeyData->Key.ScanCode, KeyData->Key.UnicodeChar));
+
+  EfiAcquireLock (&mBmHotkeyLock);
+  for ( Link = GetFirstNode (&mBmHotkeyList)
+      ; !IsNull (&mBmHotkeyList, Link)
+      ; Link = GetNextNode (&mBmHotkeyList, Link)
+      ) {
+    Hotkey = BM_HOTKEY_FROM_LINK (Link);
+
+    //
+    // Is this Key Stroke we are waiting for?
+    //
+    ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));
+    HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];
+    if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&
+        (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&
+        (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? 
+          (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE
+        )
+       ) {
+
+      //
+      // Receive an expecting key stroke, transit to next waiting state
+      //
+      Hotkey->WaitingKey++;
+
+      if (Hotkey->WaitingKey == Hotkey->CodeCount) {
+        //
+        // Reset to initial waiting state
+        //
+        Hotkey->WaitingKey = 0;
+        //
+        // Received the whole key stroke sequence
+        //
+        Status = gBS->SignalEvent (mBmHotkeyTriggered);
+        ASSERT_EFI_ERROR (Status);
+
+        if (!Hotkey->IsContinue) {
+          //
+          // Launch its BootOption
+          //
+          UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", Hotkey->BootOption);
+          Status = EfiBootManagerVariableToLoadOption (OptionName, &mBmHotkeyBootOption);
+          DEBUG ((EFI_D_INFO, "[Bds]Hotkey for %s pressed - %r\n", OptionName, Status));
+          if (EFI_ERROR (Status)) {
+            mBmHotkeyBootOption.OptionNumber = LoadOptionNumberUnassigned;
+          }
+        } else {
+          DEBUG ((EFI_D_INFO, "[Bds]Continue key pressed!\n"));
+        }
+      }
+    } else {
+      //
+      // Receive an unexpected key stroke, reset to initial waiting state
+      //
+      Hotkey->WaitingKey = 0;
+    }
+
+  }
+  EfiReleaseLock (&mBmHotkeyLock);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Unregister hotkey notify list.
+
+  @param    Hotkey                Hotkey list.
+
+  @retval   EFI_SUCCESS           Unregister hotkey notify success.
+  @retval   Others                Unregister hotkey notify failed.
+**/
+EFI_STATUS
+BmUnregisterHotkeyNotify (
+  IN BM_HOTKEY                          *Hotkey
+  )
+{
+  EFI_STATUS                            Status;
+  UINTN                                 Index;
+  UINTN                                 KeyIndex;
+  EFI_HANDLE                            *Handles;
+  UINTN                                 HandleCount;
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL     *TxtInEx;
+  VOID                                  *NotifyHandle;
+
+  gBS->LocateHandleBuffer (
+          ByProtocol,
+          &gEfiSimpleTextInputExProtocolGuid,
+          NULL,
+          &HandleCount,
+          &Handles
+          );
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);
+    ASSERT_EFI_ERROR (Status);
+    for (KeyIndex = 0; KeyIndex < Hotkey->CodeCount; KeyIndex++) {
+      Status = TxtInEx->RegisterKeyNotify (
+                          TxtInEx,
+                          &Hotkey->KeyData[KeyIndex],
+                          BmHotkeyCallback,
+                          &NotifyHandle
+                          );
+      if (!EFI_ERROR (Status)) {
+        Status = TxtInEx->UnregisterKeyNotify (TxtInEx, NotifyHandle);
+        DEBUG ((EFI_D_INFO, "[Bds]UnregisterKeyNotify: %04x/%04x %r\n", Hotkey->KeyData[KeyIndex].Key.ScanCode, Hotkey->KeyData[KeyIndex].Key.UnicodeChar, Status));
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Register hotkey notify list.
+
+  @param    TxtInEx               Pointer to EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL protocol.
+  @param    Hotkey                Hotkey list.
+
+  @retval   EFI_SUCCESS           Register hotkey notify success.
+  @retval   Others                Register hotkey notify failed.
+**/
+EFI_STATUS
+BmRegisterHotkeyNotify (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *TxtInEx,
+  IN BM_HOTKEY                          *Hotkey
+  )
+{
+  EFI_STATUS                            Status;
+  UINTN                                 Index;
+  VOID                                  *NotifyHandle;
+
+  for (Index = 0; Index < Hotkey->CodeCount; Index++) {
+    Status = TxtInEx->RegisterKeyNotify (
+                        TxtInEx,
+                        &Hotkey->KeyData[Index],
+                        BmHotkeyCallback,
+                        &NotifyHandle
+                        );
+    DEBUG ((
+      EFI_D_INFO,
+      "[Bds]RegisterKeyNotify: %04x/%04x %08x/%02x %r\n",
+      Hotkey->KeyData[Index].Key.ScanCode,
+      Hotkey->KeyData[Index].Key.UnicodeChar,
+      Hotkey->KeyData[Index].KeyState.KeyShiftState,
+      Hotkey->KeyData[Index].KeyState.KeyToggleState,
+      Status
+      ));
+    if (EFI_ERROR (Status)) {
+      //
+      // some of the hotkey registry failed
+      // do not unregister all in case we have both CTRL-ALT-P and CTRL-ALT-P-R
+      //
+      break;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Generate key shift state base on the input key option info.
+
+  @param    Depth                 Which key is checked.
+  @param    KeyOption             Input key option info.
+  @param    KeyShiftState         Input key shift state.
+  @param    KeyShiftStates        Return possible key shift state array.
+  @param    KeyShiftStateCount    Possible key shift state count.
+**/
+VOID
+BmGenerateKeyShiftState (
+  IN UINTN                             Depth,
+  IN EFI_BOOT_MANAGER_KEY_OPTION       *KeyOption,
+  IN UINT32                            KeyShiftState,
+  IN UINT32                            *KeyShiftStates,
+  IN UINTN                             *KeyShiftStateCount
+  )
+{
+  switch (Depth) {
+  case 0:
+    if (KeyOption->KeyData.Options.ShiftPressed) {
+      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_SHIFT_PRESSED, KeyShiftStates, KeyShiftStateCount);
+      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_SHIFT_PRESSED,  KeyShiftStates, KeyShiftStateCount);
+    } else {
+      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);
+    }
+    break;
+
+  case 1:
+    if (KeyOption->KeyData.Options.ControlPressed) {
+      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_CONTROL_PRESSED, KeyShiftStates, KeyShiftStateCount);
+      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_CONTROL_PRESSED,  KeyShiftStates, KeyShiftStateCount);
+    } else {
+      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);
+    }
+    break;
+
+  case 2:
+    if (KeyOption->KeyData.Options.AltPressed) {
+      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_ALT_PRESSED, KeyShiftStates, KeyShiftStateCount);
+      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_ALT_PRESSED,  KeyShiftStates, KeyShiftStateCount);
+    } else {
+      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);
+    }
+    break;
+  case  3:
+    if (KeyOption->KeyData.Options.LogoPressed) {
+      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_LOGO_PRESSED, KeyShiftStates, KeyShiftStateCount);
+      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_LOGO_PRESSED,  KeyShiftStates, KeyShiftStateCount);
+    } else {
+      BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);
+    }
+    break;
+  case 4:
+    if (KeyOption->KeyData.Options.MenuPressed) {
+      KeyShiftState |= EFI_MENU_KEY_PRESSED;
+    }
+    if (KeyOption->KeyData.Options.SysReqPressed) {
+      KeyShiftState |= EFI_SYS_REQ_PRESSED;
+    }
+    KeyShiftStates[*KeyShiftStateCount] = KeyShiftState;
+    (*KeyShiftStateCount)++;
+    break;
+  }
+}
+
+/**
+  Add it to hot key database, register it to existing TxtInEx.
+  New TxtInEx will be automatically registered with all the hot key in dababase
+
+  @param    KeyOption  Input key option info.
+**/
+EFI_STATUS
+BmProcessKeyOption (
+  IN EFI_BOOT_MANAGER_KEY_OPTION       *KeyOption
+  )
+{
+  EFI_STATUS                           Status;
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL    *TxtInEx;
+  EFI_HANDLE                           *Handles;
+  UINTN                                HandleCount;
+  UINTN                                HandleIndex;
+  UINTN                                Index;
+  BM_HOTKEY                            *Hotkey;
+  UINTN                                KeyIndex;
+  //
+  // 16 is enough to enumerate all the possible combination of LEFT_XXX and RIGHT_XXX
+  //
+  UINT32                               KeyShiftStates[16];
+  UINTN                                KeyShiftStateCount;
+
+  if (KeyOption->KeyData.Options.InputKeyCount > mBmHotkeySupportCount) {
+    return EFI_UNSUPPORTED;
+  }
+
+  KeyShiftStateCount = 0;
+  BmGenerateKeyShiftState (0, KeyOption, EFI_SHIFT_STATE_VALID, KeyShiftStates, &KeyShiftStateCount);
+  ASSERT (KeyShiftStateCount <= sizeof (KeyShiftStates) / sizeof (KeyShiftStates[0]));
+
+  EfiAcquireLock (&mBmHotkeyLock);
+
+  for (Index = 0; Index < KeyShiftStateCount; Index++) {
+    Hotkey = AllocateZeroPool (sizeof (BM_HOTKEY));
+    ASSERT (Hotkey != NULL);
+
+    Hotkey->Signature  = BM_HOTKEY_SIGNATURE;
+    Hotkey->BootOption = KeyOption->BootOption;
+    Hotkey->IsContinue = (BOOLEAN) (KeyOption == mBmContinueKeyOption);
+    Hotkey->CodeCount  = (UINT8) KeyOption->KeyData.Options.InputKeyCount;
+
+    for (KeyIndex = 0; KeyIndex < Hotkey->CodeCount; KeyIndex++) {
+      CopyMem (&Hotkey->KeyData[KeyIndex].Key, &KeyOption->Keys[KeyIndex], sizeof (EFI_INPUT_KEY));
+      Hotkey->KeyData[KeyIndex].KeyState.KeyShiftState = KeyShiftStates[Index];
+    }
+    InsertTailList (&mBmHotkeyList, &Hotkey->Link);
+
+    gBS->LocateHandleBuffer (
+            ByProtocol,
+            &gEfiSimpleTextInputExProtocolGuid,
+            NULL,
+            &HandleCount,
+            &Handles
+            );
+    for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+      Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);
+      ASSERT_EFI_ERROR (Status);
+      BmRegisterHotkeyNotify (TxtInEx, Hotkey);
+    }
+  }
+
+  EfiReleaseLock (&mBmHotkeyLock);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Callback function for SimpleTextInEx protocol install events
+
+  @param Event           the event that is signaled.
+  @param Context         not used here.
+
+**/
+VOID
+EFIAPI
+BmTxtInExCallback (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  )
+{
+  EFI_STATUS                         Status;
+  UINTN                              BufferSize;
+  EFI_HANDLE                         Handle;
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *TxtInEx;
+  LIST_ENTRY                         *Link;
+
+  while (TRUE) {
+    BufferSize = sizeof (EFI_HANDLE);
+    Status = gBS->LocateHandle (
+                    ByRegisterNotify,
+                    NULL,
+                    mBmTxtInExRegistration,
+                    &BufferSize,
+                    &Handle
+                    );
+    if (EFI_ERROR (Status)) {
+      //
+      // If no more notification events exist
+      //
+      return ;
+    }
+
+    Status = gBS->HandleProtocol (
+                    Handle,
+                    &gEfiSimpleTextInputExProtocolGuid,
+                    (VOID **) &TxtInEx
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // Register the hot key notification for the existing items in the list
+    //
+    EfiAcquireLock (&mBmHotkeyLock);
+    for (Link = GetFirstNode (&mBmHotkeyList); !IsNull (&mBmHotkeyList, Link); Link = GetNextNode (&mBmHotkeyList, Link)) {
+      BmRegisterHotkeyNotify (TxtInEx, BM_HOTKEY_FROM_LINK (Link));
+    }
+    EfiReleaseLock (&mBmHotkeyLock);
+  }
+}
+
+/**
+  Free the key options returned from BmGetKeyOptions.
+
+  @param KeyOptions     Pointer to the key options.
+  @param KeyOptionCount Number of the key options.
+
+  @retval EFI_SUCCESS   The key options are freed.
+  @retval EFI_NOT_FOUND KeyOptions is NULL.
+**/
+EFI_STATUS
+BmFreeKeyOptions (
+  IN EFI_BOOT_MANAGER_KEY_OPTION    *KeyOptions,
+  IN UINTN                          KeyOptionCount
+  )
+{
+  if (KeyOptions != NULL) {
+    FreePool (KeyOptions);
+    return EFI_SUCCESS;
+  } else {
+    return EFI_NOT_FOUND;
+  }
+}
+
+/**
+  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,
+  ...
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_BOOT_MANAGER_KEY_OPTION  KeyOption;
+  VA_LIST                      Args;
+  
+  if (mBmContinueKeyOption != NULL) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
+  VA_START (Args, Modifier);
+  Status = BmInitializeKeyFields (Modifier, Args, &KeyOption);
+  VA_END (Args);
+
+  if (!EFI_ERROR (Status)) {
+    mBmContinueKeyOption = AllocateCopyPool (sizeof (EFI_BOOT_MANAGER_KEY_OPTION), &KeyOption);
+    ASSERT (mBmContinueKeyOption != NULL);
+    if (mBmHotkeyServiceStarted) {
+      BmProcessKeyOption (mBmContinueKeyOption);
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Stop the hotkey processing.
+  
+  @param    Event          Event pointer related to hotkey service.
+  @param    Context        Context pass to this function.
+**/
+VOID
+EFIAPI
+BmStopHotkeyService (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  )
+{
+  LIST_ENTRY            *Link;
+  BM_HOTKEY             *Hotkey;
+
+  DEBUG ((EFI_D_INFO, "[Bds]Stop Hotkey Service!\n"));
+  gBS->CloseEvent (Event);
+
+  EfiAcquireLock (&mBmHotkeyLock);
+  for (Link = GetFirstNode (&mBmHotkeyList); !IsNull (&mBmHotkeyList, Link); ) {
+    Hotkey = BM_HOTKEY_FROM_LINK (Link);
+    BmUnregisterHotkeyNotify (Hotkey);
+    Link   = RemoveEntryList (Link);
+    FreePool (Hotkey);
+  }
+  EfiReleaseLock (&mBmHotkeyLock);
+}
+
+/**
+  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
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_BOOT_MANAGER_KEY_OPTION  *KeyOptions;
+  UINTN                        KeyOptionCount;
+  UINTN                        Index;
+  EFI_EVENT                    Event;
+  UINT32                       *BootOptionSupport;
+
+  Status = GetEfiGlobalVariable2 (EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME, (VOID **) &BootOptionSupport, NULL);
+  ASSERT (BootOptionSupport != NULL);
+
+  if ((*BootOptionSupport & EFI_BOOT_OPTION_SUPPORT_KEY)  != 0) {
+    mBmHotkeySupportCount = ((*BootOptionSupport & EFI_BOOT_OPTION_SUPPORT_COUNT) >> LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT));
+  }
+  FreePool (BootOptionSupport);
+
+  if (mBmHotkeySupportCount == 0) {
+    DEBUG ((EFI_D_INFO, "Bds: BootOptionSupport NV variable forbids starting the hotkey service.\n"));
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = gBS->CreateEvent (
+                  EVT_NOTIFY_WAIT,
+                  TPL_CALLBACK,
+                  BmEmptyFunction,
+                  NULL,
+                  &mBmHotkeyTriggered
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  if (HotkeyTriggered != NULL) {
+    *HotkeyTriggered = mBmHotkeyTriggered;
+  }
+
+  KeyOptions = BmGetKeyOptions (&KeyOptionCount);
+  for (Index = 0; Index < KeyOptionCount; Index ++) {
+    BmProcessKeyOption (&KeyOptions[Index]);
+  }
+  BmFreeKeyOptions (KeyOptions, KeyOptionCount);
+
+  if (mBmContinueKeyOption != NULL) {
+    BmProcessKeyOption (mBmContinueKeyOption);
+  }
+
+  EfiCreateProtocolNotifyEvent (
+    &gEfiSimpleTextInputExProtocolGuid,
+    TPL_CALLBACK,
+    BmTxtInExCallback,
+    NULL,
+    &mBmTxtInExRegistration
+    );
+
+  Status = EfiCreateEventReadyToBootEx (
+             TPL_CALLBACK,
+             BmStopHotkeyService,
+             NULL,
+             &Event
+             );
+  ASSERT_EFI_ERROR (Status);
+
+
+  mBmHotkeyServiceStarted = TRUE;
+  return Status;
+}
+
+/**
+  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,
+  ...
+  )
+{
+  EFI_STATUS                     Status;
+  VA_LIST                        Args;
+  VOID                           *BootOption;
+  UINTN                          BootOptionSize;
+  CHAR16                         BootOptionName[sizeof (L"Boot####")];
+  EFI_BOOT_MANAGER_KEY_OPTION    KeyOption;
+  EFI_BOOT_MANAGER_KEY_OPTION    *KeyOptions;
+  UINTN                          KeyOptionCount;
+  UINTN                          Index;
+  UINTN                          KeyOptionNumber;
+  CHAR16                         KeyOptionName[sizeof (L"Key####")];
+
+  UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", BootOptionNumber);
+  GetEfiGlobalVariable2 (BootOptionName, &BootOption, &BootOptionSize);
+
+  if (BootOption == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
+  KeyOption.BootOption = BootOptionNumber;
+  Status = gBS->CalculateCrc32 (BootOption, BootOptionSize, &KeyOption.BootOptionCrc);
+  ASSERT_EFI_ERROR (Status);
+  FreePool (BootOption);
+
+  VA_START (Args, Modifier);
+  Status = BmInitializeKeyFields (Modifier, Args, &KeyOption);
+  VA_END (Args);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  KeyOptionNumber = LoadOptionNumberUnassigned;
+  //
+  // Check if the hot key sequence was defined already
+  //
+  KeyOptions = BmGetKeyOptions (&KeyOptionCount);
+  for (Index = 0; Index < KeyOptionCount; Index++) {
+    if ((KeyOptions[Index].KeyData.PackedValue == KeyOption.KeyData.PackedValue) &&
+      (CompareMem (KeyOptions[Index].Keys, KeyOption.Keys, KeyOption.KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY)) == 0)) {
+      break;
+    }
+
+    if ((KeyOptionNumber == LoadOptionNumberUnassigned) &&
+        (KeyOptions[Index].OptionNumber > Index)
+       ){
+      KeyOptionNumber = Index;
+    }
+  }
+  BmFreeKeyOptions (KeyOptions, KeyOptionCount);
+
+  if (Index < KeyOptionCount) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  if (KeyOptionNumber == LoadOptionNumberUnassigned) {
+    KeyOptionNumber = KeyOptionCount;
+  }
+
+  UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptionNumber);
+
+  Status = gRT->SetVariable (
+                  KeyOptionName,
+                  &gEfiGlobalVariableGuid,
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                  BmSizeOfKeyOption (&KeyOption),
+                  &KeyOption
+                  );
+  if (!EFI_ERROR (Status)) {
+    //
+    // Return the Key Option in case needed by caller
+    //
+    if (AddedOption != NULL) {
+      CopyMem (AddedOption, &KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
+    }
+
+    //
+    // Register the newly added hot key
+    // Calling this function before EfiBootManagerStartHotkeyService doesn't
+    // need to call BmProcessKeyOption
+    //
+    if (mBmHotkeyServiceStarted) {
+      BmProcessKeyOption (&KeyOption);
+    }
+  }
+
+  return Status;
+}
+
+/**
+  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,
+  ...
+  )
+{
+  EFI_STATUS                     Status;
+  UINTN                          Index;
+  VA_LIST                        Args;
+  EFI_BOOT_MANAGER_KEY_OPTION    KeyOption;
+  EFI_BOOT_MANAGER_KEY_OPTION    *KeyOptions;
+  UINTN                          KeyOptionCount;
+  LIST_ENTRY                     *Link;
+  BM_HOTKEY                      *Hotkey;
+  UINT32                         ShiftState;
+  BOOLEAN                        Match;
+  CHAR16                         KeyOptionName[sizeof (L"Key####")];
+
+  ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
+  VA_START (Args, Modifier);
+  Status = BmInitializeKeyFields (Modifier, Args, &KeyOption);
+  VA_END (Args);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  EfiAcquireLock (&mBmHotkeyLock);
+  //
+  // Delete the key option from active hot key list
+  // Could have multiple entries when modifier isn't 0 because we map the ShiftPressed to RIGHT_SHIFT and RIGHT_SHIFT
+  //
+  for (Link = GetFirstNode (&mBmHotkeyList); !IsNull (&mBmHotkeyList, Link); ) {
+    Hotkey = BM_HOTKEY_FROM_LINK (Link);
+    Match  = (BOOLEAN) (Hotkey->CodeCount == KeyOption.KeyData.Options.InputKeyCount);
+
+    for (Index = 0; Match && (Index < Hotkey->CodeCount); Index++) {
+      ShiftState = Hotkey->KeyData[Index].KeyState.KeyShiftState;
+      if (
+        (BmBitSet (ShiftState, EFI_RIGHT_SHIFT_PRESSED | EFI_LEFT_SHIFT_PRESSED) != KeyOption.KeyData.Options.ShiftPressed) ||
+        (BmBitSet (ShiftState, EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED) != KeyOption.KeyData.Options.ControlPressed) ||
+        (BmBitSet (ShiftState, EFI_RIGHT_ALT_PRESSED | EFI_LEFT_ALT_PRESSED) != KeyOption.KeyData.Options.AltPressed) ||
+        (BmBitSet (ShiftState, EFI_RIGHT_LOGO_PRESSED | EFI_LEFT_LOGO_PRESSED) != KeyOption.KeyData.Options.LogoPressed) ||
+        (BmBitSet (ShiftState, EFI_MENU_KEY_PRESSED) != KeyOption.KeyData.Options.MenuPressed) ||
+        (BmBitSet (ShiftState, EFI_SYS_REQ_PRESSED) != KeyOption.KeyData.Options.SysReqPressed) ||
+        (CompareMem (&Hotkey->KeyData[Index].Key, &KeyOption.Keys[Index], sizeof (EFI_INPUT_KEY)) != 0)
+        ) {
+        //
+        // Break when any field doesn't match
+        //
+        Match = FALSE;
+        break;
+      }
+    }
+
+    if (Match) {
+      Link = RemoveEntryList (Link);
+      FreePool (Hotkey);
+    } else {
+      Link = GetNextNode (&mBmHotkeyList, Link);
+    }
+  }
+
+  //
+  // Delete the key option from the variable
+  //
+  Status     = EFI_NOT_FOUND;
+  KeyOptions = BmGetKeyOptions (&KeyOptionCount);
+  for (Index = 0; Index < KeyOptionCount; Index++) {
+    if ((KeyOptions[Index].KeyData.PackedValue == KeyOption.KeyData.PackedValue) &&
+        (CompareMem (
+           KeyOptions[Index].Keys, KeyOption.Keys,
+           KeyOption.KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY)) == 0)
+       ) {
+      UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptions[Index].OptionNumber);
+      Status = gRT->SetVariable (
+                 KeyOptionName,
+                 &gEfiGlobalVariableGuid,
+                 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                 0,
+                 NULL
+                 );
+      //
+      // Return the deleted key option in case needed by caller
+      //
+      if (DeletedOption != NULL) {
+        CopyMem (DeletedOption, &KeyOptions[Index], sizeof (EFI_BOOT_MANAGER_KEY_OPTION));
+      }
+      break;
+    }
+  }
+  BmFreeKeyOptions (KeyOptions, KeyOptionCount);
+
+  EfiReleaseLock (&mBmHotkeyLock);
+
+  return Status;
+}
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
index 27a8db733e..630307ed03 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
@@ -1,1248 +1,1248 @@
-/** @file
-  Load option library functions which relate with creating and processing load options.
-
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "InternalBm.h"
-
-GLOBAL_REMOVE_IF_UNREFERENCED
-  CHAR16 *mBmLoadOptionName[] = {
-    L"Driver",
-    L"SysPrep",
-    L"Boot"
-  };
-
-GLOBAL_REMOVE_IF_UNREFERENCED
-  CHAR16 *mBmLoadOptionOrderName[] = {
-    EFI_DRIVER_ORDER_VARIABLE_NAME,
-    EFI_SYS_PREP_ORDER_VARIABLE_NAME,
-    EFI_BOOT_ORDER_VARIABLE_NAME
-  };
-
-/**
-  Call Visitor function for each variable in variable storage.
-
-  @param Visitor  Visitor function.
-  @param Context  The context passed to Visitor function.
-**/
-VOID
-BmForEachVariable (
-  VARIABLE_VISITOR            Visitor,
-  VOID                        *Context
-  )
-{
-  EFI_STATUS                  Status;
-  CHAR16                      *Name;
-  EFI_GUID                    Guid;
-  UINTN                       NameSize;
-  UINTN                       NewNameSize;
-
-  NameSize = sizeof (CHAR16);
-  Name = AllocateZeroPool (NameSize);
-  ASSERT (Name != NULL);
-  while (TRUE) {
-    NewNameSize = NameSize;
-    Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
-    if (Status == EFI_BUFFER_TOO_SMALL) {
-      Name = ReallocatePool (NameSize, NewNameSize, Name);
-      ASSERT (Name != NULL);
-      Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
-      NameSize = NewNameSize;
-    }
-
-    if (Status == EFI_NOT_FOUND) {
-      break;
-    }
-    ASSERT_EFI_ERROR (Status);
-
-    Visitor (Name, &Guid, Context);
-  }
-
-  FreePool (Name);
-}
-
-/**
-  Get the Option Number that wasn't used.
-
-  @param  LoadOptionType      The load option type.
-  @param  FreeOptionNumber    Return the minimal free option number.
-
-  @retval EFI_SUCCESS           The option number is found and will be returned.
-  @retval EFI_OUT_OF_RESOURCES  There is no free option number that can be used.
-  @retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
-
-**/
-EFI_STATUS
-BmGetFreeOptionNumber (
-  IN  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType,
-  OUT UINT16                            *FreeOptionNumber
-  )
-{
-  
-  UINTN         OptionNumber;
-  UINTN         Index;
-  UINT16        *OptionOrder;
-  UINTN         OptionOrderSize;
-  UINT16        *BootNext;
-
-  ASSERT (FreeOptionNumber != NULL);
-  ASSERT (LoadOptionType == LoadOptionTypeDriver || 
-          LoadOptionType == LoadOptionTypeBoot ||
-          LoadOptionType == LoadOptionTypeSysPrep);
-
-  GetEfiGlobalVariable2 (mBmLoadOptionOrderName[LoadOptionType], (VOID **) &OptionOrder, &OptionOrderSize);
-  BootNext = NULL;
-  if (LoadOptionType == LoadOptionTypeBoot) {
-    GetEfiGlobalVariable2 (L"BootNext", (VOID**) &BootNext, NULL);
-  }
-
-  for (OptionNumber = 0; 
-       OptionNumber < OptionOrderSize / sizeof (UINT16)
-                    + ((BootNext != NULL) ? 1 : 0); 
-       OptionNumber++
-       ) {
-    //
-    // Search in OptionOrder whether the OptionNumber exists
-    //
-    for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
-      if (OptionNumber == OptionOrder[Index]) {
-        break;
-      }
-    }
-
-    //
-    // We didn't find it in the ****Order array and it doesn't equal to BootNext 
-    // Otherwise, OptionNumber equals to OptionOrderSize / sizeof (UINT16) + 1
-    //
-    if ((Index == OptionOrderSize / sizeof (UINT16)) && 
-        ((BootNext == NULL) || (OptionNumber != *BootNext))
-        ) {
-      break;
-    }
-  }
-  if (OptionOrder != NULL) {
-    FreePool (OptionOrder);
-  }
-
-  if (BootNext != NULL) {
-    FreePool (BootNext);
-  }
-
-  //
-  // When BootOrder & BootNext conver all numbers in the range [0 ... 0xffff],
-  //   OptionNumber equals to 0x10000 which is not valid.
-  //
-  ASSERT (OptionNumber <= 0x10000);
-  if (OptionNumber == 0x10000) {
-    return EFI_OUT_OF_RESOURCES;
-  } else {
-    *FreeOptionNumber = (UINT16) OptionNumber;
-    return EFI_SUCCESS;
-  }
-}
-
-/**
-  Create the Boot####, Driver####, SysPrep####, variable from the load option.
-  
-  @param  LoadOption      Pointer to the load option.
-
-  @retval EFI_SUCCESS     The variable was created.
-  @retval Others          Error status returned by RT->SetVariable.
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerLoadOptionToVariable (
-  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION     *Option
-  )
-{
-  UINTN                            VariableSize;
-  UINT8                            *Variable;
-  UINT8                            *Ptr;
-  CHAR16                           OptionName[BM_OPTION_NAME_LEN];
-  CHAR16                           *Description;
-  CHAR16                           NullChar;
-  UINT32                           VariableAttributes;
-
-  if ((Option->OptionNumber == LoadOptionNumberUnassigned) ||
-      (Option->FilePath == NULL) ||
-      ((UINT32) Option->OptionType >= LoadOptionTypeMax)
-     ) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Convert NULL description to empty description
-  //
-  NullChar    = L'\0';
-  Description = Option->Description;
-  if (Description == NULL) {
-    Description = &NullChar;
-  }
-
-  /*
-  UINT32                      Attributes;
-  UINT16                      FilePathListLength;
-  CHAR16                      Description[];
-  EFI_DEVICE_PATH_PROTOCOL    FilePathList[];
-  UINT8                       OptionalData[];
-TODO: FilePathList[] IS:
-A packed array of UEFI device paths.  The first element of the 
-array is a device path that describes the device and location of the 
-Image for this load option.  The FilePathList[0] is specific 
-to the device type.  Other device paths may optionally exist in the 
-FilePathList, but their usage is OSV specific. Each element 
-in the array is variable length, and ends at the device path end 
-structure.
-  */
-  VariableSize = sizeof (Option->Attributes)
-               + sizeof (UINT16)
-               + StrSize (Description)
-               + GetDevicePathSize (Option->FilePath)
-               + Option->OptionalDataSize;
-
-  Variable     = AllocatePool (VariableSize);
-  ASSERT (Variable != NULL);
-
-  Ptr             = Variable;
-  WriteUnaligned32 ((UINT32 *) Ptr, Option->Attributes);
-  Ptr            += sizeof (Option->Attributes);
-
-  WriteUnaligned16 ((UINT16 *) Ptr, (UINT16) GetDevicePathSize (Option->FilePath));
-  Ptr            += sizeof (UINT16);
-
-  CopyMem (Ptr, Description, StrSize (Description));
-  Ptr            += StrSize (Description);
-
-  CopyMem (Ptr, Option->FilePath, GetDevicePathSize (Option->FilePath));
-  Ptr            += GetDevicePathSize (Option->FilePath);
-
-  CopyMem (Ptr, Option->OptionalData, Option->OptionalDataSize);
-
-  UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[Option->OptionType], Option->OptionNumber);
-
-  VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
-
-  return gRT->SetVariable (
-                OptionName,
-                &gEfiGlobalVariableGuid,
-                VariableAttributes,
-                VariableSize,
-                Variable
-                );
-}
-
-/**
-  Update order variable .
-
-  @param  OptionOrderName     Order variable name which need to be updated.
-  @param  OptionNumber        Option number for the new option.
-  @param  Position            Position of the new load option to put in the ****Order variable.
-
-  @retval EFI_SUCCESS           The boot#### or driver#### have been successfully registered.
-  @retval EFI_ALREADY_STARTED   The option number of Option is being used already.
-  @retval EFI_STATUS            Return the status of gRT->SetVariable ().
-
-**/
-EFI_STATUS
-BmAddOptionNumberToOrderVariable (
-  IN CHAR16               *OptionOrderName,
-  IN UINT16               OptionNumber,
-  IN UINTN                Position
-  )
-{
-  EFI_STATUS              Status;
-  UINTN                   Index;
-  UINT16                  *OptionOrder;
-  UINT16                  *NewOptionOrder;
-  UINTN                   OptionOrderSize;
-  //
-  // Update the option order variable
-  //
-  GetEfiGlobalVariable2 (OptionOrderName, (VOID **) &OptionOrder, &OptionOrderSize);
-
-  Status = EFI_SUCCESS;
-  for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
-    if (OptionOrder[Index] == OptionNumber) {
-      Status = EFI_ALREADY_STARTED;
-      break;
-    }
-  }
-
-  if (!EFI_ERROR (Status)) {
-    Position       = MIN (Position, OptionOrderSize / sizeof (UINT16));
-
-    NewOptionOrder = AllocatePool (OptionOrderSize + sizeof (UINT16));
-    ASSERT (NewOptionOrder != NULL);
-    if (OptionOrderSize != 0) {
-      CopyMem (NewOptionOrder, OptionOrder, Position * sizeof (UINT16));
-      CopyMem (&NewOptionOrder[Position + 1], &OptionOrder[Position], OptionOrderSize - Position * sizeof (UINT16));
-    }
-    NewOptionOrder[Position] = OptionNumber;
-
-    Status = gRT->SetVariable (
-                    OptionOrderName,
-                    &gEfiGlobalVariableGuid,
-                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
-                    OptionOrderSize + sizeof (UINT16),
-                    NewOptionOrder
-                    );
-    FreePool (NewOptionOrder);
-  }
-
-  if (OptionOrder != NULL) {
-    FreePool (OptionOrder);
-  }
-
-  return Status;
-}
-
-/**
-  This function will register the new Boot####, Driver#### or SysPrep#### option.
-  After the *#### is updated, the *Order will also be updated.
-
-  @param  Option            Pointer to load option to add.
-  @param  Position          Position of the new load option to put in the ****Order variable.
-
-  @retval EFI_SUCCESS           The *#### have been successfully registered.
-  @retval EFI_INVALID_PARAMETER The option number exceeds 0xFFFF.
-  @retval EFI_ALREADY_STARTED   The option number of Option is being used already.
-                                Note: this API only adds new load option, no replacement support.
-  @retval EFI_OUT_OF_RESOURCES  There is no free option number that can be used when the
-                                option number specified in the Option is LoadOptionNumberUnassigned.
-  @retval EFI_STATUS            Return the status of gRT->SetVariable ().
-
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerAddLoadOptionVariable (
-  IN EFI_BOOT_MANAGER_LOAD_OPTION *Option,
-  IN UINTN                        Position
-  )
-{
-  EFI_STATUS                      Status;
-  UINT16                          OptionNumber;
-
-  if (Option == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (Option->OptionType != LoadOptionTypeDriver && 
-      Option->OptionType != LoadOptionTypeSysPrep &&
-      Option->OptionType != LoadOptionTypeBoot
-      ) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Get the free option number if the option number is unassigned
-  //
-  if (Option->OptionNumber == LoadOptionNumberUnassigned) {
-    Status = BmGetFreeOptionNumber (Option->OptionType, &OptionNumber);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-    Option->OptionNumber = OptionNumber;
-  }
-
-  if (Option->OptionNumber >= LoadOptionNumberMax) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  Status = BmAddOptionNumberToOrderVariable (mBmLoadOptionOrderName[Option->OptionType], (UINT16) Option->OptionNumber, Position);
-  if (!EFI_ERROR (Status)) {
-    //
-    // Save the Boot#### or Driver#### variable
-    //
-    Status = EfiBootManagerLoadOptionToVariable (Option);
-    if (EFI_ERROR (Status)) {
-      //
-      // Remove the #### from *Order variable when the Driver####/SysPrep####/Boot#### cannot be saved.
-      //
-      EfiBootManagerDeleteLoadOptionVariable (Option->OptionNumber, Option->OptionType);
-    }
-  }
-
-  return Status;
-}
-
-/**
-  Sort the load option. The DriverOrder or BootOrder will be re-created to 
-  reflect the new order.
-
-  @param OptionType             Load option type
-  @param CompareFunction        The comparator
-**/
-VOID
-EFIAPI
-EfiBootManagerSortLoadOptionVariable (
-  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE        OptionType,
-  SORT_COMPARE                             CompareFunction
-  )
-{
-  EFI_STATUS                     Status;
-  EFI_BOOT_MANAGER_LOAD_OPTION   *LoadOption;
-  UINTN                          LoadOptionCount;
-  UINTN                          Index;
-  UINT16                         *OptionOrder;
-
-  LoadOption = EfiBootManagerGetLoadOptions (&LoadOptionCount, OptionType);
-
-  //
-  // Insertion sort algorithm
-  //
-  PerformQuickSort (
-    LoadOption,
-    LoadOptionCount,
-    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),
-    CompareFunction
-    );
-
-  //
-  // Create new ****Order variable
-  //
-  OptionOrder = AllocatePool (LoadOptionCount * sizeof (UINT16));
-  ASSERT (OptionOrder != NULL);
-  for (Index = 0; Index < LoadOptionCount; Index++) {
-    OptionOrder[Index] = (UINT16) LoadOption[Index].OptionNumber;
-  }
-
-  Status = gRT->SetVariable (
-                  mBmLoadOptionOrderName[OptionType],
-                  &gEfiGlobalVariableGuid,
-                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
-                  LoadOptionCount * sizeof (UINT16),
-                  OptionOrder
-                  );
-  //
-  // Changing the *Order content without increasing its size with current variable implementation shouldn't fail.
-  //
-  ASSERT_EFI_ERROR (Status);
-
-  FreePool (OptionOrder);
-  EfiBootManagerFreeLoadOptions (LoadOption, LoadOptionCount);
-}
-
-/**
-  Initialize a load option.
-
-  @param Option           Pointer to the load option to be initialized.
-  @param OptionNumber     Option number of the load option.
-  @param OptionType       Type of the load option.
-  @param Attributes       Attributes of the load option.
-  @param Description      Description of the load option.
-  @param FilePath         Device path of the load option.
-  @param OptionalData     Optional data of the load option.
-  @param OptionalDataSize Size of the optional data of the load option.
-
-  @retval EFI_SUCCESS           The load option was initialized successfully.
-  @retval EFI_INVALID_PARAMETER Option, Description or FilePath is NULL.
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerInitializeLoadOption (
-  IN OUT EFI_BOOT_MANAGER_LOAD_OPTION   *Option,
-  IN  UINTN                             OptionNumber,
-  IN  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
-  IN  UINT32                            Attributes,
-  IN  CHAR16                            *Description,
-  IN  EFI_DEVICE_PATH_PROTOCOL          *FilePath,
-  IN  UINT8                             *OptionalData,   OPTIONAL
-  IN  UINT32                            OptionalDataSize
-  )
-{
-  if ((Option == NULL) || (Description == NULL) || (FilePath == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (((OptionalData != NULL) && (OptionalDataSize == 0)) ||
-      ((OptionalData == NULL) && (OptionalDataSize != 0))) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if ((UINT32) OptionType >= LoadOptionTypeMax) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  ZeroMem (Option, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
-  Option->OptionNumber       = OptionNumber;
-  Option->OptionType         = OptionType;
-  Option->Attributes         = Attributes;
-  Option->Description        = AllocateCopyPool (StrSize (Description), Description);
-  Option->FilePath           = DuplicateDevicePath (FilePath);
-  if (OptionalData != NULL) {
-    Option->OptionalData     = AllocateCopyPool (OptionalDataSize, OptionalData);
-    Option->OptionalDataSize = OptionalDataSize;
-  }
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Return the index of the load option in the load option array.
-
-  The function consider two load options are equal when the 
-  OptionType, Attributes, Description, FilePath and OptionalData are equal.
-
-  @param Key    Pointer to the load option to be found.
-  @param Array  Pointer to the array of load options to be found.
-  @param Count  Number of entries in the Array.
-
-  @retval -1          Key wasn't found in the Array.
-  @retval 0 ~ Count-1 The index of the Key in the Array.
-**/
-INTN
-BmFindLoadOption (
-  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
-  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
-  IN UINTN                              Count
-  )
-{
-  UINTN                             Index;
-
-  for (Index = 0; Index < Count; Index++) {
-    if ((Key->OptionType == Array[Index].OptionType) &&
-        (Key->Attributes == Array[Index].Attributes) &&
-        (StrCmp (Key->Description, Array[Index].Description) == 0) &&
-        (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
-        (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
-        (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
-      return (INTN) Index;
-    }
-  }
-
-  return -1;
-}
-
-/**
-  Delete the load option.
-
-  @param  OptionNumber        Indicate the option number of load option
-  @param  OptionType          Indicate the type of load option
-
-  @retval EFI_INVALID_PARAMETER OptionType or OptionNumber is invalid.
-  @retval EFI_NOT_FOUND         The load option cannot be found
-  @retval EFI_SUCCESS           The load option was deleted
-  @retval others                Status of RT->SetVariable()
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerDeleteLoadOptionVariable (
-  IN UINTN                              OptionNumber,
-  IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE  OptionType
-  )
-{
-  UINT16                            *OptionOrder;
-  UINTN                             OptionOrderSize;
-  EFI_STATUS                        Status;
-  UINTN                             Index;
-
-  if (((UINT32) OptionType >= LoadOptionTypeMax) || (OptionNumber >= LoadOptionNumberMax)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  Status = EFI_NOT_FOUND;
-
-  if (OptionType == LoadOptionTypeDriver || OptionType == LoadOptionTypeSysPrep || OptionType == LoadOptionTypeBoot) {
-    //
-    // If the associated *Order exists, just remove the reference in *Order.
-    //
-    GetEfiGlobalVariable2 (mBmLoadOptionOrderName[OptionType], &OptionOrder, &OptionOrderSize);
-    for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
-      if (OptionOrder[Index] == OptionNumber) {
-        OptionOrderSize -= sizeof (UINT16);
-        CopyMem (&OptionOrder[Index], &OptionOrder[Index + 1], OptionOrderSize - Index * sizeof (UINT16));
-        Status = gRT->SetVariable (
-          mBmLoadOptionOrderName[OptionType],
-          &gEfiGlobalVariableGuid,
-          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
-          OptionOrderSize,
-          OptionOrder
-          );
-        break;
-      }
-    }
-    if (OptionOrder != NULL) {
-      FreePool (OptionOrder);
-    }
-  }
-
-  return Status;
-}
-
-/**
-  Convert a single character to number.
-  It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F'
-
-  @param    Char   The input char which need to convert to int.
-**/
-UINTN
-BmCharToUint (
-  IN CHAR16                           Char
-  )
-{
-  if ((Char >= L'0') && (Char <= L'9')) {
-    return (UINTN) (Char - L'0');
-  }
-
-  if ((Char >= L'A') && (Char <= L'F')) {
-    return (UINTN) (Char - L'A' + 0xA);
-  }
-
-  ASSERT (FALSE);
-  return (UINTN) -1;
-}
-
-/**
-  Returns the size of a device path in bytes.
-
-  This function returns the size, in bytes, of the device path data structure 
-  specified by DevicePath including the end of device path node. If DevicePath 
-  is NULL, then 0 is returned. If the length of the device path is bigger than
-  MaxSize, also return 0 to indicate this is an invalidate device path.
-
-  @param  DevicePath         A pointer to a device path data structure.
-  @param  MaxSize            Max valid device path size. If big than this size, 
-                             return error.
-  
-  @retval 0                  An invalid device path.
-  @retval Others             The size of a device path in bytes.
-
-**/
-UINTN
-BmGetDevicePathSizeEx (
-  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
-  IN UINTN                           MaxSize
-  )
-{
-  UINTN  Size;
-  UINTN  NodeSize;
-
-  if (DevicePath == NULL) {
-    return 0;
-  }
-
-  //
-  // Search for the end of the device path structure
-  //
-  Size = 0;
-  while (!IsDevicePathEnd (DevicePath)) {
-    NodeSize = DevicePathNodeLength (DevicePath);
-    if (NodeSize == 0) {
-      return 0;
-    }
-    Size += NodeSize;
-    if (Size > MaxSize) {
-      return 0;
-    }
-    DevicePath = NextDevicePathNode (DevicePath);
-  }
-  Size += DevicePathNodeLength (DevicePath);
-  if (Size > MaxSize) {
-    return 0;
-  }
-
-  return Size;
-}
-
-/**
-  Returns the length of a Null-terminated Unicode string. If the length is 
-  bigger than MaxStringLen, return length 0 to indicate that this is an 
-  invalidate string.
-
-  This function returns the number of Unicode characters in the Null-terminated
-  Unicode string specified by String. 
-
-  If String is NULL, then ASSERT().
-  If String is not aligned on a 16-bit boundary, then ASSERT().
-
-  @param  String           A pointer to a Null-terminated Unicode string.
-  @param  MaxStringLen     Max string len in this string.
-
-  @retval 0                An invalid string.
-  @retval Others           The length of String.
-
-**/
-UINTN
-BmStrSizeEx (
-  IN      CONST CHAR16              *String,
-  IN      UINTN                     MaxStringLen
-  )
-{
-  UINTN                             Length;
-
-  ASSERT (String != NULL && MaxStringLen != 0);
-  ASSERT (((UINTN) String & BIT0) == 0);
-
-  for (Length = 0; *String != L'\0' && MaxStringLen != Length; String++, Length+=2);
-
-  if (*String != L'\0' && MaxStringLen == Length) {
-    return 0;
-  }
-
-  return Length + 2;
-}
-
-/**
-  Validate the Boot####, Driver####, SysPrep#### variable (VendorGuid/Name)
-
-  @param  Variable              The variable data.
-  @param  VariableSize          The variable size.
-
-  @retval TRUE                  The variable data is correct.
-  @retval FALSE                 The variable data is corrupted.
-
-**/
-BOOLEAN 
-BmValidateOption (
-  UINT8                     *Variable,
-  UINTN                     VariableSize
-  )
-{
-  UINT16                    FilePathSize;
-  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
-  UINTN                     DescriptionSize;
-
-  if (VariableSize <= sizeof (UINT16) + sizeof (UINT32)) {
-    return FALSE;
-  }
-
-  //
-  // Skip the option attribute
-  //
-  Variable += sizeof (UINT32);
-
-  //
-  // Get the option's device path size
-  //
-  FilePathSize = ReadUnaligned16 ((UINT16 *) Variable);
-  Variable += sizeof (UINT16);
-
-  //
-  // Get the option's description string size
-  //
-  DescriptionSize = BmStrSizeEx ((CHAR16 *) Variable, VariableSize - sizeof (UINT16) - sizeof (UINT32));
-  Variable += DescriptionSize;
-
-  //
-  // Get the option's device path
-  //
-  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Variable;
-
-  //
-  // Validation boot option variable.
-  //
-  if ((FilePathSize == 0) || (DescriptionSize == 0)) {
-    return FALSE;
-  }
-
-  if (sizeof (UINT32) + sizeof (UINT16) + DescriptionSize + FilePathSize > VariableSize) {
-    return FALSE;
-  }
-
-  return (BOOLEAN) (BmGetDevicePathSizeEx (DevicePath, FilePathSize) != 0);
-}
-
-/**
-  Check whether the VariableName is a valid load option variable name
-  and return the load option type and option number.
-
-  @param VariableName The name of the load option variable.
-  @param OptionType   Return the load option type.
-  @param OptionNumber Return the load option number.
-
-  @retval TRUE  The variable name is valid; The load option type and
-                load option number is returned.
-  @retval FALSE The variable name is NOT valid.
-**/
-BOOLEAN
-BmIsValidLoadOptionVariableName (
-  IN CHAR16                             *VariableName,
-  OUT EFI_BOOT_MANAGER_LOAD_OPTION_TYPE *OptionType,
-  OUT UINT16                            *OptionNumber
-  )
-{
-  UINTN                             VariableNameLen;
-  UINTN                             Index;
-  UINTN                             Uint;
-
-  VariableNameLen = StrLen (VariableName);
-
-  if (VariableNameLen <= 4) {
-    return FALSE;
-  }
-
-  for (Index = 0; Index < sizeof (mBmLoadOptionName) / sizeof (mBmLoadOptionName[0]); Index++) {
-    if ((VariableNameLen - 4 == StrLen (mBmLoadOptionName[Index])) &&
-        (StrnCmp (VariableName, mBmLoadOptionName[Index], VariableNameLen - 4) == 0)
-        ) {
-      break;
-    }
-  }
-
-  if (Index == sizeof (mBmLoadOptionName) / sizeof (mBmLoadOptionName[0])) {
-    return FALSE;
-  }
-
-  *OptionType = (EFI_BOOT_MANAGER_LOAD_OPTION_TYPE) Index;
-  *OptionNumber = 0;
-  for (Index = VariableNameLen - 4; Index < VariableNameLen; Index++) {
-    Uint = BmCharToUint (VariableName[Index]);
-    if (Uint == -1) {
-      break;
-    } else {
-      *OptionNumber = (UINT16) Uint + *OptionNumber * 0x10;
-    }
-  }
-
-  return (BOOLEAN) (Index == VariableNameLen);
-}
-
-/**
-  Build the Boot#### or Driver#### option from the VariableName.
-
-  @param  VariableName          Variable name of the load option
-  @param  VendorGuid            Variable GUID of the load option
-  @param  Option                Return the load option.
-
-  @retval EFI_SUCCESS     Get the option just been created
-  @retval EFI_NOT_FOUND   Failed to get the new option
-
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerVariableToLoadOptionEx (
-  IN CHAR16                           *VariableName,
-  IN EFI_GUID                         *VendorGuid,
-  IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option  
-  )
-{
-  EFI_STATUS                         Status;
-  UINT32                             Attribute;
-  UINT16                             FilePathSize;
-  UINT8                              *Variable;
-  UINT8                              *VariablePtr;
-  UINTN                              VariableSize;
-  EFI_DEVICE_PATH_PROTOCOL           *FilePath;
-  UINT8                              *OptionalData;
-  UINT32                             OptionalDataSize;
-  CHAR16                             *Description;
-  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE  OptionType;
-  UINT16                             OptionNumber;
-
-  if ((VariableName == NULL) || (Option == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (!BmIsValidLoadOptionVariableName (VariableName, &OptionType, &OptionNumber)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Read the variable
-  //
-  GetVariable2 (VariableName, VendorGuid, (VOID **) &Variable, &VariableSize);
-  if (Variable == NULL) {
-    return EFI_NOT_FOUND;
-  }
-
-  //
-  // Validate *#### variable data.
-  //
-  if (!BmValidateOption(Variable, VariableSize)) {
-    FreePool (Variable);
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Get the option attribute
-  //
-  VariablePtr = Variable;
-  Attribute = ReadUnaligned32 ((UINT32 *) VariablePtr);
-  VariablePtr += sizeof (UINT32);
-
-  //
-  // Get the option's device path size
-  //
-  FilePathSize = ReadUnaligned16 ((UINT16 *) VariablePtr);
-  VariablePtr += sizeof (UINT16);
-
-  //
-  // Get the option's description string
-  //
-  Description = (CHAR16 *) VariablePtr;
-
-  //
-  // Get the option's description string size
-  //
-  VariablePtr += StrSize ((CHAR16 *) VariablePtr);
-
-  //
-  // Get the option's device path
-  //
-  FilePath = (EFI_DEVICE_PATH_PROTOCOL *) VariablePtr;
-  VariablePtr += FilePathSize;
-
-  OptionalDataSize = (UINT32) (VariableSize - (UINTN) (VariablePtr - Variable));
-  if (OptionalDataSize == 0) {
-    OptionalData = NULL;
-  } else {
-    OptionalData = VariablePtr;
-  }
-
-  Status = EfiBootManagerInitializeLoadOption (
-             Option,
-             OptionNumber,
-             OptionType,
-             Attribute,
-             Description,
-             FilePath,
-             OptionalData,
-             OptionalDataSize
-             );
-  ASSERT_EFI_ERROR (Status);
-
-  CopyGuid (&Option->VendorGuid, VendorGuid);
-
-  FreePool (Variable);
-  return Status;
-}
-
-/**
-Build the Boot#### or Driver#### option from the VariableName.
-
-@param  VariableName          EFI Variable name indicate if it is Boot#### or Driver####
-@param  Option                Return the Boot#### or Driver#### option.
-
-@retval EFI_SUCCESS     Get the option just been created
-@retval EFI_NOT_FOUND   Failed to get the new option
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerVariableToLoadOption (
-  IN  CHAR16                          *VariableName,
-  IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option
-  )
-{
-  return EfiBootManagerVariableToLoadOptionEx (VariableName, &gEfiGlobalVariableGuid, 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                             *OptionCount,
-  IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE  LoadOptionType
-  )
-{
-  EFI_STATUS                   Status;
-  UINT16                       *OptionOrder;
-  UINTN                        OptionOrderSize;
-  UINTN                        Index;
-  UINTN                        OptionIndex;
-  EFI_BOOT_MANAGER_LOAD_OPTION *Options;
-  CHAR16                       OptionName[BM_OPTION_NAME_LEN];
-  UINT16                       OptionNumber;
-
-  *OptionCount = 0;
-
-  if (LoadOptionType == LoadOptionTypeDriver || LoadOptionType == LoadOptionTypeSysPrep || LoadOptionType == LoadOptionTypeBoot) {
-    //
-    // Read the BootOrder, or DriverOrder variable.
-    //
-    GetEfiGlobalVariable2 (mBmLoadOptionOrderName[LoadOptionType], (VOID **) &OptionOrder, &OptionOrderSize);
-    if (OptionOrder == NULL) {
-      return NULL;
-    }
-
-    *OptionCount = OptionOrderSize / sizeof (UINT16);
-
-    Options = AllocatePool (*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
-    ASSERT (Options != NULL);
-
-    OptionIndex = 0;
-    for (Index = 0; Index < *OptionCount; Index++) {
-      OptionNumber = OptionOrder[Index];
-      UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[LoadOptionType], OptionNumber);
-
-      Status = EfiBootManagerVariableToLoadOption (OptionName, &Options[OptionIndex]);
-      if (EFI_ERROR (Status)) {
-        DEBUG ((EFI_D_INFO, "[Bds] %s doesn't exist - Update ****Order variable to remove the reference!!", OptionName));
-        EfiBootManagerDeleteLoadOptionVariable (OptionNumber, LoadOptionType);
-      } else {
-        ASSERT (Options[OptionIndex].OptionNumber == OptionNumber);
-        OptionIndex++;
-      }
-    }
-
-    if (OptionOrder != NULL) {
-      FreePool (OptionOrder);
-    }
-
-    if (OptionIndex < *OptionCount) {
-      Options = ReallocatePool (*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION), OptionIndex * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION), Options);
-      ASSERT (Options != NULL);
-      *OptionCount = OptionIndex;
-    }
-
-  } else {
-    return NULL;
-  }
-
-  return Options;
-}
-
-/**
-  Free an EFI_BOOT_MANGER_LOAD_OPTION entry that was allocate by the library.
-
-  @param  LoadOption   Pointer to boot option to Free.
-
-  @return EFI_SUCCESS   BootOption was freed 
-  @return EFI_NOT_FOUND BootOption == NULL 
-
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerFreeLoadOption (
-  IN  EFI_BOOT_MANAGER_LOAD_OPTION  *LoadOption
-  )
-{
-  if (LoadOption == NULL) {
-    return EFI_NOT_FOUND;
-  }
-
-  if (LoadOption->Description != NULL) {
-    FreePool (LoadOption->Description);
-  }
-  if (LoadOption->FilePath != NULL) {
-    FreePool (LoadOption->FilePath);
-  }
-  if (LoadOption->OptionalData != NULL) {
-    FreePool (LoadOption->OptionalData);
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Free an EFI_BOOT_MANGER_LOAD_OPTION array that was allocated by 
-  EfiBootManagerGetLoadOptions().
-
-  @param  Option       Pointer to boot option array to free.
-  @param  OptionCount  Number of array entries in BootOption
-
-  @return EFI_SUCCESS   BootOption was freed 
-  @return EFI_NOT_FOUND BootOption == NULL 
-
-**/
-EFI_STATUS
-EFIAPI
-EfiBootManagerFreeLoadOptions (
-  IN  EFI_BOOT_MANAGER_LOAD_OPTION  *Option,
-  IN  UINTN                         OptionCount
-  )
-{
-  UINTN   Index;
-
-  if (Option == NULL) {
-    return EFI_NOT_FOUND;
-  }
-
-  for (Index = 0;Index < OptionCount; Index++) {
-    EfiBootManagerFreeLoadOption (&Option[Index]);
-  }
-
-  FreePool (Option);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Return whether the PE header of the load option is valid or not.
-
-  @param[in] Type       The load option type.
-  @param[in] FileBuffer The PE file buffer of the load option.
-  @param[in] FileSize   The size of the load option file.
-
-  @retval TRUE  The PE header of the load option is valid.
-  @retval FALSE The PE header of the load option is not valid.
-**/
-BOOLEAN
-BmIsLoadOptionPeHeaderValid (
-  IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type,
-  IN VOID                              *FileBuffer,
-  IN UINTN                             FileSize
-  )
-{
-  EFI_IMAGE_DOS_HEADER              *DosHeader;
-  EFI_IMAGE_OPTIONAL_HEADER_UNION   *PeHeader;
-  EFI_IMAGE_OPTIONAL_HEADER32       *OptionalHeader;
-  UINT16                            Subsystem;
-
-  if (FileBuffer == NULL || FileSize == 0) {
-    return FALSE;
-  }
-
-  //
-  // Read dos header
-  //
-  DosHeader = (EFI_IMAGE_DOS_HEADER *) FileBuffer;
-  if (FileSize >= sizeof (EFI_IMAGE_DOS_HEADER) &&
-      FileSize > DosHeader->e_lfanew && DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE
-      ) {
-    //
-    // Read and check PE signature
-    //
-    PeHeader = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) FileBuffer + DosHeader->e_lfanew);
-    if (FileSize >= DosHeader->e_lfanew + sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) &&
-        PeHeader->Pe32.Signature == EFI_IMAGE_NT_SIGNATURE
-        ) {
-      //
-      // Check PE32 or PE32+ magic, and machine type
-      //
-      OptionalHeader = (EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHeader->Pe32.OptionalHeader;
-      if ((OptionalHeader->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC || 
-           OptionalHeader->Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) &&
-          EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeHeader->Pe32.FileHeader.Machine)
-          ) {
-        //
-        // Check the Subsystem:
-        //   Driver#### must be of type BootServiceDriver or RuntimeDriver
-        //   SysPrep####, Boot####, OsRecovery####, PlatformRecovery#### must be of type Application
-        //
-        Subsystem = OptionalHeader->Subsystem;
-        if ((Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
-            (Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ||
-            (Type == LoadOptionTypeSysPrep && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) ||
-            (Type == LoadOptionTypeBoot && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)
-            ) {
-          return TRUE;
-        }
-      }
-    }
-  }
-
-  return FALSE;
-}
-
-/**
-  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 (
-  IN EFI_BOOT_MANAGER_LOAD_OPTION       *LoadOption
-  )
-{
-  EFI_STATUS                        Status;
-  EFI_DEVICE_PATH_PROTOCOL          *FilePath;
-  EFI_HANDLE                        ImageHandle;
-  EFI_LOADED_IMAGE_PROTOCOL         *ImageInfo;
-  VOID                              *FileBuffer;
-  UINTN                             FileSize;
-
-  if ((UINT32) LoadOption->OptionType >= LoadOptionTypeMax) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (LoadOption->OptionType == LoadOptionTypeBoot) {
-    return EFI_UNSUPPORTED;
-  }
-
-  //
-  // If a load option is not marked as LOAD_OPTION_ACTIVE,
-  // the boot manager will not automatically load the option.
-  //
-  if ((LoadOption->Attributes & LOAD_OPTION_ACTIVE) == 0) {
-    return EFI_SUCCESS;
-  }
-
-  Status = EFI_INVALID_PARAMETER;
-
-  //
-  // Load and start the load option.
-  //
-  DEBUG ((
-    DEBUG_INFO | DEBUG_LOAD, "Process Load Option (%s%04x) ...\n",
-    mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber
-    ));
-  ImageHandle = NULL;
-  FileBuffer = BmGetLoadOptionBuffer (LoadOption->FilePath, &FilePath, &FileSize);
-  DEBUG_CODE (
-    if (FileBuffer != NULL && CompareMem (LoadOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {
-      DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));
-      BmPrintDp (LoadOption->FilePath);
-      DEBUG ((EFI_D_INFO, " -> "));
-      BmPrintDp (FilePath);
-      DEBUG ((EFI_D_INFO, "\n"));
-    }
-  );
-  if (BmIsLoadOptionPeHeaderValid (LoadOption->OptionType, FileBuffer, FileSize)) {
-    Status = gBS->LoadImage (
-                    FALSE,
-                    gImageHandle,
-                    FilePath,
-                    FileBuffer,
-                    FileSize,
-                    &ImageHandle
-                    );
-  }
-  if (FilePath != NULL) {
-    FreePool (FilePath);
-  }
-  if (FileBuffer != NULL) {
-    FreePool (FileBuffer);
-  }
-
-  if (!EFI_ERROR (Status)) {
-    Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
-    ASSERT_EFI_ERROR (Status);
-
-    ImageInfo->LoadOptionsSize = LoadOption->OptionalDataSize;
-    ImageInfo->LoadOptions = LoadOption->OptionalData;
-    //
-    // Before calling the image, enable the Watchdog Timer for the 5-minute period
-    //
-    gBS->SetWatchdogTimer (5 * 60, 0, 0, NULL);
-
-    LoadOption->Status = gBS->StartImage (ImageHandle, &LoadOption->ExitDataSize, &LoadOption->ExitData);
-    DEBUG ((
-      DEBUG_INFO | DEBUG_LOAD, "Load Option (%s%04x) Return Status = %r\n",
-      mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber, LoadOption->Status
-      ));
-
-    //
-    // Clear the Watchdog Timer after the image returns
-    //
-    gBS->SetWatchdogTimer (0, 0, 0, NULL);
-  }
-
-  return Status;
-}
+/** @file
+  Load option library functions which relate with creating and processing load options.
+
+Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "InternalBm.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+  CHAR16 *mBmLoadOptionName[] = {
+    L"Driver",
+    L"SysPrep",
+    L"Boot"
+  };
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+  CHAR16 *mBmLoadOptionOrderName[] = {
+    EFI_DRIVER_ORDER_VARIABLE_NAME,
+    EFI_SYS_PREP_ORDER_VARIABLE_NAME,
+    EFI_BOOT_ORDER_VARIABLE_NAME
+  };
+
+/**
+  Call Visitor function for each variable in variable storage.
+
+  @param Visitor  Visitor function.
+  @param Context  The context passed to Visitor function.
+**/
+VOID
+BmForEachVariable (
+  VARIABLE_VISITOR            Visitor,
+  VOID                        *Context
+  )
+{
+  EFI_STATUS                  Status;
+  CHAR16                      *Name;
+  EFI_GUID                    Guid;
+  UINTN                       NameSize;
+  UINTN                       NewNameSize;
+
+  NameSize = sizeof (CHAR16);
+  Name = AllocateZeroPool (NameSize);
+  ASSERT (Name != NULL);
+  while (TRUE) {
+    NewNameSize = NameSize;
+    Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
+    if (Status == EFI_BUFFER_TOO_SMALL) {
+      Name = ReallocatePool (NameSize, NewNameSize, Name);
+      ASSERT (Name != NULL);
+      Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);
+      NameSize = NewNameSize;
+    }
+
+    if (Status == EFI_NOT_FOUND) {
+      break;
+    }
+    ASSERT_EFI_ERROR (Status);
+
+    Visitor (Name, &Guid, Context);
+  }
+
+  FreePool (Name);
+}
+
+/**
+  Get the Option Number that wasn't used.
+
+  @param  LoadOptionType      The load option type.
+  @param  FreeOptionNumber    Return the minimal free option number.
+
+  @retval EFI_SUCCESS           The option number is found and will be returned.
+  @retval EFI_OUT_OF_RESOURCES  There is no free option number that can be used.
+  @retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
+
+**/
+EFI_STATUS
+BmGetFreeOptionNumber (
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType,
+  OUT UINT16                            *FreeOptionNumber
+  )
+{
+  
+  UINTN         OptionNumber;
+  UINTN         Index;
+  UINT16        *OptionOrder;
+  UINTN         OptionOrderSize;
+  UINT16        *BootNext;
+
+  ASSERT (FreeOptionNumber != NULL);
+  ASSERT (LoadOptionType == LoadOptionTypeDriver || 
+          LoadOptionType == LoadOptionTypeBoot ||
+          LoadOptionType == LoadOptionTypeSysPrep);
+
+  GetEfiGlobalVariable2 (mBmLoadOptionOrderName[LoadOptionType], (VOID **) &OptionOrder, &OptionOrderSize);
+  BootNext = NULL;
+  if (LoadOptionType == LoadOptionTypeBoot) {
+    GetEfiGlobalVariable2 (L"BootNext", (VOID**) &BootNext, NULL);
+  }
+
+  for (OptionNumber = 0; 
+       OptionNumber < OptionOrderSize / sizeof (UINT16)
+                    + ((BootNext != NULL) ? 1 : 0); 
+       OptionNumber++
+       ) {
+    //
+    // Search in OptionOrder whether the OptionNumber exists
+    //
+    for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
+      if (OptionNumber == OptionOrder[Index]) {
+        break;
+      }
+    }
+
+    //
+    // We didn't find it in the ****Order array and it doesn't equal to BootNext 
+    // Otherwise, OptionNumber equals to OptionOrderSize / sizeof (UINT16) + 1
+    //
+    if ((Index == OptionOrderSize / sizeof (UINT16)) && 
+        ((BootNext == NULL) || (OptionNumber != *BootNext))
+        ) {
+      break;
+    }
+  }
+  if (OptionOrder != NULL) {
+    FreePool (OptionOrder);
+  }
+
+  if (BootNext != NULL) {
+    FreePool (BootNext);
+  }
+
+  //
+  // When BootOrder & BootNext conver all numbers in the range [0 ... 0xffff],
+  //   OptionNumber equals to 0x10000 which is not valid.
+  //
+  ASSERT (OptionNumber <= 0x10000);
+  if (OptionNumber == 0x10000) {
+    return EFI_OUT_OF_RESOURCES;
+  } else {
+    *FreeOptionNumber = (UINT16) OptionNumber;
+    return EFI_SUCCESS;
+  }
+}
+
+/**
+  Create the Boot####, Driver####, SysPrep####, variable from the load option.
+  
+  @param  LoadOption      Pointer to the load option.
+
+  @retval EFI_SUCCESS     The variable was created.
+  @retval Others          Error status returned by RT->SetVariable.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerLoadOptionToVariable (
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION     *Option
+  )
+{
+  UINTN                            VariableSize;
+  UINT8                            *Variable;
+  UINT8                            *Ptr;
+  CHAR16                           OptionName[BM_OPTION_NAME_LEN];
+  CHAR16                           *Description;
+  CHAR16                           NullChar;
+  UINT32                           VariableAttributes;
+
+  if ((Option->OptionNumber == LoadOptionNumberUnassigned) ||
+      (Option->FilePath == NULL) ||
+      ((UINT32) Option->OptionType >= LoadOptionTypeMax)
+     ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Convert NULL description to empty description
+  //
+  NullChar    = L'\0';
+  Description = Option->Description;
+  if (Description == NULL) {
+    Description = &NullChar;
+  }
+
+  /*
+  UINT32                      Attributes;
+  UINT16                      FilePathListLength;
+  CHAR16                      Description[];
+  EFI_DEVICE_PATH_PROTOCOL    FilePathList[];
+  UINT8                       OptionalData[];
+TODO: FilePathList[] IS:
+A packed array of UEFI device paths.  The first element of the 
+array is a device path that describes the device and location of the 
+Image for this load option.  The FilePathList[0] is specific 
+to the device type.  Other device paths may optionally exist in the 
+FilePathList, but their usage is OSV specific. Each element 
+in the array is variable length, and ends at the device path end 
+structure.
+  */
+  VariableSize = sizeof (Option->Attributes)
+               + sizeof (UINT16)
+               + StrSize (Description)
+               + GetDevicePathSize (Option->FilePath)
+               + Option->OptionalDataSize;
+
+  Variable     = AllocatePool (VariableSize);
+  ASSERT (Variable != NULL);
+
+  Ptr             = Variable;
+  WriteUnaligned32 ((UINT32 *) Ptr, Option->Attributes);
+  Ptr            += sizeof (Option->Attributes);
+
+  WriteUnaligned16 ((UINT16 *) Ptr, (UINT16) GetDevicePathSize (Option->FilePath));
+  Ptr            += sizeof (UINT16);
+
+  CopyMem (Ptr, Description, StrSize (Description));
+  Ptr            += StrSize (Description);
+
+  CopyMem (Ptr, Option->FilePath, GetDevicePathSize (Option->FilePath));
+  Ptr            += GetDevicePathSize (Option->FilePath);
+
+  CopyMem (Ptr, Option->OptionalData, Option->OptionalDataSize);
+
+  UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[Option->OptionType], Option->OptionNumber);
+
+  VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
+
+  return gRT->SetVariable (
+                OptionName,
+                &gEfiGlobalVariableGuid,
+                VariableAttributes,
+                VariableSize,
+                Variable
+                );
+}
+
+/**
+  Update order variable .
+
+  @param  OptionOrderName     Order variable name which need to be updated.
+  @param  OptionNumber        Option number for the new option.
+  @param  Position            Position of the new load option to put in the ****Order variable.
+
+  @retval EFI_SUCCESS           The boot#### or driver#### have been successfully registered.
+  @retval EFI_ALREADY_STARTED   The option number of Option is being used already.
+  @retval EFI_STATUS            Return the status of gRT->SetVariable ().
+
+**/
+EFI_STATUS
+BmAddOptionNumberToOrderVariable (
+  IN CHAR16               *OptionOrderName,
+  IN UINT16               OptionNumber,
+  IN UINTN                Position
+  )
+{
+  EFI_STATUS              Status;
+  UINTN                   Index;
+  UINT16                  *OptionOrder;
+  UINT16                  *NewOptionOrder;
+  UINTN                   OptionOrderSize;
+  //
+  // Update the option order variable
+  //
+  GetEfiGlobalVariable2 (OptionOrderName, (VOID **) &OptionOrder, &OptionOrderSize);
+
+  Status = EFI_SUCCESS;
+  for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
+    if (OptionOrder[Index] == OptionNumber) {
+      Status = EFI_ALREADY_STARTED;
+      break;
+    }
+  }
+
+  if (!EFI_ERROR (Status)) {
+    Position       = MIN (Position, OptionOrderSize / sizeof (UINT16));
+
+    NewOptionOrder = AllocatePool (OptionOrderSize + sizeof (UINT16));
+    ASSERT (NewOptionOrder != NULL);
+    if (OptionOrderSize != 0) {
+      CopyMem (NewOptionOrder, OptionOrder, Position * sizeof (UINT16));
+      CopyMem (&NewOptionOrder[Position + 1], &OptionOrder[Position], OptionOrderSize - Position * sizeof (UINT16));
+    }
+    NewOptionOrder[Position] = OptionNumber;
+
+    Status = gRT->SetVariable (
+                    OptionOrderName,
+                    &gEfiGlobalVariableGuid,
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                    OptionOrderSize + sizeof (UINT16),
+                    NewOptionOrder
+                    );
+    FreePool (NewOptionOrder);
+  }
+
+  if (OptionOrder != NULL) {
+    FreePool (OptionOrder);
+  }
+
+  return Status;
+}
+
+/**
+  This function will register the new Boot####, Driver#### or SysPrep#### option.
+  After the *#### is updated, the *Order will also be updated.
+
+  @param  Option            Pointer to load option to add.
+  @param  Position          Position of the new load option to put in the ****Order variable.
+
+  @retval EFI_SUCCESS           The *#### have been successfully registered.
+  @retval EFI_INVALID_PARAMETER The option number exceeds 0xFFFF.
+  @retval EFI_ALREADY_STARTED   The option number of Option is being used already.
+                                Note: this API only adds new load option, no replacement support.
+  @retval EFI_OUT_OF_RESOURCES  There is no free option number that can be used when the
+                                option number specified in the Option is LoadOptionNumberUnassigned.
+  @retval EFI_STATUS            Return the status of gRT->SetVariable ().
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerAddLoadOptionVariable (
+  IN EFI_BOOT_MANAGER_LOAD_OPTION *Option,
+  IN UINTN                        Position
+  )
+{
+  EFI_STATUS                      Status;
+  UINT16                          OptionNumber;
+
+  if (Option == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Option->OptionType != LoadOptionTypeDriver && 
+      Option->OptionType != LoadOptionTypeSysPrep &&
+      Option->OptionType != LoadOptionTypeBoot
+      ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Get the free option number if the option number is unassigned
+  //
+  if (Option->OptionNumber == LoadOptionNumberUnassigned) {
+    Status = BmGetFreeOptionNumber (Option->OptionType, &OptionNumber);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    Option->OptionNumber = OptionNumber;
+  }
+
+  if (Option->OptionNumber >= LoadOptionNumberMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = BmAddOptionNumberToOrderVariable (mBmLoadOptionOrderName[Option->OptionType], (UINT16) Option->OptionNumber, Position);
+  if (!EFI_ERROR (Status)) {
+    //
+    // Save the Boot#### or Driver#### variable
+    //
+    Status = EfiBootManagerLoadOptionToVariable (Option);
+    if (EFI_ERROR (Status)) {
+      //
+      // Remove the #### from *Order variable when the Driver####/SysPrep####/Boot#### cannot be saved.
+      //
+      EfiBootManagerDeleteLoadOptionVariable (Option->OptionNumber, Option->OptionType);
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Sort the load option. The DriverOrder or BootOrder will be re-created to 
+  reflect the new order.
+
+  @param OptionType             Load option type
+  @param CompareFunction        The comparator
+**/
+VOID
+EFIAPI
+EfiBootManagerSortLoadOptionVariable (
+  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE        OptionType,
+  SORT_COMPARE                             CompareFunction
+  )
+{
+  EFI_STATUS                     Status;
+  EFI_BOOT_MANAGER_LOAD_OPTION   *LoadOption;
+  UINTN                          LoadOptionCount;
+  UINTN                          Index;
+  UINT16                         *OptionOrder;
+
+  LoadOption = EfiBootManagerGetLoadOptions (&LoadOptionCount, OptionType);
+
+  //
+  // Insertion sort algorithm
+  //
+  PerformQuickSort (
+    LoadOption,
+    LoadOptionCount,
+    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION),
+    CompareFunction
+    );
+
+  //
+  // Create new ****Order variable
+  //
+  OptionOrder = AllocatePool (LoadOptionCount * sizeof (UINT16));
+  ASSERT (OptionOrder != NULL);
+  for (Index = 0; Index < LoadOptionCount; Index++) {
+    OptionOrder[Index] = (UINT16) LoadOption[Index].OptionNumber;
+  }
+
+  Status = gRT->SetVariable (
+                  mBmLoadOptionOrderName[OptionType],
+                  &gEfiGlobalVariableGuid,
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                  LoadOptionCount * sizeof (UINT16),
+                  OptionOrder
+                  );
+  //
+  // Changing the *Order content without increasing its size with current variable implementation shouldn't fail.
+  //
+  ASSERT_EFI_ERROR (Status);
+
+  FreePool (OptionOrder);
+  EfiBootManagerFreeLoadOptions (LoadOption, LoadOptionCount);
+}
+
+/**
+  Initialize a load option.
+
+  @param Option           Pointer to the load option to be initialized.
+  @param OptionNumber     Option number of the load option.
+  @param OptionType       Type of the load option.
+  @param Attributes       Attributes of the load option.
+  @param Description      Description of the load option.
+  @param FilePath         Device path of the load option.
+  @param OptionalData     Optional data of the load option.
+  @param OptionalDataSize Size of the optional data of the load option.
+
+  @retval EFI_SUCCESS           The load option was initialized successfully.
+  @retval EFI_INVALID_PARAMETER Option, Description or FilePath is NULL.
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerInitializeLoadOption (
+  IN OUT EFI_BOOT_MANAGER_LOAD_OPTION   *Option,
+  IN  UINTN                             OptionNumber,
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType,
+  IN  UINT32                            Attributes,
+  IN  CHAR16                            *Description,
+  IN  EFI_DEVICE_PATH_PROTOCOL          *FilePath,
+  IN  UINT8                             *OptionalData,   OPTIONAL
+  IN  UINT32                            OptionalDataSize
+  )
+{
+  if ((Option == NULL) || (Description == NULL) || (FilePath == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (((OptionalData != NULL) && (OptionalDataSize == 0)) ||
+      ((OptionalData == NULL) && (OptionalDataSize != 0))) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((UINT32) OptionType >= LoadOptionTypeMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ZeroMem (Option, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
+  Option->OptionNumber       = OptionNumber;
+  Option->OptionType         = OptionType;
+  Option->Attributes         = Attributes;
+  Option->Description        = AllocateCopyPool (StrSize (Description), Description);
+  Option->FilePath           = DuplicateDevicePath (FilePath);
+  if (OptionalData != NULL) {
+    Option->OptionalData     = AllocateCopyPool (OptionalDataSize, OptionalData);
+    Option->OptionalDataSize = OptionalDataSize;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Return the index of the load option in the load option array.
+
+  The function consider two load options are equal when the 
+  OptionType, Attributes, Description, FilePath and OptionalData are equal.
+
+  @param Key    Pointer to the load option to be found.
+  @param Array  Pointer to the array of load options to be found.
+  @param Count  Number of entries in the Array.
+
+  @retval -1          Key wasn't found in the Array.
+  @retval 0 ~ Count-1 The index of the Key in the Array.
+**/
+INTN
+BmFindLoadOption (
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
+  IN UINTN                              Count
+  )
+{
+  UINTN                             Index;
+
+  for (Index = 0; Index < Count; Index++) {
+    if ((Key->OptionType == Array[Index].OptionType) &&
+        (Key->Attributes == Array[Index].Attributes) &&
+        (StrCmp (Key->Description, Array[Index].Description) == 0) &&
+        (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
+        (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
+        (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
+      return (INTN) Index;
+    }
+  }
+
+  return -1;
+}
+
+/**
+  Delete the load option.
+
+  @param  OptionNumber        Indicate the option number of load option
+  @param  OptionType          Indicate the type of load option
+
+  @retval EFI_INVALID_PARAMETER OptionType or OptionNumber is invalid.
+  @retval EFI_NOT_FOUND         The load option cannot be found
+  @retval EFI_SUCCESS           The load option was deleted
+  @retval others                Status of RT->SetVariable()
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerDeleteLoadOptionVariable (
+  IN UINTN                              OptionNumber,
+  IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE  OptionType
+  )
+{
+  UINT16                            *OptionOrder;
+  UINTN                             OptionOrderSize;
+  EFI_STATUS                        Status;
+  UINTN                             Index;
+
+  if (((UINT32) OptionType >= LoadOptionTypeMax) || (OptionNumber >= LoadOptionNumberMax)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = EFI_NOT_FOUND;
+
+  if (OptionType == LoadOptionTypeDriver || OptionType == LoadOptionTypeSysPrep || OptionType == LoadOptionTypeBoot) {
+    //
+    // If the associated *Order exists, just remove the reference in *Order.
+    //
+    GetEfiGlobalVariable2 (mBmLoadOptionOrderName[OptionType], &OptionOrder, &OptionOrderSize);
+    for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {
+      if (OptionOrder[Index] == OptionNumber) {
+        OptionOrderSize -= sizeof (UINT16);
+        CopyMem (&OptionOrder[Index], &OptionOrder[Index + 1], OptionOrderSize - Index * sizeof (UINT16));
+        Status = gRT->SetVariable (
+          mBmLoadOptionOrderName[OptionType],
+          &gEfiGlobalVariableGuid,
+          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+          OptionOrderSize,
+          OptionOrder
+          );
+        break;
+      }
+    }
+    if (OptionOrder != NULL) {
+      FreePool (OptionOrder);
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Convert a single character to number.
+  It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F'
+
+  @param    Char   The input char which need to convert to int.
+**/
+UINTN
+BmCharToUint (
+  IN CHAR16                           Char
+  )
+{
+  if ((Char >= L'0') && (Char <= L'9')) {
+    return (UINTN) (Char - L'0');
+  }
+
+  if ((Char >= L'A') && (Char <= L'F')) {
+    return (UINTN) (Char - L'A' + 0xA);
+  }
+
+  ASSERT (FALSE);
+  return (UINTN) -1;
+}
+
+/**
+  Returns the size of a device path in bytes.
+
+  This function returns the size, in bytes, of the device path data structure 
+  specified by DevicePath including the end of device path node. If DevicePath 
+  is NULL, then 0 is returned. If the length of the device path is bigger than
+  MaxSize, also return 0 to indicate this is an invalidate device path.
+
+  @param  DevicePath         A pointer to a device path data structure.
+  @param  MaxSize            Max valid device path size. If big than this size, 
+                             return error.
+  
+  @retval 0                  An invalid device path.
+  @retval Others             The size of a device path in bytes.
+
+**/
+UINTN
+BmGetDevicePathSizeEx (
+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
+  IN UINTN                           MaxSize
+  )
+{
+  UINTN  Size;
+  UINTN  NodeSize;
+
+  if (DevicePath == NULL) {
+    return 0;
+  }
+
+  //
+  // Search for the end of the device path structure
+  //
+  Size = 0;
+  while (!IsDevicePathEnd (DevicePath)) {
+    NodeSize = DevicePathNodeLength (DevicePath);
+    if (NodeSize == 0) {
+      return 0;
+    }
+    Size += NodeSize;
+    if (Size > MaxSize) {
+      return 0;
+    }
+    DevicePath = NextDevicePathNode (DevicePath);
+  }
+  Size += DevicePathNodeLength (DevicePath);
+  if (Size > MaxSize) {
+    return 0;
+  }
+
+  return Size;
+}
+
+/**
+  Returns the length of a Null-terminated Unicode string. If the length is 
+  bigger than MaxStringLen, return length 0 to indicate that this is an 
+  invalidate string.
+
+  This function returns the number of Unicode characters in the Null-terminated
+  Unicode string specified by String. 
+
+  If String is NULL, then ASSERT().
+  If String is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  String           A pointer to a Null-terminated Unicode string.
+  @param  MaxStringLen     Max string len in this string.
+
+  @retval 0                An invalid string.
+  @retval Others           The length of String.
+
+**/
+UINTN
+BmStrSizeEx (
+  IN      CONST CHAR16              *String,
+  IN      UINTN                     MaxStringLen
+  )
+{
+  UINTN                             Length;
+
+  ASSERT (String != NULL && MaxStringLen != 0);
+  ASSERT (((UINTN) String & BIT0) == 0);
+
+  for (Length = 0; *String != L'\0' && MaxStringLen != Length; String++, Length+=2);
+
+  if (*String != L'\0' && MaxStringLen == Length) {
+    return 0;
+  }
+
+  return Length + 2;
+}
+
+/**
+  Validate the Boot####, Driver####, SysPrep#### variable (VendorGuid/Name)
+
+  @param  Variable              The variable data.
+  @param  VariableSize          The variable size.
+
+  @retval TRUE                  The variable data is correct.
+  @retval FALSE                 The variable data is corrupted.
+
+**/
+BOOLEAN 
+BmValidateOption (
+  UINT8                     *Variable,
+  UINTN                     VariableSize
+  )
+{
+  UINT16                    FilePathSize;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  UINTN                     DescriptionSize;
+
+  if (VariableSize <= sizeof (UINT16) + sizeof (UINT32)) {
+    return FALSE;
+  }
+
+  //
+  // Skip the option attribute
+  //
+  Variable += sizeof (UINT32);
+
+  //
+  // Get the option's device path size
+  //
+  FilePathSize = ReadUnaligned16 ((UINT16 *) Variable);
+  Variable += sizeof (UINT16);
+
+  //
+  // Get the option's description string size
+  //
+  DescriptionSize = BmStrSizeEx ((CHAR16 *) Variable, VariableSize - sizeof (UINT16) - sizeof (UINT32));
+  Variable += DescriptionSize;
+
+  //
+  // Get the option's device path
+  //
+  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Variable;
+
+  //
+  // Validation boot option variable.
+  //
+  if ((FilePathSize == 0) || (DescriptionSize == 0)) {
+    return FALSE;
+  }
+
+  if (sizeof (UINT32) + sizeof (UINT16) + DescriptionSize + FilePathSize > VariableSize) {
+    return FALSE;
+  }
+
+  return (BOOLEAN) (BmGetDevicePathSizeEx (DevicePath, FilePathSize) != 0);
+}
+
+/**
+  Check whether the VariableName is a valid load option variable name
+  and return the load option type and option number.
+
+  @param VariableName The name of the load option variable.
+  @param OptionType   Return the load option type.
+  @param OptionNumber Return the load option number.
+
+  @retval TRUE  The variable name is valid; The load option type and
+                load option number is returned.
+  @retval FALSE The variable name is NOT valid.
+**/
+BOOLEAN
+BmIsValidLoadOptionVariableName (
+  IN CHAR16                             *VariableName,
+  OUT EFI_BOOT_MANAGER_LOAD_OPTION_TYPE *OptionType,
+  OUT UINT16                            *OptionNumber
+  )
+{
+  UINTN                             VariableNameLen;
+  UINTN                             Index;
+  UINTN                             Uint;
+
+  VariableNameLen = StrLen (VariableName);
+
+  if (VariableNameLen <= 4) {
+    return FALSE;
+  }
+
+  for (Index = 0; Index < sizeof (mBmLoadOptionName) / sizeof (mBmLoadOptionName[0]); Index++) {
+    if ((VariableNameLen - 4 == StrLen (mBmLoadOptionName[Index])) &&
+        (StrnCmp (VariableName, mBmLoadOptionName[Index], VariableNameLen - 4) == 0)
+        ) {
+      break;
+    }
+  }
+
+  if (Index == sizeof (mBmLoadOptionName) / sizeof (mBmLoadOptionName[0])) {
+    return FALSE;
+  }
+
+  *OptionType = (EFI_BOOT_MANAGER_LOAD_OPTION_TYPE) Index;
+  *OptionNumber = 0;
+  for (Index = VariableNameLen - 4; Index < VariableNameLen; Index++) {
+    Uint = BmCharToUint (VariableName[Index]);
+    if (Uint == -1) {
+      break;
+    } else {
+      *OptionNumber = (UINT16) Uint + *OptionNumber * 0x10;
+    }
+  }
+
+  return (BOOLEAN) (Index == VariableNameLen);
+}
+
+/**
+  Build the Boot#### or Driver#### option from the VariableName.
+
+  @param  VariableName          Variable name of the load option
+  @param  VendorGuid            Variable GUID of the load option
+  @param  Option                Return the load option.
+
+  @retval EFI_SUCCESS     Get the option just been created
+  @retval EFI_NOT_FOUND   Failed to get the new option
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerVariableToLoadOptionEx (
+  IN CHAR16                           *VariableName,
+  IN EFI_GUID                         *VendorGuid,
+  IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option  
+  )
+{
+  EFI_STATUS                         Status;
+  UINT32                             Attribute;
+  UINT16                             FilePathSize;
+  UINT8                              *Variable;
+  UINT8                              *VariablePtr;
+  UINTN                              VariableSize;
+  EFI_DEVICE_PATH_PROTOCOL           *FilePath;
+  UINT8                              *OptionalData;
+  UINT32                             OptionalDataSize;
+  CHAR16                             *Description;
+  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE  OptionType;
+  UINT16                             OptionNumber;
+
+  if ((VariableName == NULL) || (Option == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!BmIsValidLoadOptionVariableName (VariableName, &OptionType, &OptionNumber)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Read the variable
+  //
+  GetVariable2 (VariableName, VendorGuid, (VOID **) &Variable, &VariableSize);
+  if (Variable == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Validate *#### variable data.
+  //
+  if (!BmValidateOption(Variable, VariableSize)) {
+    FreePool (Variable);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Get the option attribute
+  //
+  VariablePtr = Variable;
+  Attribute = ReadUnaligned32 ((UINT32 *) VariablePtr);
+  VariablePtr += sizeof (UINT32);
+
+  //
+  // Get the option's device path size
+  //
+  FilePathSize = ReadUnaligned16 ((UINT16 *) VariablePtr);
+  VariablePtr += sizeof (UINT16);
+
+  //
+  // Get the option's description string
+  //
+  Description = (CHAR16 *) VariablePtr;
+
+  //
+  // Get the option's description string size
+  //
+  VariablePtr += StrSize ((CHAR16 *) VariablePtr);
+
+  //
+  // Get the option's device path
+  //
+  FilePath = (EFI_DEVICE_PATH_PROTOCOL *) VariablePtr;
+  VariablePtr += FilePathSize;
+
+  OptionalDataSize = (UINT32) (VariableSize - (UINTN) (VariablePtr - Variable));
+  if (OptionalDataSize == 0) {
+    OptionalData = NULL;
+  } else {
+    OptionalData = VariablePtr;
+  }
+
+  Status = EfiBootManagerInitializeLoadOption (
+             Option,
+             OptionNumber,
+             OptionType,
+             Attribute,
+             Description,
+             FilePath,
+             OptionalData,
+             OptionalDataSize
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  CopyGuid (&Option->VendorGuid, VendorGuid);
+
+  FreePool (Variable);
+  return Status;
+}
+
+/**
+Build the Boot#### or Driver#### option from the VariableName.
+
+@param  VariableName          EFI Variable name indicate if it is Boot#### or Driver####
+@param  Option                Return the Boot#### or Driver#### option.
+
+@retval EFI_SUCCESS     Get the option just been created
+@retval EFI_NOT_FOUND   Failed to get the new option
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerVariableToLoadOption (
+  IN  CHAR16                          *VariableName,
+  IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option
+  )
+{
+  return EfiBootManagerVariableToLoadOptionEx (VariableName, &gEfiGlobalVariableGuid, 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                             *OptionCount,
+  IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE  LoadOptionType
+  )
+{
+  EFI_STATUS                   Status;
+  UINT16                       *OptionOrder;
+  UINTN                        OptionOrderSize;
+  UINTN                        Index;
+  UINTN                        OptionIndex;
+  EFI_BOOT_MANAGER_LOAD_OPTION *Options;
+  CHAR16                       OptionName[BM_OPTION_NAME_LEN];
+  UINT16                       OptionNumber;
+
+  *OptionCount = 0;
+
+  if (LoadOptionType == LoadOptionTypeDriver || LoadOptionType == LoadOptionTypeSysPrep || LoadOptionType == LoadOptionTypeBoot) {
+    //
+    // Read the BootOrder, or DriverOrder variable.
+    //
+    GetEfiGlobalVariable2 (mBmLoadOptionOrderName[LoadOptionType], (VOID **) &OptionOrder, &OptionOrderSize);
+    if (OptionOrder == NULL) {
+      return NULL;
+    }
+
+    *OptionCount = OptionOrderSize / sizeof (UINT16);
+
+    Options = AllocatePool (*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
+    ASSERT (Options != NULL);
+
+    OptionIndex = 0;
+    for (Index = 0; Index < *OptionCount; Index++) {
+      OptionNumber = OptionOrder[Index];
+      UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[LoadOptionType], OptionNumber);
+
+      Status = EfiBootManagerVariableToLoadOption (OptionName, &Options[OptionIndex]);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((EFI_D_INFO, "[Bds] %s doesn't exist - Update ****Order variable to remove the reference!!", OptionName));
+        EfiBootManagerDeleteLoadOptionVariable (OptionNumber, LoadOptionType);
+      } else {
+        ASSERT (Options[OptionIndex].OptionNumber == OptionNumber);
+        OptionIndex++;
+      }
+    }
+
+    if (OptionOrder != NULL) {
+      FreePool (OptionOrder);
+    }
+
+    if (OptionIndex < *OptionCount) {
+      Options = ReallocatePool (*OptionCount * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION), OptionIndex * sizeof (EFI_BOOT_MANAGER_LOAD_OPTION), Options);
+      ASSERT (Options != NULL);
+      *OptionCount = OptionIndex;
+    }
+
+  } else {
+    return NULL;
+  }
+
+  return Options;
+}
+
+/**
+  Free an EFI_BOOT_MANGER_LOAD_OPTION entry that was allocate by the library.
+
+  @param  LoadOption   Pointer to boot option to Free.
+
+  @return EFI_SUCCESS   BootOption was freed 
+  @return EFI_NOT_FOUND BootOption == NULL 
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerFreeLoadOption (
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION  *LoadOption
+  )
+{
+  if (LoadOption == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  if (LoadOption->Description != NULL) {
+    FreePool (LoadOption->Description);
+  }
+  if (LoadOption->FilePath != NULL) {
+    FreePool (LoadOption->FilePath);
+  }
+  if (LoadOption->OptionalData != NULL) {
+    FreePool (LoadOption->OptionalData);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Free an EFI_BOOT_MANGER_LOAD_OPTION array that was allocated by 
+  EfiBootManagerGetLoadOptions().
+
+  @param  Option       Pointer to boot option array to free.
+  @param  OptionCount  Number of array entries in BootOption
+
+  @return EFI_SUCCESS   BootOption was freed 
+  @return EFI_NOT_FOUND BootOption == NULL 
+
+**/
+EFI_STATUS
+EFIAPI
+EfiBootManagerFreeLoadOptions (
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION  *Option,
+  IN  UINTN                         OptionCount
+  )
+{
+  UINTN   Index;
+
+  if (Option == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  for (Index = 0;Index < OptionCount; Index++) {
+    EfiBootManagerFreeLoadOption (&Option[Index]);
+  }
+
+  FreePool (Option);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Return whether the PE header of the load option is valid or not.
+
+  @param[in] Type       The load option type.
+  @param[in] FileBuffer The PE file buffer of the load option.
+  @param[in] FileSize   The size of the load option file.
+
+  @retval TRUE  The PE header of the load option is valid.
+  @retval FALSE The PE header of the load option is not valid.
+**/
+BOOLEAN
+BmIsLoadOptionPeHeaderValid (
+  IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type,
+  IN VOID                              *FileBuffer,
+  IN UINTN                             FileSize
+  )
+{
+  EFI_IMAGE_DOS_HEADER              *DosHeader;
+  EFI_IMAGE_OPTIONAL_HEADER_UNION   *PeHeader;
+  EFI_IMAGE_OPTIONAL_HEADER32       *OptionalHeader;
+  UINT16                            Subsystem;
+
+  if (FileBuffer == NULL || FileSize == 0) {
+    return FALSE;
+  }
+
+  //
+  // Read dos header
+  //
+  DosHeader = (EFI_IMAGE_DOS_HEADER *) FileBuffer;
+  if (FileSize >= sizeof (EFI_IMAGE_DOS_HEADER) &&
+      FileSize > DosHeader->e_lfanew && DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE
+      ) {
+    //
+    // Read and check PE signature
+    //
+    PeHeader = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) FileBuffer + DosHeader->e_lfanew);
+    if (FileSize >= DosHeader->e_lfanew + sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) &&
+        PeHeader->Pe32.Signature == EFI_IMAGE_NT_SIGNATURE
+        ) {
+      //
+      // Check PE32 or PE32+ magic, and machine type
+      //
+      OptionalHeader = (EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHeader->Pe32.OptionalHeader;
+      if ((OptionalHeader->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC || 
+           OptionalHeader->Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) &&
+          EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeHeader->Pe32.FileHeader.Machine)
+          ) {
+        //
+        // Check the Subsystem:
+        //   Driver#### must be of type BootServiceDriver or RuntimeDriver
+        //   SysPrep####, Boot####, OsRecovery####, PlatformRecovery#### must be of type Application
+        //
+        Subsystem = OptionalHeader->Subsystem;
+        if ((Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
+            (Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ||
+            (Type == LoadOptionTypeSysPrep && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) ||
+            (Type == LoadOptionTypeBoot && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)
+            ) {
+          return TRUE;
+        }
+      }
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  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 (
+  IN EFI_BOOT_MANAGER_LOAD_OPTION       *LoadOption
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_DEVICE_PATH_PROTOCOL          *FilePath;
+  EFI_HANDLE                        ImageHandle;
+  EFI_LOADED_IMAGE_PROTOCOL         *ImageInfo;
+  VOID                              *FileBuffer;
+  UINTN                             FileSize;
+
+  if ((UINT32) LoadOption->OptionType >= LoadOptionTypeMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (LoadOption->OptionType == LoadOptionTypeBoot) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // If a load option is not marked as LOAD_OPTION_ACTIVE,
+  // the boot manager will not automatically load the option.
+  //
+  if ((LoadOption->Attributes & LOAD_OPTION_ACTIVE) == 0) {
+    return EFI_SUCCESS;
+  }
+
+  Status = EFI_INVALID_PARAMETER;
+
+  //
+  // Load and start the load option.
+  //
+  DEBUG ((
+    DEBUG_INFO | DEBUG_LOAD, "Process Load Option (%s%04x) ...\n",
+    mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber
+    ));
+  ImageHandle = NULL;
+  FileBuffer = BmGetLoadOptionBuffer (LoadOption->FilePath, &FilePath, &FileSize);
+  DEBUG_CODE (
+    if (FileBuffer != NULL && CompareMem (LoadOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {
+      DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));
+      BmPrintDp (LoadOption->FilePath);
+      DEBUG ((EFI_D_INFO, " -> "));
+      BmPrintDp (FilePath);
+      DEBUG ((EFI_D_INFO, "\n"));
+    }
+  );
+  if (BmIsLoadOptionPeHeaderValid (LoadOption->OptionType, FileBuffer, FileSize)) {
+    Status = gBS->LoadImage (
+                    FALSE,
+                    gImageHandle,
+                    FilePath,
+                    FileBuffer,
+                    FileSize,
+                    &ImageHandle
+                    );
+  }
+  if (FilePath != NULL) {
+    FreePool (FilePath);
+  }
+  if (FileBuffer != NULL) {
+    FreePool (FileBuffer);
+  }
+
+  if (!EFI_ERROR (Status)) {
+    Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
+    ASSERT_EFI_ERROR (Status);
+
+    ImageInfo->LoadOptionsSize = LoadOption->OptionalDataSize;
+    ImageInfo->LoadOptions = LoadOption->OptionalData;
+    //
+    // Before calling the image, enable the Watchdog Timer for the 5-minute period
+    //
+    gBS->SetWatchdogTimer (5 * 60, 0, 0, NULL);
+
+    LoadOption->Status = gBS->StartImage (ImageHandle, &LoadOption->ExitDataSize, &LoadOption->ExitData);
+    DEBUG ((
+      DEBUG_INFO | DEBUG_LOAD, "Load Option (%s%04x) Return Status = %r\n",
+      mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber, LoadOption->Status
+      ));
+
+    //
+    // Clear the Watchdog Timer after the image returns
+    //
+    gBS->SetWatchdogTimer (0, 0, 0, NULL);
+  }
+
+  return Status;
+}
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c b/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c
index 30d955111e..97d1a48cd5 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmMisc.c
@@ -1,386 +1,386 @@
-/** @file
-  Misc library functions.
-
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "InternalBm.h"
-
-/**
-  Delete the instance in Multi which matches partly with Single instance
-
-  @param  Multi                 A pointer to a multi-instance device path data
-                                structure.
-  @param  Single                A pointer to a single-instance device path data
-                                structure.
-
-  @return This function will remove the device path instances in Multi which partly
-          match with the Single, and return the result device path. If there is no
-          remaining device path as a result, this function will return NULL.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-BmDelPartMatchInstance (
-  IN     EFI_DEVICE_PATH_PROTOCOL  *Multi,
-  IN     EFI_DEVICE_PATH_PROTOCOL  *Single
-  )
-{
-  EFI_DEVICE_PATH_PROTOCOL  *Instance;
-  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
-  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;
-  UINTN                     InstanceSize;
-  UINTN                     SingleDpSize;
-
-  NewDevicePath     = NULL;
-  TempNewDevicePath = NULL;
-
-  if (Multi == NULL || Single == NULL) {
-    return Multi;
-  }
-
-  Instance        = GetNextDevicePathInstance (&Multi, &InstanceSize);
-  SingleDpSize    = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;
-  InstanceSize   -= END_DEVICE_PATH_LENGTH;
-
-  while (Instance != NULL) {
-
-    if (CompareMem (Instance, Single, MIN (SingleDpSize, InstanceSize)) != 0) {
-      //
-      // Append the device path instance which does not match with Single
-      //
-      TempNewDevicePath = NewDevicePath;
-      NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);
-      if (TempNewDevicePath != NULL) {
-        FreePool(TempNewDevicePath);
-      }
-    }
-    FreePool(Instance);
-    Instance      = GetNextDevicePathInstance (&Multi, &InstanceSize);
-    InstanceSize -= END_DEVICE_PATH_LENGTH;
-  }
-
-  return NewDevicePath;
-}
-
-/**
-  Function compares a device path data structure to that of all the nodes of a
-  second device path instance.
-
-  @param  Multi                 A pointer to a multi-instance device path data
-                                structure.
-  @param  Single                A pointer to a single-instance device path data
-                                structure.
-
-  @retval TRUE                  If the Single device path is contained within Multi device path.
-  @retval FALSE                 The Single device path is not match within Multi device path.
-
-**/
-BOOLEAN
-BmMatchDevicePaths (
-  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,
-  IN  EFI_DEVICE_PATH_PROTOCOL  *Single
-  )
-{
-  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
-  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
-  UINTN                     Size;
-
-  if (Multi == NULL || Single  == NULL) {
-    return FALSE;
-  }
-
-  DevicePath     = Multi;
-  DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
-
-  //
-  // Search for the match of 'Single' in 'Multi'
-  //
-  while (DevicePathInst != NULL) {
-    //
-    // If the single device path is found in multiple device paths,
-    // return success
-    //
-    if (CompareMem (Single, DevicePathInst, Size) == 0) {
-      FreePool (DevicePathInst);
-      return TRUE;
-    }
-
-    FreePool (DevicePathInst);
-    DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
-  }
-
-  return FALSE;
-}
-
-/**
-  This routine adjust the memory information for different memory type and 
-  save them into the variables for next boot.
-**/
-VOID
-BmSetMemoryTypeInformationVariable (
-  VOID
-  )
-{
-  EFI_STATUS                   Status;
-  EFI_MEMORY_TYPE_INFORMATION  *PreviousMemoryTypeInformation;
-  EFI_MEMORY_TYPE_INFORMATION  *CurrentMemoryTypeInformation;
-  UINTN                        VariableSize;
-  UINTN                        Index;
-  UINTN                        Index1;
-  UINT32                       Previous;
-  UINT32                       Current;
-  UINT32                       Next;
-  EFI_HOB_GUID_TYPE            *GuidHob;
-  BOOLEAN                      MemoryTypeInformationModified;
-  BOOLEAN                      MemoryTypeInformationVariableExists;
-  EFI_BOOT_MODE                BootMode;
-
-  MemoryTypeInformationModified       = FALSE;
-  MemoryTypeInformationVariableExists = FALSE;
-
-
-  BootMode = GetBootModeHob ();
-  //
-  // In BOOT_IN_RECOVERY_MODE, Variable region is not reliable.
-  //
-  if (BootMode == BOOT_IN_RECOVERY_MODE) {
-    return;
-  }
-
-  //
-  // Only check the the Memory Type Information variable in the boot mode 
-  // other than BOOT_WITH_DEFAULT_SETTINGS because the Memory Type
-  // Information is not valid in this boot mode.
-  //
-  if (BootMode != BOOT_WITH_DEFAULT_SETTINGS) {
-    VariableSize = 0;
-    Status = gRT->GetVariable (
-                    EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
-                    &gEfiMemoryTypeInformationGuid,
-                    NULL, 
-                    &VariableSize, 
-                    NULL
-                    );
-    if (Status == EFI_BUFFER_TOO_SMALL) {
-      MemoryTypeInformationVariableExists = TRUE;
-    }
-  }
-
-  //
-  // Retrieve the current memory usage statistics.  If they are not found, then
-  // no adjustments can be made to the Memory Type Information variable.
-  //
-  Status = EfiGetSystemConfigurationTable (
-             &gEfiMemoryTypeInformationGuid,
-             (VOID **) &CurrentMemoryTypeInformation
-             );
-  if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) {
-    return;
-  }
-
-  //
-  // Get the Memory Type Information settings from Hob if they exist,
-  // PEI is responsible for getting them from variable and build a Hob to save them.
-  // If the previous Memory Type Information is not available, then set defaults
-  //
-  GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
-  if (GuidHob == NULL) {
-    //
-    // If Platform has not built Memory Type Info into the Hob, just return.
-    //
-    return;
-  }
-  PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
-  VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
-
-  //
-  // Use a heuristic to adjust the Memory Type Information for the next boot
-  //
-  DEBUG ((EFI_D_INFO, "Memory  Previous  Current    Next   \n"));
-  DEBUG ((EFI_D_INFO, " Type    Pages     Pages     Pages  \n"));
-  DEBUG ((EFI_D_INFO, "======  ========  ========  ========\n"));
-
-  for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
-
-    for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {
-      if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {
-        break;
-      }
-    }
-    if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {
-      continue;
-    }
-
-    //
-    // Previous is the number of pages pre-allocated
-    // Current is the number of pages actually needed
-    //
-    Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;
-    Current  = CurrentMemoryTypeInformation[Index1].NumberOfPages;
-    Next     = Previous;
-
-    //
-    // Inconsistent Memory Reserved across bootings may lead to S4 fail
-    // Write next varible to 125% * current when the pre-allocated memory is:
-    //  1. More than 150% of needed memory and boot mode is BOOT_WITH_DEFAULT_SETTING
-    //  2. Less than the needed memory
-    //
-    if ((Current + (Current >> 1)) < Previous) {
-      if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
-        Next = Current + (Current >> 2);
-      }
-    } else if (Current > Previous) {
-      Next = Current + (Current >> 2);
-    }
-    if (Next > 0 && Next < 4) {
-      Next = 4;
-    }
-
-    if (Next != Previous) {
-      PreviousMemoryTypeInformation[Index].NumberOfPages = Next;
-      MemoryTypeInformationModified = TRUE;
-    }
-
-    DEBUG ((EFI_D_INFO, "  %02x    %08x  %08x  %08x\n", PreviousMemoryTypeInformation[Index].Type, Previous, Current, Next));
-  }
-
-  //
-  // If any changes were made to the Memory Type Information settings, then set the new variable value;
-  // Or create the variable in first boot.
-  //
-  if (MemoryTypeInformationModified || !MemoryTypeInformationVariableExists) {
-    Status = BmSetVariableAndReportStatusCodeOnError (
-               EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
-               &gEfiMemoryTypeInformationGuid,
-               EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS,
-               VariableSize,
-               PreviousMemoryTypeInformation
-               );
-
-    if (!EFI_ERROR (Status)) {
-      //
-      // If the Memory Type Information settings have been modified, then reset the platform
-      // so the new Memory Type Information setting will be used to guarantee that an S4
-      // entry/resume cycle will not fail.
-      //
-      if (MemoryTypeInformationModified) {
-        DEBUG ((EFI_D_INFO, "Memory Type Information settings change. Warm Reset!!!\n"));
-        gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
-      }
-    } else {
-      DEBUG ((EFI_D_ERROR, "Memory Type Information settings cannot be saved. OS S4 may fail!\n"));
-    }
-  }
-}
-
-/**
-  Set the variable and report the error through status code upon failure.
-
-  @param  VariableName           A Null-terminated string that is the name of the vendor's variable.
-                                 Each VariableName is unique for each VendorGuid. VariableName must
-                                 contain 1 or more characters. If VariableName is an empty string,
-                                 then EFI_INVALID_PARAMETER is returned.
-  @param  VendorGuid             A unique identifier for the vendor.
-  @param  Attributes             Attributes bitmask to set for the variable.
-  @param  DataSize               The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, 
-                                 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or 
-                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero 
-                                 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is 
-                                 set, then a SetVariable() call with a DataSize of zero will not cause any change to 
-                                 the variable value (the timestamp associated with the variable may be updated however 
-                                 even if no new data value is provided,see the description of the 
-                                 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not 
-                                 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). 
-  @param  Data                   The contents for the variable.
-
-  @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as
-                                 defined by the Attributes.
-  @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the
-                                 DataSize exceeds the maximum allowed.
-  @retval EFI_INVALID_PARAMETER  VariableName is an empty string.
-  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
-  @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
-  @retval EFI_WRITE_PROTECTED    The variable in question is read-only.
-  @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
-  @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 
-                                 or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo 
-                                 does NOT pass the validation check carried out by the firmware.
-
-  @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.
-**/
-EFI_STATUS
-BmSetVariableAndReportStatusCodeOnError (
-  IN CHAR16     *VariableName,
-  IN EFI_GUID   *VendorGuid,
-  IN UINT32     Attributes,
-  IN UINTN      DataSize,
-  IN VOID       *Data
-  )
-{
-  EFI_STATUS                 Status;
-  EDKII_SET_VARIABLE_STATUS  *SetVariableStatus;
-  UINTN                      NameSize;
-
-  Status = gRT->SetVariable (
-                  VariableName,
-                  VendorGuid,
-                  Attributes,
-                  DataSize,
-                  Data
-                  );
-  if (EFI_ERROR (Status)) {
-    NameSize = StrSize (VariableName);
-    SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize);
-    if (SetVariableStatus != NULL) {
-      CopyGuid (&SetVariableStatus->Guid, VendorGuid);
-      SetVariableStatus->NameSize   = NameSize;
-      SetVariableStatus->DataSize   = DataSize;
-      SetVariableStatus->SetStatus  = Status;
-      SetVariableStatus->Attributes = Attributes;
-      CopyMem (SetVariableStatus + 1,                          VariableName, NameSize);
-      CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data,         DataSize);
-
-      REPORT_STATUS_CODE_EX (
-        EFI_ERROR_CODE,
-        PcdGet32 (PcdErrorCodeSetVariable),
-        0,
-        NULL,
-        &gEdkiiStatusCodeDataTypeVariableGuid,
-        SetVariableStatus,
-        sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize
-        );
-
-      FreePool (SetVariableStatus);
-    }
-  }
-
-  return Status;
-}
-
-
-/**
-  Print the device path info.
-
-  @param DevicePath           The device path need to print.
-**/
-VOID
-BmPrintDp (
-  EFI_DEVICE_PATH_PROTOCOL            *DevicePath
-  )
-{
-  CHAR16                              *Str;
-
-  Str = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
-  DEBUG ((EFI_D_INFO, "%s", Str));
-  if (Str != NULL) {
-    FreePool (Str);
-  }
-}
+/** @file
+  Misc library functions.
+
+Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "InternalBm.h"
+
+/**
+  Delete the instance in Multi which matches partly with Single instance
+
+  @param  Multi                 A pointer to a multi-instance device path data
+                                structure.
+  @param  Single                A pointer to a single-instance device path data
+                                structure.
+
+  @return This function will remove the device path instances in Multi which partly
+          match with the Single, and return the result device path. If there is no
+          remaining device path as a result, this function will return NULL.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+BmDelPartMatchInstance (
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Multi,
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Single
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;
+  UINTN                     InstanceSize;
+  UINTN                     SingleDpSize;
+
+  NewDevicePath     = NULL;
+  TempNewDevicePath = NULL;
+
+  if (Multi == NULL || Single == NULL) {
+    return Multi;
+  }
+
+  Instance        = GetNextDevicePathInstance (&Multi, &InstanceSize);
+  SingleDpSize    = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;
+  InstanceSize   -= END_DEVICE_PATH_LENGTH;
+
+  while (Instance != NULL) {
+
+    if (CompareMem (Instance, Single, MIN (SingleDpSize, InstanceSize)) != 0) {
+      //
+      // Append the device path instance which does not match with Single
+      //
+      TempNewDevicePath = NewDevicePath;
+      NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);
+      if (TempNewDevicePath != NULL) {
+        FreePool(TempNewDevicePath);
+      }
+    }
+    FreePool(Instance);
+    Instance      = GetNextDevicePathInstance (&Multi, &InstanceSize);
+    InstanceSize -= END_DEVICE_PATH_LENGTH;
+  }
+
+  return NewDevicePath;
+}
+
+/**
+  Function compares a device path data structure to that of all the nodes of a
+  second device path instance.
+
+  @param  Multi                 A pointer to a multi-instance device path data
+                                structure.
+  @param  Single                A pointer to a single-instance device path data
+                                structure.
+
+  @retval TRUE                  If the Single device path is contained within Multi device path.
+  @retval FALSE                 The Single device path is not match within Multi device path.
+
+**/
+BOOLEAN
+BmMatchDevicePaths (
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Single
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;
+  UINTN                     Size;
+
+  if (Multi == NULL || Single  == NULL) {
+    return FALSE;
+  }
+
+  DevicePath     = Multi;
+  DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
+
+  //
+  // Search for the match of 'Single' in 'Multi'
+  //
+  while (DevicePathInst != NULL) {
+    //
+    // If the single device path is found in multiple device paths,
+    // return success
+    //
+    if (CompareMem (Single, DevicePathInst, Size) == 0) {
+      FreePool (DevicePathInst);
+      return TRUE;
+    }
+
+    FreePool (DevicePathInst);
+    DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
+  }
+
+  return FALSE;
+}
+
+/**
+  This routine adjust the memory information for different memory type and 
+  save them into the variables for next boot.
+**/
+VOID
+BmSetMemoryTypeInformationVariable (
+  VOID
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_MEMORY_TYPE_INFORMATION  *PreviousMemoryTypeInformation;
+  EFI_MEMORY_TYPE_INFORMATION  *CurrentMemoryTypeInformation;
+  UINTN                        VariableSize;
+  UINTN                        Index;
+  UINTN                        Index1;
+  UINT32                       Previous;
+  UINT32                       Current;
+  UINT32                       Next;
+  EFI_HOB_GUID_TYPE            *GuidHob;
+  BOOLEAN                      MemoryTypeInformationModified;
+  BOOLEAN                      MemoryTypeInformationVariableExists;
+  EFI_BOOT_MODE                BootMode;
+
+  MemoryTypeInformationModified       = FALSE;
+  MemoryTypeInformationVariableExists = FALSE;
+
+
+  BootMode = GetBootModeHob ();
+  //
+  // In BOOT_IN_RECOVERY_MODE, Variable region is not reliable.
+  //
+  if (BootMode == BOOT_IN_RECOVERY_MODE) {
+    return;
+  }
+
+  //
+  // Only check the the Memory Type Information variable in the boot mode 
+  // other than BOOT_WITH_DEFAULT_SETTINGS because the Memory Type
+  // Information is not valid in this boot mode.
+  //
+  if (BootMode != BOOT_WITH_DEFAULT_SETTINGS) {
+    VariableSize = 0;
+    Status = gRT->GetVariable (
+                    EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
+                    &gEfiMemoryTypeInformationGuid,
+                    NULL, 
+                    &VariableSize, 
+                    NULL
+                    );
+    if (Status == EFI_BUFFER_TOO_SMALL) {
+      MemoryTypeInformationVariableExists = TRUE;
+    }
+  }
+
+  //
+  // Retrieve the current memory usage statistics.  If they are not found, then
+  // no adjustments can be made to the Memory Type Information variable.
+  //
+  Status = EfiGetSystemConfigurationTable (
+             &gEfiMemoryTypeInformationGuid,
+             (VOID **) &CurrentMemoryTypeInformation
+             );
+  if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) {
+    return;
+  }
+
+  //
+  // Get the Memory Type Information settings from Hob if they exist,
+  // PEI is responsible for getting them from variable and build a Hob to save them.
+  // If the previous Memory Type Information is not available, then set defaults
+  //
+  GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
+  if (GuidHob == NULL) {
+    //
+    // If Platform has not built Memory Type Info into the Hob, just return.
+    //
+    return;
+  }
+  PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
+  VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
+
+  //
+  // Use a heuristic to adjust the Memory Type Information for the next boot
+  //
+  DEBUG ((EFI_D_INFO, "Memory  Previous  Current    Next   \n"));
+  DEBUG ((EFI_D_INFO, " Type    Pages     Pages     Pages  \n"));
+  DEBUG ((EFI_D_INFO, "======  ========  ========  ========\n"));
+
+  for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
+
+    for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {
+      if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {
+        break;
+      }
+    }
+    if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {
+      continue;
+    }
+
+    //
+    // Previous is the number of pages pre-allocated
+    // Current is the number of pages actually needed
+    //
+    Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;
+    Current  = CurrentMemoryTypeInformation[Index1].NumberOfPages;
+    Next     = Previous;
+
+    //
+    // Inconsistent Memory Reserved across bootings may lead to S4 fail
+    // Write next varible to 125% * current when the pre-allocated memory is:
+    //  1. More than 150% of needed memory and boot mode is BOOT_WITH_DEFAULT_SETTING
+    //  2. Less than the needed memory
+    //
+    if ((Current + (Current >> 1)) < Previous) {
+      if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
+        Next = Current + (Current >> 2);
+      }
+    } else if (Current > Previous) {
+      Next = Current + (Current >> 2);
+    }
+    if (Next > 0 && Next < 4) {
+      Next = 4;
+    }
+
+    if (Next != Previous) {
+      PreviousMemoryTypeInformation[Index].NumberOfPages = Next;
+      MemoryTypeInformationModified = TRUE;
+    }
+
+    DEBUG ((EFI_D_INFO, "  %02x    %08x  %08x  %08x\n", PreviousMemoryTypeInformation[Index].Type, Previous, Current, Next));
+  }
+
+  //
+  // If any changes were made to the Memory Type Information settings, then set the new variable value;
+  // Or create the variable in first boot.
+  //
+  if (MemoryTypeInformationModified || !MemoryTypeInformationVariableExists) {
+    Status = BmSetVariableAndReportStatusCodeOnError (
+               EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
+               &gEfiMemoryTypeInformationGuid,
+               EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+               VariableSize,
+               PreviousMemoryTypeInformation
+               );
+
+    if (!EFI_ERROR (Status)) {
+      //
+      // If the Memory Type Information settings have been modified, then reset the platform
+      // so the new Memory Type Information setting will be used to guarantee that an S4
+      // entry/resume cycle will not fail.
+      //
+      if (MemoryTypeInformationModified) {
+        DEBUG ((EFI_D_INFO, "Memory Type Information settings change. Warm Reset!!!\n"));
+        gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+      }
+    } else {
+      DEBUG ((EFI_D_ERROR, "Memory Type Information settings cannot be saved. OS S4 may fail!\n"));
+    }
+  }
+}
+
+/**
+  Set the variable and report the error through status code upon failure.
+
+  @param  VariableName           A Null-terminated string that is the name of the vendor's variable.
+                                 Each VariableName is unique for each VendorGuid. VariableName must
+                                 contain 1 or more characters. If VariableName is an empty string,
+                                 then EFI_INVALID_PARAMETER is returned.
+  @param  VendorGuid             A unique identifier for the vendor.
+  @param  Attributes             Attributes bitmask to set for the variable.
+  @param  DataSize               The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, 
+                                 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or 
+                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero 
+                                 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is 
+                                 set, then a SetVariable() call with a DataSize of zero will not cause any change to 
+                                 the variable value (the timestamp associated with the variable may be updated however 
+                                 even if no new data value is provided,see the description of the 
+                                 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not 
+                                 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). 
+  @param  Data                   The contents for the variable.
+
+  @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as
+                                 defined by the Attributes.
+  @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the
+                                 DataSize exceeds the maximum allowed.
+  @retval EFI_INVALID_PARAMETER  VariableName is an empty string.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
+  @retval EFI_WRITE_PROTECTED    The variable in question is read-only.
+  @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
+  @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 
+                                 or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo 
+                                 does NOT pass the validation check carried out by the firmware.
+
+  @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.
+**/
+EFI_STATUS
+BmSetVariableAndReportStatusCodeOnError (
+  IN CHAR16     *VariableName,
+  IN EFI_GUID   *VendorGuid,
+  IN UINT32     Attributes,
+  IN UINTN      DataSize,
+  IN VOID       *Data
+  )
+{
+  EFI_STATUS                 Status;
+  EDKII_SET_VARIABLE_STATUS  *SetVariableStatus;
+  UINTN                      NameSize;
+
+  Status = gRT->SetVariable (
+                  VariableName,
+                  VendorGuid,
+                  Attributes,
+                  DataSize,
+                  Data
+                  );
+  if (EFI_ERROR (Status)) {
+    NameSize = StrSize (VariableName);
+    SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize);
+    if (SetVariableStatus != NULL) {
+      CopyGuid (&SetVariableStatus->Guid, VendorGuid);
+      SetVariableStatus->NameSize   = NameSize;
+      SetVariableStatus->DataSize   = DataSize;
+      SetVariableStatus->SetStatus  = Status;
+      SetVariableStatus->Attributes = Attributes;
+      CopyMem (SetVariableStatus + 1,                          VariableName, NameSize);
+      CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data,         DataSize);
+
+      REPORT_STATUS_CODE_EX (
+        EFI_ERROR_CODE,
+        PcdGet32 (PcdErrorCodeSetVariable),
+        0,
+        NULL,
+        &gEdkiiStatusCodeDataTypeVariableGuid,
+        SetVariableStatus,
+        sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize
+        );
+
+      FreePool (SetVariableStatus);
+    }
+  }
+
+  return Status;
+}
+
+
+/**
+  Print the device path info.
+
+  @param DevicePath           The device path need to print.
+**/
+VOID
+BmPrintDp (
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath
+  )
+{
+  CHAR16                              *Str;
+
+  Str = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+  DEBUG ((EFI_D_INFO, "%s", Str));
+  if (Str != NULL) {
+    FreePool (Str);
+  }
+}
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmPerformance.c b/MdeModulePkg/Library/UefiBootManagerLib/BmPerformance.c
index 1fdb7f1fcb..32229d0b0a 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmPerformance.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmPerformance.c
@@ -1,358 +1,358 @@
-/** @file
-  This file include the file which can help to get the system
-  performance, all the function will only include if the performance
-  switch is set.
-
-Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "InternalBm.h"
-
-PERF_HEADER               mBmPerfHeader;
-PERF_DATA                 mBmPerfData;
-EFI_PHYSICAL_ADDRESS      mBmAcpiLowMemoryBase = 0x0FFFFFFFFULL;
-
-/**
-  Get the short verion of PDB file name to be
-  used in performance data logging.
-
-  @param PdbFileName     The long PDB file name.
-  @param GaugeString     The output string to be logged by performance logger.
-
-**/
-VOID
-BmGetShortPdbFileName (
-  IN  CONST CHAR8  *PdbFileName,
-  OUT       CHAR8  *GaugeString
-  )
-{
-  UINTN Index;
-  UINTN Index1;
-  UINTN StartIndex;
-  UINTN EndIndex;
-
-  if (PdbFileName == NULL) {
-    AsciiStrCpy (GaugeString, " ");
-  } else {
-    StartIndex = 0;
-    for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
-      ;
-
-    for (Index = 0; PdbFileName[Index] != 0; Index++) {
-      if (PdbFileName[Index] == '\\') {
-        StartIndex = Index + 1;
-      }
-
-      if (PdbFileName[Index] == '.') {
-        EndIndex = Index;
-      }
-    }
-
-    Index1 = 0;
-    for (Index = StartIndex; Index < EndIndex; Index++) {
-      GaugeString[Index1] = PdbFileName[Index];
-      Index1++;
-      if (Index1 == PERF_TOKEN_LENGTH - 1) {
-        break;
-      }
-    }
-
-    GaugeString[Index1] = 0;
-  }
-
-  return ;
-}
-
-/**
-  Get the name from the Driver handle, which can be a handle with
-  EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.
-  This name can be used in performance data logging.
-
-  @param Handle          Driver handle.
-  @param GaugeString     The output string to be logged by performance logger.
-
-**/
-VOID
-BmGetNameFromHandle (
-  IN  EFI_HANDLE     Handle,
-  OUT CHAR8          *GaugeString
-  )
-{
-  EFI_STATUS                  Status;
-  EFI_LOADED_IMAGE_PROTOCOL   *Image;
-  CHAR8                       *PdbFileName;
-  EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
-
-  AsciiStrCpy (GaugeString, " ");
-
-  //
-  // Get handle name from image protocol
-  //
-  Status = gBS->HandleProtocol (
-                  Handle,
-                  &gEfiLoadedImageProtocolGuid,
-                  (VOID **) &Image
-                  );
-
-  if (EFI_ERROR (Status)) {
-    Status = gBS->OpenProtocol (
-                    Handle,
-                    &gEfiDriverBindingProtocolGuid,
-                    (VOID **) &DriverBinding,
-                    NULL,
-                    NULL,
-                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
-                    );
-    if (EFI_ERROR (Status)) {
-      return ;
-    }
-    //
-    // Get handle name from image protocol
-    //
-    Status = gBS->HandleProtocol (
-                    DriverBinding->ImageHandle,
-                    &gEfiLoadedImageProtocolGuid,
-                    (VOID **) &Image
-                    );
-  }
-
-  PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
-
-  if (PdbFileName != NULL) {
-    BmGetShortPdbFileName (PdbFileName, GaugeString);
-  }
-
-  return ;
-}
-
-/**
-
-  Writes performance data of booting into the allocated memory.
-  OS can process these records.
-
-  @param  Event                 The triggered event.
-  @param  Context               Context for this event.
-
-**/
-VOID
-EFIAPI
-BmWriteBootToOsPerformanceData (
-  IN EFI_EVENT  Event,
-  IN VOID       *Context
-  )
-{
-  EFI_STATUS                Status;
-  UINT32                    LimitCount;
-  EFI_HANDLE                *Handles;
-  UINTN                     NoHandles;
-  CHAR8                     GaugeString[PERF_TOKEN_LENGTH];
-  UINT8                     *Ptr;
-  UINT32                    Index;
-  UINT64                    Ticker;
-  UINT64                    Freq;
-  UINT32                    Duration;
-  UINTN                     LogEntryKey;
-  CONST VOID                *Handle;
-  CONST CHAR8               *Token;
-  CONST CHAR8               *Module;
-  UINT64                    StartTicker;
-  UINT64                    EndTicker;
-  UINT64                    StartValue;
-  UINT64                    EndValue;
-  BOOLEAN                   CountUp;
-  UINTN                     EntryIndex;
-  UINTN                     NumPerfEntries;
-  //
-  // List of flags indicating PerfEntry contains DXE handle
-  //
-  BOOLEAN                   *PerfEntriesAsDxeHandle;
-  UINTN                     VarSize;
-
-  //
-  // Record the performance data for End of BDS
-  //
-  PERF_END(NULL, "BDS", NULL, 0);
-
-  //
-  // Retrieve time stamp count as early as possible
-  //
-  Ticker  = GetPerformanceCounter ();
-
-  Freq    = GetPerformanceCounterProperties (&StartValue, &EndValue);
-  
-  Freq    = DivU64x32 (Freq, 1000);
-
-  mBmPerfHeader.CpuFreq = Freq;
-
-  //
-  // Record BDS raw performance data
-  //
-  if (EndValue >= StartValue) {
-    mBmPerfHeader.BDSRaw = Ticker - StartValue;
-    CountUp            = TRUE;
-  } else {
-    mBmPerfHeader.BDSRaw = StartValue - Ticker;
-    CountUp            = FALSE;
-  }
-
-  if (mBmAcpiLowMemoryBase == 0x0FFFFFFFF) {
-    VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
-    Status = gRT->GetVariable (
-                    L"PerfDataMemAddr",
-                    &gPerformanceProtocolGuid,
-                    NULL,
-                    &VarSize,
-                    &mBmAcpiLowMemoryBase
-                    );
-    if (EFI_ERROR (Status)) {
-      //
-      // Fail to get the variable, return.
-      //
-      return;
-    }
-  }
-
-  //
-  // Put Detailed performance data into memory
-  //
-  Handles = NULL;
-  Status = gBS->LocateHandleBuffer (
-                  AllHandles,
-                  NULL,
-                  NULL,
-                  &NoHandles,
-                  &Handles
-                  );
-  if (EFI_ERROR (Status)) {
-    return ;
-  }
-
-  Ptr        = (UINT8 *) ((UINT32) mBmAcpiLowMemoryBase + sizeof (PERF_HEADER));
-  LimitCount = (UINT32) (PERF_DATA_MAX_LENGTH - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
-
-  NumPerfEntries = 0;
-  LogEntryKey    = 0;
-  while ((LogEntryKey = GetPerformanceMeasurement (
-                          LogEntryKey,
-                          &Handle,
-                          &Token,
-                          &Module,
-                          &StartTicker,
-                          &EndTicker)) != 0) {
-    NumPerfEntries++;
-  }
-  PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));
-  ASSERT (PerfEntriesAsDxeHandle != NULL);
-  
-  //
-  // Get DXE drivers performance
-  //
-  for (Index = 0; Index < NoHandles; Index++) {
-    Ticker = 0;
-    LogEntryKey = 0;
-    EntryIndex  = 0;
-    while ((LogEntryKey = GetPerformanceMeasurement (
-                            LogEntryKey,
-                            &Handle,
-                            &Token,
-                            &Module,
-                            &StartTicker,
-                            &EndTicker)) != 0) {
-      if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {
-        PerfEntriesAsDxeHandle[EntryIndex] = TRUE;
-      }
-      EntryIndex++;
-      if ((Handle == Handles[Index]) && (EndTicker != 0)) {
-        if (StartTicker == 1) {
-          StartTicker = StartValue;
-        }
-        if (EndTicker == 1) {
-          EndTicker = StartValue;
-        }
-        Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
-      }
-    }
-
-    Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
-
-    if (Duration > 0) {
-
-      BmGetNameFromHandle (Handles[Index], GaugeString);
-
-      AsciiStrCpy (mBmPerfData.Token, GaugeString);
-      mBmPerfData.Duration = Duration;
-
-      CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));
-      Ptr += sizeof (PERF_DATA);
-
-      mBmPerfHeader.Count++;
-      if (mBmPerfHeader.Count == LimitCount) {
-        goto Done;
-      }
-    }
-  }
-
-  //
-  // Get inserted performance data
-  //
-  LogEntryKey = 0;
-  EntryIndex  = 0;
-  while ((LogEntryKey = GetPerformanceMeasurement (
-                          LogEntryKey,
-                          &Handle,
-                          &Token,
-                          &Module,
-                          &StartTicker,
-                          &EndTicker)) != 0) {
-    if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {
-
-      ZeroMem (&mBmPerfData, sizeof (PERF_DATA));
-
-      AsciiStrnCpy (mBmPerfData.Token, Token, PERF_TOKEN_LENGTH);
-      if (StartTicker == 1) {
-        StartTicker = StartValue;
-      }
-      if (EndTicker == 1) {
-        EndTicker = StartValue;
-      }
-      Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
-
-      mBmPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
-
-      CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));
-      Ptr += sizeof (PERF_DATA);
-
-      mBmPerfHeader.Count++;
-      if (mBmPerfHeader.Count == LimitCount) {
-        goto Done;
-      }
-    }
-    EntryIndex++;
-  }
-
-Done:
-
-  FreePool (Handles);
-  FreePool (PerfEntriesAsDxeHandle);
-
-  mBmPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
-
-  //
-  // Put performance data to Reserved memory
-  //
-  CopyMem (
-    (UINTN *) (UINTN) mBmAcpiLowMemoryBase,
-    &mBmPerfHeader,
-    sizeof (PERF_HEADER)
-    );
-
-  return ;
-}
+/** @file
+  This file include the file which can help to get the system
+  performance, all the function will only include if the performance
+  switch is set.
+
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "InternalBm.h"
+
+PERF_HEADER               mBmPerfHeader;
+PERF_DATA                 mBmPerfData;
+EFI_PHYSICAL_ADDRESS      mBmAcpiLowMemoryBase = 0x0FFFFFFFFULL;
+
+/**
+  Get the short verion of PDB file name to be
+  used in performance data logging.
+
+  @param PdbFileName     The long PDB file name.
+  @param GaugeString     The output string to be logged by performance logger.
+
+**/
+VOID
+BmGetShortPdbFileName (
+  IN  CONST CHAR8  *PdbFileName,
+  OUT       CHAR8  *GaugeString
+  )
+{
+  UINTN Index;
+  UINTN Index1;
+  UINTN StartIndex;
+  UINTN EndIndex;
+
+  if (PdbFileName == NULL) {
+    AsciiStrCpy (GaugeString, " ");
+  } else {
+    StartIndex = 0;
+    for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
+      ;
+
+    for (Index = 0; PdbFileName[Index] != 0; Index++) {
+      if (PdbFileName[Index] == '\\') {
+        StartIndex = Index + 1;
+      }
+
+      if (PdbFileName[Index] == '.') {
+        EndIndex = Index;
+      }
+    }
+
+    Index1 = 0;
+    for (Index = StartIndex; Index < EndIndex; Index++) {
+      GaugeString[Index1] = PdbFileName[Index];
+      Index1++;
+      if (Index1 == PERF_TOKEN_LENGTH - 1) {
+        break;
+      }
+    }
+
+    GaugeString[Index1] = 0;
+  }
+
+  return ;
+}
+
+/**
+  Get the name from the Driver handle, which can be a handle with
+  EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.
+  This name can be used in performance data logging.
+
+  @param Handle          Driver handle.
+  @param GaugeString     The output string to be logged by performance logger.
+
+**/
+VOID
+BmGetNameFromHandle (
+  IN  EFI_HANDLE     Handle,
+  OUT CHAR8          *GaugeString
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_LOADED_IMAGE_PROTOCOL   *Image;
+  CHAR8                       *PdbFileName;
+  EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+
+  AsciiStrCpy (GaugeString, " ");
+
+  //
+  // Get handle name from image protocol
+  //
+  Status = gBS->HandleProtocol (
+                  Handle,
+                  &gEfiLoadedImageProtocolGuid,
+                  (VOID **) &Image
+                  );
+
+  if (EFI_ERROR (Status)) {
+    Status = gBS->OpenProtocol (
+                    Handle,
+                    &gEfiDriverBindingProtocolGuid,
+                    (VOID **) &DriverBinding,
+                    NULL,
+                    NULL,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                    );
+    if (EFI_ERROR (Status)) {
+      return ;
+    }
+    //
+    // Get handle name from image protocol
+    //
+    Status = gBS->HandleProtocol (
+                    DriverBinding->ImageHandle,
+                    &gEfiLoadedImageProtocolGuid,
+                    (VOID **) &Image
+                    );
+  }
+
+  PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
+
+  if (PdbFileName != NULL) {
+    BmGetShortPdbFileName (PdbFileName, GaugeString);
+  }
+
+  return ;
+}
+
+/**
+
+  Writes performance data of booting into the allocated memory.
+  OS can process these records.
+
+  @param  Event                 The triggered event.
+  @param  Context               Context for this event.
+
+**/
+VOID
+EFIAPI
+BmWriteBootToOsPerformanceData (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  EFI_STATUS                Status;
+  UINT32                    LimitCount;
+  EFI_HANDLE                *Handles;
+  UINTN                     NoHandles;
+  CHAR8                     GaugeString[PERF_TOKEN_LENGTH];
+  UINT8                     *Ptr;
+  UINT32                    Index;
+  UINT64                    Ticker;
+  UINT64                    Freq;
+  UINT32                    Duration;
+  UINTN                     LogEntryKey;
+  CONST VOID                *Handle;
+  CONST CHAR8               *Token;
+  CONST CHAR8               *Module;
+  UINT64                    StartTicker;
+  UINT64                    EndTicker;
+  UINT64                    StartValue;
+  UINT64                    EndValue;
+  BOOLEAN                   CountUp;
+  UINTN                     EntryIndex;
+  UINTN                     NumPerfEntries;
+  //
+  // List of flags indicating PerfEntry contains DXE handle
+  //
+  BOOLEAN                   *PerfEntriesAsDxeHandle;
+  UINTN                     VarSize;
+
+  //
+  // Record the performance data for End of BDS
+  //
+  PERF_END(NULL, "BDS", NULL, 0);
+
+  //
+  // Retrieve time stamp count as early as possible
+  //
+  Ticker  = GetPerformanceCounter ();
+
+  Freq    = GetPerformanceCounterProperties (&StartValue, &EndValue);
+  
+  Freq    = DivU64x32 (Freq, 1000);
+
+  mBmPerfHeader.CpuFreq = Freq;
+
+  //
+  // Record BDS raw performance data
+  //
+  if (EndValue >= StartValue) {
+    mBmPerfHeader.BDSRaw = Ticker - StartValue;
+    CountUp            = TRUE;
+  } else {
+    mBmPerfHeader.BDSRaw = StartValue - Ticker;
+    CountUp            = FALSE;
+  }
+
+  if (mBmAcpiLowMemoryBase == 0x0FFFFFFFF) {
+    VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
+    Status = gRT->GetVariable (
+                    L"PerfDataMemAddr",
+                    &gPerformanceProtocolGuid,
+                    NULL,
+                    &VarSize,
+                    &mBmAcpiLowMemoryBase
+                    );
+    if (EFI_ERROR (Status)) {
+      //
+      // Fail to get the variable, return.
+      //
+      return;
+    }
+  }
+
+  //
+  // Put Detailed performance data into memory
+  //
+  Handles = NULL;
+  Status = gBS->LocateHandleBuffer (
+                  AllHandles,
+                  NULL,
+                  NULL,
+                  &NoHandles,
+                  &Handles
+                  );
+  if (EFI_ERROR (Status)) {
+    return ;
+  }
+
+  Ptr        = (UINT8 *) ((UINT32) mBmAcpiLowMemoryBase + sizeof (PERF_HEADER));
+  LimitCount = (UINT32) (PERF_DATA_MAX_LENGTH - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);
+
+  NumPerfEntries = 0;
+  LogEntryKey    = 0;
+  while ((LogEntryKey = GetPerformanceMeasurement (
+                          LogEntryKey,
+                          &Handle,
+                          &Token,
+                          &Module,
+                          &StartTicker,
+                          &EndTicker)) != 0) {
+    NumPerfEntries++;
+  }
+  PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));
+  ASSERT (PerfEntriesAsDxeHandle != NULL);
+  
+  //
+  // Get DXE drivers performance
+  //
+  for (Index = 0; Index < NoHandles; Index++) {
+    Ticker = 0;
+    LogEntryKey = 0;
+    EntryIndex  = 0;
+    while ((LogEntryKey = GetPerformanceMeasurement (
+                            LogEntryKey,
+                            &Handle,
+                            &Token,
+                            &Module,
+                            &StartTicker,
+                            &EndTicker)) != 0) {
+      if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {
+        PerfEntriesAsDxeHandle[EntryIndex] = TRUE;
+      }
+      EntryIndex++;
+      if ((Handle == Handles[Index]) && (EndTicker != 0)) {
+        if (StartTicker == 1) {
+          StartTicker = StartValue;
+        }
+        if (EndTicker == 1) {
+          EndTicker = StartValue;
+        }
+        Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
+      }
+    }
+
+    Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
+
+    if (Duration > 0) {
+
+      BmGetNameFromHandle (Handles[Index], GaugeString);
+
+      AsciiStrCpy (mBmPerfData.Token, GaugeString);
+      mBmPerfData.Duration = Duration;
+
+      CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));
+      Ptr += sizeof (PERF_DATA);
+
+      mBmPerfHeader.Count++;
+      if (mBmPerfHeader.Count == LimitCount) {
+        goto Done;
+      }
+    }
+  }
+
+  //
+  // Get inserted performance data
+  //
+  LogEntryKey = 0;
+  EntryIndex  = 0;
+  while ((LogEntryKey = GetPerformanceMeasurement (
+                          LogEntryKey,
+                          &Handle,
+                          &Token,
+                          &Module,
+                          &StartTicker,
+                          &EndTicker)) != 0) {
+    if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {
+
+      ZeroMem (&mBmPerfData, sizeof (PERF_DATA));
+
+      AsciiStrnCpy (mBmPerfData.Token, Token, PERF_TOKEN_LENGTH);
+      if (StartTicker == 1) {
+        StartTicker = StartValue;
+      }
+      if (EndTicker == 1) {
+        EndTicker = StartValue;
+      }
+      Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
+
+      mBmPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);
+
+      CopyMem (Ptr, &mBmPerfData, sizeof (PERF_DATA));
+      Ptr += sizeof (PERF_DATA);
+
+      mBmPerfHeader.Count++;
+      if (mBmPerfHeader.Count == LimitCount) {
+        goto Done;
+      }
+    }
+    EntryIndex++;
+  }
+
+Done:
+
+  FreePool (Handles);
+  FreePool (PerfEntriesAsDxeHandle);
+
+  mBmPerfHeader.Signiture = PERFORMANCE_SIGNATURE;
+
+  //
+  // Put performance data to Reserved memory
+  //
+  CopyMem (
+    (UINTN *) (UINTN) mBmAcpiLowMemoryBase,
+    &mBmPerfHeader,
+    sizeof (PERF_HEADER)
+    );
+
+  return ;
+}
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
index c362d8d7cc..8e8534dd4d 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
+++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
@@ -1,441 +1,441 @@
-/** @file
-  BDS library definition, include the file and data structure
-
-Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#ifndef _INTERNAL_BM_H_
-#define _INTERNAL_BM_H_
-
-#include <PiDxe.h>
-
-#include <IndustryStandard/Pci.h>
-#include <IndustryStandard/PeImage.h>
-#include <IndustryStandard/Atapi.h>
-#include <IndustryStandard/Scsi.h>
-
-#include <Protocol/PciRootBridgeIo.h>
-#include <Protocol/BlockIo.h>
-#include <Protocol/LoadedImage.h>
-#include <Protocol/SimpleFileSystem.h>
-#include <Protocol/LoadFile.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/SimpleTextIn.h>
-#include <Protocol/SimpleTextInEx.h>
-#include <Protocol/SimpleTextOut.h>
-#include <Protocol/SimpleNetwork.h>
-#include <Protocol/FirmwareVolume2.h>
-#include <Protocol/PciIo.h>
-#include <Protocol/GraphicsOutput.h>
-#include <Protocol/UsbIo.h>
-#include <Protocol/DiskInfo.h>
-#include <Protocol/IdeControllerInit.h>
-#include <Protocol/BootLogo.h>
-#include <Protocol/DriverHealth.h>
-#include <Protocol/FormBrowser2.h>
-
-#include <Guid/ZeroGuid.h>
-#include <Guid/MemoryTypeInformation.h>
-#include <Guid/FileInfo.h>
-#include <Guid/GlobalVariable.h>
-#include <Guid/Performance.h>
-#include <Guid/StatusCodeDataTypeVariable.h>
-
-#include <Library/PrintLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/UefiLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/DxeServicesTableLib.h>
-#include <Library/HobLib.h>
-#include <Library/BaseLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/PerformanceLib.h>
-#include <Library/PcdLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
-#include <Library/UefiBootManagerLib.h>
-#include <Library/TimerLib.h>
-#include <Library/DxeServicesLib.h>
-#include <Library/ReportStatusCodeLib.h>
-#include <Library/CapsuleLib.h>
-#include <Library/PerformanceLib.h>
-#include <Library/HiiLib.h>
-
-#if !defined (EFI_REMOVABLE_MEDIA_FILE_NAME)
-    #if defined (MDE_CPU_EBC)
-        //
-        // Uefi specification only defines the default boot file name for IA32, X64
-        // and IPF processor, so need define boot file name for EBC architecture here.
-        //
-        #define EFI_REMOVABLE_MEDIA_FILE_NAME L"\\EFI\\BOOT\\BOOTEBC.EFI"
-    #else
-        #error "Can not determine the default boot file name for unknown processor type!"
-    #endif
-#endif
-
-typedef enum {
-  BmAcpiFloppyBoot,
-  BmHardwareDeviceBoot,
-  BmMessageAtapiBoot,
-  BmMessageSataBoot,
-  BmMessageUsbBoot,
-  BmMessageScsiBoot,
-  BmMessageNetworkBoot,
-  BmMiscBoot
-} BM_BOOT_TYPE;
-
-typedef
-CHAR16 *
-(* BM_GET_BOOT_DESCRIPTION) (
-  IN EFI_HANDLE          Handle
-  );
-
-#define BM_OPTION_NAME_LEN                          sizeof ("SysPrep####")
-extern CHAR16  *mBmLoadOptionName[];
-
-typedef
-VOID
-(*VARIABLE_VISITOR) (
-  CHAR16                *Name,
-  EFI_GUID              *Guid,
-  VOID                  *Context
-  );
-
-/**
-  Call Visitor function for each variable in variable storage.
-
-  @param Visitor   Visitor function.
-  @param Context   The context passed to Visitor function.
-**/
-VOID
-ForEachVariable (
-  VARIABLE_VISITOR            Visitor,
-  VOID                        *Context
-  );
-
-/**
-  Repair all the controllers according to the Driver Health status queried.
-**/
-VOID
-BmRepairAllControllers (
-  VOID
-  );
-
-#define BM_HOTKEY_SIGNATURE SIGNATURE_32 ('b', 'm', 'h', 'k')
-typedef struct {
-  UINT32                    Signature;
-  LIST_ENTRY                Link;
-
-  BOOLEAN                   IsContinue;
-  UINT16                    BootOption;
-  UINT8                     CodeCount;
-  UINT8                     WaitingKey;
-  EFI_KEY_DATA              KeyData[3];
-} BM_HOTKEY;
-
-#define BM_HOTKEY_FROM_LINK(a) CR (a, BM_HOTKEY, Link, BM_HOTKEY_SIGNATURE)
-
-/**
-  Get the image file buffer data and buffer size by its device path. 
-
-  @param FilePath  On input, a pointer to an allocated buffer containing the device
-                   path of the file.
-                   On output the pointer could be NULL when the function fails to
-                   load the boot option, or could point to an allocated buffer containing
-                   the device path of the file.
-                   It could be updated by either short-form device path expanding,
-                   or default boot file path appending.
-                   Caller is responsible to free it when it's non-NULL.
-  @param FileSize  A pointer to the size of the file buffer.
-
-  @retval NULL   File is NULL, or FileSize is NULL. Or, the file can't be found.
-  @retval other  The file buffer. The caller is responsible to free the memory.
-**/
-VOID *
-BmLoadEfiBootOption (
-  IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
-  OUT    UINTN                    *FileSize
-  );
-
-/**
-  Get the Option Number that wasn't used.
-
-  @param  LoadOptionType      Load option type.
-  @param  FreeOptionNumber    To receive the minimal free option number.
-
-  @retval EFI_SUCCESS           The option number is found
-  @retval EFI_OUT_OF_RESOURCES  There is no free option number that can be used.
-  @retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
-
-**/
-EFI_STATUS
-BmGetFreeOptionNumber (
-  IN  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType,
-  OUT UINT16                            *FreeOptionNumber
-  );
-
-/**
-
-  Writes performance data of booting into the allocated memory.
-  OS can process these records.
-
-  @param  Event                 The triggered event.
-  @param  Context               Context for this event.
-
-**/
-VOID
-EFIAPI
-BmWriteBootToOsPerformanceData (
-  IN EFI_EVENT  Event,
-  IN VOID       *Context
-  );
-
-
-/**
-  Get the headers (dos, image, optional header) from an image
-
-  @param  Device                SimpleFileSystem device handle
-  @param  FileName              File name for the image
-  @param  DosHeader             Pointer to dos header
-  @param  Hdr                   The buffer in which to return the PE32, PE32+, or TE header.
-
-  @retval EFI_SUCCESS           Successfully get the machine type.
-  @retval EFI_NOT_FOUND         The file is not found.
-  @retval EFI_LOAD_ERROR        File is not a valid image file.
-
-**/
-EFI_STATUS
-BmGetImageHeader (
-  IN  EFI_HANDLE                  Device,
-  IN  CHAR16                      *FileName,
-  OUT EFI_IMAGE_DOS_HEADER        *DosHeader,
-  OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr
-  );
-
-/**
-  This routine adjust the memory information for different memory type and 
-  save them into the variables for next boot.
-**/
-VOID
-BmSetMemoryTypeInformationVariable (
-  VOID
-  );
-
-/**
-  Check whether there is a instance in BlockIoDevicePath, which contain multi device path
-  instances, has the same partition node with HardDriveDevicePath device path
-
-  @param  BlockIoDevicePath      Multi device path instances which need to check
-  @param  HardDriveDevicePath    A device path which starts with a hard drive media
-                                 device path.
-
-  @retval TRUE                   There is a matched device path instance.
-  @retval FALSE                  There is no matched device path instance.
-
-**/
-BOOLEAN
-BmMatchPartitionDevicePathNode (
-  IN  EFI_DEVICE_PATH_PROTOCOL   *BlockIoDevicePath,
-  IN  HARDDRIVE_DEVICE_PATH      *HardDriveDevicePath
-  );
-
-/**
-  Connect the specific Usb device which match the short form device path.
-
-  @param  DevicePath             A short-form device path that starts with the first
-                                 element being a USB WWID or a USB Class device
-                                 path
-
-  @return EFI_INVALID_PARAMETER  DevicePath is NULL pointer.
-                                 DevicePath is not a USB device path.
-
-  @return EFI_SUCCESS            Success to connect USB device
-  @return EFI_NOT_FOUND          Fail to find handle for USB controller to connect.
-
-**/
-EFI_STATUS
-BmConnectUsbShortFormDevicePath (
-  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
-  );
-
-/**
-  Stop the hotkey processing.
-  
-  @param    Event          Event pointer related to hotkey service. 
-  @param    Context        Context pass to this function. 
-**/
-VOID
-EFIAPI
-BmStopHotkeyService (
-  IN EFI_EVENT    Event,
-  IN VOID         *Context
-  );
-
-/**
-  Set the variable and report the error through status code upon failure.
-
-  @param  VariableName           A Null-terminated string that is the name of the vendor's variable.
-                                 Each VariableName is unique for each VendorGuid. VariableName must
-                                 contain 1 or more characters. If VariableName is an empty string,
-                                 then EFI_INVALID_PARAMETER is returned.
-  @param  VendorGuid             A unique identifier for the vendor.
-  @param  Attributes             Attributes bitmask to set for the variable.
-  @param  DataSize               The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, 
-                                 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or 
-                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero 
-                                 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is 
-                                 set, then a SetVariable() call with a DataSize of zero will not cause any change to 
-                                 the variable value (the timestamp associated with the variable may be updated however 
-                                 even if no new data value is provided,see the description of the 
-                                 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not 
-                                 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). 
-  @param  Data                   The contents for the variable.
-
-  @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as
-                                 defined by the Attributes.
-  @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the
-                                 DataSize exceeds the maximum allowed.
-  @retval EFI_INVALID_PARAMETER  VariableName is an empty string.
-  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
-  @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
-  @retval EFI_WRITE_PROTECTED    The variable in question is read-only.
-  @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
-  @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 
-                                 or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo 
-                                 does NOT pass the validation check carried out by the firmware.
-
-  @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.
-**/
-EFI_STATUS
-BmSetVariableAndReportStatusCodeOnError (
-  IN CHAR16     *VariableName,
-  IN EFI_GUID   *VendorGuid,
-  IN UINT32     Attributes,
-  IN UINTN      DataSize,
-  IN VOID       *Data
-  );
-
-/**
-  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
-  );
-
-/**
-  Return whether the PE header of the load option is valid or not.
-
-  @param[in] Type       The load option type.
-  @param[in] FileBuffer The PE file buffer of the load option.
-  @param[in] FileSize   The size of the load option file.
-
-  @retval TRUE  The PE header of the load option is valid.
-  @retval FALSE The PE header of the load option is not valid.
-**/
-BOOLEAN
-BmIsLoadOptionPeHeaderValid (
-  IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type,
-  IN VOID                              *FileBuffer,
-  IN UINTN                             FileSize
-  );
-
-/**
-  Function compares a device path data structure to that of all the nodes of a
-  second device path instance.
-
-  @param  Multi                 A pointer to a multi-instance device path data
-                                structure.
-  @param  Single                A pointer to a single-instance device path data
-                                structure.
-
-  @retval TRUE                  If the Single device path is contained within Multi device path.
-  @retval FALSE                 The Single device path is not match within Multi device path.
-
-**/
-BOOLEAN
-BmMatchDevicePaths (
-  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,
-  IN  EFI_DEVICE_PATH_PROTOCOL  *Single
-  );
-
-/**
-  Delete the instance in Multi which matches partly with Single instance
-
-  @param  Multi                 A pointer to a multi-instance device path data
-                                structure.
-  @param  Single                A pointer to a single-instance device path data
-                                structure.
-
-  @return This function will remove the device path instances in Multi which partly
-          match with the Single, and return the result device path. If there is no
-          remaining device path as a result, this function will return NULL.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-BmDelPartMatchInstance (
-  IN     EFI_DEVICE_PATH_PROTOCOL  *Multi,
-  IN     EFI_DEVICE_PATH_PROTOCOL  *Single
-  );
-
-
-/**
-  Return the index of the load option in the load option array.
-
-  The function consider two load options are equal when the 
-  OptionType, Attributes, Description, FilePath and OptionalData are equal.
-
-  @param Key    Pointer to the load option to be found.
-  @param Array  Pointer to the array of load options to be found.
-  @param Count  Number of entries in the Array.
-
-  @retval -1          Key wasn't found in the Array.
-  @retval 0 ~ Count-1 The index of the Key in the Array.
-**/
-INTN
-BmFindLoadOption (
-  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
-  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
-  IN UINTN                              Count
-  );
-
-/**
-  Repair all the controllers according to the Driver Health status queried.
-**/
-VOID
-BmRepairAllControllers (
-  VOID
-  );
-
-/**
-  Print the device path info.
-
-  @param DevicePath           The device path need to print.
-**/
-VOID
-BmPrintDp (
-  EFI_DEVICE_PATH_PROTOCOL            *DevicePath
-  );
-
-#endif // _INTERNAL_BM_H_
+/** @file
+  BDS library definition, include the file and data structure
+
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _INTERNAL_BM_H_
+#define _INTERNAL_BM_H_
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/Atapi.h>
+#include <IndustryStandard/Scsi.h>
+
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextInEx.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/UsbIo.h>
+#include <Protocol/DiskInfo.h>
+#include <Protocol/IdeControllerInit.h>
+#include <Protocol/BootLogo.h>
+#include <Protocol/DriverHealth.h>
+#include <Protocol/FormBrowser2.h>
+
+#include <Guid/ZeroGuid.h>
+#include <Guid/MemoryTypeInformation.h>
+#include <Guid/FileInfo.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/Performance.h>
+#include <Guid/StatusCodeDataTypeVariable.h>
+
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/HiiLib.h>
+
+#if !defined (EFI_REMOVABLE_MEDIA_FILE_NAME)
+    #if defined (MDE_CPU_EBC)
+        //
+        // Uefi specification only defines the default boot file name for IA32, X64
+        // and IPF processor, so need define boot file name for EBC architecture here.
+        //
+        #define EFI_REMOVABLE_MEDIA_FILE_NAME L"\\EFI\\BOOT\\BOOTEBC.EFI"
+    #else
+        #error "Can not determine the default boot file name for unknown processor type!"
+    #endif
+#endif
+
+typedef enum {
+  BmAcpiFloppyBoot,
+  BmHardwareDeviceBoot,
+  BmMessageAtapiBoot,
+  BmMessageSataBoot,
+  BmMessageUsbBoot,
+  BmMessageScsiBoot,
+  BmMessageNetworkBoot,
+  BmMiscBoot
+} BM_BOOT_TYPE;
+
+typedef
+CHAR16 *
+(* BM_GET_BOOT_DESCRIPTION) (
+  IN EFI_HANDLE          Handle
+  );
+
+#define BM_OPTION_NAME_LEN                          sizeof ("SysPrep####")
+extern CHAR16  *mBmLoadOptionName[];
+
+typedef
+VOID
+(*VARIABLE_VISITOR) (
+  CHAR16                *Name,
+  EFI_GUID              *Guid,
+  VOID                  *Context
+  );
+
+/**
+  Call Visitor function for each variable in variable storage.
+
+  @param Visitor   Visitor function.
+  @param Context   The context passed to Visitor function.
+**/
+VOID
+ForEachVariable (
+  VARIABLE_VISITOR            Visitor,
+  VOID                        *Context
+  );
+
+/**
+  Repair all the controllers according to the Driver Health status queried.
+**/
+VOID
+BmRepairAllControllers (
+  VOID
+  );
+
+#define BM_HOTKEY_SIGNATURE SIGNATURE_32 ('b', 'm', 'h', 'k')
+typedef struct {
+  UINT32                    Signature;
+  LIST_ENTRY                Link;
+
+  BOOLEAN                   IsContinue;
+  UINT16                    BootOption;
+  UINT8                     CodeCount;
+  UINT8                     WaitingKey;
+  EFI_KEY_DATA              KeyData[3];
+} BM_HOTKEY;
+
+#define BM_HOTKEY_FROM_LINK(a) CR (a, BM_HOTKEY, Link, BM_HOTKEY_SIGNATURE)
+
+/**
+  Get the image file buffer data and buffer size by its device path. 
+
+  @param FilePath  On input, a pointer to an allocated buffer containing the device
+                   path of the file.
+                   On output the pointer could be NULL when the function fails to
+                   load the boot option, or could point to an allocated buffer containing
+                   the device path of the file.
+                   It could be updated by either short-form device path expanding,
+                   or default boot file path appending.
+                   Caller is responsible to free it when it's non-NULL.
+  @param FileSize  A pointer to the size of the file buffer.
+
+  @retval NULL   File is NULL, or FileSize is NULL. Or, the file can't be found.
+  @retval other  The file buffer. The caller is responsible to free the memory.
+**/
+VOID *
+BmLoadEfiBootOption (
+  IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
+  OUT    UINTN                    *FileSize
+  );
+
+/**
+  Get the Option Number that wasn't used.
+
+  @param  LoadOptionType      Load option type.
+  @param  FreeOptionNumber    To receive the minimal free option number.
+
+  @retval EFI_SUCCESS           The option number is found
+  @retval EFI_OUT_OF_RESOURCES  There is no free option number that can be used.
+  @retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
+
+**/
+EFI_STATUS
+BmGetFreeOptionNumber (
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType,
+  OUT UINT16                            *FreeOptionNumber
+  );
+
+/**
+
+  Writes performance data of booting into the allocated memory.
+  OS can process these records.
+
+  @param  Event                 The triggered event.
+  @param  Context               Context for this event.
+
+**/
+VOID
+EFIAPI
+BmWriteBootToOsPerformanceData (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+
+/**
+  Get the headers (dos, image, optional header) from an image
+
+  @param  Device                SimpleFileSystem device handle
+  @param  FileName              File name for the image
+  @param  DosHeader             Pointer to dos header
+  @param  Hdr                   The buffer in which to return the PE32, PE32+, or TE header.
+
+  @retval EFI_SUCCESS           Successfully get the machine type.
+  @retval EFI_NOT_FOUND         The file is not found.
+  @retval EFI_LOAD_ERROR        File is not a valid image file.
+
+**/
+EFI_STATUS
+BmGetImageHeader (
+  IN  EFI_HANDLE                  Device,
+  IN  CHAR16                      *FileName,
+  OUT EFI_IMAGE_DOS_HEADER        *DosHeader,
+  OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr
+  );
+
+/**
+  This routine adjust the memory information for different memory type and 
+  save them into the variables for next boot.
+**/
+VOID
+BmSetMemoryTypeInformationVariable (
+  VOID
+  );
+
+/**
+  Check whether there is a instance in BlockIoDevicePath, which contain multi device path
+  instances, has the same partition node with HardDriveDevicePath device path
+
+  @param  BlockIoDevicePath      Multi device path instances which need to check
+  @param  HardDriveDevicePath    A device path which starts with a hard drive media
+                                 device path.
+
+  @retval TRUE                   There is a matched device path instance.
+  @retval FALSE                  There is no matched device path instance.
+
+**/
+BOOLEAN
+BmMatchPartitionDevicePathNode (
+  IN  EFI_DEVICE_PATH_PROTOCOL   *BlockIoDevicePath,
+  IN  HARDDRIVE_DEVICE_PATH      *HardDriveDevicePath
+  );
+
+/**
+  Connect the specific Usb device which match the short form device path.
+
+  @param  DevicePath             A short-form device path that starts with the first
+                                 element being a USB WWID or a USB Class device
+                                 path
+
+  @return EFI_INVALID_PARAMETER  DevicePath is NULL pointer.
+                                 DevicePath is not a USB device path.
+
+  @return EFI_SUCCESS            Success to connect USB device
+  @return EFI_NOT_FOUND          Fail to find handle for USB controller to connect.
+
+**/
+EFI_STATUS
+BmConnectUsbShortFormDevicePath (
+  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath
+  );
+
+/**
+  Stop the hotkey processing.
+  
+  @param    Event          Event pointer related to hotkey service. 
+  @param    Context        Context pass to this function. 
+**/
+VOID
+EFIAPI
+BmStopHotkeyService (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  );
+
+/**
+  Set the variable and report the error through status code upon failure.
+
+  @param  VariableName           A Null-terminated string that is the name of the vendor's variable.
+                                 Each VariableName is unique for each VendorGuid. VariableName must
+                                 contain 1 or more characters. If VariableName is an empty string,
+                                 then EFI_INVALID_PARAMETER is returned.
+  @param  VendorGuid             A unique identifier for the vendor.
+  @param  Attributes             Attributes bitmask to set for the variable.
+  @param  DataSize               The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, 
+                                 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or 
+                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero 
+                                 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is 
+                                 set, then a SetVariable() call with a DataSize of zero will not cause any change to 
+                                 the variable value (the timestamp associated with the variable may be updated however 
+                                 even if no new data value is provided,see the description of the 
+                                 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not 
+                                 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). 
+  @param  Data                   The contents for the variable.
+
+  @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as
+                                 defined by the Attributes.
+  @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the
+                                 DataSize exceeds the maximum allowed.
+  @retval EFI_INVALID_PARAMETER  VariableName is an empty string.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
+  @retval EFI_WRITE_PROTECTED    The variable in question is read-only.
+  @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
+  @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 
+                                 or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo 
+                                 does NOT pass the validation check carried out by the firmware.
+
+  @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.
+**/
+EFI_STATUS
+BmSetVariableAndReportStatusCodeOnError (
+  IN CHAR16     *VariableName,
+  IN EFI_GUID   *VendorGuid,
+  IN UINT32     Attributes,
+  IN UINTN      DataSize,
+  IN VOID       *Data
+  );
+
+/**
+  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
+  );
+
+/**
+  Return whether the PE header of the load option is valid or not.
+
+  @param[in] Type       The load option type.
+  @param[in] FileBuffer The PE file buffer of the load option.
+  @param[in] FileSize   The size of the load option file.
+
+  @retval TRUE  The PE header of the load option is valid.
+  @retval FALSE The PE header of the load option is not valid.
+**/
+BOOLEAN
+BmIsLoadOptionPeHeaderValid (
+  IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type,
+  IN VOID                              *FileBuffer,
+  IN UINTN                             FileSize
+  );
+
+/**
+  Function compares a device path data structure to that of all the nodes of a
+  second device path instance.
+
+  @param  Multi                 A pointer to a multi-instance device path data
+                                structure.
+  @param  Single                A pointer to a single-instance device path data
+                                structure.
+
+  @retval TRUE                  If the Single device path is contained within Multi device path.
+  @retval FALSE                 The Single device path is not match within Multi device path.
+
+**/
+BOOLEAN
+BmMatchDevicePaths (
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Single
+  );
+
+/**
+  Delete the instance in Multi which matches partly with Single instance
+
+  @param  Multi                 A pointer to a multi-instance device path data
+                                structure.
+  @param  Single                A pointer to a single-instance device path data
+                                structure.
+
+  @return This function will remove the device path instances in Multi which partly
+          match with the Single, and return the result device path. If there is no
+          remaining device path as a result, this function will return NULL.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+BmDelPartMatchInstance (
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Multi,
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Single
+  );
+
+
+/**
+  Return the index of the load option in the load option array.
+
+  The function consider two load options are equal when the 
+  OptionType, Attributes, Description, FilePath and OptionalData are equal.
+
+  @param Key    Pointer to the load option to be found.
+  @param Array  Pointer to the array of load options to be found.
+  @param Count  Number of entries in the Array.
+
+  @retval -1          Key wasn't found in the Array.
+  @retval 0 ~ Count-1 The index of the Key in the Array.
+**/
+INTN
+BmFindLoadOption (
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
+  IN UINTN                              Count
+  );
+
+/**
+  Repair all the controllers according to the Driver Health status queried.
+**/
+VOID
+BmRepairAllControllers (
+  VOID
+  );
+
+/**
+  Print the device path info.
+
+  @param DevicePath           The device path need to print.
+**/
+VOID
+BmPrintDp (
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath
+  );
+
+#endif // _INTERNAL_BM_H_
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
index 760cf03dd4..0e4c3ebaf1 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+++ b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
@@ -1,110 +1,110 @@
-## @file
-#  Define and produce general Boot Manager related interfaces.
-#  
-#  Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
-#  are licensed and made available under the terms and conditions of the BSD License
-#  which accompanies this distribution.  The full text of the license may be found at
-#  http://opensource.org/licenses/bsd-license.php
-#  
-#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-#  
-##
-
-[Defines]
-  INF_VERSION                    = 0x00010005
-  BASE_NAME                      = UefiBootManagerLib
-  FILE_GUID                      = 8D4752BC-595E-49a2-B4AF-F3F57B601DE9
-  MODULE_TYPE                    = DXE_DRIVER
-  VERSION_STRING                 = 1.0
-  LIBRARY_CLASS                  = UefiBootManagerLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER 
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
-#
-
-[Sources]
-  BmPerformance.c
-  BmConnect.c
-  BmMisc.c
-  BmConsole.c
-  BmBoot.c
-  BmLoadOption.c
-  BmHotkey.c
-  BmDriverHealth.c
-  InternalBm.h
-  
-[Packages]
-  MdePkg/MdePkg.dec
-  MdeModulePkg/MdeModulePkg.dec
-
-[LibraryClasses]
-  HobLib
-  PcdLib
-  BaseLib
-  UefiLib
-  TimerLib
-  DebugLib
-  PrintLib
-  BaseMemoryLib
-  DevicePathLib
-  PerformanceLib
-  PeCoffGetEntryPointLib
-  UefiBootServicesTableLib
-  UefiRuntimeServicesTableLib
-  DxeServicesTableLib
-  MemoryAllocationLib
-  DxeServicesLib
-  ReportStatusCodeLib
-  PerformanceLib
-  HiiLib
-  SortLib
-
-[Guids]
-  gEfiMemoryTypeInformationGuid                 ## CONSUMES ## GUID (The identifier of memory type information type in system table)
-                                                ## CONSUMES ## GUID HOB (The hob holding memory type information)
-  gEfiGlobalVariableGuid                        ## SOMETIMES_PRODUCES ## Variable:L"BootCurrent" (The boot option of current boot)
-                                                ## SOMETIMES_CONSUMES ## Variable:L"BootXX" (Boot option variable)
-                                                ## CONSUMES           ## Variable:L"Timeout" (The time out value in second of showing progress bar)
-                                                ## SOMETIMES_CONSUMES ## Variable:L"BootOrder" (The boot option array)
-                                                ## SOMETIMES_CONSUMES ## Variable:L"DriverOrder" (The driver order list)
-                                                ## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device)
-                                                ## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device)
-                                                ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device)
-  gEfiFileInfoGuid                              ## CONSUMES ## GUID
-  gPerformanceProtocolGuid                      ## SOMETIMES_PRODUCES ## Variable:L"PerfDataMemAddr" (The ACPI address of performance data)
-  gEdkiiStatusCodeDataTypeVariableGuid          ## SOMETIMES_CONSUMES ## GUID
-  gEfiDiskInfoAhciInterfaceGuid                 ## SOMETIMES_CONSUMES ## GUID
-  gEfiDiskInfoIdeInterfaceGuid                  ## SOMETIMES_CONSUMES ## GUID
-  gEfiDiskInfoScsiInterfaceGuid                 ## SOMETIMES_CONSUMES ## GUID
-  gZeroGuid                                     ## CONSUMES ## GUID
-
-[Protocols]
-  gEfiPciRootBridgeIoProtocolGuid               ## CONSUMES
-  gEfiSimpleFileSystemProtocolGuid              ## CONSUMES
-  gEfiLoadFileProtocolGuid                      ## CONSUMES
-  gEfiSimpleTextOutProtocolGuid                 ## CONSUMES
-  gEfiPciIoProtocolGuid                         ## CONSUMES
-  gEfiLoadedImageProtocolGuid                   ## CONSUMES
-  gEfiSimpleNetworkProtocolGuid                 ## CONSUMES
-  gEfiSimpleTextInProtocolGuid                  ## CONSUMES
-  gEfiBlockIoProtocolGuid                       ## CONSUMES
-  gEfiFirmwareVolume2ProtocolGuid               ## CONSUMES
-  gEfiDevicePathProtocolGuid                    ## CONSUMES
-  gEfiBootLogoProtocolGuid                      ## CONSUMES
-  gEfiSimpleTextInputExProtocolGuid             ## CONSUMES
-  gEfiGraphicsOutputProtocolGuid                ## SOMETIMES_CONSUMES
-  gEfiUsbIoProtocolGuid                         ## SOMETIMES_CONSUMES
-  gEfiDiskInfoProtocolGuid                      ## SOMETIMES_CONSUMES
-  gEfiDriverHealthProtocolGuid                  ## SOMETIMES_CONSUMES
-
-[Pcd]
-  gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange      ## SOMETIMES_CONSUMES
-  gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderLoad                ## SOMETIMES_CONSUMES
-  gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderStart               ## SOMETIMES_CONSUMES
-  gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable                    ## SOMETIMES_CONSUMES
-  gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile                     ## CONSUMES
-  gEfiMdeModulePkgTokenSpaceGuid.PcdDriverHealthConfigureForm               ## SOMETIMES_CONSUMES
-
+## @file
+#  Define and produce general Boot Manager related interfaces.
+#  
+#  Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#  
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#  
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = UefiBootManagerLib
+  FILE_GUID                      = 8D4752BC-595E-49a2-B4AF-F3F57B601DE9
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = UefiBootManagerLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER 
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  BmPerformance.c
+  BmConnect.c
+  BmMisc.c
+  BmConsole.c
+  BmBoot.c
+  BmLoadOption.c
+  BmHotkey.c
+  BmDriverHealth.c
+  InternalBm.h
+  
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  HobLib
+  PcdLib
+  BaseLib
+  UefiLib
+  TimerLib
+  DebugLib
+  PrintLib
+  BaseMemoryLib
+  DevicePathLib
+  PerformanceLib
+  PeCoffGetEntryPointLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  DxeServicesTableLib
+  MemoryAllocationLib
+  DxeServicesLib
+  ReportStatusCodeLib
+  PerformanceLib
+  HiiLib
+  SortLib
+
+[Guids]
+  gEfiMemoryTypeInformationGuid                 ## CONSUMES ## GUID (The identifier of memory type information type in system table)
+                                                ## CONSUMES ## GUID HOB (The hob holding memory type information)
+  gEfiGlobalVariableGuid                        ## SOMETIMES_PRODUCES ## Variable:L"BootCurrent" (The boot option of current boot)
+                                                ## SOMETIMES_CONSUMES ## Variable:L"BootXX" (Boot option variable)
+                                                ## CONSUMES           ## Variable:L"Timeout" (The time out value in second of showing progress bar)
+                                                ## SOMETIMES_CONSUMES ## Variable:L"BootOrder" (The boot option array)
+                                                ## SOMETIMES_CONSUMES ## Variable:L"DriverOrder" (The driver order list)
+                                                ## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device)
+                                                ## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device)
+                                                ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device)
+  gEfiFileInfoGuid                              ## CONSUMES ## GUID
+  gPerformanceProtocolGuid                      ## SOMETIMES_PRODUCES ## Variable:L"PerfDataMemAddr" (The ACPI address of performance data)
+  gEdkiiStatusCodeDataTypeVariableGuid          ## SOMETIMES_CONSUMES ## GUID
+  gEfiDiskInfoAhciInterfaceGuid                 ## SOMETIMES_CONSUMES ## GUID
+  gEfiDiskInfoIdeInterfaceGuid                  ## SOMETIMES_CONSUMES ## GUID
+  gEfiDiskInfoScsiInterfaceGuid                 ## SOMETIMES_CONSUMES ## GUID
+  gZeroGuid                                     ## CONSUMES ## GUID
+
+[Protocols]
+  gEfiPciRootBridgeIoProtocolGuid               ## CONSUMES
+  gEfiSimpleFileSystemProtocolGuid              ## CONSUMES
+  gEfiLoadFileProtocolGuid                      ## CONSUMES
+  gEfiSimpleTextOutProtocolGuid                 ## CONSUMES
+  gEfiPciIoProtocolGuid                         ## CONSUMES
+  gEfiLoadedImageProtocolGuid                   ## CONSUMES
+  gEfiSimpleNetworkProtocolGuid                 ## CONSUMES
+  gEfiSimpleTextInProtocolGuid                  ## CONSUMES
+  gEfiBlockIoProtocolGuid                       ## CONSUMES
+  gEfiFirmwareVolume2ProtocolGuid               ## CONSUMES
+  gEfiDevicePathProtocolGuid                    ## CONSUMES
+  gEfiBootLogoProtocolGuid                      ## CONSUMES
+  gEfiSimpleTextInputExProtocolGuid             ## CONSUMES
+  gEfiGraphicsOutputProtocolGuid                ## SOMETIMES_CONSUMES
+  gEfiUsbIoProtocolGuid                         ## SOMETIMES_CONSUMES
+  gEfiDiskInfoProtocolGuid                      ## SOMETIMES_CONSUMES
+  gEfiDriverHealthProtocolGuid                  ## SOMETIMES_CONSUMES
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange      ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderLoad                ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderStart               ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable                    ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile                     ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDriverHealthConfigureForm               ## SOMETIMES_CONSUMES
+