MdeModulePkg: Add BdsDxe driver and PlatformBootManagerNull library.
authorRuiyu Ni <ruiyu.ni@intel.com>
Wed, 6 May 2015 04:48:56 +0000 (04:48 +0000)
committerniruiyu <niruiyu@Edk2>
Wed, 6 May 2015 04:48:56 +0000 (04:48 +0000)
BdsDxe driver links to UefiBootManagerLib and PlatformBootManager to
provide a pure UEFI boot manager conforming to the UEFI spec.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17328 6f19259b-4bc3-4df7-8a09-765794883524

12 files changed:
MdeModulePkg/Include/Library/PlatformBootManagerLib.h [new file with mode: 0644]
MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManager.c [new file with mode: 0644]
MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf [new file with mode: 0644]
MdeModulePkg/MdeModulePkg.dec
MdeModulePkg/MdeModulePkg.dsc
MdeModulePkg/Universal/BdsDxe/Bds.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BdsDxe.inf [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/BdsEntry.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.h [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/Language.c [new file with mode: 0644]
MdeModulePkg/Universal/BdsDxe/Language.h [new file with mode: 0644]

diff --git a/MdeModulePkg/Include/Library/PlatformBootManagerLib.h b/MdeModulePkg/Include/Library/PlatformBootManagerLib.h
new file mode 100644 (file)
index 0000000..5274503
--- /dev/null
@@ -0,0 +1,62 @@
+/** @file\r
+  Platform Boot Manager library definition. A platform can implement \r
+  instances to support platform-specific behavior.\r
+\r
+Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef __PLATFORM_BOOT_MANAGER_LIB_H_\r
+#define __PLATFORM_BOOT_MANAGER_LIB_H_\r
+#include <Library/UefiBootManagerLib.h>\r
+\r
+/**\r
+  Do the platform specific action before the console is connected.\r
+\r
+  Such as:\r
+    Update console variable;\r
+    Register new Driver#### or Boot####;\r
+    Signal ReadyToLock event.\r
+**/\r
+VOID\r
+EFIAPI\r
+PlatformBootManagerBeforeConsole (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Do the platform specific action after the console is connected.\r
+\r
+  Such as:\r
+    Dynamically switch output mode;\r
+    Signal console ready platform customized event;\r
+    Run diagnostics like memory testing;\r
+    Connect certain devices;\r
+    Dispatch aditional option roms.\r
+**/\r
+VOID\r
+EFIAPI\r
+PlatformBootManagerAfterConsole (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function is called each second during the boot manager waits the timeout.\r
+\r
+  @param TimeoutRemain  The remaining timeout.\r
+**/\r
+VOID\r
+EFIAPI\r
+PlatformBootManagerWaitCallback (\r
+  UINT16          TimeoutRemain\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManager.c b/MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManager.c
new file mode 100644 (file)
index 0000000..1390e19
--- /dev/null
@@ -0,0 +1,67 @@
+/** @file\r
+  This file include all platform action which can be customized\r
+  by IBV/OEM.\r
+\r
+Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/PlatformBootManagerLib.h>\r
+\r
+\r
+/**\r
+  Do the platform specific action before the console is connected.\r
+\r
+  Such as:\r
+    Update console variable;\r
+    Register new Driver#### or Boot####;\r
+    Signal ReadyToLock event.\r
+**/\r
+VOID\r
+EFIAPI\r
+PlatformBootManagerBeforeConsole (\r
+  VOID\r
+  )\r
+{\r
+  return;\r
+}\r
+\r
+/**\r
+  Do the platform specific action after the console is connected.\r
+\r
+  Such as:\r
+    Dynamically switch output mode;\r
+    Signal console ready platform customized event;\r
+    Run diagnostics like memory testing;\r
+    Connect certain devices;\r
+    Dispatch aditional option roms.\r
+**/\r
+VOID\r
+EFIAPI\r
+PlatformBootManagerAfterConsole (\r
+  VOID\r
+  )\r
+{\r
+  return;\r
+}\r
+\r
+/**\r
+  This function is called each second during the boot manager waits the timeout.\r
+\r
+  @param TimeoutRemain  The remaining timeout.\r
+**/\r
+VOID\r
+EFIAPI\r
+PlatformBootManagerWaitCallback (\r
+  UINT16          TimeoutRemain\r
+  )\r
+{\r
+  return;\r
+}\r
diff --git a/MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf b/MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf
new file mode 100644 (file)
index 0000000..10cc3c4
--- /dev/null
@@ -0,0 +1,36 @@
+## @file\r
+#  Include all platform action which can be customized by IBV/OEM.\r
+#\r
+#  Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.<BR>\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = PlatformBootManagerLib\r
+  FILE_GUID                      = 95C097CC-8943-4038-BB8A-1C70CF2E9F3C\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = PlatformBootManagerLib|DXE_DRIVER\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 EBC\r
+#\r
+\r
+[Sources]\r
+  PlatformBootManager.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
index 6e72470..f854e89 100644 (file)
   ## @libraryclass   Provides core boot manager functions\r
   UefiBootManagerLib|Include/Library/UefiBootManagerLib.h\r
 \r
+  ## @libraryclass   Provides core boot manager functions\r
+  PlatformBootManagerLib|Include/Library/PlatformBootManagerLib.h\r
+\r
 [Guids]\r
   ## MdeModule package token space guid\r
   # Include/Guid/MdeModulePkgTokenSpace.h\r
index f937e83..1573942 100644 (file)
@@ -62,6 +62,7 @@
   PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf\r
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf\r
   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf\r
+  UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf\r
   #\r
   # Generic Modules\r
   #\r
@@ -93,6 +94,7 @@
   SmbusLib|MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf\r
   S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf\r
   CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf\r
+  PlatformBootManagerLib|MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf\r
 \r
 [LibraryClasses.EBC.PEIM]\r
   IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf\r
   MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf\r
   MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf\r
   MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+  MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf\r
 \r
+  MdeModulePkg/Universal/BdsDxe/BdsDxe.inf\r
   MdeModulePkg/Universal/CapsulePei/CapsulePei.inf\r
   MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf\r
   MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf\r
diff --git a/MdeModulePkg/Universal/BdsDxe/Bds.h b/MdeModulePkg/Universal/BdsDxe/Bds.h
new file mode 100644 (file)
index 0000000..2171d14
--- /dev/null
@@ -0,0 +1,106 @@
+/** @file\r
+  Head file for BDS Architectural Protocol implementation\r
+\r
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BDS_MODULE_H_\r
+#define _BDS_MODULE_H_\r
+\r
+#include <Uefi.h>\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/ConnectConInEvent.h>\r
+#include <Guid/Performance.h>\r
+#include <Guid/StatusCodeDataTypeVariable.h>\r
+\r
+#include <Protocol/Bds.h>\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/VariableLock.h>\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/LoadFile.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PrintLib.h>\r
+\r
+#include <Library/UefiBootManagerLib.h>\r
+#include <Library/PlatformBootManagerLib.h>\r
+\r
+/**\r
+\r
+  Service routine for BdsInstance->Entry(). Devices are connected, the\r
+  consoles are initialized, and the boot options are tried.\r
+\r
+  @param This            Protocol Instance structure.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+  IN  EFI_BDS_ARCH_PROTOCOL *This\r
+  );\r
+\r
+/**\r
+  Set the variable and report the error through status code upon failure.\r
+\r
+  @param  VariableName           A Null-terminated string that is the name of the vendor's variable.\r
+                                 Each VariableName is unique for each VendorGuid. VariableName must\r
+                                 contain 1 or more characters. If VariableName is an empty string,\r
+                                 then EFI_INVALID_PARAMETER is returned.\r
+  @param  VendorGuid             A unique identifier for the vendor.\r
+  @param  Attributes             Attributes bitmask to set for the variable.\r
+  @param  DataSize               The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, \r
+                                 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or \r
+                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero \r
+                                 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is \r
+                                 set, then a SetVariable() call with a DataSize of zero will not cause any change to \r
+                                 the variable value (the timestamp associated with the variable may be updated however \r
+                                 even if no new data value is provided,see the description of the \r
+                                 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not \r
+                                 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). \r
+  @param  Data                   The contents for the variable.\r
+\r
+  @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as\r
+                                 defined by the Attributes.\r
+  @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the\r
+                                 DataSize exceeds the maximum allowed.\r
+  @retval EFI_INVALID_PARAMETER  VariableName is an empty string.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.\r
+  @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.\r
+  @retval EFI_WRITE_PROTECTED    The variable in question is read-only.\r
+  @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.\r
+  @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS \r
+                                 or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo \r
+                                 does NOT pass the validation check carried out by the firmware.\r
+\r
+  @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.\r
+**/\r
+EFI_STATUS\r
+BdsDxeSetVariableAndReportStatusCodeOnError (\r
+  IN CHAR16     *VariableName,\r
+  IN EFI_GUID   *VendorGuid,\r
+  IN UINT32     Attributes,\r
+  IN UINTN      DataSize,\r
+  IN VOID       *Data\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf b/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
new file mode 100644 (file)
index 0000000..1d22175
--- /dev/null
@@ -0,0 +1,101 @@
+## @file\r
+#  BdsDxe module is core driver for BDS phase.\r
+#\r
+#  When DxeCore dispatching all DXE driver, this module will produce architecture protocol \r
+#  gEfiBdsArchProtocolGuid. After DxeCore finish dispatching, DxeCore will invoke Entry\r
+#  interface of protocol gEfiBdsArchProtocolGuid, then BDS phase is entered.\r
+#  \r
+#  Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = BdsDxe\r
+  FILE_GUID                      = 6D33944A-EC75-4855-A54D-809C75241F6C\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0 \r
+  ENTRY_POINT                    = BdsInitialize\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  Language.h\r
+  Bds.h\r
+  HwErrRecSupport.c\r
+  HwErrRecSupport.h\r
+  Language.c\r
+  BdsEntry.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  DevicePathLib\r
+  BaseLib\r
+  MemoryAllocationLib\r
+  UefiDriverEntryPoint\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeServicesTableLib\r
+  ReportStatusCodeLib\r
+  UefiLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  UefiBootManagerLib\r
+  PlatformBootManagerLib\r
+  PcdLib\r
+\r
+[Guids]\r
+  gEfiGlobalVariableGuid                        ## SOMETIMES_PRODUCES ## Variable:L"BootNext" (The number of next boot option)\r
+                                                ## SOMETIMES_PRODUCES ## Variable:L"Boot####" (Boot option variable)\r
+                                                ## SOMETIMES_PRODUCES ## Variable:L"PlatformLang" (Platform supported languange in Rfc4646 format)\r
+                                                ## SOMETIMES_PRODUCES ## Variable:L"Lang" (Platform supported languange in Iso639 format)\r
+                                                ## SOMETIMES_PRODUCES ## Variable:L"Key####" (Hotkey option variable)\r
+                                                ## PRODUCES           ## Variable:L"HwErrRecSupport" (The level of platform supported hardware Error Record Persistence)\r
+                                                ## SOMETIMES_PRODUCES ## Variable:L"BootOptionSupport" (The feature supported in boot option menu, value could be: EFI_BOOT_OPTION_SUPPORT_KEY, EFI_BOOT_OPTION_SUPPORT_APP\r
+                                                ## SOMETIMES_PRODUCES (not PcdUefiVariableDefaultLangDeprecate) ## Variable:L"LangCodes" (Value of PcdUefiVariableDefaultLangCodes)\r
+                                                ## PRODUCES           ## Variable:L"PlatformLangCodes" (Value of PcdUefiVariableDefaultPlatformLangCodes)\r
+                                                ## PRODUCES           ## Variable:L"Timeout" (The time out value in second of showing progress bar)\r
+                                                ## SOMETIMES_PRODUCES ## Variable:L"BootOrder" (The boot option array)\r
+                                                ## SOMETIMES_PRODUCES ## Variable:L"DriverOrder" (The driver order list)\r
+                                                ## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device)\r
+                                                ## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device)\r
+                                                ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device)\r
+  gConnectConInEventGuid                        ## SOMETIMES_CONSUMES ## Event\r
+  gEdkiiStatusCodeDataTypeVariableGuid          ## SOMETIMES_CONSUMES ## GUID\r
+\r
+[Protocols]\r
+  gEfiBdsArchProtocolGuid                       ## PRODUCES\r
+  gEfiSimpleTextInputExProtocolGuid             ## CONSUMES\r
+  gEdkiiVariableLockProtocolGuid                ## CONSUMES\r
+\r
+[FeaturePcd]\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate    ## CONSUMES\r
+\r
+[Pcd]\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes            ## CONSUMES\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang                 ## SOMETIMES_CONSUMES\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes    ## CONSUMES\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang         ## CONSUMES\r
+  gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel                ## CONSUMES\r
+  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut                     ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor                    ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision                  ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand              ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable              ## SOMETIMES_CONSUMES\r
+\r
+[Depex]\r
+  TRUE\r
diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
new file mode 100644 (file)
index 0000000..7eebe84
--- /dev/null
@@ -0,0 +1,1246 @@
+/** @file\r
+  This module produce main entry for BDS phase - BdsEntry.\r
+  When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed\r
+  which contains interface of BdsEntry.\r
+  After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked\r
+  to enter BDS phase.\r
+\r
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Bds.h"\r
+#include "Language.h"\r
+#include "HwErrRecSupport.h"\r
+\r
+#define SET_BOOT_OPTION_SUPPORT_KEY_COUNT(a, c) {  \\r
+      (a) = ((a) & ~EFI_BOOT_OPTION_SUPPORT_COUNT) | (((c) << LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT)) & EFI_BOOT_OPTION_SUPPORT_COUNT); \\r
+      }\r
+\r
+///\r
+/// BDS arch protocol instance initial value.\r
+///\r
+EFI_BDS_ARCH_PROTOCOL  gBds = {\r
+  BdsEntry\r
+};\r
+\r
+//\r
+// gConnectConInEvent - Event which is signaled when ConIn connection is required\r
+//\r
+EFI_EVENT      gConnectConInEvent = NULL;\r
+\r
+///\r
+/// The read-only variables defined in UEFI Spec.\r
+///\r
+CHAR16  *mReadOnlyVariables[] = {\r
+  EFI_PLATFORM_LANG_CODES_VARIABLE_NAME,\r
+  EFI_LANG_CODES_VARIABLE_NAME,\r
+  EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME,\r
+  EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME,\r
+  EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME\r
+  };\r
+\r
+CHAR16  mRecoveryBoot[] = L"Recovery Boot";\r
+/**\r
+  Event to Connect ConIn.\r
+\r
+  @param  Event                 Event whose notification function is being invoked.\r
+  @param  Context               Pointer to the notification function's context,\r
+                                which is implementation-dependent.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsDxeOnConnectConInCallBack (\r
+  IN EFI_EVENT                Event,\r
+  IN VOID                     *Context\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  // When Osloader call ReadKeyStroke to signal this event\r
+  // no driver dependency is assumed existing. So use a non-dispatch version\r
+  //\r
+  Status = EfiBootManagerConnectConsoleVariable (ConIn);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Should not enter this case, if enter, the keyboard will not work.\r
+    // May need platfrom policy to connect keyboard.\r
+    //\r
+    DEBUG ((EFI_D_WARN, "[Bds] ASSERT Connect ConIn failed!!!\n"));\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Install Boot Device Selection Protocol\r
+\r
+  @param ImageHandle     The image handle.\r
+  @param SystemTable     The system table.\r
+\r
+  @retval  EFI_SUCEESS  BDS has finished initializing.\r
+                        Return the dispatcher and recall BDS.Entry\r
+  @retval  Other        Return status from AllocatePool() or gBS->InstallProtocolInterface\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsInitialize (\r
+  IN EFI_HANDLE                            ImageHandle,\r
+  IN EFI_SYSTEM_TABLE                      *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_HANDLE  Handle;\r
+  //\r
+  // Install protocol interface\r
+  //\r
+  Handle = NULL;\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &Handle,\r
+                  &gEfiBdsArchProtocolGuid, &gBds,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Emuerate all possible bootable medias in the following order:\r
+  1. Removable BlockIo            - The boot option only points to the removable media\r
+                                    device, like USB key, DVD, Floppy etc.\r
+  2. Fixed BlockIo                - The boot option only points to a Fixed blockIo device,\r
+                                    like HardDisk.\r
+  3. Non-BlockIo SimpleFileSystem - The boot option points to a device supporting\r
+                                    SimpleFileSystem Protocol, but not supporting BlockIo\r
+                                    protocol.\r
+  4. LoadFile                     - The boot option points to the media supporting \r
+                                    LoadFile protocol.\r
+  Reference: UEFI Spec chapter 3.3 Boot Option Variables Default Boot Behavior\r
+\r
+  @param BootOptionCount   Return the boot option count which has been found.\r
+\r
+  @retval   Pointer to the boot option array.\r
+**/\r
+EFI_BOOT_MANAGER_LOAD_OPTION *\r
+BdsEnumerateBootOptions (\r
+  UINTN                                 *BootOptionCount\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION          *BootOptions;\r
+  UINT16                                NonBlockNumber;\r
+  UINTN                                 HandleCount;\r
+  EFI_HANDLE                            *Handles;\r
+  EFI_BLOCK_IO_PROTOCOL                 *BlkIo;\r
+  UINTN                                 Removable;\r
+  UINTN                                 Index;\r
+\r
+  ASSERT (BootOptionCount != NULL);\r
+\r
+  *BootOptionCount = 0;\r
+  BootOptions      = NULL;\r
+\r
+  //\r
+  // Parse removable block io followed by fixed block io\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+         ByProtocol,\r
+         &gEfiBlockIoProtocolGuid,\r
+         NULL,\r
+         &HandleCount,\r
+         &Handles\r
+         );\r
+\r
+  for (Removable = 0; Removable < 2; Removable++) {\r
+    for (Index = 0; Index < HandleCount; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      Handles[Index],\r
+                      &gEfiBlockIoProtocolGuid,\r
+                      (VOID **) &BlkIo\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Skip the logical partitions\r
+      //\r
+      if (BlkIo->Media->LogicalPartition) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Skip the fixed block io then the removable block io\r
+      //\r
+      if (BlkIo->Media->RemovableMedia == ((Removable == 0) ? FALSE : TRUE)) {\r
+        continue;\r
+      }\r
+\r
+      BootOptions = ReallocatePool (\r
+                      sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),\r
+                      sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),\r
+                      BootOptions\r
+                      );\r
+      ASSERT (BootOptions != NULL);\r
+\r
+      Status = EfiBootManagerInitializeLoadOption (\r
+                 &BootOptions[(*BootOptionCount)++],\r
+                 LoadOptionNumberUnassigned,\r
+                 LoadOptionTypeBoot,\r
+                 LOAD_OPTION_ACTIVE,\r
+                 mRecoveryBoot,\r
+                 DevicePathFromHandle (Handles[Index]),\r
+                 NULL,\r
+                 0\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
+\r
+  if (HandleCount != 0) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  //\r
+  // Parse simple file system not based on block io\r
+  //\r
+  NonBlockNumber = 0;\r
+  gBS->LocateHandleBuffer (\r
+         ByProtocol,\r
+         &gEfiSimpleFileSystemProtocolGuid,\r
+         NULL,\r
+         &HandleCount,\r
+         &Handles\r
+         );\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Status = gBS->HandleProtocol (\r
+                    Handles[Index],\r
+                    &gEfiBlockIoProtocolGuid,\r
+                    (VOID **) &BlkIo\r
+                    );\r
+     if (!EFI_ERROR (Status)) {\r
+      //\r
+      //  Skip if the file system handle supports a BlkIo protocol, which we've handled in above\r
+      //\r
+      continue;\r
+    }\r
+    BootOptions = ReallocatePool (\r
+                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),\r
+                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),\r
+                    BootOptions\r
+                    );\r
+    ASSERT (BootOptions != NULL);\r
+\r
+    Status = EfiBootManagerInitializeLoadOption (\r
+               &BootOptions[(*BootOptionCount)++],\r
+               LoadOptionNumberUnassigned,\r
+               LoadOptionTypeBoot,\r
+               LOAD_OPTION_ACTIVE,\r
+               mRecoveryBoot,\r
+               DevicePathFromHandle (Handles[Index]),\r
+               NULL,\r
+               0\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  if (HandleCount != 0) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  //\r
+  // Parse load file, assuming UEFI Network boot option\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+         ByProtocol,\r
+         &gEfiLoadFileProtocolGuid,\r
+         NULL,\r
+         &HandleCount,\r
+         &Handles\r
+         );\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+\r
+    BootOptions = ReallocatePool (\r
+                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),\r
+                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),\r
+                    BootOptions\r
+                    );\r
+    ASSERT (BootOptions != NULL);\r
+\r
+    Status = EfiBootManagerInitializeLoadOption (\r
+               &BootOptions[(*BootOptionCount)++],\r
+               LoadOptionNumberUnassigned,\r
+               LoadOptionTypeBoot,\r
+               LOAD_OPTION_ACTIVE,\r
+               mRecoveryBoot,\r
+               DevicePathFromHandle (Handles[Index]),\r
+               NULL,\r
+               0\r
+               );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  if (HandleCount != 0) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  return BootOptions;\r
+}\r
+\r
+/**\r
+  Function waits for a given event to fire, or for an optional timeout to expire.\r
+\r
+  @param   Event              The event to wait for\r
+  @param   Timeout            An optional timeout value in 100 ns units.\r
+\r
+  @retval  EFI_SUCCESS      Event fired before Timeout expired.\r
+  @retval  EFI_TIME_OUT     Timout expired before Event fired..\r
+\r
+**/\r
+EFI_STATUS\r
+BdsWaitForSingleEvent (\r
+  IN  EFI_EVENT                  Event,\r
+  IN  UINT64                     Timeout       OPTIONAL\r
+  )\r
+{\r
+  UINTN       Index;\r
+  EFI_STATUS  Status;\r
+  EFI_EVENT   TimerEvent;\r
+  EFI_EVENT   WaitList[2];\r
+\r
+  if (Timeout != 0) {\r
+    //\r
+    // Create a timer event\r
+    //\r
+    Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Set the timer event\r
+      //\r
+      gBS->SetTimer (\r
+             TimerEvent,\r
+             TimerRelative,\r
+             Timeout\r
+             );\r
+\r
+      //\r
+      // Wait for the original event or the timer\r
+      //\r
+      WaitList[0] = Event;\r
+      WaitList[1] = TimerEvent;\r
+      Status      = gBS->WaitForEvent (2, WaitList, &Index);\r
+      ASSERT_EFI_ERROR (Status);\r
+      gBS->CloseEvent (TimerEvent);\r
+\r
+      //\r
+      // If the timer expired, change the return to timed out\r
+      //\r
+      if (Index == 1) {\r
+        Status = EFI_TIMEOUT;\r
+      }\r
+    }\r
+  } else {\r
+    //\r
+    // No timeout... just wait on the event\r
+    //\r
+    Status = gBS->WaitForEvent (1, &Event, &Index);\r
+    ASSERT (!EFI_ERROR (Status));\r
+    ASSERT (Index == 0);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  The function reads user inputs.\r
+\r
+**/\r
+VOID\r
+BdsReadKeys (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS         Status;\r
+  EFI_INPUT_KEY      Key;\r
+\r
+  if (PcdGetBool (PcdConInConnectOnDemand)) {\r
+    return;\r
+  }\r
+\r
+  while (gST->ConIn != NULL) {\r
+    \r
+    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+    \r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // No more keys.\r
+      //\r
+      break;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  The function waits for the boot manager timeout expires or hotkey is pressed.\r
+\r
+  It calls PlatformBootManagerWaitCallback each second.\r
+\r
+  @param     HotkeyTriggered   Input hotkey event.\r
+**/\r
+VOID\r
+BdsWait (\r
+  IN EFI_EVENT      HotkeyTriggered\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  UINT16                TimeoutRemain;\r
+\r
+  DEBUG ((EFI_D_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n"));\r
+\r
+  TimeoutRemain = PcdGet16 (PcdPlatformBootTimeOut);\r
+  while (TimeoutRemain != 0) {\r
+    DEBUG ((EFI_D_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN) TimeoutRemain));\r
+    PlatformBootManagerWaitCallback (TimeoutRemain);\r
+\r
+    BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered\r
+                    //         Can be removed after all keyboard drivers invoke callback in timer callback.\r
+\r
+    if (HotkeyTriggered != NULL) {\r
+      Status = BdsWaitForSingleEvent (HotkeyTriggered, EFI_TIMER_PERIOD_SECONDS (1));\r
+      if (!EFI_ERROR (Status)) {\r
+        break;\r
+      }\r
+    } else {\r
+      gBS->Stall (1000000);\r
+    }\r
+\r
+    //\r
+    // 0xffff means waiting forever\r
+    // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop\r
+    //\r
+    if (TimeoutRemain != 0xffff) {\r
+      TimeoutRemain--;\r
+    }\r
+  }\r
+  DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n"));\r
+}\r
+\r
+/**\r
+  Attempt to boot each boot option in the BootOptions array.\r
+\r
+  @param BootOptions       Input boot option array.\r
+  @param BootOptionCount   Input boot option count.\r
+\r
+  @retval TRUE  Successfully boot one of the boot options.\r
+  @retval FALSE Failed boot any of the boot options.\r
+**/\r
+BOOLEAN\r
+BootAllBootOptions (\r
+  IN EFI_BOOT_MANAGER_LOAD_OPTION    *BootOptions,\r
+  IN UINTN                           BootOptionCount\r
+  )\r
+{\r
+  UINTN                              Index;\r
+\r
+  //\r
+  // Attempt boot each boot option\r
+  //\r
+  for (Index = 0; Index < BootOptionCount; Index++) {\r
+    //\r
+    // According to EFI Specification, if a load option is not marked\r
+    // as LOAD_OPTION_ACTIVE, the boot manager will not automatically\r
+    // load the option.\r
+    //\r
+    if ((BootOptions[Index].Attributes & LOAD_OPTION_ACTIVE) == 0) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Boot#### load options with LOAD_OPTION_CATEGORY_APP are executables which are not\r
+    // part of the normal boot processing. Boot options with reserved category values will be\r
+    // ignored by the boot manager.\r
+    //\r
+    if ((BootOptions[Index].Attributes & LOAD_OPTION_CATEGORY) != LOAD_OPTION_CATEGORY_BOOT) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // All the driver options should have been processed since\r
+    // now boot will be performed.\r
+    //\r
+    EfiBootManagerBoot (&BootOptions[Index]);\r
+\r
+    //\r
+    // Successful boot breaks the loop, otherwise tries next boot option\r
+    //\r
+    if (BootOptions[Index].Status == EFI_SUCCESS) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  return (BOOLEAN) (Index < BootOptionCount);\r
+}\r
+\r
+/**\r
+  This function attempts to boot per the boot order specified by platform policy.\r
+\r
+  If the boot via Boot#### returns with a status of EFI_SUCCESS the boot manager will stop \r
+  processing the BootOrder variable and present a boot manager menu to the user. If a boot via \r
+  Boot#### returns a status other than EFI_SUCCESS, the boot has failed and the next Boot####\r
+  in the BootOrder variable will be tried until all possibilities are exhausted.\r
+                                  -- Chapter 3.1.1 Boot Manager Programming, the 4th paragraph\r
+**/\r
+VOID\r
+DefaultBootBehavior (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                        BootOptionCount;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;\r
+\r
+  EfiBootManagerGetBootManagerMenu (&BootManagerMenu);\r
+  //\r
+  // BootManagerMenu always contains the correct information even the above function returns failure.\r
+  //\r
+\r
+  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
+\r
+  if (BootAllBootOptions (BootOptions, BootOptionCount)) {\r
+    //\r
+    // Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI\r
+    //\r
+    if (PcdGetBool (PcdConInConnectOnDemand)) {\r
+      BdsDxeOnConnectConInCallBack (NULL, NULL);\r
+    }\r
+\r
+    //\r
+    // Show the Boot Manager Menu after successful boot\r
+    //\r
+    EfiBootManagerBoot (&BootManagerMenu);\r
+  } else {\r
+    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
+    //\r
+    // Re-scan all EFI boot options in case all the boot#### are deleted or failed to boot\r
+    //\r
+    // If no valid boot options exist, the boot manager will enumerate all removable media\r
+    // devices followed by all fixed media devices. The order within each group is undefined.\r
+    // These new default boot options are not saved to non volatile storage.The boot manger\r
+    // will then attempt toboot from each boot option.\r
+    //                            -- Chapter 3.3 Boot Manager Programming, the 2nd paragraph\r
+    //\r
+    EfiBootManagerConnectAll ();\r
+    BootOptions = BdsEnumerateBootOptions (&BootOptionCount);\r
+\r
+    if (!BootAllBootOptions (BootOptions, BootOptionCount)) {\r
+      DEBUG ((EFI_D_ERROR, "[Bds]No bootable device!\n"));\r
+      EfiBootManagerBoot (&BootManagerMenu);\r
+    }\r
+  }\r
+\r
+  EfiBootManagerFreeLoadOption (&BootManagerMenu);\r
+  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
+}\r
+\r
+/**\r
+  The function will go through the driver option link list, load and start\r
+  every driver the driver option device path point to.\r
+\r
+  @param  DriverOption        Input driver option array.\r
+  @param  DriverOptionCount   Input driver option count.\r
+\r
+**/\r
+VOID\r
+LoadDrivers (\r
+  IN EFI_BOOT_MANAGER_LOAD_OPTION       *DriverOption,\r
+  IN UINTN                              DriverOptionCount\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINTN                     Index;\r
+  EFI_HANDLE                ImageHandle;\r
+  EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
+  BOOLEAN                   ReconnectAll;\r
+\r
+  ReconnectAll = FALSE;\r
+\r
+  //\r
+  // Process the driver option\r
+  //\r
+  for (Index = 0; Index < DriverOptionCount; Index++) {\r
+    //\r
+    // If a load option is not marked as LOAD_OPTION_ACTIVE,\r
+    // the boot manager will not automatically load the option.\r
+    //\r
+    if ((DriverOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0) {\r
+      continue;\r
+    }\r
+    \r
+    //\r
+    // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,\r
+    // then all of the EFI drivers in the system will be disconnected and\r
+    // reconnected after the last driver load option is processed.\r
+    //\r
+    if ((DriverOption[Index].Attributes & LOAD_OPTION_FORCE_RECONNECT) != 0) {\r
+      ReconnectAll = TRUE;\r
+    }\r
+    \r
+    //\r
+    // Make sure the driver path is connected.\r
+    //\r
+    EfiBootManagerConnectDevicePath (DriverOption[Index].FilePath, NULL);\r
+\r
+    //\r
+    // Load and start the image that Driver#### describes\r
+    //\r
+    Status = gBS->LoadImage (\r
+                    FALSE,\r
+                    gImageHandle,\r
+                    DriverOption[Index].FilePath,\r
+                    NULL,\r
+                    0,\r
+                    &ImageHandle\r
+                    );\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
+\r
+      //\r
+      // Verify whether this image is a driver, if not,\r
+      // exit it and continue to parse next load option\r
+      //\r
+      if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {\r
+        gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);\r
+        continue;\r
+      }\r
+\r
+      ImageInfo->LoadOptionsSize  = DriverOption[Index].OptionalDataSize;\r
+      ImageInfo->LoadOptions      = DriverOption[Index].OptionalData;\r
+      //\r
+      // Before calling the image, enable the Watchdog Timer for\r
+      // the 5 Minute period\r
+      //\r
+      gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
+\r
+      DriverOption[Index].Status = gBS->StartImage (ImageHandle, &DriverOption[Index].ExitDataSize, &DriverOption[Index].ExitData);\r
+      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Driver Return Status = %r\n", DriverOption[Index].Status));\r
+\r
+      //\r
+      // Clear the Watchdog Timer after the image returns\r
+      //\r
+      gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Process the LOAD_OPTION_FORCE_RECONNECT driver option\r
+  //\r
+  if (ReconnectAll) {\r
+    EfiBootManagerDisconnectAll ();\r
+    EfiBootManagerConnectAll ();\r
+  }\r
+\r
+}\r
+\r
+/**\r
+\r
+  Validate input console variable data. \r
+\r
+  If found the device path is not a valid device path, remove the variable.\r
+  \r
+  @param VariableName             Input console variable name.\r
+\r
+**/\r
+VOID\r
+BdsFormalizeConsoleVariable (\r
+  IN  CHAR16          *VariableName\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINTN                     VariableSize;\r
+  EFI_STATUS                Status;\r
+\r
+  GetEfiGlobalVariable2 (VariableName, (VOID **) &DevicePath, &VariableSize);\r
+  if ((DevicePath != NULL) && !IsDevicePathValid (DevicePath, VariableSize)) { \r
+    Status = gRT->SetVariable (\r
+                    VariableName,\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                    0,\r
+                    NULL\r
+                    );\r
+    //\r
+    // Deleting variable with current variable implementation shouldn't fail.\r
+    //\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  if (DevicePath != NULL) {\r
+    FreePool (DevicePath);\r
+  }\r
+}\r
+\r
+/**\r
+  Formalize OsIndication related variables. \r
+  \r
+  For OsIndicationsSupported, Create a BS/RT/UINT64 variable to report caps \r
+  Delete OsIndications variable if it is not NV/BS/RT UINT64.\r
+  \r
+  Item 3 is used to solve case when OS corrupts OsIndications. Here simply delete this NV variable.\r
+\r
+**/\r
+VOID \r
+BdsFormalizeOSIndicationVariable (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINT64     OsIndicationSupport;\r
+  UINT64     OsIndication;\r
+  UINTN      DataSize;\r
+  UINT32     Attributes;\r
+\r
+  //\r
+  // OS indicater support variable\r
+  //\r
+  OsIndicationSupport = EFI_OS_INDICATIONS_BOOT_TO_FW_UI;\r
+  Status = gRT->SetVariable (\r
+                  L"OsIndicationsSupported",\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                  sizeof(UINT64),\r
+                  &OsIndicationSupport\r
+                  );\r
+  //\r
+  // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail.\r
+  //\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // If OsIndications is invalid, remove it.\r
+  // Invalid case\r
+  //   1. Data size != UINT64\r
+  //   2. OsIndication value inconsistence\r
+  //   3. OsIndication attribute inconsistence\r
+  //\r
+  OsIndication = 0;\r
+  Attributes = 0;\r
+  DataSize = sizeof(UINT64);\r
+  Status = gRT->GetVariable (\r
+                  L"OsIndications",\r
+                  &gEfiGlobalVariableGuid,\r
+                  &Attributes,\r
+                  &DataSize,\r
+                  &OsIndication\r
+                  );\r
+  if (Status == EFI_NOT_FOUND) {\r
+    return;\r
+  }\r
+\r
+  if ((DataSize != sizeof (OsIndication)) ||\r
+      ((OsIndication & ~OsIndicationSupport) != 0) ||\r
+      (Attributes != (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE))\r
+     ){\r
+\r
+    DEBUG ((EFI_D_ERROR, "[Bds] Unformalized OsIndications variable exists. Delete it\n"));\r
+    Status = gRT->SetVariable (\r
+                    L"OsIndications",\r
+                    &gEfiGlobalVariableGuid,\r
+                    0,\r
+                    0,\r
+                    NULL\r
+                    );\r
+    //\r
+    // Deleting variable with current variable implementation shouldn't fail.\r
+    //\r
+    ASSERT_EFI_ERROR(Status);\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Validate variables. \r
+\r
+**/\r
+VOID \r
+BdsFormalizeEfiGlobalVariable (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Validate Console variable.\r
+  //\r
+  BdsFormalizeConsoleVariable (L"ConIn");\r
+  BdsFormalizeConsoleVariable (L"ConOut");\r
+  BdsFormalizeConsoleVariable (L"ErrOut");\r
+\r
+  //\r
+  // Validate OSIndication related variable.\r
+  //\r
+  BdsFormalizeOSIndicationVariable ();\r
+}\r
+\r
+/**\r
+\r
+  Allocate a block of memory that will contain performance data to OS.\r
+\r
+**/\r
+VOID\r
+BdsAllocateMemoryForPerformanceData (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_PHYSICAL_ADDRESS          AcpiLowMemoryBase;\r
+  EDKII_VARIABLE_LOCK_PROTOCOL  *VariableLock;\r
+\r
+  AcpiLowMemoryBase = 0x0FFFFFFFFULL;\r
+\r
+  //\r
+  // Allocate a block of memory that will contain performance data to OS.\r
+  //\r
+  Status = gBS->AllocatePages (\r
+                  AllocateMaxAddress,\r
+                  EfiReservedMemoryType,\r
+                  EFI_SIZE_TO_PAGES (PERF_DATA_MAX_LENGTH),\r
+                  &AcpiLowMemoryBase\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Save the pointer to variable for use in S3 resume.\r
+    //\r
+    Status = BdsDxeSetVariableAndReportStatusCodeOnError (\r
+               L"PerfDataMemAddr",\r
+               &gPerformanceProtocolGuid,\r
+               EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+               sizeof (EFI_PHYSICAL_ADDRESS),\r
+               &AcpiLowMemoryBase\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "[Bds] PerfDataMemAddr (%08x) cannot be saved to NV storage.\n", AcpiLowMemoryBase));\r
+    }\r
+    //\r
+    // Mark L"PerfDataMemAddr" variable to read-only if the Variable Lock protocol exists\r
+    // Still lock it even the variable cannot be saved to prevent it's set by 3rd party code.\r
+    //\r
+    Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = VariableLock->RequestToLock (VariableLock, L"PerfDataMemAddr", &gPerformanceProtocolGuid);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Service routine for BdsInstance->Entry(). Devices are connected, the\r
+  consoles are initialized, and the boot options are tried.\r
+\r
+  @param This             Protocol Instance structure.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+  IN EFI_BDS_ARCH_PROTOCOL  *This\r
+  )\r
+{\r
+  EFI_BOOT_MANAGER_LOAD_OPTION    *DriverOption;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION    BootOption;\r
+  UINTN                           DriverOptionCount;\r
+  CHAR16                          *FirmwareVendor;\r
+  EFI_EVENT                       HotkeyTriggered;\r
+  UINT64                          OsIndication;\r
+  UINTN                           DataSize;\r
+  EFI_STATUS                      Status;\r
+  UINT32                          BootOptionSupport;\r
+  UINT16                          BootTimeOut;\r
+  EDKII_VARIABLE_LOCK_PROTOCOL    *VariableLock;\r
+  UINTN                           Index;\r
+  UINT16                          *BootNext;\r
+  CHAR16                          BootNextVariableName[sizeof ("Boot####")];\r
+\r
+  HotkeyTriggered = NULL;\r
+  Status          = EFI_SUCCESS;\r
+\r
+  //\r
+  // Insert the performance probe\r
+  //\r
+  PERF_END (NULL, "DXE", NULL, 0);\r
+  PERF_START (NULL, "BDS", NULL, 0);\r
+  DEBUG ((EFI_D_INFO, "[Bds] Entry...\n"));\r
+\r
+  PERF_CODE (\r
+    BdsAllocateMemoryForPerformanceData ();\r
+  );\r
+\r
+  //\r
+  // Fill in FirmwareVendor and FirmwareRevision from PCDs\r
+  //\r
+  FirmwareVendor = (CHAR16 *) PcdGetPtr (PcdFirmwareVendor);\r
+  gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor);\r
+  ASSERT (gST->FirmwareVendor != NULL);\r
+  gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision);\r
+\r
+  //\r
+  // Fixup Tasble CRC after we updated Firmware Vendor and Revision\r
+  //\r
+  gST->Hdr.CRC32 = 0;\r
+  gBS->CalculateCrc32 ((VOID *) gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);\r
+\r
+  //\r
+  // Validate Variable.\r
+  //\r
+  BdsFormalizeEfiGlobalVariable ();\r
+\r
+  //\r
+  // Mark the read-only variables if the Variable Lock protocol exists\r
+  //\r
+  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
+  DEBUG ((EFI_D_INFO, "[BdsDxe] Locate Variable Lock protocol - %r\n", Status));\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index = 0; Index < sizeof (mReadOnlyVariables) / sizeof (mReadOnlyVariables[0]); Index++) {\r
+      Status = VariableLock->RequestToLock (VariableLock, mReadOnlyVariables[Index], &gEfiGlobalVariableGuid);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
+\r
+  InitializeHwErrRecSupport ();\r
+\r
+  //\r
+  // Initialize L"Timeout" EFI global variable.\r
+  //\r
+  BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut);\r
+  if (BootTimeOut != 0xFFFF) {\r
+    //\r
+    // If time out value equal 0xFFFF, no need set to 0xFFFF to variable area because UEFI specification\r
+    // define same behavior between no value or 0xFFFF value for L"Timeout".\r
+    //\r
+    BdsDxeSetVariableAndReportStatusCodeOnError (\r
+      EFI_TIME_OUT_VARIABLE_NAME,\r
+      &gEfiGlobalVariableGuid,\r
+      EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+      sizeof (UINT16),\r
+      &BootTimeOut\r
+      );\r
+  }\r
+\r
+  //\r
+  // Initialize L"BootOptionSupport" EFI global variable.\r
+  // Lazy-ConIn implictly disables BDS hotkey.\r
+  //\r
+  BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_APP;\r
+  if (!PcdGetBool (PcdConInConnectOnDemand)) {\r
+    BootOptionSupport |= EFI_BOOT_OPTION_SUPPORT_KEY;\r
+    SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);\r
+  }\r
+  Status = gRT->SetVariable (\r
+                  EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME,\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                  sizeof (BootOptionSupport),\r
+                  &BootOptionSupport\r
+                  );\r
+  //\r
+  // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail.\r
+  //\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Cache and remove the "BootNext" NV variable.\r
+  //\r
+  GetEfiGlobalVariable2 (EFI_BOOT_NEXT_VARIABLE_NAME, (VOID **) &BootNext, &DataSize);\r
+  if (DataSize != sizeof (UINT16)) {\r
+    if (BootNext != NULL) {\r
+      FreePool (BootNext);\r
+    }\r
+    BootNext = NULL;\r
+  }\r
+  Status = gRT->SetVariable (\r
+                  EFI_BOOT_NEXT_VARIABLE_NAME,\r
+                  &gEfiGlobalVariableGuid,\r
+                  0,\r
+                  0,\r
+                  NULL\r
+                  );\r
+  //\r
+  // Deleting NV variable shouldn't fail unless it doesn't exist.\r
+  //\r
+  ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);\r
+\r
+  //\r
+  // Initialize the platform language variables\r
+  //\r
+  InitializeLanguage (TRUE);\r
+\r
+  //\r
+  // Report Status Code to indicate connecting drivers will happen\r
+  //\r
+  REPORT_STATUS_CODE (\r
+    EFI_PROGRESS_CODE,\r
+    (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS)\r
+    );\r
+\r
+  //\r
+  // Do the platform init, can be customized by OEM/IBV\r
+  // Possible things that can be done in PlatformBootManagerBeforeConsole:\r
+  // > Update console variable: 1. include hot-plug devices; 2. Clear ConIn and add SOL for AMT\r
+  // > Register new Driver#### or Boot####\r
+  // > Register new Key####: e.g.: F12 \r
+  // > Signal ReadyToLock event\r
+  // > Authentication action: 1. connect Auth devices; 2. Identify auto logon user.\r
+  //\r
+  PERF_START (NULL, "PlatformBootManagerBeforeConsole", "BDS", 0);\r
+  PlatformBootManagerBeforeConsole ();\r
+  PERF_END   (NULL, "PlatformBootManagerBeforeConsole", "BDS", 0);\r
+\r
+  //\r
+  // Initialize hotkey service\r
+  //\r
+  EfiBootManagerStartHotkeyService (&HotkeyTriggered);\r
+\r
+  //\r
+  // Load Driver Options\r
+  //\r
+  DriverOption = EfiBootManagerGetLoadOptions (&DriverOptionCount, LoadOptionTypeDriver);\r
+  LoadDrivers (DriverOption, DriverOptionCount);\r
+  EfiBootManagerFreeLoadOptions (DriverOption, DriverOptionCount);\r
+\r
+  //\r
+  // Connect consoles\r
+  //\r
+  PERF_START (NULL, "EfiBootManagerConnectAllDefaultConsoles", "BDS", 0);\r
+  if (PcdGetBool (PcdConInConnectOnDemand)) {\r
+    EfiBootManagerConnectConsoleVariable (ConOut);\r
+    EfiBootManagerConnectConsoleVariable (ErrOut);\r
+\r
+    //\r
+    // Initialize ConnectConIn event\r
+    //\r
+    Status = gBS->CreateEventEx (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_CALLBACK,\r
+                    BdsDxeOnConnectConInCallBack,\r
+                    NULL,\r
+                    &gConnectConInEventGuid,\r
+                    &gConnectConInEvent\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      gConnectConInEvent = NULL;\r
+    }\r
+  } else {\r
+    EfiBootManagerConnectAllDefaultConsoles ();\r
+  }\r
+  PERF_END   (NULL, "EfiBootManagerConnectAllDefaultConsoles", "BDS", 0);\r
+\r
+  //\r
+  // Do the platform specific action after the console is ready\r
+  // Possible things that can be done in PlatformBootManagerAfterConsole:\r
+  // > Console post action:\r
+  //   > Dynamically switch output mode from 100x31 to 80x25 for certain senarino\r
+  //   > Signal console ready platform customized event\r
+  // > Run diagnostics like memory testing\r
+  // > Connect certain devices\r
+  // > Dispatch aditional option roms\r
+  // > Special boot: e.g.: USB boot, enter UI\r
+  // \r
+  PERF_START (NULL, "PlatformBootManagerAfterConsole", "BDS", 0);\r
+  PlatformBootManagerAfterConsole ();\r
+  PERF_END   (NULL, "PlatformBootManagerAfterConsole", "BDS", 0);\r
+\r
+  DEBUG_CODE (\r
+    EFI_BOOT_MANAGER_LOAD_OPTION    *BootOptions;\r
+    UINTN                           BootOptionCount;\r
+    UINTN                           Index;\r
+\r
+    BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
+    DEBUG ((EFI_D_INFO, "[Bds]=============Dumping Boot Options=============\n"));\r
+    for (Index = 0; Index < BootOptionCount; Index++) {\r
+      DEBUG ((\r
+        EFI_D_INFO, "[Bds]Boot%04x: %s \t\t 0x%04x\n",\r
+        BootOptions[Index].OptionNumber, \r
+        BootOptions[Index].Description, \r
+        BootOptions[Index].Attributes\r
+        ));\r
+    }\r
+    DEBUG ((EFI_D_INFO, "[Bds]=============Dumping Boot Options Finished====\n"));\r
+    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
+    );\r
+\r
+  //\r
+  // Boot to Boot Manager Menu when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot\r
+  //\r
+  DataSize = sizeof (UINT64);\r
+  Status = gRT->GetVariable (\r
+                  L"OsIndications",\r
+                  &gEfiGlobalVariableGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &OsIndication\r
+                  );\r
+  if (!EFI_ERROR(Status) && ((OsIndication & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0)) {\r
+    //\r
+    // Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS\r
+    // \r
+    OsIndication &= ~((UINT64) EFI_OS_INDICATIONS_BOOT_TO_FW_UI);\r
+    Status = gRT->SetVariable (\r
+               L"OsIndications",\r
+               &gEfiGlobalVariableGuid,\r
+               EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+               sizeof(UINT64),\r
+               &OsIndication\r
+               );\r
+    //\r
+    // Changing the content without increasing its size with current variable implementation shouldn't fail.\r
+    //\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI\r
+    //\r
+    if (PcdGetBool (PcdConInConnectOnDemand)) {\r
+      BdsDxeOnConnectConInCallBack (NULL, NULL);\r
+    }\r
+\r
+    //\r
+    // Directly boot to Boot Manager Menu.\r
+    //\r
+    EfiBootManagerGetBootManagerMenu (&BootOption);\r
+    EfiBootManagerBoot (&BootOption);\r
+    EfiBootManagerFreeLoadOption (&BootOption);\r
+  } else {\r
+    PERF_START (NULL, "BdsWait", "BDS", 0);\r
+    BdsWait (HotkeyTriggered);\r
+    PERF_END   (NULL, "BdsWait", "BDS", 0);\r
+\r
+    //\r
+    // BdsReadKeys() be removed after all keyboard drivers invoke callback in timer callback.\r
+    //\r
+    BdsReadKeys ();\r
+    \r
+    EfiBootManagerHotkeyBoot ();\r
+  }\r
+\r
+  //\r
+  // Boot to "BootNext"\r
+  //\r
+  if (BootNext != NULL) {\r
+    UnicodeSPrint (BootNextVariableName, sizeof (BootNextVariableName), L"Boot%04x", *BootNext);\r
+    Status = EfiBootManagerVariableToLoadOption (BootNextVariableName, &BootOption);\r
+    if (!EFI_ERROR (Status)) {\r
+      EfiBootManagerBoot (&BootOption);\r
+      EfiBootManagerFreeLoadOption (&BootOption);\r
+      if (BootOption.Status == EFI_SUCCESS) {\r
+        //\r
+        // Boot to Boot Manager Menu upon EFI_SUCCESS\r
+        //\r
+        EfiBootManagerGetBootManagerMenu (&BootOption);\r
+        EfiBootManagerBoot (&BootOption);\r
+        EfiBootManagerFreeLoadOption (&BootOption);\r
+      }\r
+    }\r
+  }\r
+\r
+  while (TRUE) {\r
+    //\r
+    // BDS select the boot device to load OS\r
+    // Try next upon boot failure\r
+    // Show Boot Manager Menu upon boot success\r
+    //\r
+    DefaultBootBehavior ();\r
+  }\r
+}\r
+\r
+/**\r
+  Set the variable and report the error through status code upon failure.\r
+\r
+  @param  VariableName           A Null-terminated string that is the name of the vendor's variable.\r
+                                 Each VariableName is unique for each VendorGuid. VariableName must\r
+                                 contain 1 or more characters. If VariableName is an empty string,\r
+                                 then EFI_INVALID_PARAMETER is returned.\r
+  @param  VendorGuid             A unique identifier for the vendor.\r
+  @param  Attributes             Attributes bitmask to set for the variable.\r
+  @param  DataSize               The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE, \r
+                                 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or \r
+                                 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero \r
+                                 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is \r
+                                 set, then a SetVariable() call with a DataSize of zero will not cause any change to \r
+                                 the variable value (the timestamp associated with the variable may be updated however \r
+                                 even if no new data value is provided,see the description of the \r
+                                 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not \r
+                                 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). \r
+  @param  Data                   The contents for the variable.\r
+\r
+  @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as\r
+                                 defined by the Attributes.\r
+  @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits, name, and GUID was supplied, or the\r
+                                 DataSize exceeds the maximum allowed.\r
+  @retval EFI_INVALID_PARAMETER  VariableName is an empty string.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.\r
+  @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.\r
+  @retval EFI_WRITE_PROTECTED    The variable in question is read-only.\r
+  @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.\r
+  @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS \r
+                                 or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo \r
+                                 does NOT pass the validation check carried out by the firmware.\r
+\r
+  @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.\r
+**/\r
+EFI_STATUS\r
+BdsDxeSetVariableAndReportStatusCodeOnError (\r
+  IN CHAR16     *VariableName,\r
+  IN EFI_GUID   *VendorGuid,\r
+  IN UINT32     Attributes,\r
+  IN UINTN      DataSize,\r
+  IN VOID       *Data\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EDKII_SET_VARIABLE_STATUS  *SetVariableStatus;\r
+  UINTN                      NameSize;\r
+\r
+  Status = gRT->SetVariable (\r
+                  VariableName,\r
+                  VendorGuid,\r
+                  Attributes,\r
+                  DataSize,\r
+                  Data\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    NameSize = StrSize (VariableName);\r
+    SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize);\r
+    if (SetVariableStatus != NULL) {\r
+      CopyGuid (&SetVariableStatus->Guid, VendorGuid);\r
+      SetVariableStatus->NameSize   = NameSize;\r
+      SetVariableStatus->DataSize   = DataSize;\r
+      SetVariableStatus->SetStatus  = Status;\r
+      SetVariableStatus->Attributes = Attributes;\r
+      CopyMem (SetVariableStatus + 1,                          VariableName, NameSize);\r
+      CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Data,         DataSize);\r
+\r
+      REPORT_STATUS_CODE_EX (\r
+        EFI_ERROR_CODE,\r
+        PcdGet32 (PcdErrorCodeSetVariable),\r
+        0,\r
+        NULL,\r
+        &gEdkiiStatusCodeDataTypeVariableGuid,\r
+        SetVariableStatus,\r
+        sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize\r
+        );\r
+\r
+      FreePool (SetVariableStatus);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.c b/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.c
new file mode 100644 (file)
index 0000000..87e39c3
--- /dev/null
@@ -0,0 +1,48 @@
+/** @file\r
+  Set the level of support for Hardware Error Record Persistence that is\r
+  implemented by the platform.\r
+\r
+Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "HwErrRecSupport.h"\r
+\r
+/**\r
+  Set the HwErrRecSupport variable contains a binary UINT16 that supplies the\r
+  level of support for Hardware Error Record Persistence that is implemented\r
+  by the platform.\r
+\r
+**/\r
+VOID\r
+InitializeHwErrRecSupport (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  UINT16        HardwareErrorRecordLevel;\r
+  \r
+  HardwareErrorRecordLevel = PcdGet16 (PcdHardwareErrorRecordLevel);\r
+  \r
+  if (HardwareErrorRecordLevel != 0) {\r
+    //\r
+    // If level value equal 0, no need set to 0 to variable area because UEFI specification\r
+    // define same behavior between no value or 0 value for L"HwErrRecSupport".\r
+    //\r
+    Status = gRT->SetVariable (\r
+                    L"HwErrRecSupport",\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                    sizeof (UINT16),\r
+                    &HardwareErrorRecordLevel\r
+                    );\r
+    ASSERT_EFI_ERROR(Status);\r
+  }\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.h b/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.h
new file mode 100644 (file)
index 0000000..2ac05d5
--- /dev/null
@@ -0,0 +1,32 @@
+/** @file\r
+  Set the level of support for Hardware Error Record Persistence that is\r
+  implemented by the platform.\r
+\r
+Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _HW_ERR_REC_SUPPORT_H_\r
+#define _HW_ERR_REC_SUPPORT_H_\r
+\r
+#include "Bds.h"\r
+\r
+/**\r
+  Set the HwErrRecSupport variable contains a binary UINT16 that supplies the\r
+  level of support for Hardware Error Record Persistence that is implemented\r
+  by the platform.\r
+\r
+**/\r
+VOID\r
+InitializeHwErrRecSupport (\r
+  VOID\r
+  );\r
+\r
+#endif\r
diff --git a/MdeModulePkg/Universal/BdsDxe/Language.c b/MdeModulePkg/Universal/BdsDxe/Language.c
new file mode 100644 (file)
index 0000000..0912731
--- /dev/null
@@ -0,0 +1,202 @@
+/** @file\r
+  Language settings\r
+\r
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Bds.h"\r
+#define ISO_639_2_ENTRY_SIZE 3\r
+\r
+/**\r
+  Check if lang is in supported language codes according to language string.\r
+\r
+  This code is used to check if lang is in in supported language codes. It can handle\r
+  RFC4646 and ISO639 language tags.\r
+  In ISO639 language tags, take 3-characters as a delimitation to find matched string.\r
+  In RFC4646 language tags, take semicolon as a delimitation to find matched string.\r
+\r
+  For example:\r
+    SupportedLang  = "engfraengfra"\r
+    Iso639Language = TRUE\r
+    Lang           = "eng", the return value is "TRUE", or\r
+    Lang           = "chs", the return value is "FALSE".\r
+  Another example:\r
+    SupportedLang  = "en;fr;en-US;fr-FR"\r
+    Iso639Language = FALSE\r
+    Lang           = "en", the return value is "TRUE", or\r
+    Lang           = "zh", the return value is "FALSE".\r
+\r
+  @param  SupportedLang               Platform supported language codes.\r
+  @param  Lang                        Configured language.\r
+  @param  Iso639Language              A bool value to signify if the handler is operated on ISO639 or RFC4646.\r
+\r
+  @retval TRUE  lang is in supported language codes.\r
+  @retval FALSE lang is not in supported language codes.\r
+\r
+**/\r
+BOOLEAN\r
+IsLangInSupportedLangCodes(\r
+  IN  CHAR8            *SupportedLang,\r
+  IN  CHAR8            *Lang,\r
+  IN  BOOLEAN          Iso639Language\r
+  ) \r
+{\r
+  UINTN    Index;\r
+  UINTN    CompareLength;\r
+  UINTN    LanguageLength;\r
+\r
+  if (Iso639Language) {\r
+    CompareLength = ISO_639_2_ENTRY_SIZE;\r
+    for (Index = 0; Index < AsciiStrLen (SupportedLang); Index += CompareLength) {\r
+      if (AsciiStrnCmp (Lang, SupportedLang + Index, CompareLength) == 0) {\r
+        //\r
+        // Successfully find the Lang string in SupportedLang string.\r
+        //\r
+        return TRUE;\r
+      }\r
+    }\r
+    return FALSE;\r
+  } else {\r
+    //\r
+    // Compare RFC4646 language code\r
+    //\r
+    for (LanguageLength = 0; Lang[LanguageLength] != '\0'; LanguageLength++);\r
+\r
+    for (; *SupportedLang != '\0'; SupportedLang += CompareLength) {\r
+      //\r
+      // Skip ';' characters in SupportedLang\r
+      //\r
+      for (; *SupportedLang != '\0' && *SupportedLang == ';'; SupportedLang++);\r
+      //\r
+      // Determine the length of the next language code in SupportedLang\r
+      //\r
+      for (CompareLength = 0; SupportedLang[CompareLength] != '\0' && SupportedLang[CompareLength] != ';'; CompareLength++);\r
+      \r
+      if ((CompareLength == LanguageLength) && \r
+          (AsciiStrnCmp (Lang, SupportedLang, CompareLength) == 0)) {\r
+        //\r
+        // Successfully find the Lang string in SupportedLang string.\r
+        //\r
+        return TRUE;\r
+      }\r
+    }\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Initialize Lang or PlatformLang variable, if Lang or PlatformLang variable is not found,\r
+  or it has been set to an unsupported value(not one of platform supported language codes),\r
+  set the default language code to it.\r
+\r
+  @param  LangName                    Language name, L"Lang" or L"PlatformLang".\r
+  @param  SupportedLang               Platform supported language codes.\r
+  @param  DefaultLang                 Default language code.\r
+  @param  Iso639Language              A bool value to signify if the handler is operated on ISO639 or RFC4646,\r
+                                      TRUE for L"Lang" LangName or FALSE for L"PlatformLang" LangName.\r
+\r
+**/\r
+VOID\r
+InitializeLangVariable (\r
+  IN CHAR16     *LangName,\r
+  IN CHAR8      *SupportedLang,\r
+  IN CHAR8      *DefaultLang,     \r
+  IN BOOLEAN    Iso639Language\r
+  )\r
+{\r
+  CHAR8       *Lang;\r
+\r
+  //\r
+  // Find current Lang or PlatformLang from EFI Variable.\r
+  //\r
+  GetEfiGlobalVariable2 (LangName, (VOID **) &Lang, NULL);\r
+\r
+  //\r
+  // If Lang or PlatformLang variable is not found,\r
+  // or it has been set to an unsupported value(not one of the supported language codes),\r
+  // set the default language code to it.\r
+  //\r
+  if ((Lang == NULL) || !IsLangInSupportedLangCodes (SupportedLang, Lang, Iso639Language)) {\r
+    //\r
+    // The default language code should be one of the supported language codes.\r
+    //\r
+    ASSERT (IsLangInSupportedLangCodes (SupportedLang, DefaultLang, Iso639Language));\r
+    BdsDxeSetVariableAndReportStatusCodeOnError (\r
+      LangName,\r
+      &gEfiGlobalVariableGuid,\r
+      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+      AsciiStrSize (DefaultLang),\r
+      DefaultLang\r
+      );\r
+  }\r
+\r
+  if (Lang != NULL) {\r
+    FreePool (Lang);\r
+  }\r
+}\r
+\r
+/**\r
+  Determine the current language that will be used\r
+  based on language related EFI Variables.\r
+\r
+  @param LangCodesSettingRequired - If required to set LangCodes variable\r
+\r
+**/\r
+VOID\r
+InitializeLanguage (\r
+  BOOLEAN LangCodesSettingRequired\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  CHAR8       *LangCodes;\r
+  CHAR8       *PlatformLangCodes;\r
+\r
+  LangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLangCodes);\r
+  PlatformLangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes);\r
+  if (LangCodesSettingRequired) {\r
+    if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {\r
+      //\r
+      // UEFI 2.1 depricated this variable so we support turning it off\r
+      //\r
+      Status = gRT->SetVariable (\r
+                      L"LangCodes",\r
+                      &gEfiGlobalVariableGuid,\r
+                      EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                      AsciiStrSize (LangCodes),\r
+                      LangCodes\r
+                      );\r
+      //\r
+      // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail.\r
+      //\r
+      ASSERT_EFI_ERROR(Status);\r
+    }\r
+\r
+    Status = gRT->SetVariable (\r
+                    L"PlatformLangCodes",\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    AsciiStrSize (PlatformLangCodes),\r
+                    PlatformLangCodes\r
+                    );\r
+    //\r
+    // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail.\r
+    //\r
+    ASSERT_EFI_ERROR(Status);\r
+  }\r
+\r
+  if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {\r
+    //\r
+    // UEFI 2.1 depricated this variable so we support turning it off\r
+    //\r
+    InitializeLangVariable (L"Lang", LangCodes, (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultLang), TRUE);\r
+  }\r
+  InitializeLangVariable (L"PlatformLang", PlatformLangCodes, (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang), FALSE);\r
+}\r
diff --git a/MdeModulePkg/Universal/BdsDxe/Language.h b/MdeModulePkg/Universal/BdsDxe/Language.h
new file mode 100644 (file)
index 0000000..3d5f34f
--- /dev/null
@@ -0,0 +1,30 @@
+/** @file\r
+  Language setting\r
+\r
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LANGUAGE_H_\r
+#define _LANGUAGE_H_\r
+\r
+/**\r
+  Determine the current language that will be used\r
+  based on language related EFI Variables.\r
+\r
+  @param LangCodesSettingRequired If required to set LangCode variable\r
+\r
+**/\r
+VOID\r
+InitializeLanguage (\r
+  BOOLEAN LangCodesSettingRequired\r
+  );\r
+\r
+#endif // _LANGUAGE_H_\r