]> git.proxmox.com Git - mirror_edk2.git/commitdiff
EdkGenericPlatformBdsLib added
authortgingold <tgingold@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 12 Feb 2007 23:40:29 +0000 (23:40 +0000)
committertgingold <tgingold@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 12 Feb 2007 23:40:29 +0000 (23:40 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2368 6f19259b-4bc3-4df7-8a09-765794883524

40 files changed:
EdkModulePkg/Include/Library/EdkGenericPlatformBdsLib.h [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/Bds.dxs [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/Bds.h [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BdsBoot.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BdsEntry.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BBSsupport.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BBSsupport.h [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Bm.vfr [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmLib.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmString.uni [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootMaint.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootMaint.h [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootOption.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/ConsoleOption.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Data.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FE.vfr [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FileExplorer.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FormGuid.h [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/UpdatePage.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Variable.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.h [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerStrings.uni [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerVfr.Vfr [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/Capsules.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManager.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManager.h [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerStrings.uni [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerVfr.Vfr [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/EdkGenericPlatformBdsLib.msa [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPage.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPage.h [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageStrings.uni [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageVfr.Vfr [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/Language.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/Language.h [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/MemoryTest.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/String.c [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/String.h [new file with mode: 0644]
EdkModulePkg/Library/EdkGenericPlatformBdsLib/Strings.uni [new file with mode: 0644]

diff --git a/EdkModulePkg/Include/Library/EdkGenericPlatformBdsLib.h b/EdkModulePkg/Include/Library/EdkGenericPlatformBdsLib.h
new file mode 100644 (file)
index 0000000..699abd8
--- /dev/null
@@ -0,0 +1,140 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name: \r
+\r
+  BdsPlatform.h\r
+\r
+Abstract:\r
+\r
+  Head file for BDS Platform specific code\r
+\r
+--*/\r
+\r
+#ifndef _BDS_PLATFORM_LIB_H\r
+#define _BDS_PLATFORM_LIB_H\r
+\r
+extern BDS_CONSOLE_CONNECT_ENTRY  gPlatformConsole[];\r
+extern EFI_DEVICE_PATH_PROTOCOL   *gPlatformConnectSequence[];\r
+extern EFI_DEVICE_PATH_PROTOCOL   *gPlatformDriverOption[];\r
+//\r
+// Bds AP Context data\r
+//\r
+#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE  EFI_SIGNATURE_32 ('B', 'd', 's', 'A')\r
+typedef struct {\r
+  UINTN                     Signature;\r
+\r
+  EFI_HANDLE                Handle;\r
+\r
+  EFI_BDS_ARCH_PROTOCOL     Bds;\r
+\r
+  //\r
+  // Save the current boot mode\r
+  //\r
+  EFI_BOOT_MODE             BootMode;\r
+\r
+  //\r
+  // Set true if boot with default settings\r
+  //\r
+  BOOLEAN                   DefaultBoot;\r
+\r
+  //\r
+  // The system default timeout for choose the boot option\r
+  //\r
+  UINT16                    TimeoutDefault;\r
+\r
+  //\r
+  // Memory Test Level\r
+  //\r
+  EXTENDMEM_COVERAGE_LEVEL  MemoryTestLevel;\r
+\r
+} EFI_BDS_ARCH_PROTOCOL_INSTANCE;\r
+\r
+#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS(_this) \\r
+  CR (_this, \\r
+      EFI_BDS_ARCH_PROTOCOL_INSTANCE, \\r
+      Bds, \\r
+      EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE \\r
+      )\r
+
+\r
+#define gEndEntire \\r
+  { \\r
+    END_DEVICE_PATH_TYPE,\\r
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,\\r
+    {\\r
+      END_DEVICE_PATH_LENGTH,\\r
+      0\\r
+    }\\r
+  }\r
+\r
+//\r
+// Platform BDS Functions\r
+//\r
+VOID\r
+PlatformBdsInit (\r
+  IN EFI_BDS_ARCH_PROTOCOL_INSTANCE  *PrivateData\r
+  )\r
+;\r
+\r
+VOID\r
+PlatformBdsPolicyBehavior (\r
+  IN EFI_BDS_ARCH_PROTOCOL_INSTANCE  *PrivateData,\r
+  IN LIST_ENTRY                      *DriverOptionList,\r
+  IN LIST_ENTRY                      *BootOptionList\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+BdsMemoryTest (\r
+  EXTENDMEM_COVERAGE_LEVEL Level\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+  CHAR16                        *Title,\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+  UINTN                         Progress,\r
+  UINTN                         PreviousValue\r
+  )\r
+;\r
+\r
+VOID\r
+PlatformBdsBootFail (\r
+  IN  BDS_COMMON_OPTION  *Option,\r
+  IN  EFI_STATUS         Status,\r
+  IN  CHAR16             *ExitData,\r
+  IN  UINTN              ExitDataSize\r
+  )\r
+;\r
+\r
+VOID\r
+PlatformBdsBootSuccess (\r
+  IN  BDS_COMMON_OPTION *Option\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+ProcessCapsules (\r
+  EFI_BOOT_MODE BootMode\r
+  )\r
+;\r
+\r
+VOID\r
+PlatformBdsEnterFrontPage (\r
+  IN UINT16                 TimeoutDefault,\r
+  IN BOOLEAN                ConnectAllHappened\r
+  );\r
+\r
+#endif // _BDS_PLATFORM_LIB_H\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Bds.dxs b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Bds.dxs
new file mode 100644 (file)
index 0000000..6647561
--- /dev/null
@@ -0,0 +1,27 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  Bds.dxs\r
+\r
+Abstract:\r
+\r
+  Dependency expression source file.  This driver produces an arch protocol, so\r
+  must dipatch early.\r
+  \r
+--*/\r
+#include <AutoGen.h>\r
+#include <DxeDepex.h>\r
+\r
+DEPENDENCY_START\r
+  EFI_HII_PROTOCOL_GUID\r
+DEPENDENCY_END
\ No newline at end of file
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Bds.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Bds.h
new file mode 100644 (file)
index 0000000..2548aaf
--- /dev/null
@@ -0,0 +1,44 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  Bds.h\r
+\r
+Abstract:\r
+\r
+  Head file for BDS Architectural Protocol implementation\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _BDS_H\r
+#define _BDS_H\r
+\r
+\r
+//\r
+// Prototypes\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+BdsInitialize (\r
+  IN EFI_HANDLE                     ImageHandle,\r
+  IN EFI_SYSTEM_TABLE               *SystemTable\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+  IN  EFI_BDS_ARCH_PROTOCOL *This\r
+  );\r
+\r
+#endif\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BdsBoot.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BdsBoot.c
new file mode 100644 (file)
index 0000000..0a9d359
--- /dev/null
@@ -0,0 +1,103 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  BdsPlatform.c\r
+\r
+Abstract:\r
+\r
+  This file include all platform action which can be customized\r
+  by IBV/OEM.\r
+\r
+--*/\r
+\r
+#include "String.h"
+\r
+VOID\r
+PlatformBdsBootSuccess (\r
+  IN  BDS_COMMON_OPTION *Option\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Hook point after a boot attempt succeeds. We don't expect a boot option to\r
+  return, so the EFI 1.0 specification defines that you will default to an\r
+  interactive mode and stop processing the BootOrder list in this case. This\r
+  is alos a platform implementation and can be customized by IBV/OEM.\r
+\r
+Arguments:\r
+\r
+  Option - Pointer to Boot Option that succeeded to boot.\r
+\r
+Returns:\r
+  \r
+  None.\r
+\r
+--*/\r
+{\r
+  CHAR16  *TmpStr;\r
+\r
+  //\r
+  // If Boot returned with EFI_SUCCESS and there is not in the boot device\r
+  // select loop then we need to pop up a UI and wait for user input.\r
+  //\r
+  TmpStr = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
+  if (TmpStr != NULL) {\r
+    BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
+    gBS->FreePool (TmpStr);\r
+  }\r
+}\r
+\r
+VOID\r
+PlatformBdsBootFail (\r
+  IN  BDS_COMMON_OPTION  *Option,\r
+  IN  EFI_STATUS         Status,\r
+  IN  CHAR16             *ExitData,\r
+  IN  UINTN              ExitDataSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Hook point after a boot attempt fails.\r
+\r
+Arguments:\r
+  \r
+  Option - Pointer to Boot Option that failed to boot.\r
+\r
+  Status - Status returned from failed boot.\r
+\r
+  ExitData - Exit data returned from failed boot.\r
+\r
+  ExitDataSize - Exit data size returned from failed boot.\r
+\r
+Returns:\r
+  \r
+  None.\r
+\r
+--*/\r
+{\r
+  CHAR16  *TmpStr;\r
+\r
+  //\r
+  // If Boot returned with failed status then we need to pop up a UI and wait\r
+  // for user input.\r
+  //\r
+  TmpStr = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+  if (TmpStr != NULL) {\r
+    BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
+    gBS->FreePool (TmpStr);\r
+  }\r
+\r
+}\r
+\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BdsEntry.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BdsEntry.c
new file mode 100644 (file)
index 0000000..7c219b6
--- /dev/null
@@ -0,0 +1,363 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  BdsEntry.c\r
+\r
+Abstract:\r
+\r
+  The entry of the bds\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+#include "Language.h"
+\r
+EFI_BDS_ARCH_PROTOCOL_INSTANCE  gBdsInstanceTemplate = {\r
+  EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE,\r
+  NULL,\r
+  {\r
+    BdsEntry\r
+  },\r
+  0xFFFF,\r
+  TRUE,\r
+  EXTENSIVE\r
+};\r
+\r
+UINT16                          *mBootNext = NULL;\r
+\r
+EFI_HANDLE                      mBdsImageHandle;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BdsInitialize (\r
+  IN EFI_HANDLE                            ImageHandle,\r
+  IN EFI_SYSTEM_TABLE                      *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Install Boot Device Selection Protocol\r
+\r
+Arguments:\r
+  \r
+  (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
+\r
+Returns:\r
+\r
+  EFI_SUCEESS - BDS has finished initializing.\r
+                Rerun the \r
+                dispatcher and recall BDS.Entry\r
+\r
+  Other       - Return value from EfiLibAllocatePool()\r
+                or gBS->InstallProtocolInterface\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  mBdsImageHandle = ImageHandle;\r
+\r
+  //\r
+  // Install protocol interface\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &gBdsInstanceTemplate.Handle,\r
+                  &gEfiBdsArchProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &gBdsInstanceTemplate.Bds\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+BdsBootDeviceSelect (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  In the loop of attempt to boot for the boot order\r
+\r
+Arguments:\r
+  \r
+  None.\r
+\r
+Returns:\r
+\r
+  None.\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS        Status;\r
+  LIST_ENTRY        *Link;\r
+  BDS_COMMON_OPTION *BootOption;\r
+  UINTN             ExitDataSize;\r
+  CHAR16            *ExitData;\r
+  UINT16            Timeout;\r
+  LIST_ENTRY        BootLists;\r
+  CHAR16            Buffer[20];\r
+  BOOLEAN           BootNextExist;\r
+  LIST_ENTRY        *LinkBootNext;\r
+\r
+  //\r
+  // Got the latest boot option\r
+  //\r
+  BootNextExist = FALSE;\r
+  LinkBootNext  = NULL;\r
+  InitializeListHead (&BootLists);\r
+\r
+  //\r
+  // First check the boot next option\r
+  //\r
+  ZeroMem (Buffer, sizeof (Buffer));\r
+\r
+  if (mBootNext != NULL) {\r
+    //\r
+    // Indicate we have the boot next variable, so this time\r
+    // boot will always have this boot option\r
+    //\r
+    BootNextExist = TRUE;\r
+\r
+    //\r
+    // Clear the this variable so it's only exist in this time boot\r
+    //\r
+    gRT->SetVariable (\r
+          L"BootNext",\r
+          &gEfiGlobalVariableGuid,\r
+          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+          0,\r
+          mBootNext\r
+          );\r
+\r
+    //\r
+    // Add the boot next boot option\r
+    //\r
+    UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);\r
+    BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
+  }\r
+  //\r
+  // Parse the boot order to get boot option\r
+  //\r
+  BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+  Link = BootLists.ForwardLink;\r
+\r
+  //\r
+  // Parameter check, make sure the loop will be valid\r
+  //\r
+  if (Link == NULL) {\r
+    return ;\r
+  }\r
+  //\r
+  // Here we make the boot in a loop, every boot success will\r
+  // return to the front page\r
+  //\r
+  for (;;) {\r
+    //\r
+    // Check the boot option list first\r
+    //\r
+    if (Link == &BootLists) {\r
+      //\r
+      // There are two ways to enter here:\r
+      // 1. There is no active boot option, give user chance to\r
+      //    add new boot option\r
+      // 2. All the active boot option processed, and there is no\r
+      //    one is success to boot, then we back here to allow user\r
+      //    add new active boot option\r
+      //\r
+      Timeout = 0xffff;\r
+      PlatformBdsEnterFrontPage (Timeout, FALSE);\r
+      InitializeListHead (&BootLists);\r
+      BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+      Link = BootLists.ForwardLink;\r
+      continue;\r
+    }\r
+    //\r
+    // Get the boot option from the link list\r
+    //\r
+    BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\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 (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {\r
+      //\r
+      // skip the header of the link list, becuase it has no boot option\r
+      //\r
+      Link = Link->ForwardLink;\r
+      continue;\r
+    }\r
+    //\r
+    // Make sure the boot option device path connected,\r
+    // but ignore the BBS device path\r
+    //\r
+    if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {\r
+      //\r
+      // Notes: the internal shell can not been connected with device path\r
+      // so we do not check the status here\r
+      //\r
+      BdsLibConnectDevicePath (BootOption->DevicePath);\r
+    }\r
+    //\r
+    // All the driver options should have been processed since\r
+    // now boot will be performed.\r
+    //\r
+    PERF_END (0, BDS_TOK, NULL, 0);\r
+    Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Call platform action to indicate the boot fail\r
+      //\r
+      PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
+\r
+      //\r
+      // Check the next boot option\r
+      //\r
+      Link = Link->ForwardLink;\r
+\r
+    } else {\r
+      //\r
+      // Call platform action to indicate the boot success\r
+      //\r
+      PlatformBdsBootSuccess (BootOption);\r
+\r
+      //\r
+      // Boot success, then stop process the boot order, and\r
+      // present the boot manager menu, front page\r
+      //\r
+      Timeout = 0xffff;\r
+      PlatformBdsEnterFrontPage (Timeout, FALSE);\r
+\r
+      //\r
+      // Rescan the boot option list, avoid pertential risk of the boot\r
+      // option change in front page\r
+      //\r
+      if (BootNextExist) {\r
+        LinkBootNext = BootLists.ForwardLink;\r
+      }\r
+\r
+      InitializeListHead (&BootLists);\r
+      if (LinkBootNext != NULL) {\r
+        //\r
+        // Reserve the boot next option\r
+        //\r
+        InsertTailList (&BootLists, LinkBootNext);\r
+      }\r
+\r
+      BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+      Link = BootLists.ForwardLink;\r
+    }\r
+  }\r
+\r
+  return ;\r
+\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+  IN EFI_BDS_ARCH_PROTOCOL  *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Service routine for BdsInstance->Entry(). Devices are connected, the \r
+  consoles are initialized, and the boot options are tried. \r
+\r
+Arguments:\r
+\r
+  This - Protocol Instance structure.\r
+\r
+Returns:\r
+\r
+  EFI_SUCEESS - BDS->Entry has finished executing. \r
+                \r
+--*/\r
+{\r
+  EFI_BDS_ARCH_PROTOCOL_INSTANCE  *PrivateData;\r
+  LIST_ENTRY                      DriverOptionList;\r
+  LIST_ENTRY                      BootOptionList;\r
+  UINTN                           BootNextSize;\r
+\r
+  //\r
+  // Insert the performance probe\r
+  //\r
+  PERF_END (0, DXE_TOK, NULL, 0);\r
+  PERF_START (0, BDS_TOK, NULL, 0);\r
+\r
+  //\r
+  // Initialize the global system boot option and driver option\r
+  //\r
+  InitializeListHead (&DriverOptionList);\r
+  InitializeListHead (&BootOptionList);\r
+\r
+  //\r
+  // Get the BDS private data\r
+  //\r
+  PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This);\r
+\r
+  //\r
+  // Do the platform init, can be customized by OEM/IBV\r
+  //\r
+  PERF_START (0, "PlatformBds", "BDS", 0);\r
+  PlatformBdsInit (PrivateData);\r
+\r
+  //\r
+  // Initialize the platform specific string and language\r
+  //\r
+  InitializeStringSupport ();\r
+  InitializeLanguage (TRUE);\r
+  InitializeFrontPage (FALSE);\r
+  //\r
+  // Set up the device list based on EFI 1.1 variables\r
+  // process Driver#### and Load the driver's in the\r
+  // driver option list\r
+  //\r
+  BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");\r
+  if (!IsListEmpty (&DriverOptionList)) {\r
+    BdsLibLoadDrivers (&DriverOptionList);\r
+  }\r
+  //\r
+  // Check if we have the boot next option\r
+  //\r
+  mBootNext = BdsLibGetVariableAndSize (\r
+                L"BootNext",\r
+                &gEfiGlobalVariableGuid,\r
+                &BootNextSize\r
+                );\r
+\r
+  //\r
+  // Setup some platform policy here\r
+  //\r
+  PlatformBdsPolicyBehavior (PrivateData, &DriverOptionList, &BootOptionList);\r
+  PERF_END (0, "PlatformBds", "BDS", 0);\r
+\r
+  //\r
+  // BDS select the boot device to load OS\r
+  //\r
+  BdsBootDeviceSelect ();\r
+\r
+  //\r
+  // Only assert here since this is the right behavior, we should never\r
+  // return back to DxeCore.\r
+  //\r
+  ASSERT (FALSE);\r
+}\r
+\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BBSsupport.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BBSsupport.c
new file mode 100644 (file)
index 0000000..76dd54f
--- /dev/null
@@ -0,0 +1,1605 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                          \r
+All rights reserved. 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
+Module Name:\r
+\r
+  BBSsupport.c\r
+\r
+Abstract:\r
+\r
+  This function deal with the legacy boot option, it create, delete\r
+  and manage the legacy boot option, all legacy boot option is getting from\r
+  the legacy BBS table.\r
+\r
+--*/\r
+\r
+#include "BBSsupport.h"\r
+\r
+EFI_DEVICE_PATH_PROTOCOL  EndDevicePath[] = {\r
+  {\r
+    END_DEVICE_PATH_TYPE,\r
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+    {\r
+      END_DEVICE_PATH_LENGTH,\r
+      0\r
+    }\r
+  }\r
+};\r
+\r
+VOID\r
+AsciiToUnicodeSize (\r
+  IN UINT8              *a,\r
+  IN UINTN              Size,\r
+  OUT UINT16            *u\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+\r
+    Translate the first n characters of an Ascii string to\r
+    Unicode characters. The count n is indicated by parameter\r
+    Size. If Size is greater than the length of string, then\r
+    the entire string is translated.\r
+\r
+  Arguments:\r
+\r
+    a         - Pointer to input Ascii string.\r
+    Size      - The number of characters to translate.\r
+    u         - Pointer to output Unicode string buffer.\r
+\r
+  Returns:\r
+\r
+    None\r
+\r
+--*/\r
+{\r
+  UINTN i;\r
+\r
+  i = 0;\r
+  while (a[i] != 0) {\r
+    u[i] = (CHAR16) a[i];\r
+    if (i == Size) {\r
+      break;\r
+    }\r
+\r
+    i++;\r
+  }\r
+  u[i] = 0;\r
+}\r
+\r
+VOID\r
+BdsBuildLegacyDevNameString (\r
+  IN BBS_TABLE                 *CurBBSEntry,\r
+  IN UINTN                     Index,\r
+  IN UINTN                     BufSize,\r
+  OUT CHAR16                   *BootString\r
+  )\r
+{\r
+  CHAR16  *Fmt;\r
+  CHAR16  *Type;\r
+  UINT8   *StringDesc;\r
+  CHAR16  temp[80];\r
+\r
+  switch (Index) {\r
+  //\r
+  // Primary Master\r
+  //\r
+  case 1:\r
+    Fmt = L"Primary Master %s";\r
+    break;\r
+\r
+ //\r
+ // Primary Slave\r
+ //\r
+  case 2:\r
+    Fmt = L"Primary Slave %s";\r
+    break;\r
+\r
+  //\r
+  // Secondary Master\r
+  //\r
+  case 3:\r
+    Fmt = L"Secondary Master %s";\r
+    break;\r
+\r
+  //\r
+  // Secondary Slave\r
+  //\r
+  case 4:\r
+    Fmt = L"Secondary Slave %s";\r
+    break;\r
+\r
+  default:\r
+    Fmt = L"%s";\r
+    break;\r
+  }\r
+\r
+  switch (CurBBSEntry->DeviceType) {\r
+  case BBS_FLOPPY:\r
+    Type = L"Floppy";\r
+    break;\r
+\r
+  case BBS_HARDDISK:\r
+    Type = L"Harddisk";\r
+    break;\r
+\r
+  case BBS_CDROM:\r
+    Type = L"CDROM";\r
+    break;\r
+\r
+  case BBS_PCMCIA:\r
+    Type = L"PCMCIAe";\r
+    break;\r
+\r
+  case BBS_USB:\r
+    Type = L"USB";\r
+    break;\r
+\r
+  case BBS_EMBED_NETWORK:\r
+    Type = L"Network";\r
+    break;\r
+\r
+  case BBS_BEV_DEVICE:\r
+    Type = L"BEVe";\r
+    break;\r
+\r
+  case BBS_UNKNOWN:\r
+  default:\r
+    Type = L"Unknown";\r
+    break;\r
+  }\r
+  //\r
+  // If current BBS entry has its description then use it.\r
+  //\r
+  StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);\r
+  if (NULL != StringDesc) {\r
+    //\r
+    // Only get fisrt 32 characters, this is suggested by BBS spec\r
+    //\r
+    AsciiToUnicodeSize (StringDesc, 32, temp);\r
+    Fmt   = L"%s";\r
+    Type  = temp;\r
+  }\r
+\r
+  UnicodeSPrint (BootString, BufSize, Fmt, Type);\r
+}\r
+\r
+EFI_STATUS\r
+BdsCreateLegacyBootOption (\r
+  IN BBS_TABLE                        *CurrentBbsEntry,\r
+  IN EFI_DEVICE_PATH_PROTOCOL         *CurrentBbsDevPath,\r
+  IN UINTN                            Index,\r
+  IN OUT UINT16                       **BootOrderList,\r
+  IN OUT UINTN                        *BootOrderListSize\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+\r
+    Create a legacy boot option for the specified entry of\r
+    BBS table, save it as variable, and append it to the boot\r
+    order list.\r
+\r
+  Arguments:\r
+\r
+    CurrentBbsEntry        - Pointer to current BBS table.\r
+    CurrentBbsDevPath      - Pointer to the Device Path Protocol instance of BBS\r
+    Index                  - Index of the specified entry in BBS table.\r
+    BootOrderList          - On input, the original boot order list.\r
+                             On output, the new boot order list attached with the\r
+                             created node.\r
+    BootOrderListSize      - On input, the original size of boot order list.\r
+                           - On output, the size of new boot order list.\r
+\r
+  Returns:\r
+\r
+    EFI_SUCCESS            - Boot Option successfully created.\r
+    EFI_OUT_OF_RESOURCES   - Fail to allocate necessary memory.\r
+    Other                  - Error occurs while setting variable.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT16      CurrentBootOptionNo;\r
+  UINT16      BootString[10];\r
+  UINT16      BootDesc[100];\r
+  UINT16      *NewBootOrderList;\r
+  UINTN       BufferSize;\r
+  VOID        *Buffer;\r
+  UINT8       *Ptr;\r
+  UINT16      CurrentBbsDevPathSize;\r
+  UINTN       BootOrderIndex;\r
+  UINTN       BootOrderLastIndex;\r
+  UINTN       ArrayIndex;\r
+  BOOLEAN     IndexNotFound;\r
+\r
+  if (NULL == (*BootOrderList)) {\r
+    CurrentBootOptionNo = 0;\r
+  } else {\r
+    for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) {\r
+      IndexNotFound = TRUE;\r
+      for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) {\r
+        if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) {\r
+          IndexNotFound = FALSE;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (!IndexNotFound) {\r
+        continue;\r
+      } else {\r
+        break;\r
+      }\r
+    }\r
+\r
+    CurrentBootOptionNo = (UINT16) ArrayIndex;\r
+  }\r
+\r
+  UnicodeSPrint (\r
+    BootString,\r
+    sizeof (BootString),\r
+    L"Boot%04x",\r
+    CurrentBootOptionNo\r
+    );\r
+\r
+  BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc);\r
+\r
+  CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath));\r
+\r
+  BufferSize = sizeof (UINT32) +\r
+    sizeof (UINT16) +\r
+    StrSize (BootDesc) +\r
+    CurrentBbsDevPathSize +\r
+    sizeof (BBS_TABLE) +\r
+    sizeof (UINT16);\r
+\r
+  Buffer = AllocateZeroPool (BufferSize);\r
+  if (Buffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Ptr               = (UINT8 *) Buffer;\r
+\r
+  *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
+  Ptr += sizeof (UINT32);\r
+\r
+  *((UINT16 *) Ptr) = CurrentBbsDevPathSize;\r
+  Ptr += sizeof (UINT16);\r
+\r
+  CopyMem (\r
+    Ptr,\r
+    BootDesc,\r
+    StrSize (BootDesc)\r
+    );\r
+  Ptr += StrSize (BootDesc);\r
+\r
+  CopyMem (\r
+    Ptr,\r
+    CurrentBbsDevPath,\r
+    CurrentBbsDevPathSize\r
+    );\r
+  Ptr += CurrentBbsDevPathSize;\r
+\r
+  CopyMem (\r
+    Ptr,\r
+    CurrentBbsEntry,\r
+    sizeof (BBS_TABLE)\r
+    );\r
+\r
+  Ptr += sizeof (BBS_TABLE);\r
+  *((UINT16 *) Ptr) = (UINT16) Index;\r
+\r
+  Status = gRT->SetVariable (\r
+                  BootString,\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BufferSize,\r
+                  Buffer\r
+                  );\r
+\r
+  SafeFreePool (Buffer);\r
+  Buffer = NULL;\r
+\r
+  NewBootOrderList = AllocateZeroPool (*BootOrderListSize + sizeof (UINT16));\r
+  if (NULL == NewBootOrderList) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (NULL != *BootOrderList) {\r
+    CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);\r
+  }\r
+\r
+  SafeFreePool (*BootOrderList);\r
+\r
+  BootOrderLastIndex                    = (UINTN) (*BootOrderListSize / sizeof (UINT16));\r
+  NewBootOrderList[BootOrderLastIndex]  = CurrentBootOptionNo;\r
+  *BootOrderListSize += sizeof (UINT16);\r
+  *BootOrderList = NewBootOrderList;\r
+\r
+  return Status;\r
+}\r
+\r
+BOOLEAN\r
+BdsIsLegacyBootOption (\r
+  IN UINT8                 *BootOptionVar,\r
+  OUT BBS_TABLE            **BbsEntry,\r
+  OUT UINT16               *BbsIndex\r
+  )\r
+{\r
+  UINT8                     *Ptr;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  BOOLEAN                   Ret;\r
+  UINT16                    DevPathLen;\r
+\r
+  Ptr = BootOptionVar;\r
+  Ptr += sizeof (UINT32);\r
+  DevPathLen = *(UINT16 *) Ptr;\r
+  Ptr += sizeof (UINT16);\r
+  Ptr += StrSize ((UINT16 *) Ptr);\r
+  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+  if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
+    Ptr += DevPathLen;\r
+    *BbsEntry = (BBS_TABLE *) Ptr;\r
+    Ptr += sizeof (BBS_TABLE);\r
+    *BbsIndex = *(UINT16 *) Ptr;\r
+    Ret       = TRUE;\r
+  } else {\r
+    *BbsEntry = NULL;\r
+    Ret       = FALSE;\r
+  }\r
+\r
+  return Ret;\r
+}\r
+\r
+EFI_STATUS\r
+BdsDeleteBootOption (\r
+  IN UINTN                       OptionNumber,\r
+  IN OUT UINT16                  *BootOrder,\r
+  IN OUT UINTN                   *BootOrderSize\r
+  )\r
+{\r
+  UINT16      BootOption[100];\r
+  UINTN       Index;\r
+  EFI_STATUS  Status;\r
+  UINTN       Index2Del;\r
+\r
+  Status    = EFI_SUCCESS;\r
+  Index2Del = 0;\r
+\r
+  UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber);\r
+  Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid);\r
+  //\r
+  // adjust boot order array\r
+  //\r
+  for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) {\r
+    if (BootOrder[Index] == OptionNumber) {\r
+      Index2Del = Index;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index != *BootOrderSize / sizeof (UINT16)) {\r
+    for (Index = 0; Index < *BootOrderSize / sizeof (UINT16) - 1; Index++) {\r
+      if (Index >= Index2Del) {\r
+        BootOrder[Index] = BootOrder[Index + 1];\r
+      }\r
+    }\r
+\r
+    *BootOrderSize -= sizeof (UINT16);\r
+  }\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+\r
+    Delete all the invalid legacy boot options.\r
+\r
+  Arguments:\r
+\r
+    None.\r
+\r
+  Returns:\r
+\r
+    EFI_SUCCESS            - All invalide legacy boot options are deleted.\r
+    EFI_OUT_OF_RESOURCES   - Fail to allocate necessary memory.\r
+    EFI_NOT_FOUND          - Fail to retrive variable of boot order.\r
+    Other                  - Error occurs while setting variable or locating\r
+                             protocol.\r
+\r
+--*/\r
+{\r
+  UINT16                    *BootOrder;\r
+  UINT8                     *BootOptionVar;\r
+  UINTN                     BootOrderSize;\r
+  UINTN                     BootOptionSize;\r
+  EFI_STATUS                Status;\r
+  UINT16                    HddCount;\r
+  UINT16                    BbsCount;\r
+  HDD_INFO                  *LocalHddInfo;\r
+  BBS_TABLE                 *LocalBbsTable;\r
+  BBS_TABLE                 *BbsEntry;\r
+  UINT16                    BbsIndex;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINTN                     Index;\r
+  UINT16                    BootOption[10];\r
+  UINT16                    BootDesc[100];\r
+  BOOLEAN                   DescStringMatch;\r
+\r
+  Status        = EFI_SUCCESS;\r
+  BootOrder     = NULL;\r
+  BootOrderSize = 0;\r
+  HddCount      = 0;\r
+  BbsCount      = 0;\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+  BbsEntry      = NULL;\r
+\r
+  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID**) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LegacyBios->GetBbsInfo (\r
+                LegacyBios,\r
+                &HddCount,\r
+                &LocalHddInfo,\r
+                &BbsCount,\r
+                &LocalBbsTable\r
+                );\r
+\r
+  BootOrder = BdsLibGetVariableAndSize (\r
+                L"BootOrder",\r
+                &gEfiGlobalVariableGuid,\r
+                &BootOrderSize\r
+                );\r
+  if (NULL == BootOrder) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Index = 0;\r
+  while (Index < BootOrderSize / sizeof (UINT16)) {\r
+    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+    BootOptionVar = BdsLibGetVariableAndSize (\r
+                      BootOption,\r
+                      &gEfiGlobalVariableGuid,\r
+                      &BootOptionSize\r
+                      );\r
+    if (NULL == BootOptionVar) {\r
+      SafeFreePool (BootOrder);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {\r
+      SafeFreePool (BootOptionVar);\r
+      Index++;\r
+      continue;\r
+    }\r
\r
+    //\r
+    // Check if BBS Description String is changed\r
+    //\r
+    DescStringMatch = FALSE;\r
+    \r
+    BdsBuildLegacyDevNameString (\r
+      &LocalBbsTable[BbsIndex], \r
+      BbsIndex, \r
+      sizeof(BootDesc), \r
+      BootDesc\r
+      );\r
+    \r
+    if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {\r
+      DescStringMatch = TRUE;\r
+    }\r
+\r
+    if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) ||\r
+          (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM) ||\r
+          (LocalBbsTable[BbsIndex].BootPriority == BBS_LOWEST_PRIORITY)) &&\r
+        (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&\r
+        DescStringMatch) {\r
+      Index++;\r
+      continue;\r
+    }\r
+\r
+    SafeFreePool (BootOptionVar);\r
+    //\r
+    // should delete\r
+    //\r
+    BdsDeleteBootOption (\r
+      BootOrder[Index],\r
+      BootOrder,\r
+      &BootOrderSize\r
+      );\r
+  }\r
+\r
+  if (BootOrderSize) {\r
+    Status = gRT->SetVariable (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    BootOrderSize,\r
+                    BootOrder\r
+                    );\r
+  } else {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  SafeFreePool (BootOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+BOOLEAN\r
+BdsFindLegacyBootOptionByDevType (\r
+  IN UINT16                 *BootOrder,\r
+  IN UINTN                  BootOptionNum,\r
+  IN UINT16                 DevType,\r
+  OUT UINT32                *Attribute,\r
+  OUT UINT16                *BbsIndex,\r
+  OUT UINTN                 *OptionNumber\r
+  )\r
+{\r
+  UINTN     Index;\r
+  UINTN     BootOrderIndex;\r
+  UINT16    BootOption[100];\r
+  UINTN     BootOptionSize;\r
+  UINT8     *BootOptionVar;\r
+  BBS_TABLE *BbsEntry;\r
+  BOOLEAN   Found;\r
+\r
+  BbsEntry  = NULL;\r
+  Found     = FALSE;\r
+\r
+  if (NULL == BootOrder) {\r
+    return Found;\r
+  }\r
+\r
+  for (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) {\r
+    Index = (UINTN) BootOrder[BootOrderIndex];\r
+    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", Index);\r
+    BootOptionVar = BdsLibGetVariableAndSize (\r
+                      BootOption,\r
+                      &gEfiGlobalVariableGuid,\r
+                      &BootOptionSize\r
+                      );\r
+    if (NULL == BootOptionVar) {\r
+      continue;\r
+    }\r
+\r
+    if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {\r
+      SafeFreePool (BootOptionVar);\r
+      continue;\r
+    }\r
+\r
+    if (BbsEntry->DeviceType != DevType) {\r
+      SafeFreePool (BootOptionVar);\r
+      continue;\r
+    }\r
+\r
+    *Attribute    = *(UINT32 *) BootOptionVar;\r
+    *OptionNumber = Index;\r
+    Found         = TRUE;\r
+    SafeFreePool (BootOptionVar);\r
+    break;\r
+  }\r
+\r
+  return Found;\r
+}\r
+\r
+EFI_STATUS\r
+BdsCreateOneLegacyBootOption (\r
+  IN BBS_TABLE              *BbsItem,\r
+  IN UINTN                  Index,\r
+  IN OUT UINT16             **BootOrderList,\r
+  IN OUT UINTN              *BootOrderListSize\r
+  )\r
+{\r
+  BBS_BBS_DEVICE_PATH       BbsDevPathNode;\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
+\r
+  DevPath                       = NULL;\r
+\r
+  BbsDevPathNode.Header.Type    = BBS_DEVICE_PATH;\r
+  BbsDevPathNode.Header.SubType = BBS_BBS_DP;\r
+  SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));\r
+  BbsDevPathNode.DeviceType = BbsItem->DeviceType;\r
+  CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16));\r
+\r
+  DevPath = AppendDevicePathNode (\r
+              EndDevicePath,\r
+              (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode\r
+              );\r
+  if (NULL == DevPath) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = BdsCreateLegacyBootOption (\r
+            BbsItem,\r
+            DevPath,\r
+            Index,\r
+            BootOrderList,\r
+            BootOrderListSize\r
+            );\r
+  BbsItem->BootPriority = 0x00;\r
+\r
+  gBS->FreePool (DevPath);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Add the legacy boot options from BBS table if they do not exist.\r
+\r
+Arguments:\r
+\r
+  None.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS       - The boot options are added successfully or they are already in boot options.\r
+  others            - An error occurred when creating legacy boot options.\r
+\r
+--*/\r
+{\r
+  UINT16                    *BootOrder;\r
+  UINTN                     BootOrderSize;\r
+  EFI_STATUS                Status;\r
+  UINT16                    HddCount;\r
+  UINT16                    BbsCount;\r
+  HDD_INFO                  *LocalHddInfo;\r
+  BBS_TABLE                 *LocalBbsTable;\r
+  UINT16                    BbsIndex;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINTN                     Index;\r
+  UINT32                    Attribute;\r
+  UINTN                     OptionNumber;\r
+  BOOLEAN                   Ret;\r
+\r
+  BootOrder     = NULL;\r
+  HddCount      = 0;\r
+  BbsCount      = 0;\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+\r
+  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID**)&LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LegacyBios->GetBbsInfo (\r
+                LegacyBios,\r
+                &HddCount,\r
+                &LocalHddInfo,\r
+                &BbsCount,\r
+                &LocalBbsTable\r
+                );\r
+\r
+  BootOrder = BdsLibGetVariableAndSize (\r
+                L"BootOrder",\r
+                &gEfiGlobalVariableGuid,\r
+                &BootOrderSize\r
+                );\r
+  if (NULL == BootOrder) {\r
+    BootOrderSize = 0;\r
+  }\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+        (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    Ret = BdsFindLegacyBootOptionByDevType (\r
+            BootOrder,\r
+            BootOrderSize / sizeof (UINT16),\r
+            LocalBbsTable[Index].DeviceType,\r
+            &Attribute,\r
+            &BbsIndex,\r
+            &OptionNumber\r
+            );\r
+    if (Ret && (Attribute & LOAD_OPTION_ACTIVE) != 0) {\r
+      continue;\r
+    }\r
+\r
+    if (Ret) {\r
+      if (Index != BbsIndex) {\r
+        BdsDeleteBootOption (\r
+          OptionNumber,\r
+          BootOrder,\r
+          &BootOrderSize\r
+          );\r
+      } else {\r
+        continue;\r
+      }\r
+    }\r
+    //\r
+    // Not found such type of legacy device in boot options or we found but it's disabled\r
+    // so we have to create one and put it to the tail of boot order list\r
+    //\r
+    Status = BdsCreateOneLegacyBootOption (\r
+              &LocalBbsTable[Index],\r
+              Index,\r
+              &BootOrder,\r
+              &BootOrderSize\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (BootOrderSize > 0) {\r
+    Status = gRT->SetVariable (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    BootOrderSize,\r
+                    BootOrder\r
+                    );\r
+  } else {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  if (BootOrder != NULL) {\r
+    SafeFreePool (BootOrder);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+UINT16 *\r
+BdsFillDevOrderBuf (\r
+  IN BBS_TABLE                    *BbsTable,\r
+  IN BBS_TYPE                     BbsType,\r
+  IN UINTN                        BbsCount,\r
+  IN UINT16                       *Buf\r
+  )\r
+{\r
+  UINTN Index;\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
+      continue;\r
+    }\r
+\r
+    if (BbsTable[Index].DeviceType != BbsType) {\r
+      continue;\r
+    }\r
+\r
+    *Buf = (UINT16) (Index & 0xFF);\r
+    Buf++;\r
+  }\r
+\r
+  return Buf;\r
+}\r
+\r
+EFI_STATUS\r
+BdsCreateDevOrder (\r
+  IN BBS_TABLE                  *BbsTable,\r
+  IN UINT16                     BbsCount\r
+  )\r
+{\r
+  UINTN       Index;\r
+  UINTN       FDCount;\r
+  UINTN       HDCount;\r
+  UINTN       CDCount;\r
+  UINTN       NETCount;\r
+  UINTN       BEVCount;\r
+  UINTN       TotalSize;\r
+  UINTN       HeaderSize;\r
+  UINT8       *DevOrder;\r
+  UINT8       *Ptr;\r
+  EFI_STATUS  Status;\r
+\r
+  FDCount     = 0;\r
+  HDCount     = 0;\r
+  CDCount     = 0;\r
+  NETCount    = 0;\r
+  BEVCount    = 0;\r
+  TotalSize   = 0;\r
+  HeaderSize  = sizeof (BBS_TYPE) + sizeof (UINT16);\r
+  DevOrder    = NULL;\r
+  Ptr         = NULL;\r
+  Status      = EFI_SUCCESS;\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
+      continue;\r
+    }\r
+\r
+    switch (BbsTable[Index].DeviceType) {\r
+    case BBS_FLOPPY:\r
+      FDCount++;\r
+      break;\r
+\r
+    case BBS_HARDDISK:\r
+      HDCount++;\r
+      break;\r
+\r
+    case BBS_CDROM:\r
+      CDCount++;\r
+      break;\r
+\r
+    case BBS_EMBED_NETWORK:\r
+      NETCount++;\r
+      break;\r
+\r
+    case BBS_BEV_DEVICE:\r
+      BEVCount++;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);\r
+\r
+  DevOrder = AllocateZeroPool (TotalSize);\r
+  if (NULL == DevOrder) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Ptr                 = DevOrder;\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_FLOPPY;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (FDCount) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_HARDDISK;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (HDCount) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_CDROM;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (CDCount) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (NETCount) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (BEVCount) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  VarLegacyDevOrder,\r
+                  &EfiLegacyDevOrderGuid,\r
+                  VAR_FLAG,\r
+                  TotalSize,\r
+                  DevOrder\r
+                  );\r
+  SafeFreePool (DevOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+  VOID\r
+  )\r
+/*++\r
+Format of LegacyDevOrder variable:\r
+|-----------------------------------------------------------------------------------------------------------------\r
+| BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...\r
+|-----------------------------------------------------------------------------------------------------------------\r
+\r
+Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself.\r
+Index# is a 16 bit integer, the low byte of it stands for the index in BBS table\r
+           the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been\r
+           disabled by user.\r
+--*/\r
+{\r
+  UINT8                     *DevOrder;\r
+  UINT8                     *NewDevOrder;\r
+  UINTN                     DevOrderSize;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  EFI_STATUS                Status;\r
+  UINT16                    HddCount;\r
+  UINT16                    BbsCount;\r
+  HDD_INFO                  *LocalHddInfo;\r
+  BBS_TABLE                 *LocalBbsTable;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  UINTN                     *Idx;\r
+  UINTN                     FDCount;\r
+  UINTN                     HDCount;\r
+  UINTN                     CDCount;\r
+  UINTN                     NETCount;\r
+  UINTN                     BEVCount;\r
+  UINTN                     TotalSize;\r
+  UINTN                     HeaderSize;\r
+  UINT8                     *Ptr;\r
+  UINT8                     *NewPtr;\r
+  UINT16                    *NewFDPtr;\r
+  UINT16                    *NewHDPtr;\r
+  UINT16                    *NewCDPtr;\r
+  UINT16                    *NewNETPtr;\r
+  UINT16                    *NewBEVPtr;\r
+  UINT16                    *NewDevPtr;\r
+  UINT16                    Length;\r
+  UINT16                    tmp;\r
+  UINTN                     FDIndex;\r
+  UINTN                     HDIndex;\r
+  UINTN                     CDIndex;\r
+  UINTN                     NETIndex;\r
+  UINTN                     BEVIndex;\r
+\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+  Idx           = NULL;\r
+  FDCount       = 0;\r
+  HDCount       = 0;\r
+  CDCount       = 0;\r
+  NETCount      = 0;\r
+  BEVCount      = 0;\r
+  TotalSize     = 0;\r
+  HeaderSize    = sizeof (BBS_TYPE) + sizeof (UINT16);\r
+  FDIndex       = 0;\r
+  HDIndex       = 0;\r
+  CDIndex       = 0;\r
+  NETIndex      = 0;\r
+  BEVIndex      = 0;\r
+  NewDevPtr     = NULL;\r
+\r
+  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID**) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LegacyBios->GetBbsInfo (\r
+                LegacyBios,\r
+                &HddCount,\r
+                &LocalHddInfo,\r
+                &BbsCount,\r
+                &LocalBbsTable\r
+                );\r
+\r
+  DevOrder = (UINT8 *) BdsLibGetVariableAndSize (\r
+                        VarLegacyDevOrder,\r
+                        &EfiLegacyDevOrderGuid,\r
+                        &DevOrderSize\r
+                        );\r
+  if (NULL == DevOrder) {\r
+    return BdsCreateDevOrder (LocalBbsTable, BbsCount);\r
+  }\r
+  //\r
+  // First we figure out how many boot devices with same device type respectively\r
+  //\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+        (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) ||\r
+        (LocalBbsTable[Index].BootPriority == BBS_LOWEST_PRIORITY)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    switch (LocalBbsTable[Index].DeviceType) {\r
+    case BBS_FLOPPY:\r
+      FDCount++;\r
+      break;\r
+\r
+    case BBS_HARDDISK:\r
+      HDCount++;\r
+      break;\r
+\r
+    case BBS_CDROM:\r
+      CDCount++;\r
+      break;\r
+\r
+    case BBS_EMBED_NETWORK:\r
+      NETCount++;\r
+      break;\r
+\r
+    case BBS_BEV_DEVICE:\r
+      BEVCount++;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+\r
+  TotalSize += (HeaderSize + FDCount * sizeof (UINT16));\r
+  TotalSize += (HeaderSize + HDCount * sizeof (UINT16));\r
+  TotalSize += (HeaderSize + CDCount * sizeof (UINT16));\r
+  TotalSize += (HeaderSize + NETCount * sizeof (UINT16));\r
+  TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));\r
+\r
+  NewDevOrder = AllocateZeroPool (TotalSize);\r
+  if (NULL == NewDevOrder) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewFDPtr  = (UINT16 *) (NewDevOrder + HeaderSize);\r
+  NewHDPtr  = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize);\r
+  NewCDPtr  = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize);\r
+  NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize);\r
+  NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize);\r
+\r
+  //\r
+  // copy FD\r
+  //\r
+  Ptr                     = DevOrder;\r
+  NewPtr                  = NewDevOrder;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewFDPtr[FDIndex] = *(UINT16 *) Ptr;\r
+    FDIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+  //\r
+  // copy HD\r
+  //\r
+  NewPtr                  = (UINT8 *) NewHDPtr - HeaderSize;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_HARDDISK\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewHDPtr[HDIndex] = *(UINT16 *) Ptr;\r
+    HDIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+  //\r
+  // copy CD\r
+  //\r
+  NewPtr                  = (UINT8 *) NewCDPtr - HeaderSize;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_CDROM\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewCDPtr[CDIndex] = *(UINT16 *) Ptr;\r
+    CDIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+  //\r
+  // copy NET\r
+  //\r
+  NewPtr                  = (UINT8 *) NewNETPtr - HeaderSize;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewNETPtr[NETIndex] = *(UINT16 *) Ptr;\r
+    NETIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+  //\r
+  // copy BEV\r
+  //\r
+  NewPtr                  = (UINT8 *) NewBEVPtr - HeaderSize;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr;\r
+    BEVIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+        (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) ||\r
+        (LocalBbsTable[Index].BootPriority == BBS_LOWEST_PRIORITY)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    switch (LocalBbsTable[Index].DeviceType) {\r
+    case BBS_FLOPPY:\r
+      Idx       = &FDIndex;\r
+      NewDevPtr = NewFDPtr;\r
+      break;\r
+\r
+    case BBS_HARDDISK:\r
+      Idx       = &HDIndex;\r
+      NewDevPtr = NewHDPtr;\r
+      break;\r
+\r
+    case BBS_CDROM:\r
+      Idx       = &CDIndex;\r
+      NewDevPtr = NewCDPtr;\r
+      break;\r
+\r
+    case BBS_EMBED_NETWORK:\r
+      Idx       = &NETIndex;\r
+      NewDevPtr = NewNETPtr;\r
+      break;\r
+\r
+    case BBS_BEV_DEVICE:\r
+      Idx       = &BEVIndex;\r
+      NewDevPtr = NewBEVPtr;\r
+      break;\r
+\r
+    default:\r
+      Idx = NULL;\r
+      break;\r
+    }\r
+    //\r
+    // at this point we have copied those valid indexes to new buffer\r
+    // and we should check if there is any new appeared boot device\r
+    //\r
+    if (Idx) {\r
+      for (Index2 = 0; Index2 < *Idx; Index2++) {\r
+        if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Index2 == *Idx) {\r
+        //\r
+        // Index2 == *Idx means we didn't find Index\r
+        // so Index is a new appeared device's index in BBS table\r
+        // save it.\r
+        //\r
+        NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);\r
+        (*Idx)++;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (FDCount) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < FDIndex - 1; Index++) {\r
+      if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < FDIndex; Index2++) {\r
+        if (0 == (NewFDPtr[Index2] & 0xFF00)) {\r
+          tmp               = NewFDPtr[Index];\r
+          NewFDPtr[Index]   = NewFDPtr[Index2];\r
+          NewFDPtr[Index2]  = tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (HDCount) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < HDIndex - 1; Index++) {\r
+      if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < HDIndex; Index2++) {\r
+        if (0 == (NewHDPtr[Index2] & 0xFF00)) {\r
+          tmp               = NewHDPtr[Index];\r
+          NewHDPtr[Index]   = NewHDPtr[Index2];\r
+          NewHDPtr[Index2]  = tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (CDCount) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < CDIndex - 1; Index++) {\r
+      if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < CDIndex; Index2++) {\r
+        if (0 == (NewCDPtr[Index2] & 0xFF00)) {\r
+          tmp               = NewCDPtr[Index];\r
+          NewCDPtr[Index]   = NewCDPtr[Index2];\r
+          NewCDPtr[Index2]  = tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (NETCount) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < NETIndex - 1; Index++) {\r
+      if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < NETIndex; Index2++) {\r
+        if (0 == (NewNETPtr[Index2] & 0xFF00)) {\r
+          tmp               = NewNETPtr[Index];\r
+          NewNETPtr[Index]  = NewNETPtr[Index2];\r
+          NewNETPtr[Index2] = tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (BEVCount) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < BEVIndex - 1; Index++) {\r
+      if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) {\r
+        if (0 == (NewBEVPtr[Index2] & 0xFF00)) {\r
+          tmp               = NewBEVPtr[Index];\r
+          NewBEVPtr[Index]  = NewBEVPtr[Index2];\r
+          NewBEVPtr[Index2] = tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  SafeFreePool (DevOrder);\r
+\r
+  Status = gRT->SetVariable (\r
+                  VarLegacyDevOrder,\r
+                  &EfiLegacyDevOrderGuid,\r
+                  VAR_FLAG,\r
+                  TotalSize,\r
+                  NewDevOrder\r
+                  );\r
+  SafeFreePool (NewDevOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BdsSetBootPriority4SameTypeDev (\r
+  IN UINT16                                              DeviceType,\r
+  IN OUT BBS_TABLE                                       *LocalBbsTable,\r
+  IN OUT UINT16                                          *Priority\r
+  )\r
+/*++\r
+DeviceType           - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on\r
+LocalBbsTable       - BBS table instance\r
+Priority                 - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot\r
+                              priority can be used next time.\r
+--*/\r
+{\r
+  UINT8   *DevOrder;\r
+\r
+  UINT8   *OrigBuffer;\r
+  UINT16  *DevIndex;\r
+  UINTN   DevOrderSize;\r
+  UINTN   DevCount;\r
+  UINTN   Index;\r
+\r
+  DevOrder = BdsLibGetVariableAndSize (\r
+              VarLegacyDevOrder,\r
+              &EfiLegacyDevOrderGuid,\r
+              &DevOrderSize\r
+              );\r
+  if (NULL == DevOrder) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  OrigBuffer = DevOrder;\r
+  while (DevOrder < OrigBuffer + DevOrderSize) {\r
+    if (DeviceType == * (BBS_TYPE *) DevOrder) {\r
+      break;\r
+    }\r
+\r
+    DevOrder += sizeof (BBS_TYPE);\r
+    DevOrder += *(UINT16 *) DevOrder;\r
+  }\r
+\r
+  if (DevOrder >= OrigBuffer + DevOrderSize) {\r
+    SafeFreePool (OrigBuffer);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  DevOrder += sizeof (BBS_TYPE);\r
+  DevCount  = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16);\r
+  DevIndex  = (UINT16 *) (DevOrder + sizeof (UINT16));\r
+  //\r
+  // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.\r
+  //\r
+  for (Index = 0; Index < DevCount; Index++) {\r
+    if ((DevIndex[Index] & 0xFF00) == 0xFF00) {\r
+      //\r
+      // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;\r
+      //\r
+    } else {\r
+      LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority;\r
+      (*Priority)++;\r
+    }\r
+  }\r
+\r
+  SafeFreePool (OrigBuffer);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+PrintBbsTable (\r
+  IN BBS_TABLE                      *LocalBbsTable\r
+  )\r
+{\r
+  UINT16  Idx;\r
+\r
+  DEBUG ((EFI_D_ERROR, "\n"));\r
+  DEBUG ((EFI_D_ERROR, " NO  Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));\r
+  DEBUG ((EFI_D_ERROR, "=============================================\n"));\r
+  for (Idx = 0; Idx < MAX_BBS_ENTRIES; Idx++) {\r
+    if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||\r
+        (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||\r
+        (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    DEBUG (\r
+      (EFI_D_ERROR,\r
+      " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n",\r
+      (UINTN) Idx,\r
+      (UINTN) LocalBbsTable[Idx].BootPriority,\r
+      (UINTN) LocalBbsTable[Idx].Bus,\r
+      (UINTN) LocalBbsTable[Idx].Device,\r
+      (UINTN) LocalBbsTable[Idx].Function,\r
+      (UINTN) LocalBbsTable[Idx].Class,\r
+      (UINTN) LocalBbsTable[Idx].SubClass,\r
+      (UINTN) LocalBbsTable[Idx].DeviceType,\r
+      (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,\r
+      (UINTN) LocalBbsTable[Idx].BootHandlerSegment,\r
+      (UINTN) LocalBbsTable[Idx].BootHandlerOffset,\r
+      (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),\r
+      (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))\r
+      );\r
+  }\r
+\r
+  DEBUG ((EFI_D_ERROR, "\n"));\r
+}\r
+\r
+EFI_STATUS\r
+BdsRefreshBbsTableForBoot (\r
+  IN BDS_COMMON_OPTION        *Entry\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINT16                    HddCount;\r
+  UINT16                    BbsCount;\r
+  HDD_INFO                  *LocalHddInfo;\r
+  BBS_TABLE                 *LocalBbsTable;\r
+  UINT16                    DevType;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINTN                     Index;\r
+  UINT16                    Priority;\r
+  UINT16                    *BootOrder;\r
+  UINTN                     BootOrderSize;\r
+  UINT8                     *BootOptionVar;\r
+  UINTN                     BootOptionSize;\r
+  UINT16                    BootOption[100];\r
+  UINT8                     *Ptr;\r
+  UINT16                    DevPathLen;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
+\r
+  HddCount      = 0;\r
+  BbsCount      = 0;\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+  DevType       = BBS_UNKNOWN;\r
+\r
+  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID**) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LegacyBios->GetBbsInfo (\r
+                LegacyBios,\r
+                &HddCount,\r
+                &LocalHddInfo,\r
+                &BbsCount,\r
+                &LocalBbsTable\r
+                );\r
+  //\r
+  // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY\r
+  // We will set them according to the settings setup by user\r
+  //\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||\r
+        (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||\r
+         (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {\r
+      LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
+    }\r
+  }\r
+  //\r
+  // boot priority always starts at 0\r
+  //\r
+  Priority = 0;\r
+  if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {\r
+    //\r
+    // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.\r
+    //\r
+    DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;\r
+    Status = BdsSetBootPriority4SameTypeDev (\r
+              DevType,\r
+              LocalBbsTable,\r
+              &Priority\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+  //\r
+  // we have to set the boot priority for other BBS entries with different device types\r
+  //\r
+  BootOrder = (UINT16 *) BdsLibGetVariableAndSize (\r
+                          L"BootOrder",\r
+                          &gEfiGlobalVariableGuid,\r
+                          &BootOrderSize\r
+                          );\r
+  for (Index = 0; BootOrder && Index < BootOrderSize / sizeof (UINT16); Index++) {\r
+    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+    BootOptionVar = BdsLibGetVariableAndSize (\r
+                      BootOption,\r
+                      &gEfiGlobalVariableGuid,\r
+                      &BootOptionSize\r
+                      );\r
+    if (NULL == BootOptionVar) {\r
+      continue;\r
+    }\r
+\r
+    Ptr = BootOptionVar;\r
+\r
+    Ptr += sizeof (UINT32);\r
+    DevPathLen = *(UINT16 *) Ptr;\r
+    Ptr += sizeof (UINT16);\r
+    Ptr += StrSize ((UINT16 *) Ptr);\r
+    DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+    if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {\r
+      SafeFreePool (BootOptionVar);\r
+      continue;\r
+    }\r
+\r
+    Ptr += DevPathLen;\r
+    if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) {\r
+      //\r
+      // We don't want to process twice for a device type\r
+      //\r
+      SafeFreePool (BootOptionVar);\r
+      continue;\r
+    }\r
+\r
+    Status = BdsSetBootPriority4SameTypeDev (\r
+              ((BBS_TABLE *) Ptr)->DeviceType,\r
+              LocalBbsTable,\r
+              &Priority\r
+              );\r
+    SafeFreePool (BootOptionVar);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (BootOrder) {\r
+    SafeFreePool (BootOrder);\r
+  }\r
+  //\r
+  // For debug\r
+  //\r
+  PrintBbsTable (LocalBbsTable);\r
+\r
+  return Status;\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BBSsupport.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BBSsupport.h
new file mode 100644 (file)
index 0000000..572beb1
--- /dev/null
@@ -0,0 +1,83 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  BBSsupport.h\r
+\r
+Abstract:\r
+\r
+  declares interface functions\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_BDS_BBS_SUPPORT_H\r
+#define _EFI_BDS_BBS_SUPPORT_H\r
+\r
+#include "BootMaint/BootMaint.h"\r
+\r
+#ifdef EFI32\r
+#define REFRESH_LEGACY_BOOT_OPTIONS \\r
+        BdsDeleteAllInvalidLegacyBootOptions ();\\r
+        BdsAddNonExistingLegacyBootOptions (); \\r
+        BdsUpdateLegacyDevOrder ()\r
+#else\r
+#define REFRESH_LEGACY_BOOT_OPTIONS\r
+#endif\r
+\r
+VOID\r
+BdsBuildLegacyDevNameString (\r
+  IN BBS_TABLE                     *CurBBSEntry,\r
+  IN UINTN                         Index,\r
+  IN UINTN                         BufSize,\r
+  OUT CHAR16                       *BootString\r
+  );\r
+\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Add the legacy boot options from BBS table if they do not exist.\r
+\r
+Arguments:\r
+\r
+  None.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS       - The boot options are added successfully or they are already in boot options.\r
+  others            - An error occurred when creating legacy boot options.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsRefreshBbsTableForBoot (\r
+  IN BDS_COMMON_OPTION        *Entry\r
+  );\r
+\r
+#endif\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Bm.vfr b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Bm.vfr
new file mode 100644 (file)
index 0000000..b5364c3
--- /dev/null
@@ -0,0 +1,495 @@
+// *++\r
+//\r
+// Copyright (c) 2006, Intel Corporation                                                         \r
+// All rights reserved. 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
+// Module Name:\r
+//\r
+//   bm.vfr \r
+// \r
+// Abstract:\r
+// \r
+//   Boot Maintenance Utility Formset\r
+// \r
+// Revision History: \r
+// \r
+// --*/\r
+\r
+#include "EdkGenericPlatformBdsLibStrDefs.h" \r
+#include "FormGuid.h"\r
+\r
+#pragma pack(1)\r
+\r
+//\r
+// This is the structure that will be used to store the \r
+// question's current value. Use it at initialize time to \r
+// set default value for each question. When using at run\r
+// time, this map is returned by the callback function,\r
+// so dynamically changing the question's value will be\r
+// possible through this mechanism\r
+//\r
+typedef struct {\r
+\r
+//\r
+// Three questions displayed at the main page\r
+// for Timeout, BootNext Variables respectively\r
+//\r
+  UINT16                    BootTimeOut;\r
+  UINT16                    BootNext;\r
+\r
+//\r
+// This is the COM1 Attributes value storage\r
+//\r
+  UINT8                     COM1BaudRate;\r
+  UINT8                     COM1DataRate;\r
+  UINT8                     COM1StopBits;\r
+  UINT8                     COM1Parity;\r
+  UINT8                     COM1TerminalType;\r
+  \r
+//\r
+// This is the COM2 Attributes value storage\r
+//\r
+  UINT8                     COM2BaudRate;\r
+  UINT8                     COM2DataRate;\r
+  UINT8                     COM2StopBits;\r
+  UINT8                     COM2Parity;\r
+  UINT8                     COM2TerminalType;\r
+\r
+// \r
+// Driver Option Add Handle page storage\r
+//\r
+  UINT16                    DriverAddHandleDesc[100];\r
+  UINT16                    DriverAddHandleOptionalData[100];\r
+  UINT8                     DriverAddActive;\r
+  UINT8                     DriverAddForceReconnect;\r
+  \r
+//\r
+// Console Input/Output/Errorout using COM port check storage\r
+//\r
+  UINT8                     ConsoleInputCOM1;\r
+  UINT8                     ConsoleInputCOM2;\r
+  UINT8                     ConsoleOutputCOM1;\r
+  UINT8                     ConsoleOutputCOM2;\r
+  UINT8                     ConsoleErrorCOM1;\r
+  UINT8                     ConsoleErrorCOM2;\r
+\r
+//\r
+// At most 100 input/output/errorout device for console storage\r
+//\r
+  UINT8                     ConsoleCheck[100];\r
+\r
+//\r
+// Boot or Driver Option Order storage\r
+//\r
+  UINT8                     OptionOrder[100];\r
+  UINT8                     DriverOptionToBeDeleted[100];\r
+\r
+//\r
+// Boot Option Delete storage\r
+// \r
+  UINT8                     BootOptionDel[100];\r
+  UINT8                     DriverOptionDel[100];\r
+  \r
+//\r
+// This is the Terminal Attributes value storage\r
+//\r
+  UINT8                     COMBaudRate;\r
+  UINT8                     COMDataRate;\r
+  UINT8                     COMStopBits;\r
+  UINT8                     COMParity;\r
+  UINT8                     COMTerminalType;\r
+  \r
+//\r
+// Legacy Device Order Selection Storage\r
+//\r
+  UINT8                     LegacyFD[100];\r
+  UINT8                     LegacyHD[100];\r
+  UINT8                     LegacyCD[100];\r
+  UINT8                     LegacyNET[100];\r
+  UINT8                     LegacyBEV[100];\r
+} BMM_FAKE_NV_DATA;\r
+#pragma pack()\r
+\r
+\r
+#define FORM_MAIN_ID                         0x0001\r
+#define FORM_BOOT_ADD_ID                     0x0002\r
+#define FORM_BOOT_DEL_ID                     0x0003\r
+#define FORM_BOOT_CHG_ID                     0x0004\r
+#define FORM_DRV_ADD_ID                      0x0005\r
+#define FORM_DRV_DEL_ID                      0x0006\r
+#define FORM_DRV_CHG_ID                      0x0007\r
+#define FORM_CON_MAIN_ID                     0x0008\r
+#define FORM_CON_IN_ID                       0x0009\r
+#define FORM_CON_OUT_ID                      0x000A\r
+#define FORM_CON_ERR_ID                      0x000B\r
+#define FORM_FILE_SEEK_ID                    0x000C\r
+#define FORM_FILE_NEW_SEEK_ID                0x000D\r
+#define FORM_DRV_ADD_FILE_ID                 0x000E\r
+#define FORM_DRV_ADD_HANDLE_ID               0x000F\r
+#define FORM_DRV_ADD_HANDLE_DESC_ID          0x0010\r
+#define FORM_BOOT_NEXT_ID                    0x0011\r
+#define FORM_TIME_OUT_ID                     0x0012\r
+#define FORM_RESET                           0x0013\r
+#define FORM_BOOT_SETUP_ID                   0x0014\r
+#define FORM_DRIVER_SETUP_ID                 0x0015\r
+#define FORM_BOOT_LEGACY_DEVICE_ID           0x0016\r
+#define FORM_CON_COM_ID                      0x0017\r
+#define FORM_CON_COM_SETUP_ID                0x0018\r
+#define FORM_SET_FD_ORDER_ID                 0x0019\r
+#define FORM_SET_HD_ORDER_ID                 0x001A\r
+#define FORM_SET_CD_ORDER_ID                 0x001B\r
+#define FORM_SET_NET_ORDER_ID                0x001C\r
+#define FORM_SET_BEV_ORDER_ID                0x001D\r
+                                                                       \r
+#define KEY_VALUE_BOOT_FROM_FILE             0x0092\r
+\r
+formset \r
+  guid = MAIN_FORMSET_GUID,\r
+  title = STRING_TOKEN(STR_FORM_MAIN_TITLE),  // uint8 opcode, uint8 length, guid Handle, uint16 Title\r
+  help = STRING_TOKEN(STR_NULL_STRING),\r
+  class = 0,      \r
+  subclass = 0,\r
+\r
+  form formid = FORM_MAIN_ID,\r
+       title = STRING_TOKEN(STR_FORM_MAIN_TITLE);\r
+\r
+    goto FORM_BOOT_SETUP_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_BOOT_SETUP_HELP),\r
+         flags = INTERACTIVE | NV_ACCESS,\r
+         key = FORM_BOOT_SETUP_ID;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+    goto FORM_DRIVER_SETUP_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_DRIVER_SETUP_HELP),\r
+         flags = INTERACTIVE | NV_ACCESS,\r
+         key = FORM_DRIVER_SETUP_ID;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+    goto FORM_CON_MAIN_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_CON_MAIN_HELP),\r
+         flags = INTERACTIVE | NV_ACCESS,\r
+         key = FORM_CON_MAIN_ID;\r
+   \r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+    text \r
+         help   = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP),  \r
+         text   = STRING_TOKEN(STR_BOOT_FROM_FILE),\r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE | NV_ACCESS,\r
+         key    = KEY_VALUE_BOOT_FROM_FILE;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+//    label FORM_MAIN_ID;\r
+\r
+    goto FORM_BOOT_NEXT_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_BOOT_NEXT_HELP),\r
+         flags = INTERACTIVE | NV_ACCESS,\r
+         key = FORM_BOOT_NEXT_ID;            \r
+\r
+    goto FORM_TIME_OUT_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_TIME_OUT_HELP),\r
+         flags = INTERACTIVE | NV_ACCESS,\r
+         key = FORM_TIME_OUT_ID;\r
+         \r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+    goto FORM_MAIN_ID,\r
+         prompt = STRING_TOKEN(STR_RESET),\r
+         help = STRING_TOKEN(STR_RESET),\r
+         flags = INTERACTIVE | NV_ACCESS,\r
+         key = FORM_RESET;\r
+         \r
+  endform;       \r
+\r
+  form formid = FORM_BOOT_SETUP_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE);\r
+\r
+       goto FORM_MAIN_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            help = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            flags = INTERACTIVE | NV_ACCESS,\r
+            key = FORM_MAIN_ID;\r
+\r
+       goto FORM_BOOT_ADD_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP),\r
+            flags = INTERACTIVE | NV_ACCESS,\r
+            key = FORM_BOOT_ADD_ID;\r
+      \r
+       goto FORM_BOOT_DEL_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+            flags = INTERACTIVE | NV_ACCESS,\r
+            key = FORM_BOOT_DEL_ID;\r
+       \r
+       goto FORM_BOOT_CHG_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+            flags = INTERACTIVE | NV_ACCESS,\r
+            key = FORM_BOOT_CHG_ID;\r
+\r
+       subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+       //\r
+          // We will add "Select Legacy Boot Floppy Drive" and "Select Legacy Boot Hard Drive" \r
+          // here dynamically\r
+          //\r
+       label FORM_BOOT_LEGACY_DEVICE_ID;\r
+\r
+  endform;       \r
+\r
+  form formid = FORM_DRIVER_SETUP_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE);\r
+\r
+       goto FORM_MAIN_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            help = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            flags = INTERACTIVE | NV_ACCESS,\r
+            key = FORM_MAIN_ID;\r
+\r
+       goto FORM_DRV_ADD_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP),\r
+            flags = INTERACTIVE | NV_ACCESS,\r
+            key = FORM_DRV_ADD_ID;\r
+     \r
+       goto FORM_DRV_DEL_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+            flags = INTERACTIVE | NV_ACCESS,\r
+            key = FORM_DRV_DEL_ID;\r
+       \r
+       goto FORM_DRV_CHG_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+            flags = INTERACTIVE | NV_ACCESS,\r
+            key = FORM_DRV_CHG_ID;\r
+  endform;       \r
+\r
+  form formid = FORM_BOOT_ADD_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+       label FORM_BOOT_ADD_ID;\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_DEL_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE);\r
+\r
+       label FORM_BOOT_DEL_ID;\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_CHG_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE);\r
+\r
+       label FORM_BOOT_CHG_ID;\r
+       \r
+       //\r
+       // This tag is added for bypassing issue of setup browser\r
+       // setup browser could not support dynamic form very well.\r
+       //\r
+       checkbox varid    = BMM_FAKE_NV_DATA.OptionOrder[0],\r
+           prompt   = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE),\r
+           help     = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE),  \r
+           flags    = 1,\r
+           key      = 0,\r
+       endcheckbox;\r
+      \r
+  endform;\r
+\r
+  form formid = FORM_BOOT_NEXT_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE);\r
+\r
+       label FORM_BOOT_NEXT_ID;\r
+  endform;\r
+  \r
+  form formid = FORM_TIME_OUT_ID,\r
+       title = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE);\r
+       \r
+       label FORM_TIME_OUT_ID;\r
+  endform;\r
+  \r
+  form formid = FORM_DRV_ADD_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE);\r
+\r
+       goto FORM_MAIN_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            help = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            flags = INTERACTIVE | NV_ACCESS,\r
+            key = FORM_MAIN_ID;\r
+              \r
+       goto FORM_DRV_ADD_FILE_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),\r
+            flags = INTERACTIVE | NV_ACCESS,\r
+            key = FORM_DRV_ADD_FILE_ID;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_DRV_DEL_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE);\r
+\r
+       label FORM_DRV_DEL_ID;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_DRV_CHG_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE);\r
+\r
+       label FORM_DRV_CHG_ID;\r
+      \r
+       //\r
+       // This tag is added for bypassing issue of setup browser\r
+       // setup browser could not support dynamic form very well.\r
+       //\r
+       checkbox varid    = BMM_FAKE_NV_DATA.OptionOrder[0],\r
+           prompt   = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE),\r
+           help     = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE),  \r
+           flags    = 1,\r
+           key      = 0,\r
+       endcheckbox;\r
+       \r
+  endform;\r
+\r
+  form formid = FORM_CON_MAIN_ID,\r
+       title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE);\r
+\r
+       goto FORM_MAIN_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+       help = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+       flags = INTERACTIVE | NV_ACCESS,\r
+       key = FORM_MAIN_ID;\r
+\r
+       goto FORM_CON_IN_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_CON_IN_HELP),\r
+       flags = INTERACTIVE | NV_ACCESS,\r
+       key = FORM_CON_IN_ID;\r
+\r
+       goto FORM_CON_OUT_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_CON_OUT_HELP),\r
+       flags = INTERACTIVE | NV_ACCESS,\r
+       key = FORM_CON_OUT_ID;\r
+  \r
+       goto FORM_CON_ERR_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_STD_ERR_HELP),\r
+       flags = INTERACTIVE | NV_ACCESS,\r
+       key = FORM_CON_ERR_ID;\r
+\r
+       goto FORM_CON_COM_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_COM_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_COM_HELP),\r
+       flags = INTERACTIVE | NV_ACCESS,\r
+       key = FORM_CON_COM_ID;\r
+  endform;\r
+\r
+  form formid = FORM_CON_COM_ID,\r
+       title = STRING_TOKEN(STR_FORM_COM_TITLE);\r
+\r
+       label FORM_CON_COM_ID;\r
+  endform;\r
+\r
+  form formid = FORM_CON_COM_SETUP_ID,\r
+       title = STRING_TOKEN(STR_CON_COM_SETUP);\r
+\r
+       label FORM_CON_COM_SETUP_ID;\r
+  endform;\r
+\r
+  form formid = FORM_FILE_SEEK_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+       label FORM_FILE_SEEK_ID;\r
+  endform;\r
+\r
+  form formid = FORM_FILE_NEW_SEEK_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+       label FORM_FILE_NEW_SEEK_ID;\r
+  endform;\r
+\r
+  form formid = FORM_DRV_ADD_FILE_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE);\r
+\r
+       label FORM_DRV_ADD_FILE_ID;\r
+  endform;\r
+\r
+  form formid = FORM_DRV_ADD_HANDLE_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE);\r
+\r
+       label FORM_DRV_ADD_HANDLE_ID;\r
+  endform;     \r
+\r
+  form formid = FORM_DRV_ADD_HANDLE_DESC_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);\r
+\r
+       label FORM_DRV_ADD_HANDLE_DESC_ID;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_CON_IN_ID,\r
+       title = STRING_TOKEN(STR_FORM_CON_IN_TITLE);\r
+\r
+       label FORM_CON_IN_ID;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_CON_OUT_ID,\r
+       title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE);\r
+\r
+       label FORM_CON_OUT_ID;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_CON_ERR_ID,\r
+       title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE);\r
+\r
+       label FORM_CON_ERR_ID;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_SET_FD_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_FD_ORDER_TITLE);\r
+\r
+       label FORM_SET_FD_ORDER_ID;\r
+  endform;\r
+  \r
+  form formid = FORM_SET_HD_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_HD_ORDER_TITLE);\r
+\r
+       label FORM_SET_HD_ORDER_ID;\r
+  endform;\r
+\r
+  form formid = FORM_SET_CD_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_CD_ORDER_TITLE);\r
+\r
+       label FORM_SET_CD_ORDER_ID;\r
+  endform;\r
+\r
+  form formid = FORM_SET_NET_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_NET_ORDER_TITLE);\r
+\r
+       label FORM_SET_NET_ORDER_ID;\r
+  endform;\r
+\r
+  form formid = FORM_SET_BEV_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_BEV_ORDER_TITLE);\r
+\r
+       label FORM_SET_BEV_ORDER_ID;\r
+  endform;\r
+\r
+endformset;\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmLib.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmLib.c
new file mode 100644 (file)
index 0000000..e9245d2
--- /dev/null
@@ -0,0 +1,627 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  BmLib.c\r
+    \r
+AgBStract:\r
+\r
+  Boot Maintainence Helper functions\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_STATUS\r
+EfiLibLocateProtocol (\r
+  IN  EFI_GUID    *ProtocolGuid,\r
+  OUT VOID        **Interface\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Find the first instance of this Protocol \r
+  in the system and return it's interface\r
+\r
+Arguments:\r
+\r
+  ProtocolGuid    - Provides the protocol to search for\r
+  Interface       - On return, a pointer to the first interface \r
+                    that matches ProtocolGuid\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     - A protocol instance matching ProtocolGuid was found\r
+\r
+  EFI_NOT_FOUND   - No protocol instances were found that match ProtocolGuid\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  ProtocolGuid,\r
+                  NULL,\r
+                  Interface\r
+                  );\r
+  return Status;\r
+}\r
+\r
+EFI_FILE_HANDLE\r
+EfiLibOpenRoot (\r
+  IN EFI_HANDLE                   DeviceHandle\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Function opens and returns a file handle to the root directory of a volume.\r
+\r
+Arguments:\r
+\r
+  DeviceHandle         - A handle for a device\r
+\r
+Returns:\r
+  \r
+  A valid file handle or NULL is returned\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
+  EFI_FILE_HANDLE                 File;\r
+\r
+  File = NULL;\r
+\r
+  //\r
+  // File the file system interface to the device\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  DeviceHandle,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  (VOID *) &Volume\r
+                  );\r
+\r
+  //\r
+  // Open the root directory of the volume\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = Volume->OpenVolume (\r
+                      Volume,\r
+                      &File\r
+                      );\r
+  }\r
+  //\r
+  // Done\r
+  //\r
+  return EFI_ERROR (Status) ? NULL : File;\r
+}\r
+\r
+BOOLEAN\r
+EfiGrowBuffer (\r
+  IN OUT EFI_STATUS   *Status,\r
+  IN OUT VOID         **Buffer,\r
+  IN UINTN            BufferSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Helper function called as part of the code needed\r
+    to allocate the proper sized buffer for various \r
+    EFI interfaces.\r
+\r
+Arguments:\r
+\r
+    Status      - Current status\r
+\r
+    Buffer      - Current allocated buffer, or NULL\r
+\r
+    BufferSize  - Current buffer size needed\r
+    \r
+Returns:\r
+    \r
+    TRUE - if the buffer was reallocated and the caller \r
+    should try the API again.\r
+\r
+--*/\r
+{\r
+  BOOLEAN TryAgain;\r
+\r
+  //\r
+  // If this is an initial request, buffer will be null with a new buffer size\r
+  //\r
+  if (!*Buffer && BufferSize) {\r
+    *Status = EFI_BUFFER_TOO_SMALL;\r
+  }\r
+  //\r
+  // If the status code is "buffer too small", resize the buffer\r
+  //\r
+  TryAgain = FALSE;\r
+  if (*Status == EFI_BUFFER_TOO_SMALL) {\r
+\r
+    SafeFreePool (*Buffer);\r
+\r
+    *Buffer = AllocateZeroPool (BufferSize);\r
+\r
+    if (*Buffer) {\r
+      TryAgain = TRUE;\r
+    } else {\r
+      *Status = EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+  //\r
+  // If there's an error, free the buffer\r
+  //\r
+  if (!TryAgain && EFI_ERROR (*Status) && *Buffer) {\r
+    SafeFreePool (*Buffer);\r
+    *Buffer = NULL;\r
+  }\r
+\r
+  return TryAgain;\r
+}\r
+\r
+VOID *\r
+EfiLibGetVariable (\r
+  IN CHAR16               *Name,\r
+  IN EFI_GUID             *VendorGuid\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Function returns the value of the specified variable.\r
+\r
+Arguments:\r
+  Name                - A Null-terminated Unicode string that is \r
+                        the name of the vendor's variable.\r
+\r
+  VendorGuid          - A unique identifier for the vendor.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN VarSize;\r
+\r
+  return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize);\r
+}\r
+\r
+EFI_STATUS\r
+EfiLibDeleteVariable (\r
+  IN CHAR16   *VarName,\r
+  IN EFI_GUID *VarGuid\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Function deletes the variable specified by VarName and VarGuid.\r
+\r
+Arguments:\r
+  VarName              - A Null-terminated Unicode string that is \r
+                         the name of the vendor's variable.\r
+\r
+  VendorGuid           - A unique identifier for the vendor.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS          - The variable was found and removed\r
+\r
+  EFI_UNSUPPORTED      - The variable store was inaccessible\r
+\r
+  EFI_OUT_OF_RESOURCES - The temporary buffer was not available\r
+\r
+  EFI_NOT_FOUND        - The variable was not found\r
+\r
+--*/\r
+{\r
+  VOID        *VarBuf;\r
+  EFI_STATUS  Status;\r
+\r
+  VarBuf  = EfiLibGetVariable (VarName, VarGuid);\r
+  Status  = EFI_NOT_FOUND;\r
+\r
+  if (VarBuf) {\r
+    //\r
+    // Delete variable from Storage\r
+    //\r
+    Status = gRT->SetVariable (VarName, VarGuid, VAR_FLAG, 0, NULL);\r
+    ASSERT (!EFI_ERROR (Status));\r
+    SafeFreePool (VarBuf);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *\r
+EfiLibFileSystemVolumeLabelInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Function gets the file system information from an open file descriptor, \r
+  and stores it in a buffer allocated from pool.\r
+\r
+Arguments:\r
+\r
+  Fhand         - A file handle\r
+\r
+Returns:\r
+  \r
+  A pointer to a buffer with file information or NULL is returned\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;\r
+  UINTN                             BufferSize;\r
+  //\r
+  // Initialize for GrowBuffer loop\r
+  //\r
+  Buffer      = NULL;\r
+  BufferSize  = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;\r
+\r
+  //\r
+  // Call the real function\r
+  //\r
+  while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
+    Status = FHand->GetInfo (\r
+                      FHand,\r
+                      &gEfiFileSystemVolumeLabelInfoIdGuid,\r
+                      &BufferSize,\r
+                      Buffer\r
+                      );\r
+  }\r
+\r
+  return Buffer;\r
+}\r
+\r
+CHAR16 *\r
+EfiStrDuplicate (\r
+  IN CHAR16   *Src\r
+  )\r
+{\r
+  CHAR16  *Dest;\r
+  UINTN   Size;\r
+\r
+  Size  = StrSize (Src);\r
+  Dest  = AllocateZeroPool (Size);\r
+  ASSERT (Dest != NULL);\r
+  if (Dest) {\r
+    CopyMem (Dest, Src, Size);\r
+  }\r
+\r
+  return Dest;\r
+}\r
+\r
+EFI_FILE_INFO *\r
+EfiLibFileInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Function gets the file information from an open file descriptor, and stores it \r
+  in a buffer allocated from pool.\r
+\r
+Arguments:\r
+\r
+  Fhand         - A file handle\r
+\r
+Returns:\r
+  \r
+  A pointer to a buffer with file information or NULL is returned\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  EFI_FILE_INFO *Buffer;\r
+  UINTN         BufferSize;\r
+\r
+  //\r
+  // Initialize for GrowBuffer loop\r
+  //\r
+  Buffer      = NULL;\r
+  BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;\r
+\r
+  //\r
+  // Call the real function\r
+  //\r
+  while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
+    Status = FHand->GetInfo (\r
+                      FHand,\r
+                      &gEfiFileInfoGuid,\r
+                      &BufferSize,\r
+                      Buffer\r
+                      );\r
+  }\r
+\r
+  return Buffer;\r
+}\r
+\r
+UINTN\r
+EfiDevicePathInstanceCount (\r
+  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Function is used to determine the number of device path instances \r
+  that exist in a device path.\r
+\r
+Arguments:\r
+  DevicePath           - A pointer to a device path data structure.\r
+\r
+Returns:\r
+\r
+  This function counts and returns the number of device path instances \r
+  in DevicePath.\r
+\r
+--*/\r
+{\r
+  UINTN Count;\r
+  UINTN Size;\r
+\r
+  Count = 0;\r
+  while (GetNextDevicePathInstance (&DevicePath, &Size)) {\r
+    Count += 1;\r
+  }\r
+\r
+  return Count;\r
+}\r
+\r
+VOID *\r
+EfiReallocatePool (\r
+  IN VOID                 *OldPool,\r
+  IN UINTN                OldSize,\r
+  IN UINTN                NewSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Adjusts the size of a previously allocated buffer.\r
+\r
+Arguments:\r
+  OldPool               - A pointer to the buffer whose size is being adjusted.\r
+  OldSize               - The size of the current buffer.\r
+  NewSize               - The size of the new buffer.\r
+\r
+Returns:\r
+\r
+  EFI_SUCEESS           - The requested number of bytes were allocated.\r
+\r
+  EFI_OUT_OF_RESOURCES  - The pool requested could not be allocated.\r
+\r
+  EFI_INVALID_PARAMETER - The buffer was invalid.\r
+\r
+--*/\r
+{\r
+  VOID  *NewPool;\r
+\r
+  NewPool = NULL;\r
+  if (NewSize) {\r
+    NewPool = AllocateZeroPool (NewSize);\r
+  }\r
+\r
+  if (OldPool) {\r
+    if (NewPool) {\r
+      CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
+    }\r
+\r
+    SafeFreePool (OldPool);\r
+  }\r
+\r
+  return NewPool;\r
+}\r
+\r
+EFI_STATUS\r
+EfiLibGetStringFromToken (\r
+  IN      EFI_GUID                  *ProducerGuid,\r
+  IN      STRING_REF                Token,\r
+  OUT     CHAR16                    **String\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Acquire the string associated with the ProducerGuid and return it.\r
+\r
+Arguments:\r
+  \r
+  ProducerGuid - The Guid to search the HII database for\r
+  Token        - The token value of the string to extract\r
+  String       - The string that is extracted\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS           -  Buffer filled with the requested forms. BufferLength\r
+                           was updated.\r
+  EFI_BUFFER_TOO_SMALL  -  The buffer provided was not large enough to allow the form to be stored.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS        Status;\r
+  UINT16            HandleBufferLength;\r
+  EFI_HII_HANDLE    *HiiHandleBuffer;\r
+  UINTN             StringBufferLength;\r
+  UINTN             NumberOfHiiHandles;\r
+  UINTN             Index;\r
+  UINT16            Length;\r
+  EFI_GUID          HiiGuid;\r
+  EFI_HII_PROTOCOL  *Hii;\r
+\r
+  //\r
+  // Initialize params.\r
+  //\r
+  HandleBufferLength  = 0;\r
+  HiiHandleBuffer     = NULL;\r
+  \r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiProtocolGuid,\r
+                  NULL,\r
+                  (VOID**) &Hii\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    *String = NULL;\r
+    return Status;\r
+  }\r
+  //\r
+  // Get all the Hii handles\r
+  //\r
+  Status = BdsLibGetHiiHandles (Hii, &HandleBufferLength, &HiiHandleBuffer);\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  //\r
+  // Get the Hii Handle that matches the StructureNode->ProducerName\r
+  //\r
+  NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);\r
+  for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
+    Length = 0;\r
+    Status = ExtractDataFromHiiHandle (\r
+              HiiHandleBuffer[Index],\r
+              &Length,\r
+              NULL,\r
+              &HiiGuid\r
+              );\r
+    if (CompareGuid (ProducerGuid, &HiiGuid)) {\r
+      break;\r
+    }\r
+  }\r
+  //\r
+  // Find the string based on the current language\r
+  //\r
+  StringBufferLength  = 0x100;\r
+  *String             = AllocateZeroPool (0x100);\r
+  ASSERT (*String != NULL);\r
+\r
+  Status = Hii->GetString (\r
+                  Hii,\r
+                  HiiHandleBuffer[Index],\r
+                  Token,\r
+                  FALSE,\r
+                  NULL,\r
+                  &StringBufferLength,\r
+                  *String\r
+                  );\r
+\r
+  gBS->FreePool (HiiHandleBuffer);\r
+\r
+  return Status;\r
+}\r
+\r
+BOOLEAN\r
+TimeCompare (\r
+  IN EFI_TIME               *FirstTime,\r
+  IN EFI_TIME               *SecondTime\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Compare two EFI_TIME data.\r
+\r
+Arguments:\r
+\r
+  FirstTime         - A pointer to the first EFI_TIME data.\r
+  SecondTime        - A pointer to the second EFI_TIME data.\r
+\r
+Returns:\r
+  TRUE              The FirstTime is not later than the SecondTime.\r
+  FALSE             The FirstTime is later than the SecondTime.\r
+  \r
+--*/\r
+{\r
+  if (FirstTime->Year != SecondTime->Year) {\r
+    return (BOOLEAN) (FirstTime->Year < SecondTime->Year);\r
+  } else if (FirstTime->Month != SecondTime->Month) {\r
+    return (BOOLEAN) (FirstTime->Month < SecondTime->Month);\r
+  } else if (FirstTime->Day != SecondTime->Day) {\r
+    return (BOOLEAN) (FirstTime->Day < SecondTime->Day);\r
+  } else if (FirstTime->Hour != SecondTime->Hour) {\r
+    return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);\r
+  } else if (FirstTime->Minute != SecondTime->Minute) {\r
+    return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);\r
+  } else if (FirstTime->Second != SecondTime->Second) {\r
+    return (BOOLEAN) (FirstTime->Second < SecondTime->Second);\r
+  }\r
+\r
+  return (BOOLEAN) (FirstTime->Nanosecond <= SecondTime->Nanosecond);\r
+}\r
+\r
+UINT16 *\r
+EfiLibStrFromDatahub (\r
+  IN EFI_DEVICE_PATH_PROTOCOL                 *DevPath\r
+  )\r
+{\r
+  EFI_STATUS                                  Status;\r
+  UINT16                                      *Desc;\r
+  EFI_DATA_HUB_PROTOCOL                       *Datahub;\r
+  UINT64                                      Count;\r
+  EFI_DATA_RECORD_HEADER                      *Record;\r
+  EFI_SUBCLASS_TYPE1_HEADER                   *DataHdr;\r
+  EFI_GUID                                    MiscGuid = EFI_MISC_SUBCLASS_GUID;\r
+  EFI_MISC_ONBOARD_DEVICE_DATA                *ob;\r
+  EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *Port;\r
+  EFI_TIME                                    CurTime;\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiDataHubProtocolGuid,\r
+                  NULL,\r
+                  (VOID**) &Datahub\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  Status = gRT->GetTime (&CurTime, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  Count = 0;\r
+  do {\r
+    Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) {\r
+      //\r
+      // This record is what we need\r
+      //\r
+      DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
+      if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) {\r
+        ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1);\r
+        if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &ob->OnBoardDevicePath, DevPath)) {\r
+          EfiLibGetStringFromToken (&Record->ProducerName, ob->OnBoardDeviceDescription, &Desc);\r
+          return Desc;\r
+        }\r
+      }\r
+\r
+      if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) {\r
+        Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1);\r
+        if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) {\r
+          EfiLibGetStringFromToken (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc);\r
+          return Desc;\r
+        }\r
+      }\r
+    }\r
+\r
+  } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0);\r
+\r
+  return NULL;\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmString.uni b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmString.uni
new file mode 100644 (file)
index 0000000..f646d8b
Binary files /dev/null and b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BmString.uni differ
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootMaint.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootMaint.c
new file mode 100644 (file)
index 0000000..0f5087a
--- /dev/null
@@ -0,0 +1,1315 @@
+/*++ \r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  BootMaint.c\r
+    \r
+Abstract:\r
+\r
+  Boot Maintainence Main File\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "BootMaint.h"\r
+#include "FormGuid.h"\r
+\r
+//\r
+// Form binary for Boot Maintenance\r
+//\r
+extern UINT8    BmBin[];\r
+extern UINT8    FEBin[];\r
+extern EFI_GUID gBdsStringPackGuid;\r
+extern BOOLEAN  gConnectAllHappened;\r
+\r
+EFI_GUID        EfiLegacyDevOrderGuid = EFI_LEGACY_DEV_ORDER_VARIABLE_GUID;\r
+\r
+VOID\r
+InitAllMenu (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  );\r
+\r
+VOID\r
+FreeAllMenu (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+CreateMenuStringToken (\r
+  IN BMM_CALLBACK_DATA                *CallbackData,\r
+  IN EFI_HII_HANDLE                   HiiHandle,\r
+  IN BM_MENU_OPTION                   *MenuOption\r
+  )\r
+/*++\r
+Routine Description:\r
+\r
+  Create string tokens for a menu from its help strings and display strings\r
+\r
+Arguments:\r
+\r
+  HiiHandle       - Hii Handle of the package to be updated.\r
+  \r
+  MenuOption      - The Menu whose string tokens need to be created\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     - string tokens created successfully\r
+  \r
+  others          - contain some errors\r
+  \r
+--*/\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINTN         Index;\r
+\r
+  for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);\r
+    CallbackData->Hii->NewString (\r
+                        CallbackData->Hii,\r
+                        NULL,\r
+                        HiiHandle,\r
+                        &NewMenuEntry->DisplayStringToken,\r
+                        NewMenuEntry->DisplayString\r
+                        );\r
+\r
+    if (NULL == NewMenuEntry->HelpString) {\r
+      NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;\r
+    } else {\r
+      CallbackData->Hii->NewString (\r
+                          CallbackData->Hii,\r
+                          NULL,\r
+                          HiiHandle,\r
+                          &NewMenuEntry->HelpStringToken,\r
+                          NewMenuEntry->HelpString\r
+                          );\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DriverCallback (\r
+  IN EFI_FORM_CALLBACK_PROTOCOL       *This,\r
+  IN UINT16                           KeyValue,\r
+  IN EFI_IFR_DATA_ARRAY               *Data,\r
+  OUT EFI_HII_CALLBACK_PACKET         **Packet\r
+  )\r
+/*++\r
+Routine Description:\r
+\r
+  Callback Function for boot maintenance utility user interface interaction.\r
+\r
+Arguments:\r
+\r
+  This            - File explorer callback protocol pointer.     \r
+  KeyValue        - Key value to identify the type of data to expect.\r
+  Data            - A pointer to the data being sent to the original exporting driver.\r
+  Packet          - A pointer to a packet of information which a driver passes back to the browser.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     - Callback ended successfully.\r
+  Others          - Contain some errors.\r
+  \r
+--*/\r
+{\r
+  BMM_CALLBACK_DATA *Private;\r
+  BM_MENU_ENTRY     *NewMenuEntry;\r
+  BMM_FAKE_NV_DATA  *CurrentFakeNVMap;\r
+  EFI_STATUS        Status;\r
+  UINTN             OldValue;\r
+  UINTN             NewValue;\r
+  UINTN             Number;\r
+  UINTN             Pos;\r
+  UINTN             Bit;\r
+  UINT16            NewValuePos;\r
+  UINT16            Index2;\r
+  UINT16            Index;\r
+  UINT8             *OldLegacyDev;\r
+  UINT8             *NewLegacyDev;\r
+  UINT8             *Location;\r
+  UINT8             *DisMap;\r
+  FORM_ID           FormId;\r
+\r
+  OldValue                        = 0;\r
+  NewValue                        = 0;\r
+  Number                          = 0;\r
+  OldLegacyDev                    = NULL;\r
+  NewLegacyDev                    = NULL;\r
+  NewValuePos                     = 0;\r
+  DisMap                          = NULL;\r
+\r
+  Private                         = BMM_CALLBACK_DATA_FROM_THIS (This);\r
+  UpdateData->FormCallbackHandle  = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->BmmCallbackHandle;\r
+  CurrentFakeNVMap                = (BMM_FAKE_NV_DATA *) Data->NvRamMap;\r
+  Private->BmmFakeNvData          = CurrentFakeNVMap;\r
+  Location                        = (UINT8 *) &UpdateData->Data;\r
+\r
+  UpdatePageId (Private, KeyValue);\r
+\r
+  //\r
+  // need to be subtituded.\r
+  //\r
+  // Update Select FD/HD/CD/NET/BEV Order Form\r
+  //\r
+  if (FORM_SET_FD_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_HD_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_CD_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_NET_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_BEV_ORDER_ID == Private->BmmPreviousPageId ||\r
+      ((FORM_BOOT_SETUP_ID == Private->BmmPreviousPageId) &&\r
+      (KeyValue >= LEGACY_FD_QUESTION_ID) &&\r
+       (KeyValue < (LEGACY_BEV_QUESTION_ID + 100)) )\r
+      ) {\r
+\r
+    DisMap  = Private->BmmOldFakeNVData.DisableMap;\r
+\r
+    FormId  = Private->BmmPreviousPageId;\r
+    if (FormId == FORM_BOOT_SETUP_ID) {\r
+      FormId = Private->BmmCurrentPageId;\r
+    }\r
+\r
+    switch (FormId) {\r
+    case FORM_SET_FD_ORDER_ID:\r
+      Number        = (UINT16) LegacyFDMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyFD;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyFD;\r
+      break;\r
+\r
+    case FORM_SET_HD_ORDER_ID:\r
+      Number        = (UINT16) LegacyHDMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyHD;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyHD;\r
+      break;\r
+\r
+    case FORM_SET_CD_ORDER_ID:\r
+      Number        = (UINT16) LegacyCDMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyCD;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyCD;\r
+      break;\r
+\r
+    case FORM_SET_NET_ORDER_ID:\r
+      Number        = (UINT16) LegacyNETMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyNET;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyNET;\r
+      break;\r
+\r
+    case FORM_SET_BEV_ORDER_ID:\r
+      Number        = (UINT16) LegacyBEVMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyBEV;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyBEV;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+    //\r
+    //  First, find the different position\r
+    //  if there is change, it should be only one\r
+    //\r
+    for (Index = 0; Index < Number; Index++) {\r
+      if (OldLegacyDev[Index] != NewLegacyDev[Index]) {\r
+        OldValue  = OldLegacyDev[Index];\r
+        NewValue  = NewLegacyDev[Index];\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (Index != Number) {\r
+      //\r
+      // there is change, now process\r
+      //\r
+      if (0xFF == NewValue) {\r
+        //\r
+        // This item will be disable\r
+        // Just move the items behind this forward to overlap it\r
+        //\r
+        Pos = OldValue / 8;\r
+        Bit = 7 - (OldValue % 8);\r
+        DisMap[Pos] |= (UINT8) (1 << Bit);\r
+        for (Index2 = Index; Index2 < Number - 1; Index2++) {\r
+          NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1];\r
+        }\r
+\r
+        NewLegacyDev[Index2] = 0xFF;\r
+      } else {\r
+        for (Index2 = 0; Index2 < Number; Index2++) {\r
+          if (Index2 == Index) {\r
+            continue;\r
+          }\r
+\r
+          if (OldLegacyDev[Index2] == NewValue) {\r
+            //\r
+            // If NewValue is in OldLegacyDev array\r
+            // remember its old position\r
+            //\r
+            NewValuePos = Index2;\r
+            break;\r
+          }\r
+        }\r
+\r
+        if (Index2 != Number) {\r
+          //\r
+          // We will change current item to an existing item\r
+          // (It's hard to describe here, please read code, it's like a cycle-moving)\r
+          //\r
+          for (Index2 = NewValuePos; Index2 != Index;) {\r
+            if (NewValuePos < Index) {\r
+              NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1];\r
+              Index2++;\r
+            } else {\r
+              NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1];\r
+              Index2--;\r
+            }\r
+          }\r
+        } else {\r
+          //\r
+          // If NewValue is not in OldlegacyDev array, we are changing to a disabled item\r
+          // so we should modify DisMap to reflect the change\r
+          //\r
+          Pos = NewValue / 8;\r
+          Bit = 7 - (NewValue % 8);\r
+          DisMap[Pos] &= ~ (UINT8) (1 << Bit);\r
+          if (0xFF != OldValue) {\r
+            //\r
+            // Because NewValue is a item that was disabled before\r
+            // so after changing the OldValue should be disabled\r
+            // actually we are doing a swap of enable-disable states of two items\r
+            //\r
+            Pos = OldValue / 8;\r
+            Bit = 7 - (OldValue % 8);\r
+            DisMap[Pos] |= (UINT8) (1 << Bit);\r
+          }\r
+        }\r
+      }\r
+      //\r
+      // To prevent DISABLE appears in the middle of the list\r
+      // we should perform a re-ordering\r
+      //\r
+      Index = 0;\r
+      while (Index < Number) {\r
+        if (0xFF != NewLegacyDev[Index]) {\r
+          Index++;\r
+          continue;\r
+        }\r
+\r
+        Index2 = Index;\r
+        Index2++;\r
+        while (Index2 < Number) {\r
+          if (0xFF != NewLegacyDev[Index2]) {\r
+            break;\r
+          }\r
+\r
+          Index2++;\r
+        }\r
+\r
+        if (Index2 < Number) {\r
+          NewLegacyDev[Index]   = NewLegacyDev[Index2];\r
+          NewLegacyDev[Index2]  = 0xFF;\r
+        }\r
+\r
+        Index++;\r
+      }\r
+\r
+      CopyMem (\r
+        OldLegacyDev,\r
+        NewLegacyDev,\r
+        Number\r
+        );\r
+    }\r
+  }\r
+\r
+  if (KeyValue < FILE_OPTION_OFFSET) {\r
+    if (KeyValue < NORMAL_GOTO_OFFSET) {\r
+      switch (KeyValue) {\r
+      case KEY_VALUE_BOOT_FROM_FILE:\r
+        Private->FeCurrentState = BOOT_FROM_FILE_STATE;\r
+\r
+        //\r
+        // Exit Bmm main formset to send File Explorer formset.\r
+        //\r
+        CreateCallbackPacket (Packet, EXIT_REQUIRED);\r
+\r
+        break;\r
+\r
+      case FORM_BOOT_ADD_ID:\r
+        Private->FeCurrentState = ADD_BOOT_OPTION_STATE;\r
+\r
+        //\r
+        // Exit Bmm main formset to send File Explorer formset.\r
+        //\r
+        CreateCallbackPacket (Packet, EXIT_REQUIRED);\r
+        break;\r
+\r
+      case FORM_DRV_ADD_FILE_ID:\r
+        Private->FeCurrentState = ADD_DRIVER_OPTION_STATE;\r
+\r
+        //\r
+        // Exit Bmm main formset to send File Explorer formset.\r
+        //\r
+        CreateCallbackPacket (Packet, EXIT_REQUIRED);\r
+\r
+        break;\r
+\r
+      case FORM_DRV_ADD_HANDLE_ID:\r
+        CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);\r
+        UpdateDrvAddHandlePage (Private);\r
+        break;\r
+\r
+      case FORM_BOOT_DEL_ID:\r
+        CleanUpPage (FORM_BOOT_DEL_ID, Private);\r
+        UpdateBootDelPage (Private);\r
+        break;\r
+\r
+      case FORM_BOOT_CHG_ID:\r
+      case FORM_DRV_CHG_ID:\r
+        UpdatePageBody (KeyValue, Private);\r
+        break;\r
+\r
+      case FORM_DRV_DEL_ID:\r
+        CleanUpPage (FORM_DRV_DEL_ID, Private);\r
+        UpdateDrvDelPage (Private);\r
+        break;\r
+\r
+      case FORM_BOOT_NEXT_ID:\r
+        CleanUpPage (FORM_BOOT_NEXT_ID, Private);\r
+        UpdateBootNextPage (Private);\r
+        break;\r
+\r
+      case FORM_TIME_OUT_ID:\r
+        CleanUpPage (FORM_TIME_OUT_ID, Private);\r
+        UpdateTimeOutPage (Private);\r
+        break;\r
+\r
+      case FORM_RESET:\r
+        gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+        return EFI_UNSUPPORTED;\r
+\r
+      case FORM_CON_IN_ID:\r
+      case FORM_CON_OUT_ID:\r
+      case FORM_CON_ERR_ID:\r
+        UpdatePageBody (KeyValue, Private);\r
+        break;\r
+\r
+      case FORM_CON_COM_ID:\r
+        CleanUpPage (FORM_CON_COM_ID, Private);\r
+        UpdateConCOMPage (Private);\r
+        break;\r
+\r
+      case FORM_SET_FD_ORDER_ID:\r
+      case FORM_SET_HD_ORDER_ID:\r
+      case FORM_SET_CD_ORDER_ID:\r
+      case FORM_SET_NET_ORDER_ID:\r
+      case FORM_SET_BEV_ORDER_ID:\r
+        CleanUpPage (KeyValue, Private);\r
+        UpdateSetLegacyDeviceOrderPage (KeyValue, Private);\r
+        break;\r
+\r
+      case KEY_VALUE_SAVE_AND_EXIT:\r
+      case KEY_VALUE_NO_SAVE_AND_EXIT:\r
+\r
+        if (KeyValue == KEY_VALUE_SAVE_AND_EXIT) {\r
+          Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId);\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+        } else if (KeyValue == KEY_VALUE_NO_SAVE_AND_EXIT) {\r
+          DiscardChangeHandler (Private, CurrentFakeNVMap);\r
+        }\r
+        //\r
+        // Tell browser not to ask for confirmation of changes,\r
+        // since we have already applied or discarded.\r
+        //\r
+        CreateCallbackPacket (Packet, NV_NOT_CHANGED);\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+    } else if ((KeyValue >= TERMINAL_OPTION_OFFSET) && (KeyValue < CONSOLE_OPTION_OFFSET)) {\r
+      Index2                    = (UINT16) (KeyValue - TERMINAL_OPTION_OFFSET);\r
+      Private->CurrentTerminal  = Index2;\r
+\r
+      CleanUpPage (FORM_CON_COM_SETUP_ID, Private);\r
+      UpdateTerminalPage (Private);\r
+\r
+    } else if (KeyValue >= HANDLE_OPTION_OFFSET) {\r
+      Index2                  = (UINT16) (KeyValue - HANDLE_OPTION_OFFSET);\r
+\r
+      NewMenuEntry            = BOpt_GetMenuEntry (&DriverMenu, Index2);\r
+      Private->HandleContext  = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+      CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);\r
+\r
+      Private->MenuEntry                  = NewMenuEntry;\r
+      Private->LoadContext->FilePathList  = Private->HandleContext->DevicePath;\r
+\r
+      UpdateDriverAddHandleDescPage (Private);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ApplyChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap,\r
+  IN  FORM_ID                         FormId\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Function handling request to apply changes for BMM pages.\r
+\r
+Arguments:\r
+\r
+  Private          - Pointer to callback data buffer.\r
+  CurrentFakeNVMap - Pointer to buffer holding data of various values used by BMM\r
+  FormId           - ID of the form which has sent the request to apply change.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS      - Change successfully applied.\r
+  Other            - Error occurs while trying to apply changes.\r
+\r
+--*/\r
+{\r
+  BM_CONSOLE_CONTEXT  *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+  BM_LOAD_CONTEXT     *NewLoadContext;\r
+  BM_MENU_ENTRY       *NewMenuEntry;\r
+  EFI_STATUS          Status;\r
+  UINT16              Index;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (FormId) {\r
+  case FORM_SET_FD_ORDER_ID:\r
+  case FORM_SET_HD_ORDER_ID:\r
+  case FORM_SET_CD_ORDER_ID:\r
+  case FORM_SET_NET_ORDER_ID:\r
+  case FORM_SET_BEV_ORDER_ID:\r
+    Var_UpdateBBSOption (Private);\r
+    break;\r
+\r
+  case FORM_BOOT_DEL_ID:\r
+    for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+      NewMenuEntry            = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+      NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index];\r
+    }\r
+\r
+    Var_DelBootOption ();\r
+    break;\r
+\r
+  case FORM_DRV_DEL_ID:\r
+    for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+      NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+      NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index];\r
+    }\r
+\r
+    Var_DelDriverOption ();\r
+    break;\r
+\r
+  case FORM_BOOT_CHG_ID:\r
+    Status = Var_UpdateBootOrder (Private);\r
+    break;\r
+\r
+  case FORM_DRV_CHG_ID:\r
+    Status = Var_UpdateDriverOrder (Private);\r
+    break;\r
+\r
+  case FORM_TIME_OUT_ID:\r
+    Status = gRT->SetVariable (\r
+                    L"Timeout",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    sizeof (UINT16),\r
+                    &(CurrentFakeNVMap->BootTimeOut)\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+\r
+    Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut;\r
+    break;\r
+\r
+  case FORM_BOOT_NEXT_ID:\r
+    Status = Var_UpdateBootNext (Private);\r
+    break;\r
+\r
+  case FORM_CON_COM_ID:\r
+    NewMenuEntry                      = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal);\r
+\r
+    NewTerminalContext                = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate;\r
+    NewTerminalContext->BaudRate      = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value;\r
+    NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate;\r
+    NewTerminalContext->DataBits      = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value;\r
+    NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits;\r
+    NewTerminalContext->StopBits      = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value;\r
+    NewTerminalContext->ParityIndex   = CurrentFakeNVMap->COMParity;\r
+    NewTerminalContext->Parity        = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value;\r
+    NewTerminalContext->TerminalType  = CurrentFakeNVMap->COMTerminalType;\r
+\r
+    ChangeTerminalDevicePath (\r
+      NewTerminalContext->DevicePath,\r
+      FALSE\r
+      );\r
+\r
+    Var_UpdateConsoleInpOption ();\r
+    Var_UpdateConsoleOutOption ();\r
+    Var_UpdateErrorOutOption ();\r
+    break;\r
+\r
+  case FORM_CON_IN_ID:\r
+    for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+    }\r
+\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext          = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber];\r
+    }\r
+\r
+    Var_UpdateConsoleInpOption ();\r
+    break;\r
+\r
+  case FORM_CON_OUT_ID:\r
+    for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+    }\r
+\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                  = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext            = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewTerminalContext->IsConOut  = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber];\r
+    }\r
+\r
+    Var_UpdateConsoleOutOption ();\r
+    break;\r
+\r
+  case FORM_CON_ERR_ID:\r
+    for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+    }\r
+\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                  = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext            = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewTerminalContext->IsStdErr  = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber];\r
+    }\r
+\r
+    Var_UpdateErrorOutOption ();\r
+    break;\r
+\r
+  case FORM_DRV_ADD_HANDLE_DESC_ID:\r
+    Status = Var_UpdateDriverOption (\r
+               Private,\r
+               Private->BmmHiiHandle,\r
+               CurrentFakeNVMap->DriverAddHandleDesc,\r
+               CurrentFakeNVMap->DriverAddHandleOptionalData,\r
+               CurrentFakeNVMap->DriverAddForceReconnect\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+\r
+    BOpt_GetDriverOptions (Private);\r
+    CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu);\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+Error:\r
+  return Status;\r
+}\r
+\r
+VOID\r
+DiscardChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap\r
+  )\r
+{\r
+  UINT16  Index;\r
+\r
+  switch (Private->BmmPreviousPageId) {\r
+  case FORM_BOOT_CHG_ID:\r
+  case FORM_DRV_CHG_ID:\r
+    CopyMem (CurrentFakeNVMap->OptionOrder, Private->BmmOldFakeNVData.OptionOrder, 100);\r
+    break;\r
+\r
+  case FORM_BOOT_DEL_ID:\r
+    for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+      CurrentFakeNVMap->BootOptionDel[Index] = 0x00;\r
+    }\r
+    break;\r
+\r
+  case FORM_DRV_DEL_ID:\r
+    for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+      CurrentFakeNVMap->DriverOptionDel[Index] = 0x00;\r
+    }\r
+    break;\r
+\r
+  case FORM_BOOT_NEXT_ID:\r
+    CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;\r
+    break;\r
+\r
+  case FORM_TIME_OUT_ID:\r
+    CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;\r
+    break;\r
+\r
+  case FORM_DRV_ADD_HANDLE_DESC_ID:\r
+  case FORM_DRV_ADD_FILE_ID:\r
+  case FORM_DRV_ADD_HANDLE_ID:\r
+    CurrentFakeNVMap->DriverAddHandleDesc[0]          = 0x0000;\r
+    CurrentFakeNVMap->DriverAddHandleOptionalData[0]  = 0x0000;\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+NvWrite (\r
+  IN     EFI_FORM_CALLBACK_PROTOCOL              *This,\r
+  IN     CHAR16                                  *VariableName,\r
+  IN     EFI_GUID                                *VendorGuid,\r
+  OUT    UINT32                                  Attributes OPTIONAL,\r
+  IN OUT UINTN                                   DataSize,\r
+  OUT    VOID                                    *Buffer,\r
+  OUT    BOOLEAN                                 *ResetRequired\r
+  )\r
+{\r
+  //\r
+  // Do nothing here. Just to catch the F10, we use "Apply Changes" tag to save.\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeBM (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+\r
+  Initialize the Boot Maintenance Utitliy\r
+\r
+Arguments:\r
+\r
+  ImageHandle     - caller provided handle\r
+  \r
+  SystemTable     - caller provided system tables\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS     - utility ended successfully\r
+  \r
+  others          - contain some errors\r
+  \r
+--*/\r
+{\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  EFI_HII_PACKAGES          *PackageList;\r
+  BMM_CALLBACK_DATA         *BmmCallbackInfo;\r
+  EFI_HII_PROTOCOL          *Hii;\r
+  EFI_HII_HANDLE            HiiHandle;\r
+  EFI_STATUS                Status;\r
+  EFI_HANDLE                Handle;\r
+  UINT8                     *Ptr;\r
+  UINT8                     *Location;\r
+\r
+  Status      = EFI_SUCCESS;\r
+  UpdateData  = NULL;\r
+  //\r
+  // Initialize EfiUtilityLib and EfiDriverLib\r
+  // Since many functions in UtilityLib must be used and\r
+  // SetupBrowser use DriverLib\r
+  //\r
+  //\r
+  // There should be only one EFI_HII_PROTOCOL Image\r
+  //\r
+  Status = EfiLibLocateProtocol (&gEfiHiiProtocolGuid, (VOID**)&Hii);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Create CallbackData structures for Driver Callback\r
+  //\r
+  BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA));\r
+  if (!BmmCallbackInfo) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Create LoadOption in BmmCallbackInfo for Driver Callback\r
+  //\r
+  Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));\r
+  if (!Ptr) {\r
+    SafeFreePool (BmmCallbackInfo);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Initialize Bmm callback data.\r
+  //\r
+  BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;\r
+  Ptr += sizeof (BM_LOAD_CONTEXT);\r
+\r
+  BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;\r
+  Ptr += sizeof (BM_FILE_CONTEXT);\r
+\r
+  BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;\r
+  Ptr += sizeof (BM_HANDLE_CONTEXT);\r
+\r
+  BmmCallbackInfo->MenuEntry      = (BM_MENU_ENTRY *) Ptr;\r
+\r
+  BmmCallbackInfo->BmmFakeNvData  = &BmmCallbackInfo->BmmOldFakeNVData;\r
+\r
+  ZeroMem (BmmCallbackInfo->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA));\r
+\r
+  BmmCallbackInfo->Signature                  = BMM_CALLBACK_DATA_SIGNATURE;\r
+  BmmCallbackInfo->Hii                        = Hii;\r
+  BmmCallbackInfo->BmmDriverCallback.NvRead   = NULL;\r
+  BmmCallbackInfo->BmmDriverCallback.NvWrite  = NvWrite;\r
+  BmmCallbackInfo->BmmDriverCallback.Callback = DriverCallback;\r
+  BmmCallbackInfo->BmmPreviousPageId          = FORM_MAIN_ID;\r
+  BmmCallbackInfo->BmmCurrentPageId           = FORM_MAIN_ID;\r
+  BmmCallbackInfo->FeDriverCallback.NvRead    = NULL;\r
+  BmmCallbackInfo->FeDriverCallback.NvWrite   = NvWrite;\r
+  BmmCallbackInfo->FeDriverCallback.Callback  = FileExplorerCallback;\r
+  BmmCallbackInfo->FeCurrentState             = INACTIVE_STATE;\r
+  BmmCallbackInfo->FeDisplayContext           = UNKNOWN_CONTEXT;\r
+\r
+  //\r
+  // Install bmm callback protocol interface\r
+  //\r
+  Handle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Handle,\r
+                  &gEfiFormCallbackProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &BmmCallbackInfo->BmmDriverCallback\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  BmmCallbackInfo->BmmCallbackHandle = Handle;\r
+\r
+  //\r
+  // Install file explorer callback protocol interface\r
+  //\r
+  Handle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Handle,\r
+                  &gEfiFormCallbackProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &BmmCallbackInfo->FeDriverCallback\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  BmmCallbackInfo->FeCallbackHandle = Handle;\r
+\r
+  //\r
+  // Post our VFR to the HII database.\r
+  //\r
+  PackageList = PreparePackages (1, &gBdsStringPackGuid, BmBin);\r
+  Status      = Hii->NewPack (Hii, PackageList, &HiiHandle);\r
+  gBS->FreePool (PackageList);\r
+\r
+  BmmCallbackInfo->BmmHiiHandle = HiiHandle;\r
+\r
+  PackageList                   = PreparePackages (1, &gBdsStringPackGuid, FEBin);\r
+  Status                        = Hii->NewPack (Hii, PackageList, &HiiHandle);\r
+  gBS->FreePool (PackageList);\r
+\r
+  BmmCallbackInfo->FeHiiHandle = HiiHandle;\r
+\r
+  //\r
+  // Allocate space for creation of Buffer\r
+  //\r
+  UpdateData = AllocateZeroPool (UPDATE_DATA_SIZE);\r
+  if (!UpdateData) {\r
+    SafeFreePool (BmmCallbackInfo->LoadContext);\r
+    SafeFreePool (BmmCallbackInfo);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Initialize UpdateData structure\r
+  //\r
+  RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) BmmCallbackInfo->BmmCallbackHandle, FALSE, 0, 0);\r
+\r
+  Location = (UINT8 *) &UpdateData->Data;\r
+\r
+  InitializeStringDepository ();\r
+\r
+  InitAllMenu (BmmCallbackInfo);\r
+\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu);\r
+\r
+  UpdateBootDelPage (BmmCallbackInfo);\r
+  UpdateDrvDelPage (BmmCallbackInfo);\r
+\r
+  if (TerminalMenu.MenuNumber > 0) {\r
+    BmmCallbackInfo->CurrentTerminal = 0;\r
+    UpdateTerminalPage (BmmCallbackInfo);\r
+  }\r
+\r
+  Location  = (UINT8 *) &UpdateData->Data;\r
+  Status    = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID**) &LegacyBios);\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // If LegacyBios Protocol is installed, add 3 tags about legacy boot option\r
+    // in BootOption form: legacy FD/HD/CD/NET/BEV\r
+    //\r
+    UpdateData->DataCount = 5;\r
+    CreateGotoOpCode (\r
+      FORM_SET_FD_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      FORM_SET_FD_ORDER_ID,\r
+      Location\r
+      );\r
+\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_HD_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      FORM_SET_HD_ORDER_ID,\r
+      Location\r
+      );\r
+\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_CD_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      FORM_SET_CD_ORDER_ID,\r
+      Location\r
+      );\r
+\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_NET_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      FORM_SET_NET_ORDER_ID,\r
+      Location\r
+      );\r
+\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_BEV_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      FORM_SET_BEV_ORDER_ID,\r
+      Location\r
+      );\r
+\r
+    Hii->UpdateForm (\r
+          Hii,\r
+          BmmCallbackInfo->BmmHiiHandle,\r
+          (EFI_FORM_LABEL) FORM_BOOT_LEGACY_DEVICE_ID,\r
+          TRUE,\r
+          UpdateData\r
+          );\r
+  }\r
+  //\r
+  // Dispatch BMM main formset and File Explorer formset.\r
+  //\r
+  FormSetDispatcher (BmmCallbackInfo);\r
+\r
+  Hii->ResetStrings (Hii, HiiHandle);\r
+\r
+  CleanUpStringDepository ();\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  FreeAllMenu ();\r
+\r
+  SafeFreePool (BmmCallbackInfo->LoadContext);\r
+  BmmCallbackInfo->LoadContext = NULL;\r
+  SafeFreePool (BmmCallbackInfo);\r
+  BmmCallbackInfo = NULL;\r
+  SafeFreePool (UpdateData);\r
+  UpdateData = NULL;\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+InitAllMenu (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  )\r
+{\r
+  InitializeListHead (&BootOptionMenu.Head);\r
+  InitializeListHead (&DriverOptionMenu.Head);\r
+  BOpt_GetBootOptions (CallbackData);\r
+  BOpt_GetDriverOptions (CallbackData);\r
+  BOpt_GetLegacyOptions ();\r
+  InitializeListHead (&FsOptionMenu.Head);\r
+  BOpt_FindDrivers ();\r
+  InitializeListHead (&DirectoryMenu.Head);\r
+  InitializeListHead (&ConsoleInpMenu.Head);\r
+  InitializeListHead (&ConsoleOutMenu.Head);\r
+  InitializeListHead (&ConsoleErrMenu.Head);\r
+  InitializeListHead (&TerminalMenu.Head);\r
+  LocateSerialIo ();\r
+  GetAllConsoles ();\r
+}\r
+\r
+VOID\r
+FreeAllMenu (\r
+  VOID\r
+  )\r
+{\r
+  BOpt_FreeMenu (&DirectoryMenu);\r
+  BOpt_FreeMenu (&FsOptionMenu);\r
+  BOpt_FreeMenu (&BootOptionMenu);\r
+  BOpt_FreeMenu (&DriverOptionMenu);\r
+  BOpt_FreeMenu (&DriverMenu);\r
+  BOpt_FreeLegacyOptions ();\r
+  FreeAllConsoles ();\r
+}\r
+\r
+VOID\r
+InitializeStringDepository (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+  Intialize all the string depositories.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  None.  \r
+--*/\r
+{\r
+  STRING_DEPOSITORY *StringDepository;\r
+  StringDepository              = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER);\r
+  FileOptionStrDepository       = StringDepository++;\r
+  ConsoleOptionStrDepository    = StringDepository++;\r
+  BootOptionStrDepository       = StringDepository++;\r
+  BootOptionHelpStrDepository   = StringDepository++;\r
+  DriverOptionStrDepository     = StringDepository++;\r
+  DriverOptionHelpStrDepository = StringDepository++;\r
+  TerminalStrDepository         = StringDepository;\r
+}\r
+\r
+STRING_REF\r
+GetStringTokenFromDepository (\r
+  IN   BMM_CALLBACK_DATA     *CallbackData,\r
+  IN   STRING_DEPOSITORY     *StringDepository\r
+  )\r
+/*++\r
+Routine Description:\r
+  Fetch a usable string node from the string depository and return the string token.\r
+\r
+Arguments:\r
+  StringDepository       - Pointer of the string depository.\r
+\r
+Returns:\r
+  STRING_REF             - String token.\r
+--*/\r
+{\r
+  STRING_LIST_NODE  *CurrentListNode;\r
+  STRING_LIST_NODE  *NextListNode;\r
+\r
+  CurrentListNode = StringDepository->CurrentNode;\r
+\r
+  if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) {\r
+    //\r
+    // Fetch one reclaimed node from the list.\r
+    //\r
+    NextListNode = StringDepository->CurrentNode->Next;\r
+  } else {\r
+    //\r
+    // If there is no usable node in the list, update the list.\r
+    //\r
+    NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE));\r
+\r
+    CallbackData->Hii->NewString (\r
+                        CallbackData->Hii,\r
+                        NULL,\r
+                        CallbackData->BmmHiiHandle,\r
+                        &(NextListNode->StringToken),\r
+                        L" "\r
+                        );\r
+\r
+    ASSERT (NextListNode->StringToken != 0);\r
+\r
+    StringDepository->TotalNodeNumber++;\r
+\r
+    if (NULL == CurrentListNode) {\r
+      StringDepository->ListHead = NextListNode;\r
+    } else {\r
+      CurrentListNode->Next = NextListNode;\r
+    }\r
+  }\r
+\r
+  StringDepository->CurrentNode = NextListNode;\r
+\r
+  return StringDepository->CurrentNode->StringToken;\r
+}\r
+\r
+VOID\r
+ReclaimStringDepository (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+  Reclaim string depositories by moving the current node pointer to list head..\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  None.\r
+--*/\r
+{\r
+  UINTN             DepositoryIndex;\r
+  STRING_DEPOSITORY *StringDepository;\r
+\r
+  StringDepository = FileOptionStrDepository;\r
+  for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
+    StringDepository->CurrentNode = StringDepository->ListHead;\r
+    StringDepository++;\r
+  }\r
+}\r
+\r
+VOID\r
+CleanUpStringDepository (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+  Release resource for all the string depositories.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  None.\r
+--*/\r
+{\r
+  UINTN             NodeIndex;\r
+  UINTN             DepositoryIndex;\r
+  STRING_LIST_NODE  *CurrentListNode;\r
+  STRING_LIST_NODE  *NextListNode;\r
+  STRING_DEPOSITORY *StringDepository;\r
+\r
+  //\r
+  // Release string list nodes.\r
+  //\r
+  StringDepository = FileOptionStrDepository;\r
+  for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
+    CurrentListNode = StringDepository->ListHead;\r
+    for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) {\r
+      NextListNode = CurrentListNode->Next;\r
+      SafeFreePool (CurrentListNode);\r
+      CurrentListNode = NextListNode;\r
+    }\r
+\r
+    StringDepository++;\r
+  }\r
+  //\r
+  // Release string depository.\r
+  //\r
+  SafeFreePool (FileOptionStrDepository);\r
+}\r
+\r
+EFI_STATUS\r
+BdsStartBootMaint (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Start boot maintenance manager\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  LIST_ENTRY  BdsBootOptionList;\r
+\r
+  InitializeListHead (&BdsBootOptionList);\r
+\r
+  //\r
+  // Connect all prior to entering the platform setup menu.\r
+  //\r
+  if (!gConnectAllHappened) {\r
+    BdsLibConnectAllDriversToAllControllers ();\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+  //\r
+  // Have chance to enumerate boot device\r
+  //\r
+  BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
+\r
+  //\r
+  // Init the BMM\r
+  //\r
+  Status = InitializeBM ();\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+FormSetDispatcher (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Dispatch BMM formset and FileExplorer formset.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_FORM_BROWSER_PROTOCOL *FormConfig;\r
+  UINT8                     *Location;\r
+  EFI_STATUS                Status;\r
+  UINTN                     Index;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_FILE_CONTEXT           *NewFileContext;\r
+  BOOLEAN                       BootMaintMenuResetRequired;\r
+\r
+  Location        = NULL;\r
+  Index           = 0;\r
+  NewMenuEntry    = NULL;\r
+  NewFileContext  = NULL;\r
+\r
+  //\r
+  // There should only be one Form Configuration protocol\r
+  //\r
+  Status = EfiLibLocateProtocol (&gEfiFormBrowserProtocolGuid, (VOID**) &FormConfig);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  while (1) {\r
+    UpdatePageId (CallbackData, FORM_MAIN_ID);\r
+\r
+    BootMaintMenuResetRequired = FALSE;\r
+    Status = FormConfig->SendForm (\r
+                          FormConfig,\r
+                          TRUE,\r
+                          &(CallbackData->BmmHiiHandle),\r
+                          1,\r
+                          NULL,\r
+                          NULL,\r
+                          (UINT8 *) CallbackData->BmmFakeNvData,\r
+                          NULL,\r
+                          &BootMaintMenuResetRequired\r
+                          );\r
+\r
+    if (BootMaintMenuResetRequired) {\r
+      EnableResetRequired ();\r
+    }\r
+\r
+    ReclaimStringDepository ();\r
+\r
+    //\r
+    // When this Formset returns, check if we are going to explore files.\r
+    //\r
+    if (INACTIVE_STATE != CallbackData->FeCurrentState) {\r
+      UpdateFileExplorer (CallbackData, 0);\r
+\r
+      BootMaintMenuResetRequired = FALSE;\r
+      Status = FormConfig->SendForm (\r
+                            FormConfig,\r
+                            TRUE,\r
+                            &(CallbackData->FeHiiHandle),\r
+                            1,\r
+                            NULL,\r
+                            NULL,\r
+                            NULL,\r
+                            NULL,\r
+                            &BootMaintMenuResetRequired\r
+                            );\r
+\r
+      if (BootMaintMenuResetRequired) {\r
+        EnableResetRequired ();\r
+      }\r
+\r
+      CallbackData->FeCurrentState    = INACTIVE_STATE;\r
+      CallbackData->FeDisplayContext  = UNKNOWN_CONTEXT;\r
+      ReclaimStringDepository ();\r
+    } else {\r
+      break;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+CreateCallbackPacket (\r
+  OUT EFI_HII_CALLBACK_PACKET         **Packet,\r
+  IN  UINT16                          Flags\r
+  )\r
+{\r
+  *Packet = (EFI_HII_CALLBACK_PACKET *) AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + 2);\r
+  ASSERT (*Packet != NULL);\r
+\r
+  (*Packet)->DataArray.EntryCount   = 1;\r
+  (*Packet)->DataArray.NvRamMap     = NULL;\r
+  ((EFI_IFR_DATA_ENTRY *) (&((*Packet)->DataArray) + 1))->Flags  = Flags;\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootMaint.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootMaint.h
new file mode 100644 (file)
index 0000000..6c3489f
--- /dev/null
@@ -0,0 +1,1161 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  BootMaint.h\r
+\r
+Abstract:\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _BOOT_MAINT_H\r
+#define _BOOT_MAINT_H\r
+\r
+#include "EdkGenericPlatformBdsLibStrDefs.h"\r
+#include "BootMaint/BBSsupport.h"\r
+\r
+//\r
+// Constants which are variable names used to access variables\r
+//\r
+#define VarLegacyDevOrder L"LegacyDevOrder"\r
+\r
+//\r
+// Guid of a NV Variable which store the information about the\r
+// FD/HD/CD/NET/BEV order\r
+//\r
+#define EFI_LEGACY_DEV_ORDER_VARIABLE_GUID \\r
+  { \\r
+    0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52 } \\r
+  }\r
+\r
+//\r
+// String Contant\r
+//\r
+#define StrFloppy       L"Floppy Drive #%02x"\r
+#define StrHardDisk     L"HardDisk Drive #%02x"\r
+#define StrCDROM        L"ATAPI CDROM Drive #%02x"\r
+#define StrNET          L"NET Drive #%02x"\r
+#define StrBEV          L"BEV Drive #%02x"\r
+#define StrFloppyHelp   L"Select Floppy Drive #%02x"\r
+#define StrHardDiskHelp L"Select HardDisk Drive #%02x"\r
+#define StrCDROMHelp    L"Select ATAPI CDROM Drive #%02x"\r
+#define StrNETHelp      L"NET Drive #%02x"\r
+#define StrBEVHelp      L"BEV Drive #%02x"\r
+\r
+//\r
+// Constant will be used in display and file system navigation\r
+//\r
+#define UPDATE_DATA_SIZE        0x100000\r
+#define MAX_BBS_OFFSET          0xE000\r
+#define NET_OPTION_OFFSET       0xD800\r
+#define BEV_OPTION_OFFSET       0xD000\r
+#define FD_OPTION_OFFSET        0xC000\r
+#define HD_OPTION_OFFSET        0xB000\r
+#define CD_OPTION_OFFSET        0xA000\r
+#define FILE_OPTION_OFFSET      0x8000\r
+#define FILE_OPTION_MASK        0x7FFF\r
+#define HANDLE_OPTION_OFFSET    0x7000\r
+#define CONSOLE_OPTION_OFFSET   0x0A00\r
+#define TERMINAL_OPTION_OFFSET  0x0700\r
+#define NORMAL_GOTO_OFFSET      0x0100\r
+#define MAX_STRING_TOKEN_COUNT  0x00FF\r
+//\r
+// Variable created with this flag will be "Efi:...."\r
+//\r
+#define VAR_FLAG  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE\r
+\r
+//\r
+// Define Maxmim characters that will be accepted\r
+//\r
+#define MAX_CHAR      480\r
+#define MAX_CHAR_SIZE (MAX_CHAR * 2)\r
+\r
+//\r
+// Check to see if current build support option active feature of\r
+// some driver option\r
+//\r
+#ifndef LOAD_OPTION_ACTIVE\r
+#define LOAD_OPTION_ACTIVE  0x00000001\r
+#endif\r
+//\r
+// Check to see if current build support force reconnect feature of\r
+// some driver option\r
+//\r
+#ifndef LOAD_OPTION_FORCE_RECONNECT\r
+#define LOAD_OPTION_FORCE_RECONNECT 0x00000002\r
+#endif\r
+//\r
+// Below are the form ids for display, form id is used as callback key value,\r
+// some key value definitions are also defined here. By defining this enum type,\r
+// We can easy know where we are. The int to UINT16 convertion should be ok because\r
+// there is a MAXIMUM_FORM_ID which in within the range of UINT16.\r
+//\r
+typedef enum {\r
+  IplRelative,\r
+  BcvRelative\r
+} BBS_TYPE;\r
+\r
+typedef enum {\r
+  FORM_RESERVED_ID                    = 0,\r
+  FORM_MAIN_ID,                         // 0x0001\r
+  FORM_BOOT_ADD_ID,                     // 0x0002\r
+  FORM_BOOT_DEL_ID,                     // 0x0003\r
+  FORM_BOOT_CHG_ID,                     // 0x0004\r
+  FORM_DRV_ADD_ID,                      // 0x0005\r
+  FORM_DRV_DEL_ID,                      // 0x0006\r
+  FORM_DRV_CHG_ID,                      // 0x0007\r
+  FORM_CON_MAIN_ID,                     // 0x0008\r
+  FORM_CON_IN_ID,                       // 0x0009\r
+  FORM_CON_OUT_ID,                      // 0x000A\r
+  FORM_CON_ERR_ID,                      // 0x000B\r
+  FORM_FILE_SEEK_ID,                    // 0x000C\r
+  FORM_FILE_NEW_SEEK_ID,                // 0x000D\r
+  FORM_DRV_ADD_FILE_ID,                 // 0x000E\r
+  FORM_DRV_ADD_HANDLE_ID,               // 0x000F\r
+  FORM_DRV_ADD_HANDLE_DESC_ID,          // 0x0010\r
+  FORM_BOOT_NEXT_ID,                    // 0x0011\r
+  FORM_TIME_OUT_ID,                     // 0x0012\r
+  FORM_RESET,                           // 0x0013\r
+  FORM_BOOT_SETUP_ID,                   // 0x0014\r
+  FORM_DRIVER_SETUP_ID,                 // 0x0015\r
+  FORM_BOOT_LEGACY_DEVICE_ID,           // 0x0016\r
+  FORM_CON_COM_ID,                      // 0x0017\r
+  FORM_CON_COM_SETUP_ID,                // 0x0018\r
+  FORM_SET_FD_ORDER_ID,                 // 0x0019\r
+  FORM_SET_HD_ORDER_ID,                 // 0x001A\r
+  FORM_SET_CD_ORDER_ID,                 // 0x001B\r
+  FORM_SET_NET_ORDER_ID,                // 0x001C\r
+  FORM_SET_BEV_ORDER_ID,                // 0x001D\r
+  FORM_FILE_EXPLORER_ID,                // 0x001E\r
+  FORM_BOOT_ADD_DESCRIPTION_ID,         // 0x001F\r
+  FORM_DRIVER_ADD_FILE_DESCRIPTION_ID,  // 0x0020\r
+} FORM_ID;\r
+\r
+#define MAXIMUM_FORM_ID                 0x007F\r
+\r
+#define KEY_VALUE_COM_SET_BAUD_RATE     0x0080\r
+#define KEY_VALUE_COM_SET_DATA_BITS     0x0081\r
+#define KEY_VALUE_COM_SET_STOP_BITS     0x0082\r
+#define KEY_VALUE_COM_SET_PARITY        0x0083\r
+#define KEY_VALUE_COM_SET_TERMI_TYPE    0x0084\r
+#define KEY_VALUE_MAIN_BOOT_NEXT        0x0085\r
+#define KEY_VALUE_BOOT_ADD_DESC_DATA    0x0086\r
+#define KEY_VALUE_BOOT_ADD_OPT_DATA     0x0087\r
+#define KEY_VALUE_DRIVER_ADD_DESC_DATA  0x0088\r
+#define KEY_VALUE_DRIVER_ADD_OPT_DATA   0x0089\r
+#define KEY_VALUE_SAVE_AND_EXIT         0x0090\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT      0x0091\r
+#define KEY_VALUE_BOOT_FROM_FILE        0x0092\r
+\r
+#define MAXIMUM_NORMAL_KEY_VALUE        NORMAL_GOTO_OFFSET\r
+//\r
+// Below are the number of options in Baudrate, Databits,\r
+// Parity and Stopbits selection for serial ports.\r
+//\r
+#define BM_COM_ATTR_BUADRATE  19\r
+#define BM_COM_ATTR_DATABITS  4\r
+#define BM_COM_ATTR_PARITY    5\r
+#define BM_COM_ATTR_STOPBITS  3\r
+\r
+//\r
+// Callback function helper\r
+//\r
+#define BMM_CALLBACK_DATA_SIGNATURE     EFI_SIGNATURE_32 ('C', 'b', 'c', 'k')\r
+#define BMM_CALLBACK_DATA_FROM_THIS(a)  CR (a, BMM_CALLBACK_DATA, BmmDriverCallback, BMM_CALLBACK_DATA_SIGNATURE)\r
+\r
+#define FE_CALLBACK_DATA_FROM_THIS(a)   CR (a, BMM_CALLBACK_DATA, FeDriverCallback, BMM_CALLBACK_DATA_SIGNATURE)\r
+\r
+//\r
+// Enumeration type definition\r
+//\r
+typedef enum {\r
+  PC_ANSI                             = 0,\r
+  VT_100,\r
+  VT_100_PLUS,\r
+  VT_UTF8\r
+} TYPE_OF_TERMINAL;\r
+\r
+typedef enum {\r
+  COM1                                = 0,\r
+  COM2,\r
+  UNKNOW_COM\r
+} TYPE_OF_COM;\r
+\r
+typedef enum {\r
+  CONIN                               = 0,\r
+  CONOUT,\r
+  CONERR,\r
+  UNKNOWN_CON\r
+} TYPE_OF_CON;\r
+\r
+typedef enum {\r
+  BAUDRATE                            = 0,\r
+  DATABITS,\r
+  PARITY,\r
+  STOPBITS,\r
+  UNKNOW_ATTR\r
+} TYPE_OF_ATTRIBUTE;\r
+\r
+typedef enum {\r
+  MANNER_GOTO                         = 0,\r
+  MANNER_CHECK,\r
+  MANNER_ONEOF,\r
+  MANNER_USER_DEFINE\r
+} TYPE_OF_UPATE_MANNER;\r
+\r
+typedef enum {\r
+  INACTIVE_STATE                      = 0,\r
+  BOOT_FROM_FILE_STATE,\r
+  ADD_BOOT_OPTION_STATE,\r
+  ADD_DRIVER_OPTION_STATE,\r
+  UNKNOWN_STATE\r
+} FILE_EXPLORER_STATE;\r
+\r
+typedef enum {\r
+  FILE_SYSTEM,\r
+  DIRECTORY,\r
+  UNKNOWN_CONTEXT\r
+} FILE_EXPLORER_DISPLAY_CONTEXT;\r
+\r
+//\r
+// All of the signatures that will be used in list structure\r
+//\r
+#define BM_MENU_OPTION_SIGNATURE      EFI_SIGNATURE_32 ('m', 'e', 'n', 'u')\r
+#define BM_LOAD_OPTION_SIGNATURE      EFI_SIGNATURE_32 ('l', 'o', 'a', 'd')\r
+#define BM_CONSOLE_OPTION_SIGNATURE   EFI_SIGNATURE_32 ('c', 'n', 's', 'l')\r
+#define BM_FILE_OPTION_SIGNATURE      EFI_SIGNATURE_32 ('f', 'i', 'l', 'e')\r
+#define BM_HANDLE_OPTION_SIGNATURE    EFI_SIGNATURE_32 ('h', 'n', 'd', 'l')\r
+#define BM_TERMINAL_OPTION_SIGNATURE  EFI_SIGNATURE_32 ('t', 'r', 'm', 'l')\r
+#define BM_MENU_ENTRY_SIGNATURE       EFI_SIGNATURE_32 ('e', 'n', 't', 'r')\r
+\r
+#define BM_LOAD_CONTEXT_SELECT        0x0\r
+#define BM_CONSOLE_CONTEXT_SELECT     0x1\r
+#define BM_FILE_CONTEXT_SELECT        0x2\r
+#define BM_HANDLE_CONTEXT_SELECT      0x3\r
+#define BM_TERMINAL_CONTEXT_SELECT    0x5\r
+\r
+#define BM_CONSOLE_IN_CONTEXT_SELECT  0x6\r
+#define BM_CONSOLE_OUT_CONTEXT_SELECT 0x7\r
+#define BM_CONSOLE_ERR_CONTEXT_SELECT 0x8\r
+#define BM_LEGACY_DEV_CONTEXT_SELECT  0x9\r
+\r
+//\r
+// Question Id that will be used to create question\r
+// all these values are computed from the structure\r
+// defined below\r
+//\r
+#define QUESTION_ID(Field)              ((UINTN) &(((BMM_FAKE_NV_DATA *) 0)->Field))\r
+\r
+#define BOOT_TIME_OUT_QUESTION_ID       QUESTION_ID (BootTimeOut)\r
+#define BOOT_NEXT_QUESTION_ID           QUESTION_ID (BootNext)\r
+#define COM1_BAUD_RATE_QUESTION_ID      QUESTION_ID (COM1BaudRate)\r
+#define COM1_DATA_RATE_QUESTION_ID      QUESTION_ID (COM1DataRate)\r
+#define COM1_STOP_BITS_QUESTION_ID      QUESTION_ID (COM1StopBits)\r
+#define COM1_PARITY_QUESTION_ID         QUESTION_ID (COM1Parity)\r
+#define COM1_TERMINAL_QUESTION_ID       QUESTION_ID (COM2TerminalType)\r
+#define COM2_BAUD_RATE_QUESTION_ID      QUESTION_ID (COM2BaudRate)\r
+#define COM2_DATA_RATE_QUESTION_ID      QUESTION_ID (COM2DataRate)\r
+#define COM2_STOP_BITS_QUESTION_ID      QUESTION_ID (COM2StopBits)\r
+#define COM2_PARITY_QUESTION_ID         QUESTION_ID (COM2Parity)\r
+#define COM2_TERMINAL_QUESTION_ID       QUESTION_ID (COM2TerminalType)\r
+#define DRV_ADD_HANDLE_DESC_QUESTION_ID QUESTION_ID (DriverAddHandleDesc)\r
+#define DRV_ADD_ACTIVE_QUESTION_ID      QUESTION_ID (DriverAddActive)\r
+#define DRV_ADD_RECON_QUESTION_ID       QUESTION_ID (DriverAddForceReconnect)\r
+#define CON_IN_COM1_QUESTION_ID         QUESTION_ID (ConsoleInputCOM1)\r
+#define CON_IN_COM2_QUESTION_ID         QUESTION_ID (ConsoleInputCOM2)\r
+#define CON_OUT_COM1_QUESTION_ID        QUESTION_ID (ConsoleOutputCOM1)\r
+#define CON_OUT_COM2_QUESTION_ID        QUESTION_ID (ConsoleOutputCOM2)\r
+#define CON_ERR_COM1_QUESTION_ID        QUESTION_ID (ConsoleErrorCOM1)\r
+#define CON_ERR_COM2_QUESTION_ID        QUESTION_ID (ConsoleErrorCOM2)\r
+#define CON_DEVICE_QUESTION_ID          QUESTION_ID (ConsoleCheck)\r
+#define OPTION_ORDER_QUESTION_ID        QUESTION_ID (OptionOrder)\r
+#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionToBeDeleted)\r
+#define BOOT_OPTION_DEL_QUESTION_ID     QUESTION_ID (BootOptionDel)\r
+#define DRIVER_OPTION_DEL_QUESTION_ID   QUESTION_ID (DriverOptionDel)\r
+#define DRIVER_ADD_OPTION_QUESTION_ID   QUESTION_ID (DriverAddHandleOptionalData)\r
+#define COM_BAUD_RATE_QUESTION_ID       QUESTION_ID (COMBaudRate)\r
+#define COM_DATA_RATE_QUESTION_ID       QUESTION_ID (COMDataRate)\r
+#define COM_STOP_BITS_QUESTION_ID       QUESTION_ID (COMStopBits)\r
+#define COM_PARITY_QUESTION_ID          QUESTION_ID (COMParity)\r
+#define COM_TERMINAL_QUESTION_ID        QUESTION_ID (COMTerminalType)\r
+#define LEGACY_FD_QUESTION_ID           QUESTION_ID (LegacyFD)\r
+#define LEGACY_HD_QUESTION_ID           QUESTION_ID (LegacyHD)\r
+#define LEGACY_CD_QUESTION_ID           QUESTION_ID (LegacyCD)\r
+#define LEGACY_NET_QUESTION_ID          QUESTION_ID (LegacyNET)\r
+#define LEGACY_BEV_QUESTION_ID          QUESTION_ID (LegacyBEV)\r
+\r
+#define STRING_DEPOSITORY_NUMBER        8\r
+\r
+//\r
+// #pragma pack(1)\r
+//\r
+// Serial Ports attributes, first one is the value for\r
+// return from callback function, stringtoken is used to\r
+// display the value properly\r
+//\r
+typedef struct {\r
+  UINTN   Value;\r
+  UINT16  StringToken;\r
+} COM_ATTR;\r
+\r
+//\r
+// This is the structure that will be used to store the\r
+// question's current value. Use it at initialize time to\r
+// set default value for each question. When using at run\r
+// time, this map is returned by the callback function,\r
+// so dynamically changing the question's value will be\r
+// possible through this mechanism\r
+//\r
+typedef struct {\r
+  //\r
+  // Three questions displayed at the main page\r
+  // for Timeout, BootNext Variables respectively\r
+  //\r
+  UINT16  BootTimeOut;\r
+  UINT16  BootNext;\r
+\r
+  //\r
+  // This is the COM1 Attributes value storage\r
+  //\r
+  UINT8   COM1BaudRate;\r
+  UINT8   COM1DataRate;\r
+  UINT8   COM1StopBits;\r
+  UINT8   COM1Parity;\r
+  UINT8   COM1TerminalType;\r
+\r
+  //\r
+  // This is the COM2 Attributes value storage\r
+  //\r
+  UINT8   COM2BaudRate;\r
+  UINT8   COM2DataRate;\r
+  UINT8   COM2StopBits;\r
+  UINT8   COM2Parity;\r
+  UINT8   COM2TerminalType;\r
+\r
+  //\r
+  // Driver Option Add Handle page storage\r
+  //\r
+  UINT16  DriverAddHandleDesc[100];\r
+  UINT16  DriverAddHandleOptionalData[100];\r
+  UINT8   DriverAddActive;\r
+  UINT8   DriverAddForceReconnect;\r
+\r
+  //\r
+  // Console Input/Output/Errorout using COM port check storage\r
+  //\r
+  UINT8   ConsoleInputCOM1;\r
+  UINT8   ConsoleInputCOM2;\r
+  UINT8   ConsoleOutputCOM1;\r
+  UINT8   ConsoleOutputCOM2;\r
+  UINT8   ConsoleErrorCOM1;\r
+  UINT8   ConsoleErrorCOM2;\r
+\r
+  //\r
+  // At most 100 input/output/errorout device for console storage\r
+  //\r
+  UINT8   ConsoleCheck[100];\r
+\r
+  //\r
+  // Boot or Driver Option Order storage\r
+  //\r
+  UINT8   OptionOrder[100];\r
+  UINT8   DriverOptionToBeDeleted[100];\r
+\r
+  //\r
+  // Boot Option Delete storage\r
+  //\r
+  UINT8   BootOptionDel[100];\r
+  UINT8   DriverOptionDel[100];\r
+\r
+  //\r
+  // This is the Terminal Attributes value storage\r
+  //\r
+  UINT8   COMBaudRate;\r
+  UINT8   COMDataRate;\r
+  UINT8   COMStopBits;\r
+  UINT8   COMParity;\r
+  UINT8   COMTerminalType;\r
+\r
+  //\r
+  // Legacy Device Order Selection Storage\r
+  //\r
+  UINT8   LegacyFD[100];\r
+  UINT8   LegacyHD[100];\r
+  UINT8   LegacyCD[100];\r
+  UINT8   LegacyNET[100];\r
+  UINT8   LegacyBEV[100];\r
+\r
+  //\r
+  // We use DisableMap array to record the enable/disable state of each boot device\r
+  // It should be taken as a bit array, from left to right there are totally 256 bits\r
+  // the most left one stands for BBS table item 0, and the most right one stands for item 256\r
+  // If the bit is 1, it means the boot device has been disabled.\r
+  //\r
+  UINT8   DisableMap[32];\r
+\r
+  //\r
+  //  UINT16                    PadArea[10];\r
+  //\r
+} BMM_FAKE_NV_DATA;\r
+\r
+typedef struct {\r
+  UINT16  DescriptionData[75];\r
+  UINT16                    OptionalData[127];\r
+  UINT8   Active;\r
+  UINT8   ForceReconnect;\r
+} FILE_EXPLORER_NV_DATA;\r
+\r
+typedef struct {\r
+  BBS_TYPE  BbsType;\r
+  //\r
+  // Length = sizeof (UINT16) + SIZEOF (Data)\r
+  //\r
+  UINT16    Length;\r
+  UINT16    *Data;\r
+} BM_LEGACY_DEV_ORDER_CONTEXT;\r
+\r
+typedef struct {\r
+  UINT64                    BaudRate;\r
+  UINT8                     DataBits;\r
+  UINT8                     Parity;\r
+  UINT8                     StopBits;\r
+\r
+  UINT8                     BaudRateIndex;\r
+  UINT8                     DataBitsIndex;\r
+  UINT8                     ParityIndex;\r
+  UINT8                     StopBitsIndex;\r
+\r
+  UINT8                     IsConIn;\r
+  UINT8                     IsConOut;\r
+  UINT8                     IsStdErr;\r
+  UINT8                     TerminalType;\r
+\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+} BM_TERMINAL_CONTEXT;\r
+\r
+typedef struct {\r
+  BOOLEAN                   IsBootNext;\r
+  BOOLEAN                   LoadOptionModified;\r
+  BOOLEAN                   Deleted;\r
+\r
+  BOOLEAN                   IsLegacy;\r
+  BOOLEAN                   IsActive;\r
+  BOOLEAN                   ForceReconnect;\r
+  UINTN                     OptionalDataSize;\r
+\r
+  UINTN                     LoadOptionSize;\r
+  UINT8                     *LoadOption;\r
+\r
+  UINT32                    Attributes;\r
+  UINT16                    FilePathListLength;\r
+  UINT16                    *Description;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FilePathList;\r
+  UINT8                     *OptionalData;\r
+\r
+  UINT16                    BbsIndex;\r
+} BM_LOAD_CONTEXT;\r
+\r
+typedef struct {\r
+  BBS_TABLE *BbsTable;\r
+  UINTN     Index;\r
+  UINTN     BbsCount;\r
+  UINT16    *Description;\r
+} BM_LEGACY_DEVICE_CONTEXT;\r
+\r
+typedef struct {\r
+\r
+  BOOLEAN                   IsActive;\r
+\r
+  BOOLEAN                   IsTerminal;\r
+\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+} BM_CONSOLE_CONTEXT;\r
+\r
+typedef struct {\r
+  EFI_HANDLE                        Handle;\r
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;\r
+  EFI_FILE_HANDLE                   FHandle;\r
+  UINT16                            *FileName;\r
+  EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Info;\r
+\r
+  BOOLEAN                           IsRoot;\r
+  BOOLEAN                           IsDir;\r
+  BOOLEAN                           IsRemovableMedia;\r
+  BOOLEAN                           IsLoadFile;\r
+  BOOLEAN                           IsBootLegacy;\r
+} BM_FILE_CONTEXT;\r
+\r
+typedef struct {\r
+  EFI_HANDLE                Handle;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+} BM_HANDLE_CONTEXT;\r
+\r
+typedef struct {\r
+  UINTN           Signature;\r
+  LIST_ENTRY      Head;\r
+  UINTN           MenuNumber;\r
+} BM_MENU_OPTION;\r
+\r
+typedef struct {\r
+  UINTN           Signature;\r
+  LIST_ENTRY      Link;\r
+  UINTN           OptionNumber;\r
+  UINT16          *DisplayString;\r
+  UINT16          *HelpString;\r
+  STRING_REF      DisplayStringToken;\r
+  STRING_REF      HelpStringToken;\r
+  UINTN           ContextSelection;\r
+  VOID            *VariableContext;\r
+} BM_MENU_ENTRY;\r
+\r
+typedef struct {\r
+  //\r
+  // Shared callback data.\r
+  //\r
+  UINTN                         Signature;\r
+  EFI_HII_PROTOCOL              *Hii;\r
+  BM_MENU_ENTRY                 *MenuEntry;\r
+  BM_HANDLE_CONTEXT             *HandleContext;\r
+  BM_FILE_CONTEXT               *FileContext;\r
+  BM_LOAD_CONTEXT               *LoadContext;\r
+  BM_TERMINAL_CONTEXT           *TerminalContext;\r
+  UINTN                         CurrentTerminal;\r
+  BBS_TYPE                      BbsType;\r
+\r
+  //\r
+  // BMM main formset callback data.\r
+  //\r
+  EFI_HII_HANDLE                BmmHiiHandle;\r
+  EFI_HANDLE                    BmmCallbackHandle;\r
+  EFI_FORM_CALLBACK_PROTOCOL    BmmDriverCallback;\r
+  FORM_ID                       BmmCurrentPageId;\r
+  FORM_ID                       BmmPreviousPageId;\r
+  BOOLEAN                       BmmAskSaveOrNot;\r
+  BMM_FAKE_NV_DATA              *BmmFakeNvData;\r
+  BMM_FAKE_NV_DATA              BmmOldFakeNVData;\r
+\r
+  //\r
+  // File explorer formset callback data.\r
+  //\r
+  EFI_HII_HANDLE                FeHiiHandle;\r
+  EFI_HANDLE                    FeCallbackHandle;\r
+  EFI_FORM_CALLBACK_PROTOCOL    FeDriverCallback;\r
+  FILE_EXPLORER_STATE           FeCurrentState;\r
+  FILE_EXPLORER_DISPLAY_CONTEXT FeDisplayContext;\r
+} BMM_CALLBACK_DATA;\r
+\r
+typedef struct _STRING_LIST_NODE {\r
+  STRING_REF                StringToken;\r
+  struct _STRING_LIST_NODE  *Next;\r
+} STRING_LIST_NODE;\r
+\r
+typedef struct _STRING_DEPOSITORY {\r
+  UINTN             TotalNodeNumber;\r
+  STRING_LIST_NODE  *CurrentNode;\r
+  STRING_LIST_NODE  *ListHead;\r
+} STRING_DEPOSITORY;\r
+\r
+//\r
+// #pragma pack()\r
+//\r
+// For initializing File System menu\r
+//\r
+EFI_STATUS\r
+BOpt_FindFileSystem (\r
+  IN BMM_CALLBACK_DATA          *CallbackData\r
+  )\r
+;\r
+\r
+//\r
+// For cleaning up File System menu\r
+//\r
+VOID\r
+BOpt_FreeFileSystem (\r
+  VOID\r
+  )\r
+;\r
+\r
+//\r
+// For initializing File Navigation menu\r
+//\r
+EFI_STATUS\r
+BOpt_FindFiles (\r
+  IN BMM_CALLBACK_DATA          *CallbackData,\r
+  IN BM_MENU_ENTRY              *MenuEntry\r
+  )\r
+;\r
+\r
+//\r
+// For cleaning up File Navigation menu\r
+//\r
+VOID\r
+BOpt_FreeFiles (\r
+  VOID\r
+  )\r
+;\r
+\r
+//\r
+// For Initializing handle navigation menu\r
+//\r
+EFI_STATUS\r
+BOpt_FindDrivers (\r
+  VOID\r
+  )\r
+;\r
+\r
+//\r
+// For Cleaning up handle navigation menu\r
+//\r
+VOID\r
+BOpt_FreeDrivers();\r
+\r
+//\r
+// For initializing Boot Option menu\r
+//\r
+EFI_STATUS\r
+BOpt_GetBootOptions (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData\r
+  );\r
+\r
+//\r
+// For Initializing Driver option menu\r
+//\r
+EFI_STATUS\r
+BOpt_GetDriverOptions (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData\r
+  );\r
+\r
+//\r
+// For Cleaning up boot option menu\r
+//\r
+VOID\r
+BOpt_FreeBootOptions ();\r
+\r
+//\r
+// For cleaning up driver option menu\r
+//\r
+VOID\r
+BOpt_FreeDriverOptions();\r
+\r
+//\r
+// For Initializing HD/FD/CD/NET/BEV option menu\r
+//\r
+EFI_STATUS\r
+BOpt_GetLegacyOptions();\r
+\r
+//\r
+// For cleaning up driver option menu\r
+//\r
+VOID\r
+BOpt_FreeLegacyOptions();\r
+\r
+//\r
+// this function is used to take place of all other free menu actions\r
+//\r
+VOID\r
+BOpt_FreeMenu (\r
+  BM_MENU_OPTION        *FreeMenu\r
+  );\r
+\r
+\r
+//\r
+// Following are the helper functions used\r
+//\r
+CHAR16                            *\r
+BOpt_AppendFileName (\r
+  IN  CHAR16  *Str1,\r
+  IN  CHAR16  *Str2\r
+  );\r
+\r
+BOOLEAN\r
+BOpt_IsEfiImageName (\r
+  IN UINT16  *FileName\r
+  );\r
+\r
+BOOLEAN\r
+BOpt_IsEfiApp (\r
+  IN EFI_FILE_HANDLE Dir,\r
+  IN UINT16          *FileName\r
+  );\r
+\r
+//\r
+// Get current unused boot option number\r
+//\r
+UINT16\r
+BOpt_GetBootOptionNumber ();\r
+\r
+//\r
+// Get current unused driver option number\r
+//\r
+UINT16\r
+BOpt_GetDriverOptionNumber ();\r
+\r
+BM_MENU_ENTRY                     *\r
+BOpt_CreateMenuEntry (\r
+  UINTN           MenuType\r
+  );\r
+\r
+VOID\r
+BOpt_DestroyMenuEntry (\r
+  BM_MENU_ENTRY         *MenuEntry\r
+  );\r
+\r
+BM_MENU_ENTRY                     *\r
+BOpt_GetMenuEntry (\r
+  BM_MENU_OPTION      *MenuOption,\r
+  UINTN               MenuNumber\r
+  );\r
+\r
+//\r
+// a helper function used to free pool type memory\r
+//\r
+VOID\r
+SafeFreePool (\r
+  IN VOID *Buffer\r
+  );\r
+\r
+//\r
+// Locate all serial io devices for console\r
+//\r
+EFI_STATUS\r
+LocateSerialIo ();\r
+\r
+//\r
+// Initializing Console menu\r
+//\r
+EFI_STATUS\r
+GetAllConsoles();\r
+\r
+//\r
+// Cleaning up console menu\r
+//\r
+EFI_STATUS\r
+FreeAllConsoles();\r
+\r
+VOID\r
+ChangeVariableDevicePath (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+); \r
+\r
+EFI_STATUS\r
+ChangeTerminalDevicePath (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  BOOLEAN                   ChangeTerminal\r
+);\r
+//\r
+// Variable operation by menu selection\r
+//\r
+EFI_STATUS\r
+Var_UpdateBootOption (\r
+  IN  BMM_CALLBACK_DATA                   *CallbackData,\r
+  IN  FILE_EXPLORER_NV_DATA               *NvRamMap\r
+  );\r
+\r
+EFI_STATUS\r
+Var_DelBootOption ();\r
+\r
+EFI_STATUS\r
+Var_ChangeBootOrder ();\r
+\r
+EFI_STATUS\r
+Var_UpdateDriverOption (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData,\r
+  IN  EFI_HII_HANDLE            HiiHandle,\r
+  IN  UINT16                    *DescriptionData,\r
+  IN  UINT16                    *OptionalData,\r
+  IN  UINT8                     ForceReconnect\r
+  );\r
+\r
+EFI_STATUS\r
+Var_DelDriverOption ();\r
+\r
+EFI_STATUS\r
+Var_ChangeDriverOrder ();\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleInpOption ();\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleOutOption ();\r
+\r
+EFI_STATUS\r
+Var_UpdateErrorOutOption ();\r
+\r
+VOID\r
+Var_UpdateAllConsoleOption ();\r
+\r
+EFI_STATUS\r
+Var_UpdateBootNext (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+EFI_STATUS\r
+Var_UpdateBootOrder (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+EFI_STATUS\r
+Var_UpdateDriverOrder (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+EFI_STATUS\r
+Var_UpdateBBSOption (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+//\r
+// Following are page create and refresh functions\r
+//\r
+VOID\r
+RefreshUpdateData (\r
+  IN BOOLEAN                          FormSetUpdate,\r
+  IN EFI_PHYSICAL_ADDRESS             FormCallbackHandle,\r
+  IN BOOLEAN                          FormUpdate,\r
+  IN STRING_REF                       FormTitle,\r
+  IN UINT16                           DataCount\r
+  );\r
+\r
+VOID\r
+CleanUpPage (\r
+  IN EFI_FORM_LABEL                   LabelId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+EFI_STATUS\r
+UpdatePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData,\r
+  IN BM_MENU_OPTION                   *UpdatingMenu,\r
+  IN UINT16                           UpdatingPage,\r
+  IN UINT16                           UpdatingManner,\r
+  IN UINT16                           QuestionIdStart,\r
+  IN UINT16                           GotoForm,\r
+  IN UINT16                           GotoAlternateForm,\r
+  IN STRING_REF                       DisplayTokenStart,\r
+  IN STRING_REF                       HelpTokenStart,\r
+  IN UINT16                           KeyValueStart\r
+  );\r
+\r
+VOID\r
+UpdateBootAddPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateBootDelPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateDrvAddFilePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateDrvAddHandlePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateDrvDelPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateDriverAddHandleDescPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateBootTimeOut (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateConInPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateConOutPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateStdErrPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdatePageBody (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateCOM1Page (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateCOM2Page (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateBootOrderPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateDriverOrderPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateBootNextPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateTimeOutPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateTerminalPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateConCOMPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+VOID\r
+UpdateSetLegacyDeviceOrderPage (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+);\r
+\r
+EFI_STATUS\r
+BootLegacy (\r
+  IN  UINT16  BbsType,\r
+  IN  UINT16  BbsFlag\r
+);\r
+\r
+BM_MENU_ENTRY                     *\r
+GetCurrentTerminal (\r
+  UINTN       TerminalNumber\r
+);\r
+\r
+EFI_FILE_HANDLE\r
+EfiLibOpenRoot (\r
+  IN EFI_HANDLE       DeviceHandle\r
+  );\r
+\r
+EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *\r
+EfiLibFileSystemVolumeLabelInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  );\r
+\r
+EFI_FILE_INFO                     *\r
+EfiLibFileInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  );\r
+\r
+CHAR16                            *\r
+DevicePathToStr (\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevPath\r
+  );\r
+\r
+EFI_STATUS\r
+EfiLibLocateProtocol (\r
+  IN  EFI_GUID        *ProtocolGuid,\r
+  OUT VOID            **Interface\r
+  );\r
+\r
+VOID                              *\r
+EfiReallocatePool (\r
+  IN VOID                 *OldPool,\r
+  IN UINTN                OldSize,\r
+  IN UINTN                NewSize\r
+  );\r
+\r
+CHAR16                            *\r
+DevicePathToStr (\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevPath\r
+  );\r
+\r
+VOID                              *\r
+BdsLibGetVariableAndSize (\r
+  IN CHAR16               *Name,\r
+  IN EFI_GUID             *VendorGuid,\r
+  OUT UINTN               *VarSize\r
+  );\r
+\r
+EFI_STATUS\r
+EfiLibDeleteVariable (\r
+  IN CHAR16   *VarName,\r
+  IN EFI_GUID *VarGuid\r
+  );\r
+\r
+CHAR16                            *\r
+EfiStrDuplicate (\r
+  IN CHAR16   *Src\r
+  );\r
+\r
+BOOLEAN\r
+EfiLibMatchDevicePaths (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *Multi,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *Single\r
+  );\r
+\r
+UINTN\r
+EfiDevicePathInstanceCount (\r
+  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath\r
+  );\r
+\r
+EFI_STATUS\r
+CreateMenuStringToken (\r
+  IN BMM_CALLBACK_DATA                *CallbackData,\r
+  IN EFI_HII_HANDLE                   HiiHandle,\r
+  IN BM_MENU_OPTION                   *MenuOption\r
+  );\r
+\r
+UINT16                            *\r
+EfiLibStrFromDatahub (\r
+  IN EFI_DEVICE_PATH_PROTOCOL                 *DevPath\r
+  );\r
+\r
+VOID                              *\r
+GetLegacyBootOptionVar (\r
+  IN  UINTN                            DeviceType,\r
+  OUT UINTN                            *OptionIndex,\r
+  OUT UINTN                            *OptionSize\r
+ );\r
+\r
+EFI_STATUS\r
+InitializeBM (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+BdsStartBootMaint (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+InitializeStringDepository ();\r
+\r
+STRING_REF\r
+GetStringTokenFromDepository (\r
+  IN   BMM_CALLBACK_DATA     *CallbackData,\r
+  IN   STRING_DEPOSITORY     *StringDepository\r
+  ) ;\r
+\r
+VOID\r
+ReclaimStringDepository (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+CleanUpStringDepository (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+ApplyChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap,\r
+  IN  FORM_ID                         FormId\r
+  );\r
+\r
+VOID\r
+DiscardChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap\r
+  );\r
+\r
+VOID\r
+UpdatePageId (\r
+  BMM_CALLBACK_DATA              *Private,\r
+  UINT16                         NewPageId\r
+  );\r
+\r
+EFI_STATUS\r
+BootThisFile (\r
+  IN BM_FILE_CONTEXT                   *FileContext\r
+  );\r
+\r
+BOOLEAN\r
+UpdateFileExplorer (\r
+  IN BMM_CALLBACK_DATA            *CallbackData,\r
+  IN UINT16                       KeyValue\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FileExplorerCallback (\r
+  IN EFI_FORM_CALLBACK_PROTOCOL       *This,\r
+  IN UINT16                           KeyValue,\r
+  IN EFI_IFR_DATA_ARRAY               *Data,\r
+  OUT EFI_HII_CALLBACK_PACKET         **Packet\r
+  );\r
+\r
+EFI_STATUS\r
+FormSetDispatcher (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  );\r
+\r
+VOID CreateCallbackPacket (\r
+  OUT EFI_HII_CALLBACK_PACKET         **Packet,\r
+  IN  UINT16                          Flags\r
+  );\r
+\r
+//\r
+// Global variable in this program (defined in data.c)\r
+//\r
+extern BM_MENU_OPTION             BootOptionMenu;\r
+extern BM_MENU_OPTION             DriverOptionMenu;\r
+extern BM_MENU_OPTION             FsOptionMenu;\r
+extern BM_MENU_OPTION             ConsoleInpMenu;\r
+extern BM_MENU_OPTION             ConsoleOutMenu;\r
+extern BM_MENU_OPTION             ConsoleErrMenu;\r
+extern BM_MENU_OPTION             DirectoryMenu;\r
+extern BM_MENU_OPTION             DriverMenu;\r
+extern BM_MENU_OPTION             TerminalMenu;\r
+extern BM_MENU_OPTION             LegacyFDMenu;\r
+extern BM_MENU_OPTION             LegacyHDMenu;\r
+extern BM_MENU_OPTION             LegacyCDMenu;\r
+extern BM_MENU_OPTION             LegacyNETMenu;\r
+extern BM_MENU_OPTION             LegacyBEVMenu;\r
+extern UINT16                     TerminalType[];\r
+extern COM_ATTR                   BaudRateList[19];\r
+extern COM_ATTR                   DataBitsList[4];\r
+extern COM_ATTR                   ParityList[5];\r
+extern COM_ATTR                   StopBitsList[3];\r
+extern EFI_GUID                   Guid[4];\r
+extern EFI_HII_UPDATE_DATA        *UpdateData;\r
+extern STRING_DEPOSITORY          *FileOptionStrDepository;\r
+extern STRING_DEPOSITORY          *ConsoleOptionStrDepository;\r
+extern STRING_DEPOSITORY          *BootOptionStrDepository;\r
+extern STRING_DEPOSITORY          *BootOptionHelpStrDepository;\r
+extern STRING_DEPOSITORY          *DriverOptionStrDepository;\r
+extern STRING_DEPOSITORY          *DriverOptionHelpStrDepository;\r
+extern STRING_DEPOSITORY          *TerminalStrDepository;\r
+extern EFI_DEVICE_PATH_PROTOCOL   EndDevicePath[];\r
+extern EFI_GUID                   EfiLegacyDevOrderGuid;\r
+\r
+#endif\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootOption.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/BootOption.c
new file mode 100644 (file)
index 0000000..2d67e0b
--- /dev/null
@@ -0,0 +1,1685 @@
+/*++\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  BootOption.c\r
+  \r
+Abstract:\r
+\r
+  Provide boot option support for Application "BootMaint"\r
+\r
+  Include file system navigation, system handle selection\r
+\r
+  Boot option manipulation\r
+  \r
+Revision History\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+#include "BBSsupport.h"\r
+\r
+BM_MENU_ENTRY *\r
+BOpt_CreateMenuEntry (\r
+  UINTN           MenuType\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Create Menu Entry for future use, make all types together\r
+  in order to reduce code size\r
+\r
+Arguments:\r
+  MenuType            Use this parameter to identify current\r
+                      Menu type\r
+\r
+Returns:\r
+  NULL                Cannot allocate memory for current menu \r
+                      entry\r
+  Others              A valid pointer pointing to the allocated\r
+                      memory pool for current menu entry\r
+\r
+--*/\r
+{\r
+  BM_MENU_ENTRY *MenuEntry;\r
+  UINTN         ContextSize;\r
+\r
+  switch (MenuType) {\r
+  case BM_LOAD_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_LOAD_CONTEXT);\r
+    break;\r
+\r
+  case BM_FILE_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_FILE_CONTEXT);\r
+    break;\r
+\r
+  case BM_CONSOLE_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_CONSOLE_CONTEXT);\r
+    break;\r
+\r
+  case BM_TERMINAL_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_TERMINAL_CONTEXT);\r
+    break;\r
+\r
+  case BM_HANDLE_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_HANDLE_CONTEXT);\r
+    break;\r
+\r
+  case BM_LEGACY_DEV_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT);\r
+    break;\r
+\r
+  default:\r
+    ContextSize = 0;\r
+    break;\r
+\r
+  }\r
+\r
+  if (0 == ContextSize) {\r
+    return NULL;\r
+  }\r
+\r
+  MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY));\r
+  if (NULL == MenuEntry) {\r
+    return MenuEntry;\r
+  }\r
+\r
+  MenuEntry->VariableContext = AllocateZeroPool (ContextSize);\r
+  if (NULL == MenuEntry->VariableContext) {\r
+    SafeFreePool (MenuEntry);\r
+    MenuEntry = NULL;\r
+    return MenuEntry;\r
+  }\r
+\r
+  MenuEntry->Signature        = BM_MENU_ENTRY_SIGNATURE;\r
+  MenuEntry->ContextSelection = MenuType;\r
+  return MenuEntry;\r
+}\r
+\r
+VOID\r
+BOpt_DestroyMenuEntry (\r
+  BM_MENU_ENTRY         *MenuEntry\r
+  )\r
+/*++\r
+  Routine Description :\r
+    Destroy the menu entry passed in\r
+\r
+  Arguments :\r
+    The menu entry need to be destroyed\r
+\r
+  Returns :\r
+    None\r
+\r
+--*/\r
+{\r
+  BM_LOAD_CONTEXT           *LoadContext;\r
+  BM_FILE_CONTEXT           *FileContext;\r
+  BM_CONSOLE_CONTEXT        *ConsoleContext;\r
+  BM_TERMINAL_CONTEXT       *TerminalContext;\r
+  BM_HANDLE_CONTEXT         *HandleContext;\r
+  BM_LEGACY_DEVICE_CONTEXT  *LegacyDevContext;\r
+\r
+  //\r
+  //  Select by the type in Menu entry for current context type\r
+  //\r
+  switch (MenuEntry->ContextSelection) {\r
+  case BM_LOAD_CONTEXT_SELECT:\r
+    LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext;\r
+    SafeFreePool (LoadContext->FilePathList);\r
+    SafeFreePool (LoadContext->LoadOption);\r
+    SafeFreePool (LoadContext->OptionalData);\r
+    SafeFreePool (LoadContext);\r
+    break;\r
+\r
+  case BM_FILE_CONTEXT_SELECT:\r
+    FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+    if (!FileContext->IsRoot) {\r
+      SafeFreePool (FileContext->DevicePath);\r
+    } else {\r
+      if (FileContext->FHandle != NULL) {\r
+        FileContext->FHandle->Close (FileContext->FHandle);\r
+      }\r
+    }\r
+\r
+    SafeFreePool (FileContext->FileName);\r
+    SafeFreePool (FileContext->Info);\r
+    SafeFreePool (FileContext);\r
+    break;\r
+\r
+  case BM_CONSOLE_CONTEXT_SELECT:\r
+    ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext;\r
+    SafeFreePool (ConsoleContext->DevicePath);\r
+    SafeFreePool (ConsoleContext);\r
+    break;\r
+\r
+  case BM_TERMINAL_CONTEXT_SELECT:\r
+    TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext;\r
+    SafeFreePool (TerminalContext->DevicePath);\r
+    SafeFreePool (TerminalContext);\r
+    break;\r
+\r
+  case BM_HANDLE_CONTEXT_SELECT:\r
+    HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext;\r
+    SafeFreePool (HandleContext);\r
+    break;\r
+\r
+  case BM_LEGACY_DEV_CONTEXT_SELECT:\r
+    LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext;\r
+    SafeFreePool (LegacyDevContext);\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  SafeFreePool (MenuEntry->DisplayString);\r
+  if (NULL != MenuEntry->HelpString) {\r
+    SafeFreePool (MenuEntry->HelpString);\r
+  }\r
+\r
+  SafeFreePool (MenuEntry);\r
+}\r
+\r
+BM_MENU_ENTRY *\r
+BOpt_GetMenuEntry (\r
+  BM_MENU_OPTION      *MenuOption,\r
+  UINTN               MenuNumber\r
+  )\r
+/*++\r
+  Rountine Description :\r
+    Use this routine to get one particular menu entry in specified \r
+    menu\r
+\r
+  Arguments :\r
+    MenuOption        The menu that we will search \r
+\r
+    MenuNumber        The menunubmer that we want\r
+\r
+  Returns :\r
+    The desired menu entry\r
+\r
+--*/\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  UINTN           Index;\r
+  LIST_ENTRY      *List;\r
+\r
+  if (MenuNumber >= MenuOption->MenuNumber) {\r
+    return NULL;\r
+  }\r
+\r
+  List = MenuOption->Head.ForwardLink;\r
+  for (Index = 0; Index < MenuNumber; Index++) {\r
+    List = List->ForwardLink;\r
+  }\r
+\r
+  NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);\r
+\r
+  return NewMenuEntry;\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_FindFileSystem (\r
+  IN BMM_CALLBACK_DATA          *CallbackData\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Find file systems for current Extensible Firmware\r
+  Including Handles that support Simple File System\r
+  protocol, Load File protocol.\r
+\r
+  Building up the FileSystem Menu for user selection\r
+  All file system will be stored in FsOptionMenu \r
+  for future use.\r
+\r
+Arguments:\r
+  CallbackData           -   BMM context data\r
+\r
+Returns:\r
+  EFI_SUCCESS            -   Success find the file system\r
+  EFI_OUT_OF_RESOURCES   -   Can not create menu entry\r
+\r
+--*/\r
+{\r
+  UINTN                     NoSimpleFsHandles;\r
+  UINTN                     NoLoadFileHandles;\r
+  EFI_HANDLE                *SimpleFsHandle;\r
+  EFI_HANDLE                *LoadFileHandle;\r
+  UINT16                    *VolumeLabel;\r
+  EFI_BLOCK_IO_PROTOCOL     *BlkIo;\r
+  UINTN                     Index;\r
+  EFI_STATUS                Status;\r
+  BM_MENU_ENTRY             *MenuEntry;\r
+  BM_FILE_CONTEXT           *FileContext;\r
+  UINT16                    *TempStr;\r
+  UINTN                     OptionNumber;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINT16                    DeviceType;\r
+  BBS_BBS_DEVICE_PATH       BbsDevicePathNode;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  BOOLEAN                   RemovableMedia;\r
+\r
+\r
+  NoSimpleFsHandles = 0;\r
+  NoLoadFileHandles = 0;\r
+  OptionNumber      = 0;\r
+  InitializeListHead (&FsOptionMenu.Head);\r
+\r
+  //\r
+  // Locate Handles that support Simple File System protocol\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  NULL,\r
+                  &NoSimpleFsHandles,\r
+                  &SimpleFsHandle\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Find all the instances of the File System prototocol\r
+    //\r
+    for (Index = 0; Index < NoSimpleFsHandles; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      SimpleFsHandle[Index],\r
+                      &gEfiBlockIoProtocolGuid,\r
+                      (VOID**) &BlkIo\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // If no block IO exists assume it's NOT a removable media\r
+        //\r
+        RemovableMedia = FALSE;\r
+      } else {\r
+        //\r
+        // If block IO exists check to see if it's remobable media\r
+        //\r
+        RemovableMedia = BlkIo->Media->RemovableMedia; \r
+      }\r
+\r
+      //\r
+      // Allocate pool for this load option\r
+      //\r
+      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+      if (NULL == MenuEntry) {\r
+        SafeFreePool (SimpleFsHandle);    \r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+            \r
+      FileContext->Handle     = SimpleFsHandle[Index];\r
+      MenuEntry->OptionNumber = Index;\r
+      FileContext->FHandle    = EfiLibOpenRoot (FileContext->Handle);\r
+      if (!FileContext->FHandle) {\r
+        BOpt_DestroyMenuEntry (MenuEntry);\r
+        continue;\r
+      }\r
+\r
+      MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));\r
+      FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle);\r
+      FileContext->FileName = EfiStrDuplicate (L"\\");\r
+      FileContext->DevicePath = FileDevicePath (\r
+                                  FileContext->Handle,\r
+                                  FileContext->FileName\r
+                                  );\r
+      FileContext->IsDir            = TRUE;\r
+      FileContext->IsRoot           = TRUE;\r
+      FileContext->IsRemovableMedia = FALSE;\r
+      FileContext->IsLoadFile       = FALSE;\r
+\r
+      //\r
+      // Get current file system's Volume Label\r
+      //\r
+      if (FileContext->Info == NULL) {\r
+        VolumeLabel = L"NO FILE SYSTEM INFO";\r
+      } else {\r
+        if (FileContext->Info->VolumeLabel == NULL) {\r
+          VolumeLabel = L"NULL VOLUME LABEL";\r
+        } else {\r
+          VolumeLabel = FileContext->Info->VolumeLabel;\r
+          if (*VolumeLabel == 0x0000) {\r
+            VolumeLabel = L"NO VOLUME LABEL";\r
+          }\r
+        }\r
+      }\r
+\r
+      TempStr                   = MenuEntry->HelpString;\r
+      MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);\r
+      ASSERT (MenuEntry->DisplayString != NULL);\r
+      UnicodeSPrint (\r
+        MenuEntry->DisplayString,\r
+        MAX_CHAR,\r
+        L"%s, [%s]",\r
+        VolumeLabel,\r
+        TempStr\r
+        );\r
+      OptionNumber++;\r
+      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);      \r
+    }\r
+  }\r
+\r
+  if (NoSimpleFsHandles != 0) {\r
+    SafeFreePool (SimpleFsHandle);\r
+  }\r
+  //\r
+  // Searching for handles that support Load File protocol\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiLoadFileProtocolGuid,\r
+                  NULL,\r
+                  &NoLoadFileHandles,\r
+                  &LoadFileHandle\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index = 0; Index < NoLoadFileHandles; Index++) {\r
+      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+      if (NULL == MenuEntry) {\r
+        SafeFreePool (LoadFileHandle);    \r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      FileContext                   = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+      FileContext->IsRemovableMedia = FALSE;\r
+      FileContext->IsLoadFile       = TRUE;\r
+      FileContext->Handle           = LoadFileHandle[Index];\r
+      FileContext->IsRoot           = TRUE;\r
+\r
+      FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle);\r
+\r
+      MenuEntry->HelpString     = DevicePathToStr (FileContext->DevicePath);\r
+\r
+      TempStr                   = MenuEntry->HelpString;\r
+      MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);\r
+      ASSERT (MenuEntry->DisplayString != NULL);\r
+      UnicodeSPrint (\r
+        MenuEntry->DisplayString,\r
+        MAX_CHAR,\r
+        L"Load File [%s]",\r
+        TempStr\r
+        );\r
+\r
+      MenuEntry->OptionNumber = OptionNumber;\r
+      OptionNumber++;\r
+      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  if (NoLoadFileHandles != 0) {\r
+    SafeFreePool (LoadFileHandle);\r
+  }\r
+\r
+  //\r
+  // Add Legacy Boot Option Support Here\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiLegacyBiosProtocolGuid,\r
+                  NULL,\r
+                  (VOID**) &LegacyBios\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {\r
+      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+      if (NULL == MenuEntry) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      FileContext                       = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+      FileContext->IsRemovableMedia     = FALSE;\r
+      FileContext->IsLoadFile           = TRUE;\r
+      FileContext->IsBootLegacy         = TRUE;\r
+      DeviceType                        = (UINT16) Index;\r
+      BbsDevicePathNode.Header.Type     = BBS_DEVICE_PATH;\r
+      BbsDevicePathNode.Header.SubType  = BBS_BBS_DP;\r
+      SetDevicePathNodeLength (\r
+        &BbsDevicePathNode.Header,\r
+        sizeof (BBS_BBS_DEVICE_PATH)\r
+        );\r
+      BbsDevicePathNode.DeviceType  = DeviceType;\r
+      BbsDevicePathNode.StatusFlag  = 0;\r
+      BbsDevicePathNode.String[0]   = 0;\r
+      DevicePath = AppendDevicePathNode (\r
+                    EndDevicePath,\r
+                    (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode\r
+                    );\r
+\r
+      FileContext->DevicePath   = DevicePath;\r
+      MenuEntry->HelpString     = DevicePathToStr (FileContext->DevicePath);\r
+\r
+      TempStr                   = MenuEntry->HelpString;\r
+      MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);\r
+      ASSERT (MenuEntry->DisplayString != NULL);\r
+      UnicodeSPrint (\r
+        MenuEntry->DisplayString,\r
+        MAX_CHAR,\r
+        L"Boot Legacy [%s]",\r
+        TempStr\r
+        );\r
+      MenuEntry->OptionNumber = OptionNumber;\r
+      OptionNumber++;\r
+      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+    }\r
+  }\r
+  //\r
+  // Remember how many file system options are here\r
+  //\r
+  FsOptionMenu.MenuNumber = OptionNumber;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+BOpt_FreeMenu (\r
+  BM_MENU_OPTION        *FreeMenu\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Free resources allocated in Allocate Rountine\r
+\r
+Arguments:\r
+  FreeMenu        Menu to be freed\r
+\r
+Returns:\r
+  VOID\r
+  \r
+--*/\r
+{\r
+  BM_MENU_ENTRY *MenuEntry;\r
+  while (!IsListEmpty (&FreeMenu->Head)) {\r
+    MenuEntry = CR (\r
+                  FreeMenu->Head.ForwardLink,\r
+                  BM_MENU_ENTRY,\r
+                  Link,\r
+                  BM_MENU_ENTRY_SIGNATURE\r
+                  );\r
+    RemoveEntryList (&MenuEntry->Link);\r
+    BOpt_DestroyMenuEntry (MenuEntry);\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_FindFiles (\r
+  IN BMM_CALLBACK_DATA          *CallbackData,\r
+  IN BM_MENU_ENTRY              *MenuEntry\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Find files under current directory\r
+  All files and sub-directories in current directory\r
+  will be stored in DirectoryMenu for future use.\r
+\r
+Arguments:\r
+  FileOption   -- Pointer for Dir to explore\r
+\r
+Returns:\r
+  TRUE         -- Get files from current dir successfully\r
+  FALSE        -- Can't get files from current dir\r
+\r
+--*/\r
+{\r
+  EFI_FILE_HANDLE NewDir;\r
+  EFI_FILE_HANDLE Dir;\r
+  EFI_FILE_INFO   *DirInfo;\r
+  UINTN           BufferSize;\r
+  UINTN           DirBufferSize;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_FILE_CONTEXT *FileContext;\r
+  BM_FILE_CONTEXT *NewFileContext;\r
+  UINTN           Pass;\r
+  EFI_STATUS      Status;\r
+  UINTN           OptionNumber;\r
+\r
+  FileContext   = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+  Dir           = FileContext->FHandle;\r
+  OptionNumber  = 0;\r
+  //\r
+  // Open current directory to get files from it\r
+  //\r
+  Status = Dir->Open (\r
+                  Dir,\r
+                  &NewDir,\r
+                  FileContext->FileName,\r
+                  EFI_FILE_READ_ONLY,\r
+                  0\r
+                  );\r
+  if (!FileContext->IsRoot) {\r
+    Dir->Close (Dir);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DirInfo = EfiLibFileInfo (NewDir);\r
+  if (!DirInfo) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (!(DirInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  FileContext->DevicePath = FileDevicePath (\r
+                              FileContext->Handle,\r
+                              FileContext->FileName\r
+                              );\r
+\r
+  DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;\r
+  DirInfo       = AllocateZeroPool (DirBufferSize);\r
+  if (!DirInfo) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Get all files in current directory\r
+  // Pass 1 to get Directories\r
+  // Pass 2 to get files that are EFI images\r
+  //\r
+  for (Pass = 1; Pass <= 2; Pass++) {\r
+    NewDir->SetPosition (NewDir, 0);\r
+    for (;;) {\r
+      BufferSize  = DirBufferSize;\r
+      Status      = NewDir->Read (NewDir, &BufferSize, DirInfo);\r
+      if (EFI_ERROR (Status) || BufferSize == 0) {\r
+        break;\r
+      }\r
+\r
+      if ((DirInfo->Attribute & EFI_FILE_DIRECTORY && Pass == 2) ||\r
+          (!(DirInfo->Attribute & EFI_FILE_DIRECTORY) && Pass == 1)\r
+          ) {\r
+        //\r
+        // Pass 1 is for Directories\r
+        // Pass 2 is for file names\r
+        //\r
+        continue;\r
+      }\r
+\r
+      if (!(BOpt_IsEfiImageName (DirInfo->FileName) || DirInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
+        //\r
+        // Slip file unless it is a directory entry or a .EFI file\r
+        //\r
+        continue;\r
+      }\r
+\r
+      NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+      if (NULL == NewMenuEntry) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      NewFileContext          = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewFileContext->Handle  = FileContext->Handle;\r
+      NewFileContext->FileName = BOpt_AppendFileName (\r
+                                  FileContext->FileName,\r
+                                  DirInfo->FileName\r
+                                  );\r
+      NewFileContext->FHandle = NewDir;\r
+      NewFileContext->DevicePath = FileDevicePath (\r
+                                    NewFileContext->Handle,\r
+                                    NewFileContext->FileName\r
+                                    );\r
+      NewMenuEntry->HelpString = NULL;\r
+\r
+      MenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                        CallbackData,\r
+                                        FileOptionStrDepository\r
+                                        );\r
+\r
+      NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);\r
+\r
+      if (NewFileContext->IsDir) {\r
+        BufferSize                  = StrLen (DirInfo->FileName) * 2 + 6;\r
+        NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);\r
+\r
+        UnicodeSPrint (\r
+          NewMenuEntry->DisplayString,\r
+          BufferSize,\r
+          L"<%s>",\r
+          DirInfo->FileName\r
+          );\r
+\r
+      } else {\r
+        NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName);\r
+      }\r
+\r
+      NewFileContext->IsRoot            = FALSE;\r
+      NewFileContext->IsLoadFile        = FALSE;\r
+      NewFileContext->IsRemovableMedia  = FALSE;\r
+\r
+      NewMenuEntry->OptionNumber        = OptionNumber;\r
+      OptionNumber++;\r
+      InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  DirectoryMenu.MenuNumber = OptionNumber;\r
+  SafeFreePool (DirInfo);\r
+  return TRUE;\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_GetLegacyOptions (\r
+  VOID\r
+  )\r
+/*++\r
+Routine Description:\r
+  \r
+  Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().\r
+    \r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  The device info of legacy device.\r
+  \r
+--*/\r
+{\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_LEGACY_DEVICE_CONTEXT  *NewLegacyDevContext;\r
+  EFI_STATUS                Status;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINT16                    HddCount;\r
+  HDD_INFO                  *HddInfo;\r
+  UINT16                    BbsCount;\r
+  BBS_TABLE                 *BbsTable;\r
+  UINTN                     Index;\r
+  CHAR16                    DescString[100];\r
+  UINTN                     FDNum;\r
+  UINTN                     HDNum;\r
+  UINTN                     CDNum;\r
+  UINTN                     NETNum;\r
+  UINTN                     BEVNum;\r
+\r
+  NewMenuEntry  = NULL;\r
+  HddInfo       = NULL;\r
+  BbsTable      = NULL;\r
+  BbsCount      = 0;\r
+\r
+  //\r
+  // Initialize Bbs Table Context from BBS info data\r
+  //\r
+  InitializeListHead (&LegacyFDMenu.Head);\r
+  InitializeListHead (&LegacyHDMenu.Head);\r
+  InitializeListHead (&LegacyCDMenu.Head);\r
+  InitializeListHead (&LegacyNETMenu.Head);\r
+  InitializeListHead (&LegacyBEVMenu.Head);\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiLegacyBiosProtocolGuid,\r
+                  NULL,\r
+                  (VOID**) &LegacyBios\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = LegacyBios->GetBbsInfo (\r
+                          LegacyBios,\r
+                          &HddCount,\r
+                          &HddInfo,\r
+                          &BbsCount,\r
+                          &BbsTable\r
+                          );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  FDNum   = 0;\r
+  HDNum   = 0;\r
+  CDNum   = 0;\r
+  NETNum  = 0;\r
+  BEVNum  = 0;\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) ||\r
+        (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority) ||\r
+        (BBS_LOWEST_PRIORITY == BbsTable[Index].BootPriority)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      break;\r
+    }\r
+\r
+    NewLegacyDevContext           = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewLegacyDevContext->BbsTable = &BbsTable[Index];\r
+    NewLegacyDevContext->Index    = Index;\r
+    NewLegacyDevContext->BbsCount = BbsCount;\r
+    BdsBuildLegacyDevNameString (\r
+      &BbsTable[Index],\r
+      Index,\r
+      sizeof (DescString),\r
+      DescString\r
+      );\r
+    NewLegacyDevContext->Description = AllocateZeroPool (StrSize (DescString));\r
+    if (NULL == NewLegacyDevContext->Description) {\r
+      break;\r
+    }\r
+\r
+    CopyMem (NewLegacyDevContext->Description, DescString, StrSize (DescString));\r
+    NewMenuEntry->DisplayString = NewLegacyDevContext->Description;\r
+    NewMenuEntry->HelpString    = NULL;\r
+\r
+    switch (BbsTable[Index].DeviceType) {\r
+    case BBS_FLOPPY:\r
+      InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);\r
+      FDNum++;\r
+      break;\r
+\r
+    case BBS_HARDDISK:\r
+      InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);\r
+      HDNum++;\r
+      break;\r
+\r
+    case BBS_CDROM:\r
+      InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);\r
+      CDNum++;\r
+      break;\r
+\r
+    case BBS_EMBED_NETWORK:\r
+      InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);\r
+      NETNum++;\r
+      break;\r
+\r
+    case BBS_BEV_DEVICE:\r
+      InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);\r
+      BEVNum++;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index != BbsCount) {\r
+    BOpt_FreeLegacyOptions ();\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  LegacyFDMenu.MenuNumber   = FDNum;\r
+  LegacyHDMenu.MenuNumber   = HDNum;\r
+  LegacyCDMenu.MenuNumber   = CDNum;\r
+  LegacyNETMenu.MenuNumber  = NETNum;\r
+  LegacyBEVMenu.MenuNumber  = BEVNum;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+BOpt_FreeLegacyOptions (\r
+  VOID\r
+  )\r
+{\r
+  BOpt_FreeMenu (&LegacyFDMenu);\r
+  BOpt_FreeMenu (&LegacyHDMenu);\r
+  BOpt_FreeMenu (&LegacyCDMenu);\r
+  BOpt_FreeMenu (&LegacyNETMenu);\r
+  BOpt_FreeMenu (&LegacyBEVMenu);\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_GetBootOptions (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Build the BootOptionMenu according to BootOrder Variable.\r
+  This Routine will access the Boot#### to get EFI_LOAD_OPTION \r
+  \r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  The number of the Var Boot####\r
+  \r
+--*/\r
+{\r
+  UINTN                     Index;\r
+  UINT16                    BootString[10];\r
+  UINT8                     *LoadOptionFromVar;\r
+  UINT8                     *LoadOption;\r
+  UINTN                     BootOptionSize;\r
+  BOOLEAN                   BootNextFlag;\r
+  UINT16                    *BootOrderList;\r
+  UINTN                     BootOrderListSize;\r
+  UINT16                    *BootNext;\r
+  UINTN                     BootNextSize;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_LOAD_CONTEXT           *NewLoadContext;\r
+  UINT8                     *LoadOptionPtr;\r
+  UINTN                     StringSize;\r
+  UINTN                     OptionalDataSize;\r
+  UINT8                     *LoadOptionEnd;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINTN                     MenuCount;\r
+  UINT8                     *Ptr;\r
+\r
+  MenuCount         = 0;\r
+  BootOrderListSize = 0;\r
+  BootNextSize      = 0;\r
+  BootOrderList     = NULL;\r
+  BootNext          = NULL;\r
+  LoadOptionFromVar = NULL;\r
+  BOpt_FreeMenu (&BootOptionMenu);\r
+  InitializeListHead (&BootOptionMenu.Head);\r
+\r
+  //\r
+  // Get the BootOrder from the Var\r
+  //\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+\r
+  //\r
+  // Get the BootNext from the Var\r
+  //\r
+  BootNext = BdsLibGetVariableAndSize (\r
+              L"BootNext",\r
+              &gEfiGlobalVariableGuid,\r
+              &BootNextSize\r
+              );\r
+\r
+  if (BootNext) {\r
+    if (BootNextSize != sizeof (UINT16)) {\r
+      SafeFreePool (BootNext);\r
+      BootNext = NULL;\r
+    }\r
+  }\r
+\r
+  for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
+    UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);\r
+    //\r
+    //  Get all loadoptions from the VAR\r
+    //\r
+    LoadOptionFromVar = BdsLibGetVariableAndSize (\r
+                          BootString,\r
+                          &gEfiGlobalVariableGuid,\r
+                          &BootOptionSize\r
+                          );\r
+    if (!LoadOptionFromVar) {\r
+      continue;\r
+    }\r
+\r
+    LoadOption = AllocateZeroPool (BootOptionSize);\r
+    if (!LoadOption) {\r
+      continue;\r
+    }\r
+\r
+    CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize);\r
+    SafeFreePool (LoadOptionFromVar);\r
+\r
+    if (BootNext) {\r
+      BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);\r
+    } else {\r
+      BootNextFlag = FALSE;\r
+    }\r
+\r
+    if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) {\r
+      SafeFreePool (LoadOption);\r
+      continue;\r
+    }\r
+    //\r
+    // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.\r
+    // the buffer allocated already should be freed before returning.\r
+    //\r
+    NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewLoadContext                      = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    LoadOptionPtr                       = LoadOption;\r
+    LoadOptionEnd                       = LoadOption + BootOptionSize;\r
+\r
+    NewMenuEntry->OptionNumber          = BootOrderList[Index];\r
+    NewLoadContext->LoadOptionModified  = FALSE;\r
+    NewLoadContext->Deleted             = FALSE;\r
+    NewLoadContext->IsBootNext          = BootNextFlag;\r
+\r
+    //\r
+    // Is a Legacy Device?\r
+    //\r
+    Ptr = (UINT8 *) LoadOption;\r
+\r
+    //\r
+    // Attribute = *(UINT32 *)Ptr;\r
+    //\r
+    Ptr += sizeof (UINT32);\r
+\r
+    //\r
+    // FilePathSize = *(UINT16 *)Ptr;\r
+    //\r
+    Ptr += sizeof (UINT16);\r
+\r
+    //\r
+    // Description = (CHAR16 *)Ptr;\r
+    //\r
+    Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+    //\r
+    // Now Ptr point to Device Path\r
+    //\r
+    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+    if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
+      NewLoadContext->IsLegacy = TRUE;\r
+    } else {\r
+      NewLoadContext->IsLegacy = FALSE;\r
+    }\r
+    //\r
+    // LoadOption is a pointer type of UINT8\r
+    // for easy use with following LOAD_OPTION\r
+    // embedded in this struct\r
+    //\r
+    NewLoadContext->LoadOption      = LoadOption;\r
+    NewLoadContext->LoadOptionSize  = BootOptionSize;\r
+\r
+    NewLoadContext->Attributes      = *(UINT32 *) LoadOptionPtr;\r
+    NewLoadContext->IsActive        = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
+\r
+    NewLoadContext->ForceReconnect  = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+    LoadOptionPtr += sizeof (UINT32);\r
+\r
+    NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
+    LoadOptionPtr += sizeof (UINT16);\r
+\r
+    StringSize                  = StrSize ((UINT16 *) LoadOptionPtr);\r
+    NewLoadContext->Description = AllocateZeroPool (StringSize);\r
+    ASSERT (NewLoadContext->Description != NULL);\r
+    CopyMem (\r
+      NewLoadContext->Description,\r
+      (UINT16 *) LoadOptionPtr,\r
+      StringSize\r
+      );\r
+    NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+\r
+    LoadOptionPtr += StringSize;\r
+\r
+    NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);\r
+    ASSERT (NewLoadContext->FilePathList != NULL);\r
+    CopyMem (\r
+      NewLoadContext->FilePathList,\r
+      (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
+      NewLoadContext->FilePathListLength\r
+      );\r
+\r
+    NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+    NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                        CallbackData,\r
+                                        BootOptionStrDepository\r
+                                        );\r
+    NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+                                      CallbackData,\r
+                                      BootOptionHelpStrDepository\r
+                                      );\r
+    LoadOptionPtr += NewLoadContext->FilePathListLength;\r
+\r
+    if (LoadOptionPtr < LoadOptionEnd) {\r
+      OptionalDataSize = BootOptionSize -\r
+        sizeof (UINT32) -\r
+        sizeof (UINT16) -\r
+        StringSize -\r
+        NewLoadContext->FilePathListLength;\r
+\r
+      NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);\r
+      ASSERT (NewLoadContext->OptionalData != NULL);\r
+      CopyMem (\r
+        NewLoadContext->OptionalData,\r
+        LoadOptionPtr,\r
+        OptionalDataSize\r
+        );\r
+\r
+      NewLoadContext->OptionalDataSize = OptionalDataSize;\r
+    }\r
+\r
+    InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
+    MenuCount++;\r
+  }\r
+\r
+  SafeFreePool (BootNext);\r
+  SafeFreePool (BootOrderList);\r
+  BootOptionMenu.MenuNumber = MenuCount;\r
+  return MenuCount;\r
+}\r
+\r
+CHAR16 *\r
+BdsStrCpy (\r
+  OUT     CHAR16                    *Destination,\r
+  IN      CONST CHAR16              *Source\r
+  )\r
+{\r
+  CHAR16                            *ReturnValue;\r
+\r
+  //\r
+  // Destination cannot be NULL\r
+  //\r
+  ASSERT (Destination != NULL);\r
+\r
+  ReturnValue = Destination;\r
+  while (*Source) {\r
+    *(Destination++) = *(Source++);\r
+  }\r
+  *Destination = 0;\r
+  return ReturnValue;\r
+}\r
+\r
+CHAR16 *\r
+BOpt_AppendFileName (\r
+  IN  CHAR16  *Str1,\r
+  IN  CHAR16  *Str2\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Append file name to existing file name.\r
+\r
+Arguments:\r
+  Str1  -   existing file name\r
+  Str2  -   file name to be appended\r
+\r
+Returns:\r
+  Allocate a new string to hold the appended result.\r
+  Caller is responsible to free the returned string.\r
+\r
+--*/\r
+{\r
+  UINTN   Size1;\r
+  UINTN   Size2;\r
+  CHAR16  *Str;\r
+  CHAR16  *Ptr;\r
+  CHAR16  *LastSlash;\r
+\r
+  Size1 = StrSize (Str1);\r
+  Size2 = StrSize (Str2);\r
+  Str   = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));\r
+  ASSERT (Str != NULL);\r
+\r
+  StrCat (Str, Str1);\r
+  if (!((*Str == '\\') && (*(Str + 1) == 0))) {\r
+    StrCat (Str, L"\\");\r
+  }\r
+\r
+  StrCat (Str, Str2);\r
+\r
+  Ptr       = Str;\r
+  LastSlash = Str;\r
+  while (*Ptr != 0) {\r
+    if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) != 0) {\r
+      //\r
+      // Convert "\Name\..\" to "\"\r
+      // DO NOT convert the .. if it is at the end of the string. This will\r
+      // break the .. behavior in changing directories.\r
+      //\r
+      BdsStrCpy (LastSlash, Ptr + 3);\r
+      Ptr = LastSlash;\r
+    } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {\r
+      //\r
+      // Convert a "\.\" to a "\"\r
+      //\r
+      BdsStrCpy (Ptr, Ptr + 2);\r
+      Ptr = LastSlash;\r
+    } else if (*Ptr == '\\') {\r
+      LastSlash = Ptr;\r
+    }\r
+\r
+    Ptr++;\r
+  }\r
+\r
+  return Str;\r
+}\r
+\r
+BOOLEAN\r
+BOpt_IsEfiImageName (\r
+  IN UINT16  *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Check whether current FileName point to a valid \r
+  Efi Image File.\r
+\r
+Arguments:\r
+  FileName  -   File need to be checked.\r
+\r
+Returns:\r
+  TRUE  -   Is Efi Image\r
+  FALSE -   Not a valid Efi Image\r
+  \r
+--*/\r
+{\r
+  //\r
+  // Search for ".efi" extension\r
+  //\r
+  while (*FileName) {\r
+    if (FileName[0] == '.') {\r
+      if (FileName[1] == 'e' || FileName[1] == 'E') {\r
+        if (FileName[2] == 'f' || FileName[2] == 'F') {\r
+          if (FileName[3] == 'i' || FileName[3] == 'I') {\r
+            return TRUE;\r
+          } else if (FileName[3] == 0x0000) {\r
+            return FALSE;\r
+          }\r
+        } else if (FileName[2] == 0x0000) {\r
+          return FALSE;\r
+        }\r
+      } else if (FileName[1] == 0x0000) {\r
+        return FALSE;\r
+      }\r
+    }\r
+\r
+    FileName += 1;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+IsEfiAppReadFromFile (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINTN   *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  EFI_FILE_HANDLE   File;\r
+    \r
+  File = (EFI_FILE_HANDLE)FileHandle;\r
+  Status = File->SetPosition (File, FileOffset);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return File->Read (File, ReadSize, Buffer);\r
+}\r
+\r
+\r
+\r
+BOOLEAN\r
+BOpt_IsEfiApp (\r
+  IN EFI_FILE_HANDLE Dir,\r
+  IN UINT16          *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Check whether current FileName point to a valid Efi Application\r
+  \r
+Arguments:\r
+  Dir       -   Pointer to current Directory\r
+  FileName  -   Pointer to current File name.\r
+  \r
+Returns:\r
+  TRUE      -   Is a valid Efi Application\r
+  FALSE     -   not a valid Efi Application\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS                            Status;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;\r
+  EFI_FILE_HANDLE                       File;\r
+\r
+  Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  ZeroMem (&ImageContext, sizeof (ImageContext));\r
+  ImageContext.Handle    = (VOID *)File;\r
+  ImageContext.ImageRead = IsEfiAppReadFromFile;\r
+\r
+  Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  File->Close (File);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+ }\r
+\r
+\r
+EFI_STATUS\r
+BOpt_FindDrivers (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description\r
+  Find drivers that will be added as Driver#### variables from handles\r
+  in current system environment\r
+  All valid handles in the system except those consume SimpleFs, LoadFile\r
+  are stored in DriverMenu for future use.\r
+  \r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  EFI_SUCCESS\r
+  Others\r
+\r
+--*/\r
+{\r
+  UINTN                           NoDevicePathHandles;\r
+  EFI_HANDLE                      *DevicePathHandle;\r
+  UINTN                           Index;\r
+  EFI_STATUS                      Status;\r
+  BM_MENU_ENTRY                   *NewMenuEntry;\r
+  BM_HANDLE_CONTEXT               *NewHandleContext;\r
+  EFI_HANDLE                      CurHandle;\r
+  UINTN                           OptionNumber;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;\r
+  EFI_LOAD_FILE_PROTOCOL          *LoadFile;\r
+\r
+  SimpleFs  = NULL;\r
+  LoadFile  = NULL;\r
+\r
+  InitializeListHead (&DriverMenu.Head);\r
+\r
+  //\r
+  // At first, get all handles that support Device Path\r
+  // protocol which is the basic requirement for\r
+  // Driver####\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  NULL,\r
+                  &NoDevicePathHandles,\r
+                  &DevicePathHandle\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  OptionNumber = 0;\r
+  for (Index = 0; Index < NoDevicePathHandles; Index++) {\r
+    CurHandle = DevicePathHandle[Index];\r
+\r
+    //\r
+    //  Check whether this handle support\r
+    //  driver binding\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    CurHandle,\r
+                    &gEfiSimpleFileSystemProtocolGuid,\r
+                    (VOID**) &SimpleFs\r
+                    );\r
+    if (Status == EFI_SUCCESS) {\r
+      continue;\r
+    }\r
+\r
+    Status = gBS->HandleProtocol (\r
+                    CurHandle,\r
+                    &gEfiLoadFileProtocolGuid,\r
+                    (VOID**) &LoadFile\r
+                    );\r
+    if (Status == EFI_SUCCESS) {\r
+      continue;\r
+    }\r
+\r
+    NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewHandleContext              = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewHandleContext->Handle      = CurHandle;\r
+    NewHandleContext->DevicePath  = DevicePathFromHandle (CurHandle);\r
+    NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath);\r
+    NewMenuEntry->HelpString    = NULL;\r
+    NewMenuEntry->OptionNumber  = OptionNumber;\r
+    OptionNumber++;\r
+    InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);\r
+\r
+  }\r
+\r
+  DriverMenu.MenuNumber = OptionNumber;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+UINT16\r
+BOpt_GetBootOptionNumber (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Get the Option Number that does not used \r
+  \r
+Arguments:\r
+\r
+Returns:\r
+  The Option Number\r
+  \r
+--*/\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        *BootOrderList;\r
+  UINTN         BootOrderListSize;\r
+  UINT16        Number;\r
+  UINTN         Index;\r
+  UINTN         Index2;\r
+  BOOLEAN       Found;\r
+  CHAR16        StrTemp[100];\r
+  UINT16        *OptionBuffer;\r
+  UINTN         OptionSize;\r
+\r
+  BootOrderListSize = 0;\r
+  BootOrderList     = NULL;\r
+\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+  if (BootOrderList) {\r
+    //\r
+    // already have Boot####\r
+    //\r
+    // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);\r
+    //\r
+    for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
+      Found = TRUE;\r
+      for (Index2 = 0; Index2 < BootOptionMenu.MenuNumber; Index2++) {\r
+        NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index2);\r
+        if (Index == NewMenuEntry->OptionNumber) {\r
+          Found = FALSE;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Found) {\r
+          UnicodeSPrint (StrTemp, 100, L"Boot%04x", Index);\r
+          DEBUG((EFI_D_ERROR,"INdex= %s\n", StrTemp));\r
+       OptionBuffer = BdsLibGetVariableAndSize (\r
+                StrTemp,\r
+                &gEfiGlobalVariableGuid,\r
+                &OptionSize\r
+                );\r
+      if (NULL == OptionBuffer) \r
+        break;\r
+      }\r
+    }\r
+    //\r
+    // end for Index\r
+    //\r
+    Number = (UINT16) Index;\r
+  } else {\r
+    //\r
+    // No Boot####\r
+    //\r
+    Number = 0;\r
+  }\r
+\r
+  return Number;\r
+}\r
+\r
+UINT16\r
+BOpt_GetDriverOptionNumber (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Get the Option Number that does not used \r
+  \r
+Arguments:\r
+\r
+Returns:\r
+  The Option Number\r
+  \r
+--*/\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        *DriverOrderList;\r
+  UINTN         DriverOrderListSize;\r
+  UINT16        Number;\r
+  UINTN         Index;\r
+  UINTN         Index2;\r
+  BOOLEAN       Found;\r
+\r
+  DriverOrderListSize = 0;\r
+  DriverOrderList     = NULL;\r
+\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+  if (DriverOrderList) {\r
+    //\r
+    // already have Driver####\r
+    //\r
+    // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);\r
+    //\r
+    for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
+      Found = TRUE;\r
+      for (Index2 = 0; Index2 < DriverOptionMenu.MenuNumber; Index2++) {\r
+        NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index2);\r
+        if (Index == NewMenuEntry->OptionNumber) {\r
+          Found = FALSE;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Found) {\r
+        break;\r
+      }\r
+    }\r
+    //\r
+    // end for Index\r
+    //\r
+    Number = (UINT16) Index;\r
+  } else {\r
+    //\r
+    // No Driver####\r
+    //\r
+    Number = 0;\r
+  }\r
+\r
+  return Number;\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_GetDriverOptions (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Build up all DriverOptionMenu\r
+  \r
+Arguments:\r
+\r
+Returns:\r
+  The Option Number\r
+  \r
+--*/\r
+{\r
+  UINTN           Index;\r
+  UINT16          DriverString[12];\r
+  UINT8           *LoadOptionFromVar;\r
+  UINT8           *LoadOption;\r
+  UINTN           DriverOptionSize;\r
+\r
+  UINT16          *DriverOrderList;\r
+  UINTN           DriverOrderListSize;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT8           *LoadOptionPtr;\r
+  UINTN           StringSize;\r
+  UINTN           OptionalDataSize;\r
+  UINT8           *LoadOptionEnd;\r
+\r
+  DriverOrderListSize = 0;\r
+  DriverOrderList     = NULL;\r
+  DriverOptionSize    = 0;\r
+  LoadOptionFromVar   = NULL;\r
+  BOpt_FreeMenu (&DriverOptionMenu);\r
+  InitializeListHead (&DriverOptionMenu.Head);\r
+  //\r
+  // Get the DriverOrder from the Var\r
+  //\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+\r
+  for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
+    UnicodeSPrint (\r
+      DriverString,\r
+      sizeof (DriverString),\r
+      L"Driver%04x",\r
+      DriverOrderList[Index]\r
+      );\r
+    //\r
+    //  Get all loadoptions from the VAR\r
+    //\r
+    LoadOptionFromVar = BdsLibGetVariableAndSize (\r
+                          DriverString,\r
+                          &gEfiGlobalVariableGuid,\r
+                          &DriverOptionSize\r
+                          );\r
+    if (!LoadOptionFromVar) {\r
+      continue;\r
+    }\r
+\r
+    LoadOption = AllocateZeroPool (DriverOptionSize);\r
+    if (!LoadOption) {\r
+      continue;\r
+    }\r
+\r
+    CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize);\r
+    SafeFreePool (LoadOptionFromVar);\r
+\r
+    NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewLoadContext                      = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    LoadOptionPtr                       = LoadOption;\r
+    LoadOptionEnd                       = LoadOption + DriverOptionSize;\r
+    NewMenuEntry->OptionNumber          = DriverOrderList[Index];\r
+    NewLoadContext->LoadOptionModified  = FALSE;\r
+    NewLoadContext->Deleted             = FALSE;\r
+    NewLoadContext->IsLegacy            = FALSE;\r
+\r
+    //\r
+    // LoadOption is a pointer type of UINT8\r
+    // for easy use with following LOAD_OPTION\r
+    // embedded in this struct\r
+    //\r
+    NewLoadContext->LoadOption      = LoadOption;\r
+    NewLoadContext->LoadOptionSize  = DriverOptionSize;\r
+\r
+    NewLoadContext->Attributes      = *(UINT32 *) LoadOptionPtr;\r
+    NewLoadContext->IsActive        = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
+\r
+    NewLoadContext->ForceReconnect  = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+    LoadOptionPtr += sizeof (UINT32);\r
+\r
+    NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
+    LoadOptionPtr += sizeof (UINT16);\r
+\r
+    StringSize                  = StrSize ((UINT16 *) LoadOptionPtr);\r
+    NewLoadContext->Description = AllocateZeroPool (StringSize);\r
+    ASSERT (NewLoadContext->Description != NULL);\r
+    CopyMem (\r
+      NewLoadContext->Description,\r
+      (UINT16 *) LoadOptionPtr,\r
+      StringSize\r
+      );\r
+    NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+\r
+    LoadOptionPtr += StringSize;\r
+\r
+    NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);\r
+    ASSERT (NewLoadContext->FilePathList != NULL);\r
+    CopyMem (\r
+      NewLoadContext->FilePathList,\r
+      (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
+      NewLoadContext->FilePathListLength\r
+      );\r
+\r
+    NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+    NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                        CallbackData,\r
+                                        DriverOptionStrDepository\r
+                                        );\r
+    NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+                                      CallbackData,\r
+                                      DriverOptionHelpStrDepository\r
+                                      );\r
+    LoadOptionPtr += NewLoadContext->FilePathListLength;\r
+\r
+    if (LoadOptionPtr < LoadOptionEnd) {\r
+      OptionalDataSize = DriverOptionSize -\r
+        sizeof (UINT32) -\r
+        sizeof (UINT16) -\r
+        StringSize -\r
+        NewLoadContext->FilePathListLength;\r
+\r
+      NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);\r
+      ASSERT (NewLoadContext->OptionalData != NULL);\r
+      CopyMem (\r
+        NewLoadContext->OptionalData,\r
+        LoadOptionPtr,\r
+        OptionalDataSize\r
+        );\r
+\r
+      NewLoadContext->OptionalDataSize = OptionalDataSize;\r
+    }\r
+\r
+    InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
+\r
+  }\r
+\r
+  SafeFreePool (DriverOrderList);\r
+  DriverOptionMenu.MenuNumber = Index;\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+VOID\r
+SafeFreePool (\r
+  IN VOID    *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Wrap original FreePool gBS call\r
+  in order to decrease code length\r
+  \r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+  if (Buffer != NULL) {\r
+    gBS->FreePool (Buffer);\r
+    Buffer = NULL;\r
+  }\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/ConsoleOption.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/ConsoleOption.c
new file mode 100644 (file)
index 0000000..297c2cf
--- /dev/null
@@ -0,0 +1,840 @@
+/*++\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+    ConsoleOption.c\r
+    \r
+Abstract:\r
+\r
+    handles console redirection from boot manager\r
+\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_DEVICE_PATH_PROTOCOL  *\r
+DevicePathInstanceDup (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevPath\r
+  );\r
+\r
+EFI_STATUS\r
+UpdateComAttributeFromVariable (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  );\r
+\r
+EFI_STATUS\r
+ChangeTerminalDevicePath (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  BOOLEAN                   ChangeTerminal\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node1;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  UART_DEVICE_PATH          *Uart;\r
+  UART_DEVICE_PATH          *Uart1;\r
+  UINTN                     Com;\r
+  UINT32                    Match;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+\r
+  Match = EISA_PNP_ID (0x0501);\r
+  Node  = DevicePath;\r
+  Node  = NextDevicePathNode (Node);\r
+  Com   = 0;\r
+  while (!IsDevicePathEnd (Node)) {\r
+    if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+      Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+      if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+        CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
+      }\r
+    }\r
+\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+      Uart = (UART_DEVICE_PATH *) Node;\r
+      CopyMem (\r
+        &Uart->BaudRate,\r
+        &NewTerminalContext->BaudRate,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->DataBits,\r
+        &NewTerminalContext->DataBits,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->Parity,\r
+        &NewTerminalContext->Parity,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->StopBits,\r
+        &NewTerminalContext->StopBits,\r
+        sizeof (UINT8)\r
+        );\r
+      //\r
+      // Change the device path in the ComPort\r
+      //\r
+      if (ChangeTerminal) {\r
+        Node1 = NewTerminalContext->DevicePath;\r
+        Node1 = NextDevicePathNode (Node1);\r
+        while (!IsDevicePathEnd (Node1)) {\r
+          if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) {\r
+            Uart1 = (UART_DEVICE_PATH *) Node1;\r
+            CopyMem (\r
+              &Uart1->BaudRate,\r
+              &NewTerminalContext->BaudRate,\r
+              sizeof (UINT64)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->DataBits,\r
+              &NewTerminalContext->DataBits,\r
+              sizeof (UINT8)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->Parity,\r
+              &NewTerminalContext->Parity,\r
+              sizeof (UINT8)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->StopBits,\r
+              &NewTerminalContext->StopBits,\r
+              sizeof (UINT8)\r
+              );\r
+            break;\r
+          }\r
+          //\r
+          // end if\r
+          //\r
+          Node1 = NextDevicePathNode (Node1);\r
+        }\r
+        //\r
+        // end while\r
+        //\r
+        break;\r
+      }\r
+    }\r
+\r
+    Node = NextDevicePathNode (Node);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+VOID\r
+ChangeVariableDevicePath (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  UART_DEVICE_PATH          *Uart;\r
+  UINTN                     Com;\r
+  UINT32                    Match;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+\r
+  Match = EISA_PNP_ID (0x0501);\r
+  Node  = DevicePath;\r
+  Node  = NextDevicePathNode (Node);\r
+  Com   = 0;\r
+  while (!IsDevicePathEnd (Node)) {\r
+    if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+      Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+      if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+        CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
+      }\r
+    }\r
+\r
+    if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+      NewMenuEntry = BOpt_GetMenuEntry (\r
+                      &TerminalMenu,\r
+                      Com\r
+                      );\r
+      NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      Uart                = (UART_DEVICE_PATH *) Node;\r
+      CopyMem (\r
+        &Uart->BaudRate,\r
+        &NewTerminalContext->BaudRate,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->DataBits,\r
+        &NewTerminalContext->DataBits,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->Parity,\r
+        &NewTerminalContext->Parity,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->StopBits,\r
+        &NewTerminalContext->StopBits,\r
+        sizeof (UINT8)\r
+        );\r
+    }\r
+\r
+    Node = NextDevicePathNode (Node);\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+BOOLEAN\r
+IsTerminalDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+  OUT TYPE_OF_TERMINAL         *Termi,\r
+  OUT UINTN                    *Com\r
+  );\r
+\r
+EFI_STATUS\r
+LocateSerialIo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Build a list containing all serial devices \r
+  \r
+Arguments:\r
+  \r
+Returns:\r
+  \r
+--*/\r
+{\r
+  UINT8                     *Ptr;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  UINTN                     NoHandles;\r
+  EFI_HANDLE                *Handles;\r
+  EFI_STATUS                Status;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINT32                    Match;\r
+  EFI_SERIAL_IO_PROTOCOL    *SerialIo;\r
+  EFI_DEVICE_PATH_PROTOCOL  *OutDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *InpDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ErrDevicePath;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;\r
+  VENDOR_DEVICE_PATH        Vendor;\r
+  //\r
+  // Get all handles that have SerialIo protocol installed\r
+  //\r
+  InitializeListHead (&TerminalMenu.Head);\r
+  TerminalMenu.MenuNumber = 0;\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiSerialIoProtocolGuid,\r
+                  NULL,\r
+                  &NoHandles,\r
+                  &Handles\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // No serial ports present\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  for (Index = 0; Index < NoHandles; Index++) {\r
+    //\r
+    // Check to see whether the handle has DevicePath Protocol installed\r
+    //\r
+    gBS->HandleProtocol (\r
+          Handles[Index],\r
+          &gEfiDevicePathProtocolGuid,\r
+          (VOID**) &DevicePath\r
+          );\r
+    Ptr = (UINT8 *) DevicePath;\r
+    while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+      Ptr++;\r
+    }\r
+\r
+    Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+    Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+    Match = EISA_PNP_ID (0x0501);\r
+\r
+    if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+      NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);\r
+      if (!NewMenuEntry) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));\r
+      NewTerminalContext->DevicePath = DevicePathInstanceDup (DevicePath);\r
+      //\r
+      // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!\r
+      // coz' the misc data for each platform is not correct, actually it's the device path stored in\r
+      // datahub which is not completed, so a searching for end of device path will enter a\r
+      // dead-loop.\r
+      //\r
+      NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);\r
+      if (NULL == NewMenuEntry->DisplayString) {\r
+        NewMenuEntry->DisplayString = DevicePathToStr (DevicePath);\r
+      }\r
+\r
+      NewMenuEntry->HelpString = NULL;\r
+\r
+      gBS->HandleProtocol (\r
+            Handles[Index],\r
+            &gEfiSerialIoProtocolGuid,\r
+            (VOID**) &SerialIo\r
+            );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->BaudRate,\r
+        &SerialIo->Mode->BaudRate,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->DataBits,\r
+        &SerialIo->Mode->DataBits,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->Parity,\r
+        &SerialIo->Mode->Parity,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->StopBits,\r
+        &SerialIo->Mode->StopBits,\r
+        sizeof (UINT8)\r
+        );\r
+      InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);\r
+      TerminalMenu.MenuNumber++;\r
+    }\r
+  }\r
+  //\r
+  // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var\r
+  //\r
+  OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
+  InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
+  ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
+  if (OutDevicePath) {\r
+    UpdateComAttributeFromVariable (OutDevicePath);\r
+  }\r
+\r
+  if (InpDevicePath) {\r
+    UpdateComAttributeFromVariable (InpDevicePath);\r
+  }\r
+\r
+  if (ErrDevicePath) {\r
+    UpdateComAttributeFromVariable (ErrDevicePath);\r
+  }\r
+\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewTerminalContext                = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    NewTerminalContext->TerminalType  = 0;\r
+    NewTerminalContext->IsConIn       = FALSE;\r
+    NewTerminalContext->IsConOut      = FALSE;\r
+    NewTerminalContext->IsStdErr      = FALSE;\r
+\r
+    Vendor.Header.Type                = MESSAGING_DEVICE_PATH;\r
+    Vendor.Header.SubType             = MSG_VENDOR_DP;\r
+\r
+    for (Index2 = 0; Index2 < 4; Index2++) {\r
+      CopyMem (&Vendor.Guid, &Guid[Index2], sizeof (EFI_GUID));\r
+      SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
+      NewDevicePath = AppendDevicePathNode (\r
+                        NewTerminalContext->DevicePath,\r
+                        (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
+                        );\r
+      SafeFreePool (NewMenuEntry->HelpString);\r
+      //\r
+      // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);\r
+      // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;\r
+      //\r
+      NewMenuEntry->HelpString = NULL;\r
+\r
+      if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {\r
+        NewTerminalContext->IsConOut      = TRUE;\r
+        NewTerminalContext->TerminalType  = (UINT8) Index2;\r
+      }\r
+\r
+      if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {\r
+        NewTerminalContext->IsConIn       = TRUE;\r
+        NewTerminalContext->TerminalType  = (UINT8) Index2;\r
+      }\r
+\r
+      if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) {\r
+        NewTerminalContext->IsStdErr      = TRUE;\r
+        NewTerminalContext->TerminalType  = (UINT8) Index2;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+UpdateComAttributeFromVariable (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Update Com Ports attributes from DevicePath\r
+  \r
+Arguments:\r
+  DevicePath  -   DevicePath that contains Com ports\r
+  \r
+Returns:\r
+  \r
+--*/\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  EFI_DEVICE_PATH_PROTOCOL  *SerialNode;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  UART_DEVICE_PATH          *Uart;\r
+  UART_DEVICE_PATH          *Uart1;\r
+  UINT32                    Match;\r
+  UINTN                     TerminalNumber;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  UINTN                     Index;\r
+\r
+  Match           = EISA_PNP_ID (0x0501);\r
+  Node            = DevicePath;\r
+  Node            = NextDevicePathNode (Node);\r
+  TerminalNumber  = 0;\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    while (!IsDevicePathEnd (Node)) {\r
+      if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+        Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+        if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+          CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));\r
+        }\r
+      }\r
+\r
+      if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+        Uart          = (UART_DEVICE_PATH *) Node;\r
+        NewMenuEntry  = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);\r
+        if (NULL == NewMenuEntry) {\r
+          return EFI_NOT_FOUND;\r
+        }\r
+\r
+        NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+        CopyMem (\r
+          &NewTerminalContext->BaudRate,\r
+          &Uart->BaudRate,\r
+          sizeof (UINT64)\r
+          );\r
+\r
+        CopyMem (\r
+          &NewTerminalContext->DataBits,\r
+          &Uart->DataBits,\r
+          sizeof (UINT8)\r
+          );\r
+\r
+        CopyMem (\r
+          &NewTerminalContext->Parity,\r
+          &Uart->Parity,\r
+          sizeof (UINT8)\r
+          );\r
+\r
+        CopyMem (\r
+          &NewTerminalContext->StopBits,\r
+          &Uart->StopBits,\r
+          sizeof (UINT8)\r
+          );\r
+\r
+        SerialNode  = NewTerminalContext->DevicePath;\r
+        SerialNode  = NextDevicePathNode (SerialNode);\r
+        while (!IsDevicePathEnd (SerialNode)) {\r
+          if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {\r
+            //\r
+            // Update following device paths according to\r
+            // previous acquired uart attributes\r
+            //\r
+            Uart1 = (UART_DEVICE_PATH *) SerialNode;\r
+            CopyMem (\r
+              &Uart1->BaudRate,\r
+              &NewTerminalContext->BaudRate,\r
+              sizeof (UINT64)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->DataBits,\r
+              &NewTerminalContext->DataBits,\r
+              sizeof (UINT8)\r
+              );\r
+            CopyMem (\r
+              &Uart1->Parity,\r
+              &NewTerminalContext->Parity,\r
+              sizeof (UINT8)\r
+              );\r
+            CopyMem (\r
+              &Uart1->StopBits,\r
+              &NewTerminalContext->StopBits,\r
+              sizeof (UINT8)\r
+              );\r
+\r
+            break;\r
+          }\r
+\r
+          SerialNode = NextDevicePathNode (SerialNode);\r
+        }\r
+        //\r
+        // end while\r
+        //\r
+      }\r
+\r
+      Node = NextDevicePathNode (Node);\r
+    }\r
+    //\r
+    // end while\r
+    //\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+DevicePathInstanceDup (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevPath\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Function creates a device path data structure that identically matches the \r
+  device path passed in.\r
+\r
+Arguments:\r
+  DevPath      - A pointer to a device path data structure.\r
+\r
+Returns:\r
+\r
+  The new copy of DevPath is created to identically match the input.  \r
+  Otherwise, NULL is returned.\r
+\r
+--*/\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevPath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Temp;\r
+  UINT8                     *Ptr;\r
+  UINTN                     Size;\r
+\r
+  //\r
+  // get the size of an instance from the input\r
+  //\r
+  Temp            = DevPath;\r
+  DevicePathInst  = GetNextDevicePathInstance (&Temp, &Size);\r
+\r
+  //\r
+  // Make a copy and set proper end type\r
+  //\r
+  NewDevPath = NULL;\r
+  if (Size) {\r
+    NewDevPath = AllocateZeroPool (Size);\r
+    ASSERT (NewDevPath != NULL);\r
+  }\r
+\r
+  if (NewDevPath) {\r
+    CopyMem (NewDevPath, DevicePathInst, Size);\r
+    Ptr = (UINT8 *) NewDevPath;\r
+    Ptr += Size - sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+    Temp = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+    SetDevicePathEndNode (Temp);\r
+  }\r
+\r
+  return NewDevPath;\r
+}\r
+\r
+EFI_STATUS\r
+GetConsoleMenu (\r
+  IN UINTN              ConsoleMenuType\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *AllDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *MultiDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
+  UINTN                     Size;\r
+  UINTN                     AllCount;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_CONSOLE_CONTEXT        *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  TYPE_OF_TERMINAL          Terminal;\r
+  BM_MENU_ENTRY             *NewTerminalMenuEntry;\r
+  UINTN                     Com;\r
+  BM_MENU_OPTION            *ConsoleMenu;\r
+\r
+  DevicePath    = NULL;\r
+  AllDevicePath = NULL;\r
+  AllCount      = 0;\r
+  switch (ConsoleMenuType) {\r
+  case BM_CONSOLE_IN_CONTEXT_SELECT:\r
+    ConsoleMenu = &ConsoleInpMenu;\r
+    DevicePath = EfiLibGetVariable (\r
+                  L"ConIn",\r
+                  &gEfiGlobalVariableGuid\r
+                  );\r
+\r
+    AllDevicePath = EfiLibGetVariable (\r
+                      L"ConInDev",\r
+                      &gEfiGlobalVariableGuid\r
+                      );\r
+    break;\r
+\r
+  case BM_CONSOLE_OUT_CONTEXT_SELECT:\r
+    ConsoleMenu = &ConsoleOutMenu;\r
+    DevicePath = EfiLibGetVariable (\r
+                  L"ConOut",\r
+                  &gEfiGlobalVariableGuid\r
+                  );\r
+\r
+    AllDevicePath = EfiLibGetVariable (\r
+                      L"ConOutDev",\r
+                      &gEfiGlobalVariableGuid\r
+                      );\r
+    break;\r
+\r
+  case BM_CONSOLE_ERR_CONTEXT_SELECT:\r
+    ConsoleMenu = &ConsoleErrMenu;\r
+    DevicePath = EfiLibGetVariable (\r
+                  L"ErrOut",\r
+                  &gEfiGlobalVariableGuid\r
+                  );\r
+\r
+    AllDevicePath = EfiLibGetVariable (\r
+                      L"ErrOutDev",\r
+                      &gEfiGlobalVariableGuid\r
+                      );\r
+    break;\r
+\r
+  default:\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (NULL == AllDevicePath) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  InitializeListHead (&ConsoleMenu->Head);\r
+\r
+  AllCount                = EfiDevicePathInstanceCount (AllDevicePath);\r
+  ConsoleMenu->MenuNumber = 0;\r
+  //\r
+  // Following is menu building up for Console Out Devices\r
+  //\r
+  MultiDevicePath = AllDevicePath;\r
+  Index2          = 0;\r
+  for (Index = 0; Index < AllCount; Index++) {\r
+    DevicePathInst  = GetNextDevicePathInstance (&MultiDevicePath, &Size);\r
+\r
+    NewMenuEntry    = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewConsoleContext             = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewMenuEntry->OptionNumber    = Index2;\r
+\r
+    NewConsoleContext->DevicePath = DevicePathInstanceDup (DevicePathInst);\r
+    NewMenuEntry->DisplayString   = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);\r
+    if (NULL == NewMenuEntry->DisplayString) {\r
+      NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath);\r
+    }\r
+\r
+    NewConsoleContext->IsTerminal = IsTerminalDevicePath (\r
+                                      NewConsoleContext->DevicePath,\r
+                                      &Terminal,\r
+                                      &Com\r
+                                      );\r
+\r
+    NewConsoleContext->IsActive = BdsLibMatchDevicePaths (\r
+                                    DevicePath,\r
+                                    NewConsoleContext->DevicePath\r
+                                    );\r
+    NewTerminalMenuEntry  = NULL;\r
+    NewTerminalContext    = NULL;\r
+\r
+    if (NewConsoleContext->IsTerminal) {\r
+      BOpt_DestroyMenuEntry (NewMenuEntry);\r
+    } else {\r
+      Index2++;\r
+      ConsoleMenu->MenuNumber++;\r
+      InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetAllConsoles (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+Arguments:\r
+  \r
+Returns:\r
+  EFI_SUCCESS \r
+  Others\r
+  \r
+--*/\r
+{\r
+  GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);\r
+  GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);\r
+  GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FreeAllConsoles (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+Arguments:\r
+  \r
+Returns:\r
+  EFI_SUCCESS \r
+  Others\r
+  \r
+--*/\r
+{\r
+  BOpt_FreeMenu (&ConsoleOutMenu);\r
+  BOpt_FreeMenu (&ConsoleInpMenu);\r
+  BOpt_FreeMenu (&ConsoleErrMenu);\r
+  BOpt_FreeMenu (&TerminalMenu);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+IsTerminalDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+  OUT TYPE_OF_TERMINAL         *Termi,\r
+  OUT UINTN                    *Com\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Test whether DevicePath is a valid Terminal\r
+\r
+Arguments:\r
+  DevicePath  -   DevicePath to be checked\r
+  Termi       -   If is terminal, give its type\r
+  Com         -   If is Com Port, give its type\r
+  \r
+Returns:\r
+  TRUE        -   If DevicePath point to a Terminal\r
+  FALSE\r
+  \r
+--*/\r
+{\r
+  UINT8                 *Ptr;\r
+  BOOLEAN               IsTerminal;\r
+  VENDOR_DEVICE_PATH    *Vendor;\r
+  ACPI_HID_DEVICE_PATH  *Acpi;\r
+  UINT32                Match;\r
+  EFI_GUID              TempGuid;\r
+\r
+  IsTerminal = FALSE;\r
+\r
+  //\r
+  // Parse the Device Path, should be change later!!!\r
+  //\r
+  Ptr = (UINT8 *) DevicePath;\r
+  while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+    Ptr++;\r
+  }\r
+\r
+  Ptr     = Ptr - sizeof (VENDOR_DEVICE_PATH);\r
+  Vendor  = (VENDOR_DEVICE_PATH *) Ptr;\r
+\r
+  //\r
+  // There are four kinds of Terminal types\r
+  // check to see whether this devicepath\r
+  // is one of that type\r
+  //\r
+  CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID));\r
+\r
+  if (CompareGuid (&TempGuid, &Guid[0])) {\r
+    *Termi      = PC_ANSI;\r
+    IsTerminal  = TRUE;\r
+  } else {\r
+    if (CompareGuid (&TempGuid, &Guid[1])) {\r
+      *Termi      = VT_100;\r
+      IsTerminal  = TRUE;\r
+    } else {\r
+      if (CompareGuid (&TempGuid, &Guid[2])) {\r
+        *Termi      = VT_100_PLUS;\r
+        IsTerminal  = TRUE;\r
+      } else {\r
+        if (CompareGuid (&TempGuid, &Guid[3])) {\r
+          *Termi      = VT_UTF8;\r
+          IsTerminal  = TRUE;\r
+        } else {\r
+          IsTerminal = FALSE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (!IsTerminal) {\r
+    return FALSE;\r
+  }\r
+\r
+  Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+  Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+  Match = EISA_PNP_ID (0x0501);\r
+  if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+    CopyMem (Com, &Acpi->UID, sizeof (UINT32));\r
+  } else {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Data.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Data.c
new file mode 100644 (file)
index 0000000..196bbe2
--- /dev/null
@@ -0,0 +1,324 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  Data.c\r
+    \r
+Abstract:\r
+\r
+  Define some data used for Boot Maint\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_HII_UPDATE_DATA *UpdateData;\r
+STRING_DEPOSITORY   *FileOptionStrDepository;\r
+STRING_DEPOSITORY   *ConsoleOptionStrDepository;\r
+STRING_DEPOSITORY   *BootOptionStrDepository;\r
+STRING_DEPOSITORY   *BootOptionHelpStrDepository;\r
+STRING_DEPOSITORY   *DriverOptionStrDepository;\r
+STRING_DEPOSITORY   *DriverOptionHelpStrDepository;\r
+STRING_DEPOSITORY   *TerminalStrDepository;\r
+\r
+//\r
+// Terminal type string token storage\r
+//\r
+UINT16              TerminalType[] = {\r
+  STRING_TOKEN(STR_COM_TYPE_0),\r
+  STRING_TOKEN(STR_COM_TYPE_1),\r
+  STRING_TOKEN(STR_COM_TYPE_2),\r
+  STRING_TOKEN(STR_COM_TYPE_3),\r
+};\r
+\r
+//\r
+// File system selection menu\r
+//\r
+BM_MENU_OPTION      FsOptionMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Console Input Device Selection Menu\r
+//\r
+BM_MENU_OPTION      ConsoleInpMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Console Output Device Selection Menu\r
+//\r
+BM_MENU_OPTION      ConsoleOutMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Error Output Device Selection Menu\r
+//\r
+BM_MENU_OPTION      ConsoleErrMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Boot Option from variable Menu\r
+//\r
+BM_MENU_OPTION      BootOptionMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Driver Option from variable menu\r
+//\r
+BM_MENU_OPTION      DriverOptionMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Legacy FD Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION      LegacyFDMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Legacy HD Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION      LegacyHDMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Legacy CD Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION      LegacyCDMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Legacy NET Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION      LegacyNETMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Legacy NET Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION      LegacyBEVMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Files and sub-directories in current directory menu\r
+//\r
+BM_MENU_OPTION      DirectoryMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Handles in current system selection menu\r
+//\r
+BM_MENU_OPTION      DriverMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+BM_MENU_OPTION      TerminalMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  { NULL, NULL},\r
+  0\r
+};\r
+\r
+//\r
+// Value and string token correspondency for BaudRate\r
+//\r
+COM_ATTR            BaudRateList[19] = {\r
+  {\r
+    115200,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_0)\r
+  },\r
+  {\r
+    57600,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_1)\r
+  },\r
+  {\r
+    38400,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_2)\r
+  },\r
+  {\r
+    19200,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_3)\r
+  },\r
+  {\r
+    9600,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_4)\r
+  },\r
+  {\r
+    7200,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_5)\r
+  },\r
+  {\r
+    4800,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_6)\r
+  },\r
+  {\r
+    3600,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_7)\r
+  },\r
+  {\r
+    2400,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_8)\r
+  },\r
+  {\r
+    2000,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_9)\r
+  },\r
+  {\r
+    1800,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_10)\r
+  },\r
+  {\r
+    1200,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_11)\r
+  },\r
+  {\r
+    600,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_12)\r
+  },\r
+  {\r
+    300,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_13)\r
+  },\r
+  {\r
+    150,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_14)\r
+  },\r
+  {\r
+    134,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_15)\r
+  },\r
+  {\r
+    110,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_16)\r
+  },\r
+  {\r
+    75,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_17)\r
+  },\r
+  {\r
+    50,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_18)\r
+  }\r
+};\r
+\r
+//\r
+// Value and string token correspondency for DataBits\r
+//\r
+COM_ATTR            DataBitsList[4] = {\r
+  {\r
+    5,\r
+    STRING_TOKEN(STR_COM_DATA_BITS_0)\r
+  },\r
+  {\r
+    6,\r
+    STRING_TOKEN(STR_COM_DATA_BITS_1)\r
+  },\r
+  {\r
+    7,\r
+    STRING_TOKEN(STR_COM_DATA_BITS_2)\r
+  },\r
+  {\r
+    8,\r
+    STRING_TOKEN(STR_COM_DATA_BITS_3)\r
+  }\r
+};\r
+\r
+//\r
+// Value and string token correspondency for Parity\r
+//\r
+COM_ATTR            ParityList[5] = {\r
+  {\r
+    NoParity,\r
+    STRING_TOKEN(STR_COM_PAR_0)\r
+  },\r
+  {\r
+    EvenParity,\r
+    STRING_TOKEN(STR_COM_PAR_1)\r
+  },\r
+  {\r
+    OddParity,\r
+    STRING_TOKEN(STR_COM_PAR_2)\r
+  },\r
+  {\r
+    MarkParity,\r
+    STRING_TOKEN(STR_COM_PAR_3)\r
+  },\r
+  {\r
+    SpaceParity,\r
+    STRING_TOKEN(STR_COM_PAR_4)\r
+  }\r
+};\r
+\r
+//\r
+// Value and string token correspondency for Baudreate\r
+//\r
+COM_ATTR            StopBitsList[3] = {\r
+  {\r
+    OneStopBit,\r
+    STRING_TOKEN(STR_COM_STOP_BITS_0)\r
+  },\r
+  {\r
+    OneFiveStopBits,\r
+    STRING_TOKEN(STR_COM_STOP_BITS_1)\r
+  },\r
+  {\r
+    TwoStopBits,\r
+    STRING_TOKEN(STR_COM_STOP_BITS_2)\r
+  }\r
+};\r
+\r
+//\r
+// Guid for messaging path, used in Serial port setting.\r
+//\r
+EFI_GUID            Guid[4] = {\r
+  DEVICE_PATH_MESSAGING_PC_ANSI,\r
+  DEVICE_PATH_MESSAGING_VT_100,\r
+  DEVICE_PATH_MESSAGING_VT_100_PLUS,\r
+  DEVICE_PATH_MESSAGING_VT_UTF8\r
+};\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FE.vfr b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FE.vfr
new file mode 100644 (file)
index 0000000..b9c5bb3
--- /dev/null
@@ -0,0 +1,138 @@
+// *++\r
+//\r
+// Copyright (c) 2006, Intel Corporation                                                         \r
+// All rights reserved. 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
+// Module Name:\r
+//\r
+//   FE.vfr \r
+// \r
+// Abstract:\r
+// \r
+//   File Explorer Formset\r
+// \r
+// Revision History: \r
+// \r
+// --*/\r
+\r
+#include "EdkGenericPlatformBdsLibStrDefs.h" \r
+#include "FormGuid.h"\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+  UINT16                    DescriptionData[75];\r
+  UINT16                    OptionalData[127];\r
+  UINT8                     Active;\r
+  UINT8                     ForceReconnect;  \r
+} FILE_EXPLORER_NV_DATA;\r
+#pragma pack()\r
+\r
+#define FORM_FILE_EXPLORER_ID                 0x001E\r
+#define FORM_BOOT_ADD_DESCRIPTION_ID          0x001F\r
+#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID   0x0020\r
+#define KEY_VALUE_SAVE_AND_EXIT               0x0090\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT            0x0091\r
+\r
+\r
+\r
+formset \r
+  guid = FILE_EXPLORE_FORMSET_GUID,\r
+  title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE),\r
+  help = STRING_TOKEN(STR_NULL_STRING),\r
+  class = 0,\r
+  subclass = 0,\r
+\r
+  form formid = FORM_FILE_EXPLORER_ID,\r
+       title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);\r
+\r
+       label FORM_FILE_EXPLORER_ID;\r
+  endform;\r
+  \r
+  form formid = FORM_BOOT_ADD_DESCRIPTION_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE);\r
+       \r
+       label FORM_BOOT_ADD_DESCRIPTION_ID;\r
+\r
+       subtitle  text = STRING_TOKEN(STR_NULL_STRING);\r
+       \r
+       string    varid    = FILE_EXPLORER_NV_DATA.DescriptionData,\r
+                 prompt   = STRING_TOKEN(STR_LOAD_OPTION_DESC),\r
+                 help     = STRING_TOKEN(STR_NULL_STRING),\r
+                 minsize  = 6,\r
+                 maxsize  = 75,\r
+       endstring;\r
+\r
+       string    varid    = FILE_EXPLORER_NV_DATA.OptionalData,\r
+                       prompt   = STRING_TOKEN(STR_OPTIONAL_DATA),\r
+                       help     = STRING_TOKEN(STR_NULL_STRING),\r
+                       minsize  = 0,\r
+                       maxsize  = 120,\r
+       endstring;\r
+\r
+       text \r
+         help   = STRING_TOKEN(STR_SAVE_AND_EXIT),  \r
+         text   = STRING_TOKEN(STR_SAVE_AND_EXIT), \r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE | NV_ACCESS,\r
+         key    = KEY_VALUE_SAVE_AND_EXIT;\r
+             \r
+       text \r
+         help   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),  \r
+         text   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), \r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE | NV_ACCESS,\r
+         key    = KEY_VALUE_NO_SAVE_AND_EXIT;\r
+    \r
+  endform;\r
+\r
+  form formid = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);\r
+       \r
+       label FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+       \r
+       subtitle  text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+       string    varid    = FILE_EXPLORER_NV_DATA.DescriptionData,\r
+                 prompt   = STRING_TOKEN(STR_LOAD_OPTION_DESC),\r
+                 help     = STRING_TOKEN(STR_NULL_STRING),\r
+                 minsize  = 6,\r
+                 maxsize  = 75,\r
+       endstring;\r
+\r
+       string    varid    = FILE_EXPLORER_NV_DATA.OptionalData,\r
+                 prompt   = STRING_TOKEN(STR_OPTIONAL_DATA),\r
+                 help     = STRING_TOKEN(STR_NULL_STRING),\r
+                 minsize  = 0,\r
+                 maxsize  = 120,\r
+       endstring; \r
+       \r
+       checkbox varid    = FILE_EXPLORER_NV_DATA.ForceReconnect,\r
+               prompt   = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),\r
+               help     = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),  \r
+               flags    = 1,\r
+               key      = 0,\r
+       endcheckbox;\r
+\r
+       text \r
+         help   = STRING_TOKEN(STR_SAVE_AND_EXIT),  \r
+         text   = STRING_TOKEN(STR_SAVE_AND_EXIT), \r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE | NV_ACCESS,\r
+         key    = KEY_VALUE_SAVE_AND_EXIT;\r
+      \r
+       text \r
+         help   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),  \r
+         text   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), \r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE | NV_ACCESS,\r
+         key    = KEY_VALUE_NO_SAVE_AND_EXIT;\r
+               \r
+  endform;\r
+  \r
+endformset;
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FileExplorer.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FileExplorer.c
new file mode 100644 (file)
index 0000000..2c8ec52
--- /dev/null
@@ -0,0 +1,339 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  FileExplorer.c\r
+    \r
+AgBStract:\r
+\r
+  File explorer related functions.\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "BootMaint.h"\r
+\r
+VOID\r
+UpdateFileExplorePage (\r
+  IN BMM_CALLBACK_DATA            *CallbackData,\r
+  BM_MENU_OPTION                  *MenuOption\r
+  )\r
+/*++\r
+Routine Description:\r
+  Update the File Explore page.\r
+\r
+Arguments:\r
+  MenuOption      - Pointer to menu options to display.\r
+\r
+Returns:\r
+  None.\r
+\r
+--*/\r
+{\r
+  UINT8           *Location;\r
+  UINTN           Index;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_FILE_CONTEXT *NewFileContext;\r
+  FORM_ID         FormId;\r
+\r
+  NewMenuEntry    = NULL;\r
+  NewFileContext  = NULL;\r
+  FormId          = 0;\r
+\r
+  //\r
+  // Clean up file explore page.\r
+  //\r
+  RefreshUpdateData (FALSE, 0, FALSE, 0, 0xff);\r
+\r
+  //\r
+  // Remove all op-codes from dynamic page\r
+  //\r
+  CallbackData->Hii->UpdateForm (\r
+                      CallbackData->Hii,\r
+                      CallbackData->FeHiiHandle,\r
+                      FORM_FILE_EXPLORER_ID,\r
+                      FALSE,\r
+                      UpdateData\r
+                      );\r
+\r
+  RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackData->FeCallbackHandle, FALSE, 0, 0);\r
+\r
+  Location = (UINT8 *) &UpdateData->Data;\r
+\r
+  for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+    NewMenuEntry    = BOpt_GetMenuEntry (MenuOption, Index);\r
+    NewFileContext  = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    if (NewFileContext->IsBootLegacy) {\r
+      continue;\r
+    }\r
+\r
+    if ((NewFileContext->IsDir) || (BOOT_FROM_FILE_STATE == CallbackData->FeCurrentState)) {\r
+      //\r
+      // Create Text opcode for directory, also create Text opcode for file in BOOT_FROM_FILE_STATE.\r
+      //\r
+      CreateTextOpCode (\r
+        NewMenuEntry->DisplayStringToken,\r
+        STR_NULL_STRING,\r
+        STR_NULL_STRING,\r
+        EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+        (UINT16) (FILE_OPTION_OFFSET + Index),\r
+        Location\r
+        );\r
+    } else {\r
+      //\r
+      // Create Goto opcode for file in ADD_BOOT_OPTION_STATE or ADD_DRIVER_OPTION_STATE.\r
+      //\r
+      if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {\r
+        FormId = FORM_BOOT_ADD_DESCRIPTION_ID;\r
+      } else if (ADD_DRIVER_OPTION_STATE == CallbackData->FeCurrentState) {\r
+        FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+      }\r
+\r
+      CreateGotoOpCode (\r
+        FormId,\r
+        NewMenuEntry->DisplayStringToken,\r
+        STRING_TOKEN (STR_NULL_STRING),\r
+        EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+        (UINT16) (FILE_OPTION_OFFSET + Index),\r
+        Location\r
+        );\r
+    }\r
+\r
+    UpdateData->DataCount++;\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  }\r
+\r
+  CallbackData->Hii->UpdateForm (\r
+                      CallbackData->Hii,\r
+                      CallbackData->FeHiiHandle,\r
+                      FORM_FILE_EXPLORER_ID,\r
+                      TRUE,\r
+                      UpdateData\r
+                      );\r
+}\r
+\r
+BOOLEAN\r
+UpdateFileExplorer (\r
+  IN BMM_CALLBACK_DATA            *CallbackData,\r
+  IN UINT16                       KeyValue\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Update the file explower page with the refershed file system.\r
+\r
+Arguments:\r
+  CallbackData  -   BMM context data\r
+  KeyValue        - Key value to identify the type of data to expect.\r
+\r
+Returns:\r
+  TRUE          - Inform the caller to create a callback packet to exit file explorer.\r
+  FALSE         - Indicate that there is no need to exit file explorer.\r
+\r
+--*/\r
+{\r
+  UINT16          FileOptionMask;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_FILE_CONTEXT *NewFileContext;\r
+  FORM_ID         FormId;\r
+  BOOLEAN         ExitFileExplorer;\r
+  EFI_STATUS      Status;\r
+  \r
+  NewMenuEntry      = NULL;\r
+  NewFileContext    = NULL;\r
+  ExitFileExplorer  = FALSE;\r
+\r
+  FileOptionMask    = (UINT16) (FILE_OPTION_MASK & KeyValue);\r
+\r
+  if (UNKNOWN_CONTEXT == CallbackData->FeDisplayContext) {\r
+    //\r
+    // First in, display file system.\r
+    //\r
+    BOpt_FreeMenu (&FsOptionMenu);\r
+    BOpt_FindFileSystem (CallbackData);\r
+    CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu);\r
+\r
+    UpdateFileExplorePage (CallbackData, &FsOptionMenu);\r
+\r
+    CallbackData->FeDisplayContext = FILE_SYSTEM;\r
+  } else {\r
+    if (FILE_SYSTEM == CallbackData->FeDisplayContext) {\r
+      NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask);\r
+    } else if (DIRECTORY == CallbackData->FeDisplayContext) {\r
+      NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask);\r
+    }\r
+\r
+    CallbackData->FeDisplayContext  = DIRECTORY;\r
+\r
+    NewFileContext                  = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    if (NewFileContext->IsDir ) {\r
+      RemoveEntryList (&NewMenuEntry->Link);\r
+      BOpt_FreeMenu (&DirectoryMenu);\r
+      Status = BOpt_FindFiles (CallbackData, NewMenuEntry);\r
+       if (EFI_ERROR (Status)) {\r
+         ExitFileExplorer = TRUE;\r
+         goto exit;\r
+       }\r
+      CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu);\r
+      BOpt_DestroyMenuEntry (NewMenuEntry);\r
+\r
+      UpdateFileExplorePage (CallbackData, &DirectoryMenu);\r
+\r
+    } else {\r
+      switch (CallbackData->FeCurrentState) {\r
+      case BOOT_FROM_FILE_STATE:\r
+        //\r
+        // Here boot from file\r
+        //\r
+        BootThisFile (NewFileContext);\r
+        ExitFileExplorer = TRUE;\r
+        break;\r
+\r
+      case ADD_BOOT_OPTION_STATE:\r
+      case ADD_DRIVER_OPTION_STATE:\r
+        if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {\r
+          FormId = FORM_BOOT_ADD_DESCRIPTION_ID;\r
+        } else {\r
+          FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+        }\r
+\r
+        CallbackData->MenuEntry = NewMenuEntry;\r
+        CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath;\r
+\r
+        //\r
+        // Clean up file explore page.\r
+        //\r
+        RefreshUpdateData (FALSE, 0, FALSE, 0, 1);\r
+\r
+        //\r
+        // Remove the Subtitle op-code.\r
+        //\r
+        CallbackData->Hii->UpdateForm (\r
+                            CallbackData->Hii,\r
+                            CallbackData->FeHiiHandle,\r
+                            FormId,\r
+                            FALSE,\r
+                            UpdateData\r
+                            );\r
+\r
+        //\r
+        // Create Subtitle op-code for the display string of the option.\r
+        //\r
+        RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackData->FeCallbackHandle, FALSE, 0, 1);\r
+\r
+        CreateSubTitleOpCode (\r
+          NewMenuEntry->DisplayStringToken,\r
+          &UpdateData->Data\r
+          );\r
+\r
+        CallbackData->Hii->UpdateForm (\r
+                            CallbackData->Hii,\r
+                            CallbackData->FeHiiHandle,\r
+                            FormId,\r
+                            TRUE,\r
+                            UpdateData\r
+                            );\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+    }\r
+  }\r
+exit:\r
+  return ExitFileExplorer;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FileExplorerCallback (\r
+  IN EFI_FORM_CALLBACK_PROTOCOL       *This,\r
+  IN UINT16                           KeyValue,\r
+  IN EFI_IFR_DATA_ARRAY               *Data,\r
+  OUT EFI_HII_CALLBACK_PACKET         **Packet\r
+  )\r
+/*++\r
+Routine Description:\r
+  Callback Function for file exploration and file interaction.\r
+\r
+Arguments:\r
+  This            - File explorer callback protocol pointer.     \r
+  KeyValue        - Key value to identify the type of data to expect.\r
+  Data            - A pointer to the data being sent to the original exporting driver.\r
+  Packet          - A pointer to a packet of information which a driver passes back to the browser.\r
+\r
+Returns:\r
+  EFI_SUCCESS     - Callback ended successfully.\r
+  Others          - Contain some errors.\r
+  \r
+--*/\r
+{\r
+  BMM_CALLBACK_DATA     *Private;\r
+  FILE_EXPLORER_NV_DATA *NvRamMap;\r
+  EFI_STATUS            Status;\r
+\r
+  Status                          = EFI_SUCCESS;\r
+  Private                         = FE_CALLBACK_DATA_FROM_THIS (This);\r
+  UpdateData->FormCallbackHandle  = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->FeCallbackHandle;\r
+  NvRamMap                        = (FILE_EXPLORER_NV_DATA *) Data->NvRamMap;\r
+\r
+  if (KEY_VALUE_SAVE_AND_EXIT == KeyValue) {\r
+    //\r
+    // Apply changes and exit formset.\r
+    //\r
+    if (ADD_BOOT_OPTION_STATE == Private->FeCurrentState) {\r
+      Status = Var_UpdateBootOption (Private, NvRamMap);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      BOpt_GetBootOptions (Private);\r
+      CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu);\r
+    } else if (ADD_DRIVER_OPTION_STATE == Private->FeCurrentState) {\r
+      Status = Var_UpdateDriverOption (\r
+                Private,\r
+                Private->FeHiiHandle,\r
+                NvRamMap->DescriptionData,\r
+                NvRamMap->OptionalData,\r
+                NvRamMap->ForceReconnect\r
+                );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      BOpt_GetDriverOptions (Private);\r
+      CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu);\r
+    }\r
+\r
+    CreateCallbackPacket (Packet, EXIT_REQUIRED | NV_NOT_CHANGED);\r
+  } else if (KEY_VALUE_NO_SAVE_AND_EXIT == KeyValue) {\r
+    //\r
+    // Discard changes and exit formset.\r
+    //\r
+    NvRamMap->OptionalData[0]     = 0x0000;\r
+    NvRamMap->DescriptionData[0]  = 0x0000;\r
+    CreateCallbackPacket (Packet, EXIT_REQUIRED | NV_NOT_CHANGED);\r
+  } else if (KeyValue < FILE_OPTION_OFFSET) {\r
+    //\r
+    // Exit File Explorer formset.\r
+    //\r
+    CreateCallbackPacket (Packet, EXIT_REQUIRED);\r
+  } else {\r
+    if (UpdateFileExplorer (Private, KeyValue)) {\r
+      CreateCallbackPacket (Packet, EXIT_REQUIRED);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FormGuid.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/FormGuid.h
new file mode 100644 (file)
index 0000000..8b55159
--- /dev/null
@@ -0,0 +1,32 @@
+// *++\r
+//\r
+// Copyright (c) 2006, Intel Corporation\r
+// All rights reserved. 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
+// Module Name:\r
+//\r
+//   FormGuid.h\r
+//\r
+// Abstract:\r
+//\r
+//   Formset guids for Boot Maintenance Manager\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+//\r
+#define MAIN_FORMSET_GUID \\r
+  { \\r
+    0x642237c7, 0x35d4, 0x472d, { 0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22 } \\r
+  }\r
+\r
+#define FILE_EXPLORE_FORMSET_GUID \\r
+  { \\r
+    0x1f2d63e1, 0xfebd, 0x4dc7, { 0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b } \\r
+  }\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/UpdatePage.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/UpdatePage.c
new file mode 100644 (file)
index 0000000..dfc12dc
--- /dev/null
@@ -0,0 +1,1274 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  UpdatePage.c\r
+    \r
+AgBStract:\r
+\r
+  Dynamically Update the pages\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "BootMaint.h"\r
+\r
+EFI_GUID gTerminalDriverGuid = {\r
+  0x10634d8e, 0x1c05, 0x46cb, {0xbb, 0xc, 0x5a, 0xfd, 0xc8, 0x29, 0xa8, 0xc8}\r
+};\r
+\r
+VOID\r
+RefreshUpdateData (\r
+  IN BOOLEAN                      FormSetUpdate,\r
+  IN EFI_PHYSICAL_ADDRESS         FormCallbackHandle,\r
+  IN BOOLEAN                      FormUpdate,\r
+  IN STRING_REF                   FormTitle,\r
+  IN UINT16                       DataCount\r
+  )\r
+/*++\r
+Routine Description:\r
+  Refresh the global UpdateData structure.\r
+\r
+Arguments:\r
+  FormSetUpdate      - If TRUE, next variable is significant\r
+  FormCallbackHandle - If not 0, will update FormSet with this info\r
+  FormUpdate         - If TRUE, next variable is significant\r
+  FormTitle          - If not 0, will update Form with this info\r
+  DataCount          - The number of Data entries in this structure\r
+\r
+Returns:\r
+  None.\r
+--*/\r
+{\r
+  UpdateData->FormSetUpdate = FormSetUpdate;\r
+  if (FormSetUpdate) {\r
+    ASSERT (0 != FormCallbackHandle);\r
+    UpdateData->FormCallbackHandle = FormCallbackHandle;\r
+  }\r
+\r
+  UpdateData->FormUpdate  = FALSE;\r
+  UpdateData->FormTitle   = FormTitle;\r
+  UpdateData->DataCount   = DataCount;\r
+}\r
+\r
+VOID\r
+UpdatePageStart (\r
+  IN BMM_CALLBACK_DATA                *CallbackData,\r
+  IN OUT UINT8                        **CurrentLocation\r
+  )\r
+{\r
+  RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackData->BmmCallbackHandle, FALSE, 0, 0);\r
+\r
+  if (!(CallbackData->BmmAskSaveOrNot)) {\r
+    //\r
+    // Add a "Go back to main page" tag in front of the form when there are no\r
+    // "Apply changes" and "Discard changes" tags in the end of the form.\r
+    //\r
+    CreateGotoOpCode (\r
+      FORM_MAIN_ID,\r
+      STRING_TOKEN (STR_FORM_GOTO_MAIN),\r
+      STRING_TOKEN (STR_FORM_GOTO_MAIN),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      FORM_MAIN_ID,\r
+      *CurrentLocation\r
+      );\r
+\r
+    UpdateData->DataCount++;\r
+\r
+    *CurrentLocation = *CurrentLocation + ((EFI_IFR_OP_HEADER *) (*CurrentLocation))->Length;\r
+  }\r
+\r
+}\r
+\r
+VOID\r
+UpdatePageEnd (\r
+  IN BMM_CALLBACK_DATA                *CallbackData,\r
+  IN UINT8                            *CurrentLocation\r
+  )\r
+{\r
+  //\r
+  // Create the "Apply changes" and "Discard changes" tags.\r
+  //\r
+  if (CallbackData->BmmAskSaveOrNot) {\r
+    CreateGotoOpCode (\r
+      FORM_MAIN_ID,\r
+      STRING_TOKEN (STR_SAVE_AND_EXIT),\r
+      STRING_TOKEN (STR_NULL_STRING),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      KEY_VALUE_SAVE_AND_EXIT,\r
+      CurrentLocation\r
+      );\r
+\r
+    UpdateData->DataCount++;\r
+\r
+    CurrentLocation = CurrentLocation + ((EFI_IFR_OP_HEADER *) CurrentLocation)->Length;\r
+\r
+    CreateGotoOpCode (\r
+      FORM_MAIN_ID,\r
+      STRING_TOKEN (STR_NO_SAVE_AND_EXIT),\r
+      STRING_TOKEN (STR_NULL_STRING),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      KEY_VALUE_NO_SAVE_AND_EXIT,\r
+      CurrentLocation\r
+      );\r
+\r
+    UpdateData->DataCount++;\r
+  }\r
+  //\r
+  // Ensure user can return to the main page.\r
+  //\r
+  if (0 == UpdateData->DataCount) {\r
+    CreateGotoOpCode (\r
+      FORM_MAIN_ID,\r
+      STRING_TOKEN (STR_NO_SAVE_AND_EXIT),\r
+      STRING_TOKEN (STR_NULL_STRING),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      KEY_VALUE_NO_SAVE_AND_EXIT,\r
+      CurrentLocation\r
+      );\r
+\r
+    UpdateData->DataCount++;\r
+  }\r
+\r
+  CallbackData->Hii->UpdateForm (\r
+                      CallbackData->Hii,\r
+                      CallbackData->BmmHiiHandle,\r
+                      CallbackData->BmmCurrentPageId,\r
+                      TRUE,\r
+                      UpdateData\r
+                      );\r
+}\r
+\r
+VOID\r
+CleanUpPage (\r
+  IN EFI_FORM_LABEL                   LabelId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  RefreshUpdateData (FALSE, 0, FALSE, 0, 0xff);\r
+\r
+  //\r
+  // Remove all op-codes from dynamic page\r
+  //\r
+  CallbackData->Hii->UpdateForm (\r
+                      CallbackData->Hii,\r
+                      CallbackData->BmmHiiHandle,\r
+                      LabelId,\r
+                      FALSE,\r
+                      UpdateData\r
+                      );\r
+}\r
+\r
+EFI_STATUS\r
+BootThisFile (\r
+  IN BM_FILE_CONTEXT                   *FileContext\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  UINTN             ExitDataSize;\r
+  CHAR16            *ExitData;\r
+  BDS_COMMON_OPTION *Option;\r
+\r
+  Status                  = gBS->AllocatePool (EfiBootServicesData, sizeof (BDS_COMMON_OPTION), (VOID**) &Option);\r
+  Option->Description     = FileContext->FileName;\r
+  Option->DevicePath      = FileContext->DevicePath;\r
+  Option->LoadOptionsSize = 0;\r
+  Option->LoadOptions     = NULL;\r
+\r
+  //\r
+  // Since current no boot from removable media directly is allowed */\r
+  //\r
+  gST->ConOut->ClearScreen (gST->ConOut);\r
+\r
+  ExitDataSize  = 0;\r
+\r
+  Status        = BdsLibBootViaBootOption (Option, Option->DevicePath, &ExitDataSize, &ExitData);\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+VOID\r
+UpdateConCOMPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        Index;\r
+  UINT8         *Location;\r
+  EFI_STATUS    Status;\r
+  VOID         *Interface;\r
+\r
+  Location                      = (UINT8 *) &UpdateData->Data;\r
+  CallbackData->BmmAskSaveOrNot = FALSE;\r
+\r
+  UpdatePageStart (CallbackData, &Location);\r
+\r
+  Status = EfiLibLocateProtocol (&gTerminalDriverGuid, &Interface);\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
\r
+      CreateGotoOpCode (\r
+        FORM_CON_COM_SETUP_ID,\r
+        NewMenuEntry->DisplayStringToken,\r
+        STRING_TOKEN (STR_NULL_STRING),\r
+        EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+        (UINT16) (TERMINAL_OPTION_OFFSET + Index),\r
+        Location\r
+        );\r
+      Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+      UpdateData->DataCount++;\r
+    }\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData, Location);\r
+}\r
+\r
+VOID\r
+UpdateBootDelPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT16          Index;\r
+  UINT8           *Location;\r
+\r
+  Location                      = (UINT8 *) &UpdateData->Data;\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData, &Location);\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);\r
+\r
+  for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+    NewLoadContext  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (NewLoadContext->IsLegacy) {\r
+      continue;\r
+    }\r
+\r
+    NewLoadContext->Deleted = FALSE;\r
+    CallbackData->BmmFakeNvData->BootOptionDel[Index] = 0x00;\r
+\r
+    CreateCheckBoxOpCode (\r
+      (UINT16) (BOOT_OPTION_DEL_QUESTION_ID + Index),\r
+      (UINT8) 1,\r
+      NewMenuEntry->DisplayStringToken,\r
+      NewMenuEntry->HelpStringToken,\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      (UINT16) BOOT_OPTION_DEL_QUESTION_ID,\r
+      Location\r
+      );\r
+\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+    UpdateData->DataCount++;\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData, Location);\r
+}\r
+\r
+VOID\r
+UpdateDrvAddHandlePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        Index;\r
+  UINT8         *Location;\r
+\r
+  Location                      = (UINT8 *) &UpdateData->Data;\r
+  CallbackData->BmmAskSaveOrNot = FALSE;\r
+\r
+  UpdatePageStart (CallbackData, &Location);\r
+\r
+  for (Index = 0; Index < DriverMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);\r
+\r
+    CreateGotoOpCode (\r
+      FORM_DRV_ADD_HANDLE_DESC_ID,\r
+      NewMenuEntry->DisplayStringToken,\r
+      STRING_TOKEN (STR_NULL_STRING),\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      (UINT16) (HANDLE_OPTION_OFFSET + Index),\r
+      Location\r
+      );\r
+\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+    UpdateData->DataCount++;\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData, Location);\r
+}\r
+\r
+VOID\r
+UpdateDrvDelPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT16          Index;\r
+  UINT8           *Location;\r
+\r
+  Location                      = (UINT8 *) &UpdateData->Data;\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData, &Location);\r
+\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu);\r
+\r
+  for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+\r
+    NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewLoadContext->Deleted = FALSE;\r
+    CallbackData->BmmFakeNvData->DriverOptionDel[Index] = 0x00;\r
+\r
+    CreateCheckBoxOpCode (\r
+      (UINT16) (DRIVER_OPTION_DEL_QUESTION_ID + Index),\r
+      (UINT8) 1,\r
+      NewMenuEntry->DisplayStringToken,\r
+      NewMenuEntry->HelpStringToken,\r
+      EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+      (UINT16) DRIVER_OPTION_DEL_QUESTION_ID,\r
+      Location\r
+      );\r
+\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+    UpdateData->DataCount++;\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData, Location);\r
+}\r
+\r
+VOID\r
+UpdateDriverAddHandleDescPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT8         *Location;\r
+\r
+  Location  = (UINT8 *) &UpdateData->Data;\r
+  CallbackData->BmmFakeNvData->DriverAddActive          = 0x01;\r
+  CallbackData->BmmFakeNvData->DriverAddForceReconnect  = 0x00;\r
+  CallbackData->BmmAskSaveOrNot                         = TRUE;\r
+  NewMenuEntry = CallbackData->MenuEntry;\r
+\r
+  UpdatePageStart (CallbackData, &Location);\r
+\r
+  UpdateData->DataCount += (UINT16) 4;\r
+\r
+  CreateSubTitleOpCode (\r
+    NewMenuEntry->DisplayStringToken,\r
+    Location\r
+    );\r
+\r
+  Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+  CreateStringOpCode (\r
+    DRV_ADD_HANDLE_DESC_QUESTION_ID,\r
+    (UINT8) 150,\r
+    STRING_TOKEN (STR_LOAD_OPTION_DESC),\r
+    STRING_TOKEN (STR_NULL_STRING),\r
+    6,\r
+    75,\r
+    EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+    KEY_VALUE_DRIVER_ADD_DESC_DATA,\r
+    Location\r
+    );\r
+\r
+  Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+  CreateCheckBoxOpCode (\r
+    DRV_ADD_RECON_QUESTION_ID,\r
+    (UINT8) 1,\r
+    STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),\r
+    STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),\r
+    EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+    DRV_ADD_RECON_QUESTION_ID,\r
+    Location\r
+    );\r
+  Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+  CreateStringOpCode (\r
+    DRIVER_ADD_OPTION_QUESTION_ID,\r
+    (UINT8) 150,\r
+    STRING_TOKEN (STR_OPTIONAL_DATA),\r
+    STRING_TOKEN (STR_NULL_STRING),\r
+    6,\r
+    75,\r
+    EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+    KEY_VALUE_DRIVER_ADD_OPT_DATA,\r
+    Location\r
+    );\r
+\r
+  Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  UpdatePageEnd (CallbackData, Location);\r
+}\r
+\r
+VOID\r
+UpdateConsolePage (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BM_MENU_OPTION                   *ConsoleMenu,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY       *NewMenuEntry;\r
+  BM_CONSOLE_CONTEXT  *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+  UINT16              Index;\r
+  UINT16              Index2;\r
+  UINT8               *Location;\r
+  UINT8               CheckFlags;\r
+  EFI_STATUS          Status;\r
+  VOID               *Interface;\r
+\r
+  Location                      = (UINT8 *) &UpdateData->Data;\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData, &Location);\r
+\r
+  for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {\r
+    NewMenuEntry      = BOpt_GetMenuEntry (ConsoleMenu, Index);\r
+    NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    CheckFlags        = EFI_IFR_FLAG_INTERACTIVE;\r
+    if (NewConsoleContext->IsActive) {\r
+      CheckFlags |= EFI_IFR_FLAG_DEFAULT;\r
+      CallbackData->BmmFakeNvData->ConsoleCheck[Index] = TRUE;\r
+    } else {\r
+      CallbackData->BmmFakeNvData->ConsoleCheck[Index] = FALSE;\r
+    }\r
+\r
+    CreateCheckBoxOpCode (\r
+      (UINT16) (CON_DEVICE_QUESTION_ID + Index),\r
+      (UINT8) 1,\r
+      NewMenuEntry->DisplayStringToken,\r
+      NewMenuEntry->HelpStringToken,\r
+      CheckFlags,\r
+      (UINT16) (CONSOLE_OPTION_OFFSET + Index),\r
+      Location\r
+      );\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+    UpdateData->DataCount++;\r
+  }\r
+\r
+  Status = EfiLibLocateProtocol (&gTerminalDriverGuid, &Interface);\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index2 = 0; Index2 < TerminalMenu.MenuNumber; Index2++) {\r
+      CheckFlags          = EFI_IFR_FLAG_INTERACTIVE;\r
+      NewMenuEntry        = BOpt_GetMenuEntry (&TerminalMenu, Index2);\r
+      NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+      if ((NewTerminalContext->IsConIn && (UpdatePageId == FORM_CON_IN_ID)) ||\r
+          (NewTerminalContext->IsConOut && (UpdatePageId == FORM_CON_OUT_ID)) ||\r
+          (NewTerminalContext->IsStdErr && (UpdatePageId == FORM_CON_ERR_ID))\r
+          ) {\r
+        CheckFlags |= EFI_IFR_FLAG_DEFAULT;\r
+        CallbackData->BmmFakeNvData->ConsoleCheck[Index] = TRUE;\r
+      } else {\r
+        CallbackData->BmmFakeNvData->ConsoleCheck[Index] = FALSE;\r
+      }\r
+\r
+      CreateCheckBoxOpCode (\r
+        (UINT16) (CON_DEVICE_QUESTION_ID + Index),\r
+        (UINT8) 1,\r
+        NewMenuEntry->DisplayStringToken,\r
+        NewMenuEntry->HelpStringToken,\r
+        CheckFlags,\r
+        (UINT16) (CONSOLE_OPTION_OFFSET + Index),\r
+        Location\r
+        );\r
+      Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+      UpdateData->DataCount++;\r
+      Index++;\r
+    }\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData, Location);\r
+}\r
+\r
+VOID\r
+UpdateOrderPage (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BM_MENU_OPTION                   *OptionMenu,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        Index;\r
+  UINT8         *Location;\r
+  IFR_OPTION    *IfrOptionList;\r
+\r
+  Location                      = (UINT8 *) &UpdateData->Data;\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData, &Location);\r
+\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);\r
+\r
+  ZeroMem (CallbackData->BmmFakeNvData->OptionOrder, 100);\r
+\r
+  IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * OptionMenu->MenuNumber);\r
+  if (NULL == IfrOptionList) {\r
+    return ;\r
+  }\r
+\r
+  for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);\r
+    IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;\r
+    IfrOptionList[Index].Value = (UINT16) (NewMenuEntry->OptionNumber + 1);\r
+    IfrOptionList[Index].OptionString = NULL;\r
+    CallbackData->BmmFakeNvData->OptionOrder[Index] = (UINT8) (IfrOptionList[Index].Value);\r
+  }\r
+\r
+  if (OptionMenu->MenuNumber > 0) {\r
+    CreateOrderedListOpCode (\r
+      (UINT16) OPTION_ORDER_QUESTION_ID,\r
+      (UINT8) 100,\r
+      STRING_TOKEN (STR_CHANGE_ORDER),\r
+      STRING_TOKEN (STR_CHANGE_ORDER),\r
+      IfrOptionList,\r
+      OptionMenu->MenuNumber,\r
+      Location\r
+      );\r
+\r
+    for (Index = 0; Index < OptionMenu->MenuNumber + 2; Index++) {\r
+      Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+    }\r
+\r
+    UpdateData->DataCount = (UINT16) (UpdateData->DataCount + OptionMenu->MenuNumber + 2);\r
+  }\r
+\r
+  SafeFreePool (IfrOptionList);\r
+\r
+  UpdatePageEnd (CallbackData, Location);\r
+\r
+  CopyMem (\r
+    CallbackData->BmmOldFakeNVData.OptionOrder,\r
+    CallbackData->BmmFakeNvData->OptionOrder,\r
+    100\r
+    );\r
+}\r
+\r
+VOID\r
+UpdateBootNextPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  UINT8           *Location;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  IFR_OPTION      *IfrOptionList;\r
+  UINTN           NumberOfOptions;\r
+  UINT16          Index;\r
+\r
+  Location                      = (UINT8 *) &UpdateData->Data;\r
+  IfrOptionList                 = NULL;\r
+  NumberOfOptions               = BootOptionMenu.MenuNumber;\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData, &Location);\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);\r
+\r
+  if (NumberOfOptions > 0) {\r
+    UpdateData->DataCount = (UINT8) (UpdateData->DataCount + NumberOfOptions);\r
+    IfrOptionList = AllocateZeroPool ((NumberOfOptions + 1) * sizeof (IFR_OPTION));\r
+\r
+    ASSERT (IfrOptionList);\r
+\r
+    CallbackData->BmmFakeNvData->BootNext = (UINT16) (BootOptionMenu.MenuNumber);\r
+\r
+    for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+      NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+      NewLoadContext  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+      if (NewLoadContext->IsBootNext) {\r
+        IfrOptionList[Index].Flags            = EFI_IFR_FLAG_DEFAULT | EFI_IFR_FLAG_INTERACTIVE;\r
+        CallbackData->BmmFakeNvData->BootNext = Index;\r
+      } else {\r
+        IfrOptionList[Index].Flags = EFI_IFR_FLAG_INTERACTIVE;\r
+      }\r
+\r
+      IfrOptionList[Index].Key          = (UINT16) KEY_VALUE_MAIN_BOOT_NEXT;\r
+      IfrOptionList[Index].Value        = Index;\r
+      IfrOptionList[Index].StringToken  = NewMenuEntry->DisplayStringToken;\r
+      IfrOptionList[Index].OptionString = NULL;\r
+    }\r
+\r
+    IfrOptionList[Index].Key          = (UINT16) KEY_VALUE_MAIN_BOOT_NEXT;\r
+    IfrOptionList[Index].Value        = Index;\r
+    IfrOptionList[Index].StringToken  = STRING_TOKEN (STR_NONE);\r
+    IfrOptionList[Index].Flags        = EFI_IFR_FLAG_INTERACTIVE;\r
+    if (CallbackData->BmmFakeNvData->BootNext == Index) {\r
+      IfrOptionList[Index].Flags |= EFI_IFR_FLAG_DEFAULT;\r
+    }\r
+\r
+    IfrOptionList[Index].OptionString = NULL;\r
+\r
+    CreateOneOfOpCode (\r
+      (UINT16) BOOT_NEXT_QUESTION_ID,\r
+      (UINT8) 2,\r
+      STRING_TOKEN (STR_BOOT_NEXT),\r
+      STRING_TOKEN (STR_BOOT_NEXT_HELP),\r
+      IfrOptionList,\r
+      (UINTN) (NumberOfOptions + 1),\r
+      Location\r
+      );\r
+    Location  = Location + (NumberOfOptions + 2) * ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+    Location  = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+    UpdateData->DataCount += 3;\r
+    SafeFreePool (IfrOptionList);\r
+    IfrOptionList = NULL;\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData, Location);\r
+}\r
+\r
+VOID\r
+UpdateTimeOutPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  UINT8   *Location;\r
+  UINT16  BootTimeOut;\r
+\r
+  Location                      = (UINT8 *) &UpdateData->Data;\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData, &Location);\r
+\r
+  BootTimeOut = BdsLibGetTimeout ();\r
+\r
+  CreateNumericOpCode (\r
+    (UINT16) BOOT_TIME_OUT_QUESTION_ID,\r
+    (UINT8) 2,\r
+    STRING_TOKEN (STR_NUM_AUTO_BOOT),\r
+    STRING_TOKEN (STR_HLP_AUTO_BOOT),\r
+    0,\r
+    65535,\r
+    0,\r
+    10,\r
+    0,\r
+    0,\r
+    Location\r
+    );\r
+\r
+  CallbackData->BmmFakeNvData->BootTimeOut = (UINT16) BootTimeOut;\r
+  UpdateData->DataCount++;\r
+  Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+  UpdatePageEnd (CallbackData, Location);\r
+}\r
+\r
+VOID\r
+UpdateTerminalPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  UINT16              Index;\r
+  UINT8               *Location;\r
+  UINT8               CheckFlags;\r
+  IFR_OPTION          *IfrOptionList;\r
+  BM_MENU_ENTRY       *NewMenuEntry;\r
+  BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+\r
+  ZeroMem (UpdateData, UPDATE_DATA_SIZE);\r
+  Location = (UINT8 *) &UpdateData->Data;\r
+  UpdatePageStart (CallbackData, &Location);\r
+\r
+  NewMenuEntry = BOpt_GetMenuEntry (\r
+                  &TerminalMenu,\r
+                  CallbackData->CurrentTerminal\r
+                  );\r
+\r
+  if (!NewMenuEntry) {\r
+    return ;\r
+  }\r
+\r
+  NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+  IfrOptionList       = AllocateZeroPool (sizeof (IFR_OPTION) * 19);\r
+  if (!IfrOptionList) {\r
+    return ;\r
+  }\r
+\r
+  for (Index = 0; Index < 19; Index++) {\r
+    CheckFlags = EFI_IFR_FLAG_INTERACTIVE;\r
+    if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[Index].Value)) {\r
+      CheckFlags |= EFI_IFR_FLAG_DEFAULT;\r
+      NewTerminalContext->BaudRateIndex         = (UINT8) Index;\r
+      CallbackData->BmmFakeNvData->COMBaudRate  = NewTerminalContext->BaudRateIndex;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].Key          = KEY_VALUE_COM_SET_BAUD_RATE;\r
+    IfrOptionList[Index].StringToken  = BaudRateList[Index].StringToken;\r
+    IfrOptionList[Index].Value        = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (UINT16) COM_BAUD_RATE_QUESTION_ID,\r
+    (UINT8) 1,\r
+    STRING_TOKEN (STR_COM_BAUD_RATE),\r
+    STRING_TOKEN (STR_COM_BAUD_RATE),\r
+    IfrOptionList,\r
+    19,\r
+    Location\r
+    );\r
+\r
+  Location              = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  Location              = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index);\r
+  UpdateData->DataCount += 2;\r
+\r
+  SafeFreePool (IfrOptionList);\r
+\r
+  IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 4);\r
+  if (!IfrOptionList) {\r
+    return ;\r
+  }\r
+\r
+  for (Index = 0; Index < 4; Index++) {\r
+    CheckFlags = EFI_IFR_FLAG_INTERACTIVE;\r
+\r
+    if (NewTerminalContext->DataBits == DataBitsList[Index].Value) {\r
+      NewTerminalContext->DataBitsIndex         = (UINT8) Index;\r
+      CallbackData->BmmFakeNvData->COMDataRate  = NewTerminalContext->DataBitsIndex;\r
+      CheckFlags |= EFI_IFR_FLAG_DEFAULT;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].Key          = KEY_VALUE_COM_SET_DATA_BITS;\r
+    IfrOptionList[Index].StringToken  = DataBitsList[Index].StringToken;\r
+    IfrOptionList[Index].Value        = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (UINT16) COM_DATA_RATE_QUESTION_ID,\r
+    (UINT8) 1,\r
+    STRING_TOKEN (STR_COM_DATA_BITS),\r
+    STRING_TOKEN (STR_COM_DATA_BITS),\r
+    IfrOptionList,\r
+    4,\r
+    Location\r
+    );\r
+\r
+  Location              = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  Location              = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index);\r
+  UpdateData->DataCount += 2;\r
+\r
+  SafeFreePool (IfrOptionList);\r
+\r
+  IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 5);\r
+  if (!IfrOptionList) {\r
+    return ;\r
+  }\r
+\r
+  for (Index = 0; Index < 5; Index++) {\r
+    CheckFlags = EFI_IFR_FLAG_INTERACTIVE;\r
+    if (NewTerminalContext->Parity == ParityList[Index].Value) {\r
+      CheckFlags |= EFI_IFR_FLAG_DEFAULT;\r
+      NewTerminalContext->ParityIndex         = (UINT8) Index;\r
+      CallbackData->BmmFakeNvData->COMParity  = NewTerminalContext->ParityIndex;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].Key          = KEY_VALUE_COM_SET_PARITY;\r
+    IfrOptionList[Index].StringToken  = ParityList[Index].StringToken;\r
+    IfrOptionList[Index].Value        = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (UINT16) COM_PARITY_QUESTION_ID,\r
+    (UINT8) 1,\r
+    STRING_TOKEN (STR_COM_PARITY),\r
+    STRING_TOKEN (STR_COM_PARITY),\r
+    IfrOptionList,\r
+    5,\r
+    Location\r
+    );\r
+\r
+  Location              = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  Location              = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index);\r
+  UpdateData->DataCount += 2;\r
+\r
+  SafeFreePool (IfrOptionList);\r
+\r
+  IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 3);\r
+  if (!IfrOptionList) {\r
+    return ;\r
+  }\r
+\r
+  for (Index = 0; Index < 3; Index++) {\r
+    CheckFlags = EFI_IFR_FLAG_INTERACTIVE;\r
+    if (NewTerminalContext->StopBits == StopBitsList[Index].Value) {\r
+      CheckFlags |= EFI_IFR_FLAG_DEFAULT;\r
+      NewTerminalContext->StopBitsIndex         = (UINT8) Index;\r
+      CallbackData->BmmFakeNvData->COMStopBits  = NewTerminalContext->StopBitsIndex;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].Key          = KEY_VALUE_COM_SET_STOP_BITS;\r
+    IfrOptionList[Index].StringToken  = StopBitsList[Index].StringToken;\r
+    IfrOptionList[Index].Value        = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (UINT16) COM_STOP_BITS_QUESTION_ID,\r
+    (UINT8) 1,\r
+    STRING_TOKEN (STR_COM_STOP_BITS),\r
+    STRING_TOKEN (STR_COM_STOP_BITS),\r
+    IfrOptionList,\r
+    3,\r
+    Location\r
+    );\r
+\r
+  Location              = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  Location              = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index);\r
+  UpdateData->DataCount += 2;\r
+\r
+  SafeFreePool (IfrOptionList);\r
+\r
+  IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 4);\r
+  if (!IfrOptionList) {\r
+    return ;\r
+  }\r
+\r
+  for (Index = 0; Index < 4; Index++) {\r
+    CheckFlags = EFI_IFR_FLAG_INTERACTIVE;\r
+    if (NewTerminalContext->TerminalType == Index) {\r
+      CheckFlags |= EFI_IFR_FLAG_DEFAULT;\r
+      CallbackData->BmmFakeNvData->COMTerminalType = NewTerminalContext->TerminalType;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].Key          = KEY_VALUE_COM_SET_TERMI_TYPE;\r
+    IfrOptionList[Index].StringToken  = (STRING_REF) TerminalType[Index];\r
+    IfrOptionList[Index].Value        = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (UINT16) COM_TERMINAL_QUESTION_ID,\r
+    (UINT8) 1,\r
+    STRING_TOKEN (STR_COM_TERMI_TYPE),\r
+    STRING_TOKEN (STR_COM_TERMI_TYPE),\r
+    IfrOptionList,\r
+    4,\r
+    Location\r
+    );\r
+\r
+  Location              = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  Location              = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index);\r
+  UpdateData->DataCount += 2;\r
+\r
+  SafeFreePool (IfrOptionList);\r
+\r
+  CreateGotoOpCode (\r
+    FORM_MAIN_ID,\r
+    STRING_TOKEN (STR_SAVE_AND_EXIT),\r
+    STRING_TOKEN (STR_NULL_STRING),\r
+    EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+    KEY_VALUE_SAVE_AND_EXIT,\r
+    Location\r
+    );\r
+\r
+  Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+  UpdateData->DataCount++;\r
+\r
+  CreateGotoOpCode (\r
+    FORM_MAIN_ID,\r
+    STRING_TOKEN (STR_NO_SAVE_AND_EXIT),\r
+    STRING_TOKEN (STR_NULL_STRING),\r
+    EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
+    KEY_VALUE_NO_SAVE_AND_EXIT,\r
+    Location\r
+    );\r
+\r
+  UpdateData->DataCount++;\r
+\r
+  CallbackData->Hii->UpdateForm (\r
+                      CallbackData->Hii,\r
+                      CallbackData->BmmHiiHandle,\r
+                      (EFI_FORM_LABEL) FORM_CON_COM_SETUP_ID,\r
+                      TRUE,\r
+                      UpdateData\r
+                      );\r
+\r
+}\r
+\r
+VOID\r
+UpdatePageBody (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  CleanUpPage (UpdatePageId, CallbackData);\r
+  switch (UpdatePageId) {\r
+  case FORM_CON_IN_ID:\r
+    UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData);\r
+    break;\r
+\r
+  case FORM_CON_OUT_ID:\r
+    UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData);\r
+    break;\r
+\r
+  case FORM_CON_ERR_ID:\r
+    UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData);\r
+    break;\r
+\r
+  case FORM_BOOT_CHG_ID:\r
+    UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData);\r
+    break;\r
+\r
+  case FORM_DRV_CHG_ID:\r
+    UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData);\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+VOID *\r
+GetLegacyBootOptionVar (\r
+  IN  UINTN                            DeviceType,\r
+  OUT UINTN                            *OptionIndex,\r
+  OUT UINTN                            *OptionSize\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  VOID                      *OptionBuffer;\r
+  UINTN                     OrderSize;\r
+  UINTN                     Index;\r
+  UINT32                    Attribute;\r
+  UINT16                    *OrderBuffer;\r
+  CHAR16                    StrTemp[100];\r
+  UINT16                    FilePathSize;\r
+  CHAR16                    *Description;\r
+  UINT8                     *Ptr;\r
+  UINT8                     *OptionalData;\r
+\r
+  //\r
+  // Get Boot Option number from the size of BootOrder\r
+  //\r
+  OrderBuffer = BdsLibGetVariableAndSize (\r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  &OrderSize\r
+                  );\r
+\r
+  for (Index = 0; Index < OrderSize / sizeof (UINT16); Index++) {\r
+    UnicodeSPrint (StrTemp, 100, L"Boot%04x", OrderBuffer[Index]);\r
+    OptionBuffer = BdsLibGetVariableAndSize (\r
+                    StrTemp,\r
+                    &gEfiGlobalVariableGuid,\r
+                    OptionSize\r
+                    );\r
+    if (NULL == OptionBuffer) {\r
+      continue;\r
+    }\r
+\r
+    Ptr       = (UINT8 *) OptionBuffer;\r
+    Attribute = *(UINT32 *) Ptr;\r
+    Ptr += sizeof (UINT32);\r
+\r
+    FilePathSize = *(UINT16 *) Ptr;\r
+    Ptr += sizeof (UINT16);\r
+\r
+    Description = (CHAR16 *) Ptr;\r
+    Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+    //\r
+    // Now Ptr point to Device Path\r
+    //\r
+    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+    Ptr += FilePathSize;\r
+\r
+    //\r
+    // Now Ptr point to Optional Data\r
+    //\r
+    OptionalData = Ptr;\r
+\r
+    if ((DeviceType == ((BBS_TABLE *) OptionalData)->DeviceType) &&\r
+        (BBS_DEVICE_PATH == DevicePath->Type) &&\r
+        (BBS_BBS_DP == DevicePath->SubType)\r
+        ) {\r
+      *OptionIndex = OrderBuffer[Index];\r
+      SafeFreePool (OrderBuffer);\r
+      return OptionBuffer;\r
+    } else {\r
+      SafeFreePool (OptionBuffer);\r
+    }\r
+  }\r
+\r
+  SafeFreePool (OrderBuffer);\r
+  return NULL;\r
+}\r
+\r
+VOID\r
+UpdateSetLegacyDeviceOrderPage (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
+  BM_MENU_OPTION              *OptionMenu;\r
+  BM_MENU_ENTRY               *NewMenuEntry;\r
+  IFR_OPTION                  *IfrOptionList;\r
+  STRING_REF                  StrRef;\r
+  STRING_REF                  StrRefHelp;\r
+  BBS_TYPE                    BbsType;\r
+  UINTN                       VarSize;\r
+  UINTN                       Pos;\r
+  UINTN                       Bit;\r
+  UINT16                      Index;\r
+  UINT16                      Index2;\r
+  UINT16                      Key;\r
+  CHAR16                      String[100];\r
+  CHAR16                      *TypeStr;\r
+  CHAR16                      *TypeStrHelp;\r
+  UINT16                      VarDevOrder;\r
+  UINT8                       *Location;\r
+  UINT8                       *VarData;\r
+  UINT8                       *OriginalPtr;\r
+  UINT8                       *LegacyOrder;\r
+  UINT8                       *OldData;\r
+  UINT8                       *DisMap;\r
+\r
+  OptionMenu                    = NULL;\r
+  Key = 0;\r
+  StrRef = 0;\r
+  StrRefHelp = 0;\r
+  TypeStr = NULL;\r
+  TypeStrHelp = NULL;\r
+  BbsType = BBS_FLOPPY;\r
+  LegacyOrder = NULL;\r
+  OldData = NULL;\r
+  DisMap = NULL;\r
+\r
+  Location = (UINT8 *) &UpdateData->Data;\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData, &Location);\r
+\r
+  DisMap = CallbackData->BmmOldFakeNVData.DisableMap;\r
+\r
+  SetMem (DisMap, 32, 0);\r
+  //\r
+  // Create oneof option list\r
+  //\r
+  switch (UpdatePageId) {\r
+  case FORM_SET_FD_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyFDMenu;\r
+    Key         = LEGACY_FD_QUESTION_ID;\r
+    TypeStr     = StrFloppy;\r
+    TypeStrHelp = StrFloppyHelp;\r
+    BbsType     = BBS_FLOPPY;\r
+    LegacyOrder = CallbackData->BmmFakeNvData->LegacyFD;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyFD;\r
+    break;\r
+\r
+  case FORM_SET_HD_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyHDMenu;\r
+    Key         = LEGACY_HD_QUESTION_ID;\r
+    TypeStr     = StrHardDisk;\r
+    TypeStrHelp = StrHardDiskHelp;\r
+    BbsType     = BBS_HARDDISK;\r
+    LegacyOrder = CallbackData->BmmFakeNvData->LegacyHD;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyHD;\r
+    break;\r
+\r
+  case FORM_SET_CD_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyCDMenu;\r
+    Key         = LEGACY_CD_QUESTION_ID;\r
+    TypeStr     = StrCDROM;\r
+    TypeStrHelp = StrCDROMHelp;\r
+    BbsType     = BBS_CDROM;\r
+    LegacyOrder = CallbackData->BmmFakeNvData->LegacyCD;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyCD;\r
+    break;\r
+\r
+  case FORM_SET_NET_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyNETMenu;\r
+    Key         = LEGACY_NET_QUESTION_ID;\r
+    TypeStr     = StrNET;\r
+    TypeStrHelp = StrNETHelp;\r
+    BbsType     = BBS_EMBED_NETWORK;\r
+    LegacyOrder = CallbackData->BmmFakeNvData->LegacyNET;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyNET;\r
+    break;\r
+\r
+  case FORM_SET_BEV_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
+    Key         = LEGACY_BEV_QUESTION_ID;\r
+    TypeStr     = StrBEV;\r
+    TypeStrHelp = StrBEVHelp;\r
+    BbsType     = BBS_BEV_DEVICE;\r
+    LegacyOrder = CallbackData->BmmFakeNvData->LegacyBEV;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyBEV;\r
+    break;\r
+\r
+  }\r
+\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);\r
+\r
+  IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * (OptionMenu->MenuNumber + 1));\r
+  if (NULL == IfrOptionList) {\r
+    return ;\r
+  }\r
+\r
+  for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+    NewMenuEntry                = BOpt_GetMenuEntry (OptionMenu, Index);\r
+    IfrOptionList[Index].Flags  = EFI_IFR_FLAG_INTERACTIVE;\r
+    if (0 == Index) {\r
+      IfrOptionList[Index].Flags |= EFI_IFR_FLAG_DEFAULT;\r
+    }\r
+\r
+    IfrOptionList[Index].Key          = Key;\r
+    IfrOptionList[Index].StringToken  = NewMenuEntry->DisplayStringToken;\r
+    IfrOptionList[Index].Value        = (UINT16) ((BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->Index;\r
+    IfrOptionList[Index].OptionString = NULL;\r
+  }\r
+  //\r
+  // for item "Disabled"\r
+  //\r
+  IfrOptionList[Index].Flags        = EFI_IFR_FLAG_INTERACTIVE;\r
+  IfrOptionList[Index].Key          = Key;\r
+  IfrOptionList[Index].StringToken  = STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE);\r
+  IfrOptionList[Index].Value        = 0xFF;\r
+  IfrOptionList[Index].OptionString = NULL;\r
+\r
+  //\r
+  // Get Device Order from variable\r
+  //\r
+  VarData = BdsLibGetVariableAndSize (\r
+              VarLegacyDevOrder,\r
+              &EfiLegacyDevOrderGuid,\r
+              &VarSize\r
+              );\r
+\r
+  if (NULL != VarData) {\r
+    OriginalPtr = VarData;\r
+    DevOrder    = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+    while (VarData < VarData + VarSize) {\r
+      if (DevOrder->BbsType == BbsType) {\r
+        break;\r
+      }\r
+\r
+      VarData += sizeof (BBS_TYPE);\r
+      VarData += *(UINT16 *) VarData;\r
+      DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+    }\r
+    //\r
+    // Create oneof tag here for FD/HD/CD #1 #2\r
+    //\r
+    for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+      for (Index2 = 0; Index2 <= OptionMenu->MenuNumber; Index2++) {\r
+        IfrOptionList[Index2].Key = (UINT16) (Key + Index);\r
+      }\r
+      //\r
+      // Create the string for oneof tag\r
+      //\r
+      UnicodeSPrint (String, sizeof (String), TypeStr, Index);\r
+      StrRef = 0;\r
+      CallbackData->Hii->NewString (\r
+                          CallbackData->Hii,\r
+                          NULL,\r
+                          CallbackData->BmmHiiHandle,\r
+                          &StrRef,\r
+                          String\r
+                          );\r
+\r
+      UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index);\r
+      StrRefHelp = 0;\r
+      CallbackData->Hii->NewString (\r
+                          CallbackData->Hii,\r
+                          NULL,\r
+                          CallbackData->BmmHiiHandle,\r
+                          &StrRefHelp,\r
+                          String\r
+                          );\r
+\r
+      CreateOneOfOpCode (\r
+        (UINT16) (Key + Index),\r
+        (UINT8) 1,\r
+        StrRef,\r
+        StrRefHelp,\r
+        IfrOptionList,\r
+        OptionMenu->MenuNumber + 1,\r
+        Location\r
+        );\r
+\r
+      VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16));\r
+\r
+      if (0xFF00 == (VarDevOrder & 0xFF00)) {\r
+        LegacyOrder[Index]  = 0xFF;\r
+        Pos                 = (VarDevOrder & 0xFF) / 8;\r
+        Bit                 = 7 - ((VarDevOrder & 0xFF) % 8);\r
+        DisMap[Pos] |= (UINT8) (1 << Bit);\r
+      } else {\r
+        LegacyOrder[Index] = (UINT8) (VarDevOrder & 0xFF);\r
+      }\r
+\r
+      Location              = Location + (OptionMenu->MenuNumber + 2) * ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+      Location              = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+      UpdateData->DataCount = (UINT16) (UpdateData->DataCount + (OptionMenu->MenuNumber + 3));\r
+    }\r
+  }\r
+\r
+  CopyMem (\r
+    OldData,\r
+    LegacyOrder,\r
+    100\r
+    );\r
+\r
+  if (IfrOptionList != NULL) {\r
+    SafeFreePool (IfrOptionList);\r
+    IfrOptionList = NULL;\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData, Location);\r
+}\r
+\r
+VOID\r
+UpdatePageId (\r
+  BMM_CALLBACK_DATA              *Private,\r
+  UINT16                         NewPageId\r
+  )\r
+{\r
+  UINT16  FileOptionMask;\r
+\r
+  FileOptionMask = (UINT16) (FILE_OPTION_MASK & NewPageId);\r
+\r
+  if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) {\r
+    //\r
+    // If we select a handle to add driver option, advance to the add handle description page.\r
+    //\r
+    NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID;\r
+  } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) {\r
+    //\r
+    // Return to main page after "Save Changes" or "Discard Changes".\r
+    //\r
+    NewPageId = FORM_MAIN_ID;\r
+  }\r
+\r
+  if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) {\r
+    Private->BmmPreviousPageId  = Private->BmmCurrentPageId;\r
+    Private->BmmCurrentPageId   = NewPageId;\r
+  }\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Variable.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMaint/Variable.c
new file mode 100644 (file)
index 0000000..c65f841
--- /dev/null
@@ -0,0 +1,1278 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  Variable.c\r
+\r
+Abstract:\r
+\r
+  Variable operation that will be used by BootMaint\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "BootMaint.h"\r
+\r
+EFI_STATUS\r
+Var_DelBootOption (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Delete Boot Option that represent a Deleted state in BootOptionMenu.\r
+  After deleting this boot option, call Var_ChangeBootOrder to\r
+  make sure BootOrder is in valid state.\r
+  \r
+Arguments:\r
+  LoadOption -- Pointer to the boot option that to be deleted\r
+\r
+Returns:\r
+  EFI_SUCCESS\r
+  Others\r
+  \r
+--*/\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+\r
+  UINT16          BootString[10];\r
+  EFI_STATUS      Status;\r
+  UINTN           Index;\r
+  UINTN           Index2;\r
+\r
+  Status  = EFI_SUCCESS;\r
+  Index2  = 0;\r
+  for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (!NewLoadContext->Deleted) {\r
+      continue;\r
+    }\r
+\r
+    UnicodeSPrint (\r
+      BootString,\r
+      sizeof (BootString),\r
+      L"Boot%04x",\r
+      NewMenuEntry->OptionNumber\r
+      );\r
+\r
+    EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);\r
+    Index2++;\r
+    //\r
+    // If current Load Option is the same as BootNext,\r
+    // must delete BootNext in order to make sure\r
+    // there will be no panic on next boot\r
+    //\r
+    if (NewLoadContext->IsBootNext) {\r
+      EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
+    }\r
+\r
+    RemoveEntryList (&NewMenuEntry->Link);\r
+    BOpt_DestroyMenuEntry (NewMenuEntry);\r
+    NewMenuEntry = NULL;\r
+  }\r
+\r
+  BootOptionMenu.MenuNumber -= Index2;\r
+\r
+  Status = Var_ChangeBootOrder ();\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+Var_ChangeBootOrder (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  After any operation on Boot####, there will be a discrepancy in BootOrder.\r
+  Since some are missing but in BootOrder, while some are present but are \r
+  not reflected by BootOrder. Then a function rebuild BootOrder from \r
+  scratch by content from BootOptionMenu is needed.\r
+  \r
+Arguments:\r
+\r
+Returns:\r
+  EFI_SUCCESS\r
+  Others\r
+  \r
+--*/\r
+{\r
+\r
+  EFI_STATUS    Status;\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        *BootOrderList;\r
+  UINT16        *BootOrderListPtr;\r
+  UINTN         BootOrderListSize;\r
+  UINTN         Index;\r
+\r
+  BootOrderList     = NULL;\r
+  BootOrderListSize = 0;\r
+\r
+  //\r
+  // First check whether BootOrder is present in current configuration\r
+  //\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+\r
+  //\r
+  // If exists, delete it to hold new BootOrder\r
+  //\r
+  if (BootOrderList) {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+    SafeFreePool (BootOrderList);\r
+    BootOrderList = NULL;\r
+  }\r
+  //\r
+  // Maybe here should be some check method to ensure that\r
+  // no new added boot options will be added\r
+  // but the setup engine now will give only one callback\r
+  // that is to say, user are granted only one chance to\r
+  // decide whether the boot option will be added or not\r
+  // there should be no indictor to show whether this\r
+  // is a "new" boot option\r
+  //\r
+  BootOrderListSize = BootOptionMenu.MenuNumber;\r
+\r
+  if (BootOrderListSize > 0) {\r
+    BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16));\r
+    ASSERT (BootOrderList != NULL);\r
+    BootOrderListPtr = BootOrderList;\r
+\r
+    //\r
+    // Get all current used Boot#### from BootOptionMenu.\r
+    // OptionNumber in each BM_LOAD_OPTION is really its\r
+    // #### value.\r
+    //\r
+    for (Index = 0; Index < BootOrderListSize; Index++) {\r
+      NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+      *BootOrderList  = (UINT16) NewMenuEntry->OptionNumber;\r
+      BootOrderList++;\r
+    }\r
+\r
+    BootOrderList = BootOrderListPtr;\r
+\r
+    //\r
+    // After building the BootOrderList, write it back\r
+    //\r
+    Status = gRT->SetVariable (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    BootOrderListSize * sizeof (UINT16),\r
+                    BootOrderList\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+Var_DelDriverOption (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Delete Load Option that represent a Deleted state in BootOptionMenu.\r
+  After deleting this Driver option, call Var_ChangeDriverOrder to\r
+  make sure DriverOrder is in valid state.\r
+  \r
+Arguments:\r
+  LoadOption -- Pointer to the Driver option that to be deleted\r
+\r
+Returns:\r
+  EFI_SUCCESS\r
+  Others\r
+  \r
+--*/\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+\r
+  UINT16          DriverString[12];\r
+  EFI_STATUS      Status;\r
+  UINTN           Index;\r
+  UINTN           Index2;\r
+\r
+  Status  = EFI_SUCCESS;\r
+  Index2  = 0;\r
+  for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (!NewLoadContext->Deleted) {\r
+      continue;\r
+    }\r
+\r
+    UnicodeSPrint (\r
+      DriverString,\r
+      sizeof (DriverString),\r
+      L"Driver%04x",\r
+      NewMenuEntry->OptionNumber\r
+      );\r
+\r
+    EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);\r
+    Index2++;\r
+\r
+    RemoveEntryList (&NewMenuEntry->Link);\r
+    BOpt_DestroyMenuEntry (NewMenuEntry);\r
+    NewMenuEntry = NULL;\r
+  }\r
+\r
+  DriverOptionMenu.MenuNumber -= Index2;\r
+\r
+  Status = Var_ChangeDriverOrder ();\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+Var_ChangeDriverOrder (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  After any operation on Driver####, there will be a discrepancy in \r
+  DriverOrder. Since some are missing but in DriverOrder, while some \r
+  are present but are not reflected by DriverOrder. Then a function \r
+  rebuild DriverOrder from scratch by content from DriverOptionMenu is \r
+  needed.\r
+  \r
+Arguments:\r
+\r
+Returns:\r
+  EFI_SUCCESS\r
+  Others\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        *DriverOrderList;\r
+  UINT16        *DriverOrderListPtr;\r
+  UINTN         DriverOrderListSize;\r
+  UINTN         Index;\r
+\r
+  DriverOrderList     = NULL;\r
+  DriverOrderListSize = 0;\r
+\r
+  //\r
+  // First check whether DriverOrder is present in current configuration\r
+  //\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+\r
+  //\r
+  // If exists, delete it to hold new DriverOrder\r
+  //\r
+  if (DriverOrderList) {\r
+    EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+    SafeFreePool (DriverOrderList);\r
+    DriverOrderList = NULL;\r
+  }\r
+\r
+  DriverOrderListSize = DriverOptionMenu.MenuNumber;\r
+\r
+  if (DriverOrderListSize > 0) {\r
+    DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16));\r
+    ASSERT (DriverOrderList != NULL);\r
+    DriverOrderListPtr = DriverOrderList;\r
+\r
+    //\r
+    // Get all current used Driver#### from DriverOptionMenu.\r
+    // OptionNumber in each BM_LOAD_OPTION is really its\r
+    // #### value.\r
+    //\r
+    for (Index = 0; Index < DriverOrderListSize; Index++) {\r
+      NewMenuEntry      = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+      *DriverOrderList  = (UINT16) NewMenuEntry->OptionNumber;\r
+      DriverOrderList++;\r
+    }\r
+\r
+    DriverOrderList = DriverOrderListPtr;\r
+\r
+    //\r
+    // After building the DriverOrderList, write it back\r
+    //\r
+    Status = gRT->SetVariable (\r
+                    L"DriverOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    DriverOrderListSize * sizeof (UINT16),\r
+                    DriverOrderList\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+Var_UpdateAllConsoleOption (\r
+  VOID\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *OutDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *InpDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ErrDevicePath;\r
+  EFI_STATUS                Status;\r
+\r
+  OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
+  InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
+  ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
+  if (OutDevicePath) {\r
+    ChangeVariableDevicePath (OutDevicePath);\r
+    Status = gRT->SetVariable (\r
+                    L"ConOut",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    GetDevicePathSize (OutDevicePath),\r
+                    OutDevicePath\r
+                    );\r
+    ASSERT (!EFI_ERROR (Status));\r
+  }\r
+\r
+  if (InpDevicePath) {\r
+    ChangeVariableDevicePath (InpDevicePath);\r
+    Status = gRT->SetVariable (\r
+                    L"ConIn",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    GetDevicePathSize (InpDevicePath),\r
+                    InpDevicePath\r
+                    );\r
+    ASSERT (!EFI_ERROR (Status));\r
+  }\r
+\r
+  if (ErrDevicePath) {\r
+    ChangeVariableDevicePath (ErrDevicePath);\r
+    Status = gRT->SetVariable (\r
+                    L"ErrOut",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    GetDevicePathSize (ErrDevicePath),\r
+                    ErrDevicePath\r
+                    );\r
+    ASSERT (!EFI_ERROR (Status));\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleOption (\r
+  IN UINT16                     *ConsoleName,\r
+  IN BM_MENU_OPTION             *ConsoleMenu,\r
+  IN UINT16                     UpdatePageId\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *ConDevicePath;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_CONSOLE_CONTEXT        *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  EFI_STATUS                Status;\r
+  VENDOR_DEVICE_PATH        Vendor;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TerminalDevicePath;\r
+  UINTN                     Index;\r
+  UINT16                    *Temp;\r
+\r
+  ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
+  if (ConDevicePath != NULL) {\r
+    EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
+    SafeFreePool (ConDevicePath);\r
+    ConDevicePath = NULL;\r
+  };\r
+\r
+  //\r
+  // First add all console input device to it from console input menu\r
+  //\r
+  for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (NewConsoleContext->IsActive) {\r
+      ConDevicePath = AppendDevicePathInstance (\r
+                        ConDevicePath,\r
+                        NewConsoleContext->DevicePath\r
+                        );\r
+    }\r
+  }\r
+\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if ((NewTerminalContext->IsConIn && (UpdatePageId == FORM_CON_IN_ID)) ||\r
+        (NewTerminalContext->IsConOut && (UpdatePageId == FORM_CON_OUT_ID)) ||\r
+        (NewTerminalContext->IsStdErr && (UpdatePageId == FORM_CON_ERR_ID))\r
+        ) {\r
+      Vendor.Header.Type    = MESSAGING_DEVICE_PATH;\r
+      Vendor.Header.SubType = MSG_VENDOR_DP;\r
+      CopyMem (\r
+        &Vendor.Guid,\r
+        &Guid[NewTerminalContext->TerminalType],\r
+        sizeof (EFI_GUID)\r
+        );\r
+      SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
+      TerminalDevicePath = AppendDevicePathNode (\r
+                            NewTerminalContext->DevicePath,\r
+                            (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
+                            );\r
+      ChangeTerminalDevicePath (TerminalDevicePath, TRUE);\r
+      Temp = DevicePathToStr (TerminalDevicePath);\r
+      ConDevicePath = AppendDevicePathInstance (\r
+                        ConDevicePath,\r
+                        TerminalDevicePath\r
+                        );\r
+    }\r
+  }\r
+\r
+  if (ConDevicePath) {\r
+    Status = gRT->SetVariable (\r
+                    ConsoleName,\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    GetDevicePathSize (ConDevicePath),\r
+                    ConDevicePath\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleInpOption (\r
+  VOID\r
+  )\r
+{\r
+  return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleOutOption (\r
+  VOID\r
+  )\r
+{\r
+  return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateErrorOutOption (\r
+  VOID\r
+  )\r
+{\r
+  return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateDriverOption (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData,\r
+  IN  EFI_HII_HANDLE            HiiHandle,\r
+  IN  UINT16                    *DescriptionData,\r
+  IN  UINT16                    *OptionalData,\r
+  IN  UINT8                     ForceReconnect\r
+  )\r
+{\r
+  UINT16          Index;\r
+  UINT16          *DriverOrderList;\r
+  UINT16          *NewDriverOrderList;\r
+  UINT16          DriverString[12];\r
+  UINTN           DriverOrderListSize;\r
+  VOID            *Buffer;\r
+  UINTN           BufferSize;\r
+  UINT8           *Ptr;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  BOOLEAN         OptionalDataExist;\r
+  EFI_STATUS      Status;\r
+\r
+  OptionalDataExist = FALSE;\r
+\r
+  Index             = BOpt_GetDriverOptionNumber ();\r
+  UnicodeSPrint (\r
+    DriverString,\r
+    sizeof (DriverString),\r
+    L"Driver%04x",\r
+    Index\r
+    );\r
+\r
+  if (*DescriptionData == 0x0000) {\r
+    StrCpy (DescriptionData, DriverString);\r
+  }\r
+\r
+  BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData) + GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+  if (*OptionalData != 0x0000) {\r
+    OptionalDataExist = TRUE;\r
+    BufferSize += StrSize (OptionalData);\r
+  }\r
+\r
+  Buffer = AllocateZeroPool (BufferSize);\r
+  if (NULL == Buffer) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+  if (NULL == NewMenuEntry) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewLoadContext                  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+  NewLoadContext->Deleted         = FALSE;\r
+  NewLoadContext->LoadOptionSize  = BufferSize;\r
+  Ptr = (UINT8 *) Buffer;\r
+  NewLoadContext->LoadOption = Ptr;\r
+  *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);\r
+  NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
+  NewLoadContext->IsActive = TRUE;\r
+  NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+  Ptr += sizeof (UINT32);\r
+  *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+  NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
+\r
+  Ptr += sizeof (UINT16);\r
+  CopyMem (\r
+    Ptr,\r
+    DescriptionData,\r
+    StrSize (DescriptionData)\r
+    );\r
+\r
+  NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));\r
+  ASSERT (NewLoadContext->Description != NULL);\r
+  NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+  CopyMem (\r
+    NewLoadContext->Description,\r
+    (VOID *) Ptr,\r
+    StrSize (DescriptionData)\r
+    );\r
+\r
+  Ptr += StrSize (DescriptionData);\r
+  CopyMem (\r
+    Ptr,\r
+    CallbackData->LoadContext->FilePathList,\r
+    GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+    );\r
+\r
+  NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
+  ASSERT (NewLoadContext->FilePathList != NULL);\r
+\r
+  CopyMem (\r
+    NewLoadContext->FilePathList,\r
+    (VOID *) Ptr,\r
+    GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+    );\r
+\r
+  NewMenuEntry->HelpString    = DevicePathToStr (NewLoadContext->FilePathList);\r
+  NewMenuEntry->OptionNumber  = Index;\r
+  NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                      CallbackData,\r
+                                      DriverOptionStrDepository\r
+                                      );\r
+  CallbackData->Hii->NewString (\r
+                      CallbackData->Hii,\r
+                      NULL,\r
+                      HiiHandle,\r
+                      &NewMenuEntry->DisplayStringToken,\r
+                      NewMenuEntry->DisplayString\r
+                      );\r
+\r
+  NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+                                    CallbackData,\r
+                                    DriverOptionHelpStrDepository\r
+                                    );\r
+  CallbackData->Hii->NewString (\r
+                      CallbackData->Hii,\r
+                      NULL,\r
+                      HiiHandle,\r
+                      &NewMenuEntry->HelpStringToken,\r
+                      NewMenuEntry->HelpString\r
+                      );\r
+\r
+  if (OptionalDataExist) {\r
+    Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+    CopyMem (\r
+      Ptr,\r
+      OptionalData,\r
+      StrSize (OptionalData)\r
+      );\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  DriverString,\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BufferSize,\r
+                  Buffer\r
+                  );\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+  NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));\r
+  ASSERT (NewDriverOrderList != NULL);\r
+  CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);\r
+  NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;\r
+  if (DriverOrderList != NULL) {\r
+    EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"DriverOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  DriverOrderListSize + sizeof (UINT16),\r
+                  NewDriverOrderList\r
+                  );\r
+  SafeFreePool (DriverOrderList);\r
+  DriverOrderList = NULL;\r
+  SafeFreePool (NewDriverOrderList);\r
+  NewDriverOrderList = NULL;\r
+  InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
+  DriverOptionMenu.MenuNumber++;\r
+\r
+  *DescriptionData  = 0x0000;\r
+  *OptionalData     = 0x0000;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateBootOption (\r
+  IN  BMM_CALLBACK_DATA                   *CallbackData,\r
+  IN  FILE_EXPLORER_NV_DATA               *NvRamMap\r
+  )\r
+{\r
+  UINT16          *BootOrderList;\r
+  UINT16          *NewBootOrderList;\r
+  UINTN           BootOrderListSize;\r
+  UINT16          BootString[10];\r
+  VOID            *Buffer;\r
+  UINTN           BufferSize;\r
+  UINT8           *Ptr;\r
+  UINT16          Index;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  BOOLEAN         OptionalDataExist;\r
+  EFI_STATUS      Status;\r
+\r
+  OptionalDataExist = FALSE;\r
+\r
+  Index             = BOpt_GetBootOptionNumber ();\r
+  UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);\r
+\r
+  if (NvRamMap->DescriptionData[0] == 0x0000) {\r
+    StrCpy (NvRamMap->DescriptionData, BootString);\r
+  }\r
+\r
+  BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData) + GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+  if (NvRamMap->OptionalData[0] != 0x0000) {\r
+    OptionalDataExist = TRUE;\r
+    BufferSize += StrSize (NvRamMap->OptionalData);\r
+  }\r
+\r
+  Buffer = AllocateZeroPool (BufferSize);\r
+  if (NULL == Buffer) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+  if (NULL == NewMenuEntry) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewLoadContext                  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+  NewLoadContext->Deleted         = FALSE;\r
+  NewLoadContext->LoadOptionSize  = BufferSize;\r
+  Ptr = (UINT8 *) Buffer;\r
+  NewLoadContext->LoadOption = Ptr;\r
+  *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
+  NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
+  NewLoadContext->IsActive = TRUE;\r
+  NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+  Ptr += sizeof (UINT32);\r
+  *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+  NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
+  Ptr += sizeof (UINT16);\r
+\r
+  CopyMem (\r
+    Ptr,\r
+    NvRamMap->DescriptionData,\r
+    StrSize (NvRamMap->DescriptionData)\r
+    );\r
+\r
+  NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData));\r
+  ASSERT (NewLoadContext->Description != NULL);\r
+\r
+  NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+  CopyMem (\r
+    NewLoadContext->Description,\r
+    (VOID *) Ptr,\r
+    StrSize (NvRamMap->DescriptionData)\r
+    );\r
+\r
+  Ptr += StrSize (NvRamMap->DescriptionData);\r
+  CopyMem (\r
+    Ptr,\r
+    CallbackData->LoadContext->FilePathList,\r
+    GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+    );\r
+\r
+  NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
+  ASSERT (NewLoadContext->FilePathList != NULL);\r
+\r
+  CopyMem (\r
+    NewLoadContext->FilePathList,\r
+    (VOID *) Ptr,\r
+    GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+    );\r
+\r
+  NewMenuEntry->HelpString    = DevicePathToStr (NewLoadContext->FilePathList);\r
+  NewMenuEntry->OptionNumber  = Index;\r
+  NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                      CallbackData,\r
+                                      BootOptionStrDepository\r
+                                      );\r
+  CallbackData->Hii->NewString (\r
+                      CallbackData->Hii,\r
+                      NULL,\r
+                      CallbackData->FeHiiHandle,\r
+                      &NewMenuEntry->DisplayStringToken,\r
+                      NewMenuEntry->DisplayString\r
+                      );\r
+\r
+  NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+                                    CallbackData,\r
+                                    BootOptionHelpStrDepository\r
+                                    );\r
+\r
+  CallbackData->Hii->NewString (\r
+                      CallbackData->Hii,\r
+                      NULL,\r
+                      CallbackData->FeHiiHandle,\r
+                      &NewMenuEntry->HelpStringToken,\r
+                      NewMenuEntry->HelpString\r
+                      );\r
+\r
+  if (OptionalDataExist) {\r
+    Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+    CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  BootString,\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BufferSize,\r
+                  Buffer\r
+                  );\r
+\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+\r
+  NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));\r
+  ASSERT (NewBootOrderList != NULL);\r
+  CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);\r
+  NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;\r
+\r
+  if (BootOrderList != NULL) {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BootOrderListSize + sizeof (UINT16),\r
+                  NewBootOrderList\r
+                  );\r
+\r
+  SafeFreePool (BootOrderList);\r
+  BootOrderList = NULL;\r
+  SafeFreePool (NewBootOrderList);\r
+  NewBootOrderList = NULL;\r
+  InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
+  BootOptionMenu.MenuNumber++;\r
+\r
+  NvRamMap->DescriptionData[0]  = 0x0000;\r
+  NvRamMap->OptionalData[0]     = 0x0000;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateBootNext (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY     *NewMenuEntry;\r
+  BM_LOAD_CONTEXT   *NewLoadContext;\r
+  BMM_FAKE_NV_DATA  *CurrentFakeNVMap;\r
+  UINT16            Index;\r
+  EFI_STATUS        Status;\r
+\r
+  Status            = EFI_SUCCESS;\r
+  CurrentFakeNVMap  = CallbackData->BmmFakeNvData;\r
+  for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewLoadContext              = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewLoadContext->IsBootNext  = FALSE;\r
+  }\r
+\r
+  if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {\r
+    EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  NewMenuEntry = BOpt_GetMenuEntry (\r
+                  &BootOptionMenu,\r
+                  CurrentFakeNVMap->BootNext\r
+                  );\r
+  if (NULL == NewMenuEntry) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+  Status = gRT->SetVariable (\r
+                  L"BootNext",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  sizeof (UINT16),\r
+                  &NewMenuEntry->OptionNumber\r
+                  );\r
+  NewLoadContext->IsBootNext              = TRUE;\r
+  CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateBootOrder (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT16      Index;\r
+  UINT16      *BootOrderList;\r
+  UINT16      *NewBootOrderList;\r
+  UINTN       BootOrderListSize;\r
+  UINT8       *Map;\r
+\r
+  BootOrderList     = NULL;\r
+  BootOrderListSize = 0;\r
+\r
+  //\r
+  // First check whether BootOrder is present in current configuration\r
+  //\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+\r
+  NewBootOrderList = AllocateZeroPool (BootOrderListSize);\r
+  if (!NewBootOrderList) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Map = AllocateZeroPool (BootOrderListSize / sizeof (UINT16));\r
+  if (!Map) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // If exists, delete it to hold new BootOrder\r
+  //\r
+  if (BootOrderList) {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+    NewBootOrderList[Index] = CallbackData->BmmFakeNvData->OptionOrder[Index] - 1;\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BootOrderListSize,\r
+                  NewBootOrderList\r
+                  );\r
+  SafeFreePool (BootOrderList);\r
+  SafeFreePool (NewBootOrderList);\r
+  SafeFreePool (Map);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  BOpt_FreeMenu (&BootOptionMenu);\r
+  BOpt_GetBootOptions (CallbackData);\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateDriverOrder (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT16      Index;\r
+  UINT16      *DriverOrderList;\r
+  UINT16      *NewDriverOrderList;\r
+  UINTN       DriverOrderListSize;\r
+\r
+  DriverOrderList     = NULL;\r
+  DriverOrderListSize = 0;\r
+\r
+  //\r
+  // First check whether DriverOrder is present in current configuration\r
+  //\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+\r
+  NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);\r
+\r
+  if (!NewDriverOrderList) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // If exists, delete it to hold new DriverOrder\r
+  //\r
+  if (DriverOrderList) {\r
+    EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  for (Index = 0; Index < DriverOrderListSize; Index++) {\r
+    NewDriverOrderList[Index] = CallbackData->BmmFakeNvData->OptionOrder[Index] - 1;\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"DriverOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  DriverOrderListSize,\r
+                  NewDriverOrderList\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  SafeFreePool (DriverOrderList);\r
+\r
+  BOpt_FreeMenu (&DriverOptionMenu);\r
+  BOpt_GetDriverOptions (CallbackData);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateBBSOption (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  UINTN                       Index;\r
+  UINTN                       Index2;\r
+  VOID                        *BootOptionVar;\r
+  CHAR16                      VarName[100];\r
+  UINTN                       OptionSize;\r
+  UINT16                      FilePathSize;\r
+  UINT8                       *Ptr;\r
+  EFI_STATUS                  Status;\r
+  CHAR16                      DescString[100];\r
+  UINTN                       NewOptionSize;\r
+  UINT8                       *NewOptionPtr;\r
+  UINT8                       *TempPtr;\r
+  UINT32                      *Attribute;\r
+\r
+  BM_MENU_OPTION              *OptionMenu;\r
+  BM_LEGACY_DEVICE_CONTEXT    *LegacyDeviceContext;\r
+  UINT8                       *LegacyDev;\r
+  UINT8                       *VarData;\r
+  UINTN                       VarSize;\r
+  BM_MENU_ENTRY               *NewMenuEntry;\r
+  BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
+  UINT8                       *OriginalPtr;\r
+  UINT8                       *DisMap;\r
+  UINTN                       Pos;\r
+  UINTN                       Bit;\r
+  UINT16                      *NewOrder;\r
+  UINT16                      Tmp;\r
+\r
+  LegacyDeviceContext = NULL;\r
+  DisMap              = NULL;\r
+  NewOrder            = NULL;\r
+\r
+  if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+    OptionMenu            = (BM_MENU_OPTION *) &LegacyFDMenu;\r
+    LegacyDev             = CallbackData->BmmFakeNvData->LegacyFD;\r
+    CallbackData->BbsType = BBS_FLOPPY;\r
+  } else {\r
+    if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+      OptionMenu            = (BM_MENU_OPTION *) &LegacyHDMenu;\r
+      LegacyDev             = CallbackData->BmmFakeNvData->LegacyHD;\r
+      CallbackData->BbsType = BBS_HARDDISK;\r
+    } else {\r
+      if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+        OptionMenu            = (BM_MENU_OPTION *) &LegacyCDMenu;\r
+        LegacyDev             = CallbackData->BmmFakeNvData->LegacyCD;\r
+        CallbackData->BbsType = BBS_CDROM;\r
+      } else {\r
+        if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+          OptionMenu            = (BM_MENU_OPTION *) &LegacyNETMenu;\r
+          LegacyDev             = CallbackData->BmmFakeNvData->LegacyNET;\r
+          CallbackData->BbsType = BBS_EMBED_NETWORK;\r
+        } else {\r
+          OptionMenu            = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
+          LegacyDev             = CallbackData->BmmFakeNvData->LegacyBEV;\r
+          CallbackData->BbsType = BBS_BEV_DEVICE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  DisMap  = CallbackData->BmmOldFakeNVData.DisableMap;\r
+  Status  = EFI_SUCCESS;\r
+\r
+  //\r
+  // Find the first device's context\r
+  // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext\r
+  // because we just use it to fill the desc string, and user can not see the string in UI\r
+  //\r
+  for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+    NewMenuEntry        = BOpt_GetMenuEntry (OptionMenu, Index);\r
+    LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {\r
+      DEBUG ((EFI_D_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));\r
+      break;\r
+    }\r
+  }\r
+  //\r
+  // Update the Variable "LegacyDevOrder"\r
+  //\r
+  VarData = (UINT8 *) BdsLibGetVariableAndSize (\r
+                        VarLegacyDevOrder,\r
+                        &EfiLegacyDevOrderGuid,\r
+                        &VarSize\r
+                        );\r
+\r
+  if (NULL == VarData) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  OriginalPtr = VarData;\r
+  DevOrder    = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+\r
+  while (VarData < VarData + VarSize) {\r
+    if (DevOrder->BbsType == CallbackData->BbsType) {\r
+      break;\r
+    }\r
+\r
+    VarData += sizeof (BBS_TYPE);\r
+    VarData += *(UINT16 *) VarData;\r
+    DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+  }\r
+\r
+  if (VarData >= VarData + VarSize) {\r
+    SafeFreePool (OriginalPtr);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  NewOrder = (UINT16 *) AllocateZeroPool (DevOrder->Length - sizeof (UINT16));\r
+  if (NULL == NewOrder) {\r
+    SafeFreePool (VarData);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+    if (0xFF == LegacyDev[Index]) {\r
+      break;\r
+    }\r
+\r
+    NewOrder[Index] = LegacyDev[Index];\r
+  }\r
+  //\r
+  // Only the enable/disable state of each boot device with same device type can be changed,\r
+  // so we can count on the index information in DevOrder.\r
+  // DisMap bit array is the only reliable source to check a device's en/dis state,\r
+  // so we use DisMap to set en/dis state of each item in NewOrder array\r
+  //\r
+  for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {\r
+    Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));\r
+    Tmp &= 0xFF;\r
+    Pos = Tmp / 8;\r
+    Bit = 7 - (Tmp % 8);\r
+    if (DisMap[Pos] & (1 << Bit)) {\r
+      NewOrder[Index] = (UINT16) (0xFF00 | Tmp);\r
+      Index++;\r
+    }\r
+  }\r
+\r
+  CopyMem (\r
+    (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),\r
+    NewOrder,\r
+    DevOrder->Length - sizeof (UINT16)\r
+    );\r
+  SafeFreePool (NewOrder);\r
+\r
+  Status = gRT->SetVariable (\r
+                  VarLegacyDevOrder,\r
+                  &EfiLegacyDevOrderGuid,\r
+                  VAR_FLAG,\r
+                  VarSize,\r
+                  OriginalPtr\r
+                  );\r
+\r
+  SafeFreePool (OriginalPtr);\r
+\r
+  //\r
+  // Update Optional Data of Boot####\r
+  //\r
+  BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);\r
+\r
+  if (NULL != BootOptionVar) {\r
+    CopyMem (\r
+      DescString,\r
+      LegacyDeviceContext->Description,\r
+      StrSize (LegacyDeviceContext->Description)\r
+      );\r
+\r
+    NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) + sizeof (BBS_TABLE) + sizeof (UINT16);\r
+\r
+    UnicodeSPrint (VarName, 100, L"Boot%04x", Index);\r
+\r
+    Ptr       = BootOptionVar;\r
+\r
+    Attribute = (UINT32 *) Ptr;\r
+    *Attribute |= LOAD_OPTION_ACTIVE;\r
+    if (0xFF == LegacyDev[0]) {\r
+      //\r
+      // Disable this legacy boot option\r
+      //\r
+      *Attribute &= ~LOAD_OPTION_ACTIVE;\r
+    }\r
+\r
+    Ptr += sizeof (UINT32);\r
+\r
+    FilePathSize = *(UINT16 *) Ptr;\r
+    Ptr += sizeof (UINT16);\r
+\r
+    NewOptionSize += FilePathSize;\r
+\r
+    NewOptionPtr = AllocateZeroPool (NewOptionSize);\r
+    if (NULL == NewOptionPtr) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    TempPtr = NewOptionPtr;\r
+\r
+    //\r
+    // Copy previous option data to new option except the description string\r
+    //\r
+    CopyMem (\r
+      TempPtr,\r
+      BootOptionVar,\r
+      sizeof (UINT32) + sizeof (UINT16)\r
+      );\r
+\r
+    TempPtr += (sizeof (UINT32) + sizeof (UINT16));\r
+\r
+    CopyMem (\r
+      TempPtr,\r
+      DescString,\r
+      StrSize (DescString)\r
+      );\r
+\r
+    TempPtr += StrSize (DescString);\r
+\r
+    //\r
+    // Description = (CHAR16 *)Ptr;\r
+    //\r
+    Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+    CopyMem (\r
+      TempPtr,\r
+      Ptr,\r
+      FilePathSize\r
+      );\r
+\r
+    TempPtr += FilePathSize;\r
+\r
+    //\r
+    // DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Ptr;\r
+    //\r
+    Ptr += FilePathSize;\r
+\r
+    //\r
+    // Now Ptr point to optional data, i.e. Bbs Table\r
+    //\r
+    CopyMem (\r
+      TempPtr,\r
+      LegacyDeviceContext->BbsTable,\r
+      sizeof (BBS_TABLE)\r
+      );\r
+\r
+    TempPtr += sizeof (BBS_TABLE);\r
+    *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;\r
+\r
+    Status = gRT->SetVariable (\r
+                    VarName,\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    NewOptionSize,\r
+                    NewOptionPtr\r
+                    );\r
+\r
+    SafeFreePool (NewOptionPtr);\r
+    SafeFreePool (BootOptionVar);\r
+  }\r
+\r
+  BOpt_GetBootOptions (CallbackData);\r
+  return Status;\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.c
new file mode 100644 (file)
index 0000000..4cdad1c
--- /dev/null
@@ -0,0 +1,355 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name: \r
+\r
+  BootManager.c\r
+\r
+Abstract:\r
+\r
+  The platform boot manager reference implement\r
+\r
+--*/\r
+#include "BootManager.h"\r
+\r
+UINT16                            mKeyInput;\r
+LIST_ENTRY                        *mBootOptionsList;\r
+BDS_COMMON_OPTION                 *gOption;\r
+EFI_HII_HANDLE                    gBootManagerHandle;\r
+EFI_HANDLE                        BootManagerCallbackHandle;\r
+EFI_FORM_CALLBACK_PROTOCOL        BootManagerCallback;\r
+EFI_GUID                          gBmGuid = BOOT_MANAGER_GUID;\r
+\r
+extern EFI_FORM_BROWSER_PROTOCOL  *gBrowser;\r
+extern UINT8                      BootManagerVfrBin[];\r
+extern UINT8                      EdkGenericPlatformBdsLibStrings[];\r
+extern BOOLEAN                    gConnectAllHappened;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerCallbackRoutine (\r
+  IN EFI_FORM_CALLBACK_PROTOCOL       *This,\r
+  IN UINT16                           KeyValue,\r
+  IN EFI_IFR_DATA_ARRAY               *DataArray,\r
+  OUT EFI_HII_CALLBACK_PACKET         **Packet\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This is the function that is called to provide results data to the driver.  This data\r
+  consists of a unique key which is used to identify what data is either being passed back\r
+  or being asked for. \r
+\r
+Arguments:\r
+\r
+  KeyValue -        A unique value which is sent to the original exporting driver so that it\r
+                    can identify the type of data to expect.  The format of the data tends to\r
+                    vary based on the op-code that geerated the callback.\r
+\r
+  Data -            A pointer to the data being sent to the original exporting driver.\r
+\r
+Returns: \r
+\r
+--*/\r
+{\r
+  BDS_COMMON_OPTION       *Option;\r
+  LIST_ENTRY              *Link;\r
+  UINT16                  KeyCount;\r
+  EFI_HII_CALLBACK_PACKET *DataPacket;\r
+\r
+  //\r
+  // Initialize the key count\r
+  //\r
+  KeyCount = 0;\r
+\r
+  for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) {\r
+    Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+    KeyCount++;\r
+\r
+    gOption = Option;\r
+\r
+    //\r
+    // Is this device the one chosen?\r
+    //\r
+    if (KeyCount == KeyValue) {\r
+      //\r
+      // Assigning the returned Key to a global allows the original routine to know what was chosen\r
+      //\r
+      mKeyInput = KeyValue;\r
+\r
+      *Packet   = AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + 2);\r
+      ASSERT (*Packet != NULL);\r
+\r
+      //\r
+      // Assign the buffer address to DataPacket\r
+      //\r
+      DataPacket                        = *Packet;\r
+\r
+      DataPacket->DataArray.EntryCount  = 1;\r
+      DataPacket->DataArray.NvRamMap    = NULL;\r
+      ((EFI_IFR_DATA_ENTRY *) (((EFI_IFR_DATA_ARRAY *)DataPacket) + 1))->Flags = EXIT_REQUIRED | NV_NOT_CHANGED;\r
+      return EFI_SUCCESS;\r
+    } else {\r
+      continue;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+CallBootManager (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Hook to enable UI timeout override behavior.\r
+\r
+Arguments:\r
+  BdsDeviceList - Device List that BDS needs to connect.\r
+\r
+  Entry - Pointer to current Boot Entry.\r
+\r
+Returns:\r
+  NONE\r
+\r
+--*/\r
+{\r
+  EFI_STATUS          Status;\r
+  EFI_HII_PACKAGES    *PackageList;\r
+  BDS_COMMON_OPTION   *Option;\r
+  LIST_ENTRY          *Link;\r
+  EFI_HII_UPDATE_DATA *UpdateData;\r
+  CHAR16              *ExitData;\r
+  UINTN               ExitDataSize;\r
+  STRING_REF          Token;\r
+  STRING_REF          LastToken;\r
+  EFI_INPUT_KEY       Key;\r
+  UINT8               *Location;\r
+  EFI_GUID            BmGuid;\r
+  LIST_ENTRY          BdsBootOptionList;\r
+  BOOLEAN                BootMngrMenuResetRequired;\r
+\r
+  gOption = NULL;\r
+  InitializeListHead (&BdsBootOptionList);\r
+\r
+  //\r
+  // Connect all prior to entering the platform setup menu.\r
+  //\r
+  if (!gConnectAllHappened) {\r
+    BdsLibConnectAllDriversToAllControllers ();\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+  //\r
+  // BugBug: Here we can not remove the legacy refresh macro, so we need\r
+  // get the boot order every time from "BootOrder" variable.\r
+  // Recreate the boot option list base on the BootOrder variable\r
+  //\r
+  BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
+\r
+  //\r
+  // This GUID must be the same as what is defined in BootManagerVfr.vfr\r
+  //\r
+  BmGuid            = gBmGuid;\r
+\r
+  mBootOptionsList  = &BdsBootOptionList;\r
+\r
+  //\r
+  // Post our VFR to the HII database\r
+  //\r
+  PackageList = PreparePackages (2, &BmGuid, BootManagerVfrBin, EdkGenericPlatformBdsLibStrings);\r
+  Status      = Hii->NewPack (Hii, PackageList, &gBootManagerHandle);\r
+  gBS->FreePool (PackageList);\r
+\r
+  //\r
+  // This example does not implement worker functions\r
+  // for the NV accessor functions.  Only a callback evaluator\r
+  //\r
+  BootManagerCallback.NvRead    = NULL;\r
+  BootManagerCallback.NvWrite   = NULL;\r
+  BootManagerCallback.Callback  = BootManagerCallbackRoutine;\r
+\r
+  //\r
+  // Install protocol interface\r
+  //\r
+  BootManagerCallbackHandle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &BootManagerCallbackHandle,\r
+                  &gEfiFormCallbackProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &BootManagerCallback\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  LastToken = 0;\r
+  Hii->NewString (Hii, NULL, gBootManagerHandle, &LastToken, L" ");\r
+\r
+  //\r
+  // Allocate space for creation of UpdateData Buffer\r
+  //\r
+  UpdateData = AllocateZeroPool (0x1000);\r
+  ASSERT (UpdateData != NULL);\r
+\r
+  //\r
+  // Flag update pending in FormSet\r
+  //\r
+  UpdateData->FormSetUpdate = TRUE;\r
+  //\r
+  // Register CallbackHandle data for FormSet\r
+  //\r
+  UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) BootManagerCallbackHandle;\r
+  UpdateData->FormUpdate  = FALSE;\r
+  UpdateData->FormTitle   = 0;\r
+  UpdateData->DataCount   = 1;\r
+\r
+  //\r
+  // Create blank space.  Since when we update the contents of IFR data at a label, it is\r
+  // inserted at the location of the label.  So if you want to add a string with an empty\r
+  // space afterwards, you need to add the space first and then the string like below.\r
+  //\r
+  Status = CreateSubTitleOpCode (\r
+            LastToken,        // Token Value for the string\r
+            &UpdateData->Data // Buffer containing created op-code\r
+            );\r
+\r
+  Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData);\r
+\r
+  //\r
+  // Create "Boot Option Menu" title\r
+  //\r
+  Status = CreateSubTitleOpCode (\r
+            STRING_TOKEN (STR_BOOT_OPTION_BANNER),  // Token Value for the string\r
+            &UpdateData->Data                       // Buffer containing created op-code\r
+            );\r
+\r
+  Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData);\r
+\r
+  Token                 = LastToken;\r
+  mKeyInput             = 0;\r
+\r
+  UpdateData->DataCount = 0;\r
+  Location              = (UINT8 *) &UpdateData->Data;\r
+\r
+  for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) {\r
+    Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+    //\r
+    // At this stage we are creating a menu entry, thus the Keys are reproduceable\r
+    //\r
+    mKeyInput++;\r
+    Token++;\r
+\r
+    Status = Hii->NewString (Hii, NULL, gBootManagerHandle, &Token, Option->Description);\r
+\r
+    //\r
+    // If we got an error it is almost certainly due to the token value being invalid.\r
+    // Therefore we will set the Token to 0 to automatically add a token.\r
+    //\r
+    if (EFI_ERROR (Status)) {\r
+      Token   = 0;\r
+      Status  = Hii->NewString (Hii, NULL, gBootManagerHandle, &Token, Option->Description);\r
+    }\r
+\r
+    Status = CreateGotoOpCode (\r
+              0x1000, // Form ID\r
+              Token,  // Token Value for the string\r
+              0,      // Help String (none)\r
+              EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,  // The Op-Code flags\r
+              mKeyInput,                                          // The Key to get a callback on\r
+              Location  // Buffer containing created op-code\r
+              );\r
+\r
+    UpdateData->DataCount++;\r
+    Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
+\r
+  }\r
+\r
+  Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0001, TRUE, UpdateData);\r
+\r
+  UpdateData->DataCount = 1;\r
+\r
+  //\r
+  // Create "Boot Option Menu" title\r
+  //\r
+  Status = CreateSubTitleOpCode (\r
+            STRING_TOKEN (STR_HELP_FOOTER), // Token Value for the string\r
+            &UpdateData->Data               // Buffer containing created op-code\r
+            );\r
+\r
+  Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData);\r
+\r
+  Status = CreateSubTitleOpCode (\r
+            LastToken,                      // Token Value for the string\r
+            &UpdateData->Data               // Buffer containing created op-code\r
+            );\r
+\r
+  Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData);\r
+\r
+  gBS->FreePool (UpdateData);\r
+\r
+  ASSERT (gBrowser);\r
+\r
+  BootMngrMenuResetRequired = FALSE;\r
+  gBrowser->SendForm (\r
+              gBrowser, \r
+              TRUE, \r
+              &gBootManagerHandle, \r
+              1, \r
+              NULL, \r
+              NULL, \r
+              NULL, \r
+              NULL, \r
+              &BootMngrMenuResetRequired\r
+              );\r
+\r
+  if (BootMngrMenuResetRequired) {\r
+    EnableResetRequired ();\r
+  }\r
+\r
+  Hii->ResetStrings (Hii, gBootManagerHandle);\r
+\r
+  if (gOption == NULL) {\r
+    return ;\r
+  }\r
+  \r
+  //\r
+  //Will leave browser, check any reset required change is applied? if yes, reset system\r
+  //\r
+  SetupResetReminder ();\r
+  \r
+  //\r
+  // BugBug: This code looks repeated from the BDS. Need to save code space.\r
+  //\r
+\r
+  //\r
+  // parse the selected option\r
+  //\r
+  Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    PlatformBdsBootSuccess (gOption);\r
+  } else {\r
+    PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);\r
+    gST->ConOut->OutputString (\r
+                  gST->ConOut,\r
+                  GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))\r
+                  );\r
+\r
+    //\r
+    // BdsLibUiWaitForSingleEvent (gST->ConIn->WaitForKey, 0);\r
+    //\r
+\r
+    gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+  }\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManager.h
new file mode 100644 (file)
index 0000000..f9b6bba
--- /dev/null
@@ -0,0 +1,50 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name: \r
+\r
+  BootManager.h\r
+\r
+Abstract:\r
+\r
+  The platform boot manager reference implement\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_BOOT_MANAGER_H\r
+#define _EFI_BOOT_MANAGER_H\r
+\r
+#include "Bds.h"\r
+//#include "EdkGenericPlatformBdsLib.h"\r
+#include "String.h"\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerCallbackRoutine (\r
+  IN EFI_FORM_CALLBACK_PROTOCOL       *This,\r
+  IN UINT16                           KeyValue,\r
+  IN EFI_IFR_DATA_ARRAY               *DataArray,\r
+  OUT EFI_HII_CALLBACK_PACKET         **Packet\r
+  );\r
+\r
+VOID\r
+CallBootManager (\r
+  VOID\r
+);\r
+\r
+#define BOOT_MANAGER_GUID \\r
+  { \\r
+    0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b } \\r
+  }\r
+\r
+#endif\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerStrings.uni b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerStrings.uni
new file mode 100644 (file)
index 0000000..684ac2f
Binary files /dev/null and b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerStrings.uni differ
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerVfr.Vfr b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/BootMngr/BootManagerVfr.Vfr
new file mode 100644 (file)
index 0000000..9daf7b8
--- /dev/null
@@ -0,0 +1,55 @@
+// *++\r
+//\r
+// Copyright (c) 2006, Intel Corporation                                                         \r
+// All rights reserved. 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
+// Module Name:\r
+//\r
+//   BootManager.vfr \r
+// \r
+// Abstract:\r
+// \r
+//   Browser formset.\r
+// \r
+// Revision History: \r
+// \r
+// --*/\r
+\r
+#include "EdkGenericPlatformBdsLibStrDefs.h"\r
+\r
+#define FORMSET_GUID  { 0x847bc3fe, 0xb974, 0x446d, { 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b } } \r
+\r
+#define BOOT_MANAGER_HEADER             0x00\r
+#define BOOT_MANAGER_LABEL              0x01\r
+#define BOOT_MANAGER_TAIL               0x02\r
+\r
+\r
+#define BOOT_MANAGER_CLASS       0x00\r
+#define BOOT_MANAGER_SUBCLASS    0x01\r
+\r
+formset \r
+  guid     = FORMSET_GUID,\r
+  title    = STRING_TOKEN(STR_BM_BANNER),  \r
+  help     = STRING_TOKEN(STR_LAST_STRING),\r
+  class    = BOOT_MANAGER_CLASS,      \r
+  subclass = BOOT_MANAGER_SUBCLASS,\r
+\r
+  form formid = 0x1000,\r
+       title  = STRING_TOKEN(STR_BM_BANNER);\r
+\r
+    label BOOT_MANAGER_HEADER;\r
+    label BOOT_MANAGER_LABEL;\r
+    //\r
+    // This is where we will dynamically add choices for the Boot Manager\r
+    //\r
+\r
+    label BOOT_MANAGER_TAIL;\r
+  endform;\r
+\r
+endformset;\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Capsules.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Capsules.c
new file mode 100644 (file)
index 0000000..23b83a3
--- /dev/null
@@ -0,0 +1,213 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  Capsules.c\r
+\r
+Abstract:\r
+\r
+  BDS routines to handle capsules.\r
+\r
+--*/\r
+\r
+\r
+#include <Common/FlashMap.h>\r
+\r
+VOID\r
+BdsLockFv (\r
+  IN EFI_CPU_IO_PROTOCOL          *CpuIo,\r
+  IN EFI_FLASH_SUBAREA_ENTRY      *FlashEntry\r
+  );\r
+\r
+VOID\r
+BdsLockFv (\r
+  IN EFI_CPU_IO_PROTOCOL          *CpuIo,\r
+  IN EFI_FLASH_SUBAREA_ENTRY      *FlashEntry\r
+  )\r
+{\r
+  EFI_FV_BLOCK_MAP_ENTRY      *BlockMap;\r
+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;\r
+  UINT64                      BaseAddress;\r
+  UINT8                       Data;\r
+  UINT32                      BlockLength;\r
+  UINTN                       Index;\r
+\r
+  BaseAddress = FlashEntry->Base - 0x400000 + 2;\r
+  FvHeader    = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (FlashEntry->Base));\r
+  BlockMap    = &(FvHeader->FvBlockMap[0]);\r
+\r
+  while ((BlockMap->NumBlocks != 0) && (BlockMap->BlockLength != 0)) {\r
+    BlockLength = BlockMap->BlockLength;\r
+    for (Index = 0; Index < BlockMap->NumBlocks; Index++) {\r
+      CpuIo->Mem.Read (\r
+                  CpuIo,\r
+                  EfiCpuIoWidthUint8,\r
+                  BaseAddress,\r
+                  1,\r
+                  &Data\r
+                  );\r
+      Data = (UINT8) (Data | 0x3);\r
+      CpuIo->Mem.Write (\r
+                  CpuIo,\r
+                  EfiCpuIoWidthUint8,\r
+                  BaseAddress,\r
+                  1,\r
+                  &Data\r
+                  );\r
+      BaseAddress += BlockLength;\r
+    }\r
+\r
+    BlockMap++;\r
+  }\r
+}\r
+\r
+VOID\r
+BdsLockNonUpdatableFlash (\r
+  VOID\r
+  )\r
+{\r
+  EFI_FLASH_MAP_ENTRY_DATA  *FlashMapEntryData;\r
+  EFI_PEI_HOB_POINTERS      GuidHob;\r
+  EFI_STATUS                Status;\r
+  EFI_CPU_IO_PROTOCOL       *CpuIo;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, (VOID**)&CpuIo);\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  GuidHob.Raw = GetHobList ();\r
+  while ((GuidHob.Raw = GetNextGuidHob (&gEfiFlashMapHobGuid, GuidHob.Raw)) != NULL) {\r
+    FlashMapEntryData = (EFI_FLASH_MAP_ENTRY_DATA *) GET_GUID_HOB_DATA (GuidHob.Guid);\r
+\r
+    //\r
+    // Get the variable store area\r
+    //\r
+    if ((FlashMapEntryData->AreaType == EFI_FLASH_AREA_RECOVERY_BIOS) ||\r
+        (FlashMapEntryData->AreaType == EFI_FLASH_AREA_MAIN_BIOS)\r
+        ) {\r
+      BdsLockFv (CpuIo, &(FlashMapEntryData->Entries[0]));\r
+    }\r
+    GuidHob.Raw = GET_NEXT_HOB (GuidHob);\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+EFI_STATUS\r
+ProcessCapsules (\r
+  EFI_BOOT_MODE BootMode\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine is called to see if there are any capsules we need to process.\r
+  If the boot mode is not UPDATE, then we do nothing. Otherwise find the\r
+  capsule HOBS and produce firmware volumes for them via the DXE service.\r
+  Then call the dispatcher to dispatch drivers from them. Finally, check\r
+  the status of the updates.\r
+\r
+Arguments:\r
+\r
+  BootMode - the current boot mode\r
+\r
+Returns:\r
+  \r
+  EFI_INVALID_PARAMETER - boot mode is not correct for an update\r
+\r
+Note:\r
\r
+ This function should be called by BDS in case we need to do some\r
+ sort of processing even if there is no capsule to process. We\r
+ need to do this if an earlier update went awry and we need to\r
+ clear the capsule variable so on the next reset PEI does not see it and \r
+ think there is a capsule available.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_HOB_CAPSULE_VOLUME      *CvHob;\r
+  EFI_PHYSICAL_ADDRESS        BaseAddress;\r
+  UINT64                      Length;\r
+  EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader;\r
+  EFI_HANDLE                  FvProtocolHandle;\r
+\r
+  //\r
+  // We don't do anything else if the boot mode is not flash-update\r
+  //\r
+  if (BootMode != BOOT_ON_FLASH_UPDATE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Only one capsule HOB allowed.\r
+  //\r
+  CvHob = GetFirstHob (EFI_HOB_TYPE_CV);\r
+  if (CvHob == NULL) {\r
+    //\r
+    // We didn't find a hob, so had no errors.\r
+    //\r
+    BdsLockNonUpdatableFlash ();\r
+    return EFI_SUCCESS;\r
+  }\r
+  \r
+  BaseAddress = CvHob->BaseAddress;\r
+  Length      = CvHob->Length;\r
+\r
+  Status      = EFI_SUCCESS;\r
+  //\r
+  // Now walk the capsule and call the core to process each\r
+  // firmware volume in it.\r
+  //\r
+  while (Length != 0) {\r
+    //\r
+    // Point to the next firmware volume header, and then\r
+    // call the DXE service to process it.\r
+    //\r
+    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress;\r
+    if (FwVolHeader->FvLength > Length) {\r
+      //\r
+      // Notes: need to stuff this status somewhere so that the\r
+      // error can be detected at OS runtime\r
+      //\r
+      Status = EFI_VOLUME_CORRUPTED;\r
+      break;\r
+    }\r
+\r
+    Status = gDS->ProcessFirmwareVolume (\r
+                    (VOID *) (UINTN) BaseAddress,\r
+                    (UINTN) FwVolHeader->FvLength,\r
+                    &FvProtocolHandle\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+    //\r
+    // Call the dispatcher to dispatch any drivers from the produced firmware volume\r
+    //\r
+    gDS->Dispatch ();\r
+    //\r
+    // On to the next FV in the capsule\r
+    //\r
+    Length -= FwVolHeader->FvLength;\r
+    BaseAddress = (EFI_PHYSICAL_ADDRESS) ((UINTN) BaseAddress + FwVolHeader->FvLength);\r
+    //\r
+    // Notes: when capsule spec is finalized, if the requirement is made to\r
+    // have each FV in a capsule aligned, then we will need to align the\r
+    // BaseAddress and Length here.\r
+    //\r
+  }\r
+   \r
+\r
+  BdsLockNonUpdatableFlash ();\r
+\r
+  return Status;\r
+}\r
+\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManager.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManager.c
new file mode 100644 (file)
index 0000000..3de404b
--- /dev/null
@@ -0,0 +1,497 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name: \r
+\r
+  DeviceManager.c\r
+\r
+Abstract:\r
+\r
+  The platform device manager reference implement\r
+\r
+--*/\r
+#include "DeviceManager.h"\r
+\r
+STATIC UINT16                     mTokenCount;\r
+EFI_FRONTPAGE_CALLBACK_INFO       FPCallbackInfo;\r
+extern UINTN                      gCallbackKey;\r
+extern EFI_FORM_BROWSER_PROTOCOL  *gBrowser;\r
+extern EFI_GUID                   gBdsStringPackGuid;\r
+extern BOOLEAN                    gConnectAllHappened;\r
+\r
+STRING_REF                        gStringTokenTable[] = {\r
+  STR_VIDEO_DEVICE,\r
+  STR_NETWORK_DEVICE,\r
+  STR_INPUT_DEVICE,\r
+  STR_ON_BOARD_DEVICE,\r
+  STR_OTHER_DEVICE,\r
+  STR_EMPTY_STRING,\r
+  0xFFFF\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceManagerCallbackRoutine (\r
+  IN EFI_FORM_CALLBACK_PROTOCOL       *This,\r
+  IN UINT16                           KeyValue,\r
+  IN EFI_IFR_DATA_ARRAY               *DataArray,\r
+  OUT EFI_HII_CALLBACK_PACKET         **Packet\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This is the function that is called to provide results data to the driver.  This data\r
+  consists of a unique key which is used to identify what data is either being passed back\r
+  or being asked for. \r
+\r
+Arguments:\r
+\r
+  KeyValue -        A unique value which is sent to the original exporting driver so that it\r
+                    can identify the type of data to expect.  The format of the data tends to\r
+                    vary based on the op-code that geerated the callback.\r
+\r
+  Data -            A pointer to the data being sent to the original exporting driver.\r
+\r
+Returns: \r
+\r
+--*/\r
+{\r
+  //\r
+  // The KeyValue corresponds in this case to the handle which was requested to be displayed\r
+  //\r
+  EFI_FRONTPAGE_CALLBACK_INFO *CallbackInfo;\r
+\r
+  CallbackInfo = EFI_FP_CALLBACK_DATA_FROM_THIS (This);\r
+  switch (KeyValue) {\r
+  case 0x2000:\r
+    CallbackInfo->Data.VideoBIOS = (UINT8) (UINTN) (((EFI_IFR_DATA_ENTRY *)(DataArray + 1))->Data);\r
+    gRT->SetVariable (\r
+          L"VBIOS",\r
+          &gEfiGlobalVariableGuid,\r
+          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+          sizeof (UINT8),\r
+          &CallbackInfo->Data.VideoBIOS\r
+          );\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  gCallbackKey = KeyValue;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeDeviceManager (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initialize HII information for the FrontPage\r
+\r
+Arguments:\r
+  None\r
+            \r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS          Status;\r
+  EFI_HII_PACKAGES    *PackageList;\r
+  EFI_HII_UPDATE_DATA *UpdateData;\r
+\r
+  //\r
+  // Allocate space for creation of UpdateData Buffer\r
+  //\r
+  UpdateData = AllocateZeroPool (0x1000);\r
+  ASSERT (UpdateData != NULL);\r
+\r
+  PackageList = PreparePackages (1, &gBdsStringPackGuid, DeviceManagerVfrBin);\r
+  Status      = Hii->NewPack (Hii, PackageList, &FPCallbackInfo.DevMgrHiiHandle);\r
+  gBS->FreePool (PackageList);\r
+\r
+  //\r
+  // This example does not implement worker functions for the NV accessor functions.  Only a callback evaluator\r
+  //\r
+  FPCallbackInfo.Signature                = EFI_FP_CALLBACK_DATA_SIGNATURE;\r
+  FPCallbackInfo.DevMgrCallback.NvRead    = NULL;\r
+  FPCallbackInfo.DevMgrCallback.NvWrite   = NULL;\r
+  FPCallbackInfo.DevMgrCallback.Callback  = DeviceManagerCallbackRoutine;\r
+\r
+  //\r
+  // Install protocol interface\r
+  //\r
+  FPCallbackInfo.CallbackHandle = NULL;\r
+\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &FPCallbackInfo.CallbackHandle,\r
+                  &gEfiFormCallbackProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &FPCallbackInfo.DevMgrCallback\r
+                  );\r
+\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Flag update pending in FormSet\r
+  //\r
+  UpdateData->FormSetUpdate = TRUE;\r
+  //\r
+  // Register CallbackHandle data for FormSet\r
+  //\r
+  UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) FPCallbackInfo.CallbackHandle;\r
+  //\r
+  // Simply registering the callback handle\r
+  //\r
+  Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData);\r
+\r
+  gBS->FreePool (UpdateData);\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+CallDeviceManager (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Call the browser and display the device manager\r
+\r
+Arguments:\r
+  \r
+  None\r
+  \r
+Returns:\r
+  EFI_SUCCESS            - Operation is successful.\r
+  EFI_INVALID_PARAMETER  - If the inputs to SendForm function is not valid.\r
+  \r
+--*/\r
+{\r
+  EFI_STATUS          Status;\r
+  UINTN               BufferSize;\r
+  UINTN               Count;\r
+  EFI_HII_HANDLE      Index;\r
+  UINT8               *Buffer;\r
+  EFI_IFR_FORM_SET    *FormSetData;\r
+  CHAR16              *String;\r
+  UINTN               StringLength;\r
+  EFI_HII_UPDATE_DATA *UpdateData;\r
+  STRING_REF          Token;\r
+  STRING_REF          TokenHelp;\r
+  IFR_OPTION          *IfrOptionList;\r
+  UINT8               *VideoOption;\r
+  UINTN               VideoOptionSize;\r
+  EFI_HII_HANDLE      *HiiHandles;\r
+  UINT16              HandleBufferLength;\r
+  BOOLEAN                BootDeviceMngrMenuResetRequired;\r
+\r
+  IfrOptionList       = NULL;\r
+  VideoOption         = NULL;\r
+  HiiHandles          = NULL;\r
+  HandleBufferLength  = 0;\r
+\r
+  //\r
+  // Connect all prior to entering the platform setup menu.\r
+  //\r
+  if (!gConnectAllHappened) {\r
+    BdsLibConnectAllDriversToAllControllers ();\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+  //\r
+  // Allocate space for creation of UpdateData Buffer\r
+  //\r
+  UpdateData = AllocateZeroPool (0x1000);\r
+  ASSERT (UpdateData != NULL);\r
+\r
+  Status        = EFI_SUCCESS;\r
+  Buffer        = NULL;\r
+  FormSetData   = NULL;\r
+  gCallbackKey  = 0;\r
+  if (mTokenCount == 0) {\r
+    Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &mTokenCount, L" ");\r
+  }\r
+\r
+  Token     = mTokenCount;\r
+  TokenHelp = (UINT16) (Token + 1);\r
+\r
+  //\r
+  // Reset the menu\r
+  //\r
+  for (Index = 0, Count = 1; Count < 0x10000; Count <<= 1, Index++) {\r
+    //\r
+    // We will strip off all previous menu entries\r
+    //\r
+    UpdateData->DataCount = 0xFF;\r
+\r
+    //\r
+    // Erase entries on this label\r
+    //\r
+    Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, FALSE, UpdateData);\r
+\r
+    //\r
+    // Did we reach the end of the Token Table?\r
+    //\r
+    if (gStringTokenTable[Index] == 0xFFFF) {\r
+      break;\r
+    }\r
+\r
+    CreateSubTitleOpCode (gStringTokenTable[Index], &UpdateData->Data);\r
+    //\r
+    // Add a single menu item - in this case a subtitle for the device type\r
+    //\r
+    UpdateData->DataCount = 1;\r
+\r
+    //\r
+    // Add default title for this label\r
+    //\r
+    Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData);\r
+  }\r
+  //\r
+  // Add a space and an exit string.  Remember since we add things at the label and push other things beyond the\r
+  // label down, we add this in reverse order\r
+  //\r
+  CreateSubTitleOpCode (STRING_TOKEN (STR_EXIT_STRING), &UpdateData->Data);\r
+  Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData);\r
+  CreateSubTitleOpCode (STR_EMPTY_STRING, &UpdateData->Data);\r
+  Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData);\r
+\r
+  //\r
+  // Get all the Hii handles\r
+  //\r
+  Status = BdsLibGetHiiHandles (Hii, &HandleBufferLength, &HiiHandles);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  for (Index = 1, BufferSize = 0; Index < HandleBufferLength; Index++) {\r
+    //\r
+    // Am not initializing Buffer since the first thing checked is the size\r
+    // this way I can get the real buffersize in the smallest code size\r
+    //\r
+    Status = Hii->GetForms (Hii, Index, 0, &BufferSize, Buffer);\r
+\r
+    if (Status != EFI_NOT_FOUND) {\r
+      //\r
+      // BufferSize should have the real size of the forms now\r
+      //\r
+      Buffer = AllocateZeroPool (BufferSize);\r
+      ASSERT (Buffer != NULL);\r
+\r
+      //\r
+      // Am not initializing Buffer since the first thing checked is the size\r
+      // this way I can get the real buffersize in the smallest code size\r
+      //\r
+      Status = Hii->GetForms (Hii, Index, 0, &BufferSize, Buffer);\r
+\r
+      //\r
+      // Skip EFI_HII_PACK_HEADER, advance to EFI_IFR_FORM_SET data.\r
+      //\r
+      FormSetData = (EFI_IFR_FORM_SET *) (Buffer + sizeof (EFI_HII_PACK_HEADER));\r
+\r
+      //\r
+      // If this formset belongs in the device manager, add it to the menu\r
+      //\r
+      if (FormSetData->Class != EFI_NON_DEVICE_CLASS) {\r
+\r
+        StringLength  = 0x1000;\r
+        String        = AllocateZeroPool (StringLength);\r
+        ASSERT (String != NULL);\r
+\r
+        Status  = Hii->GetString (Hii, Index, FormSetData->FormSetTitle, TRUE, NULL, &StringLength, String);\r
+        Status  = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &Token, String);\r
+\r
+        //\r
+        // If token value exceeded real token value - we need to add a new token values\r
+        //\r
+        if (Status == EFI_INVALID_PARAMETER) {\r
+          Token     = 0;\r
+          TokenHelp = 0;\r
+          Status    = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &Token, String);\r
+        }\r
+\r
+        StringLength = 0x1000;\r
+        if (FormSetData->Help == 0) {\r
+          TokenHelp = 0;\r
+        } else {\r
+          Status = Hii->GetString (Hii, Index, FormSetData->Help, TRUE, NULL, &StringLength, String);\r
+          if (StringLength == 0x02) {\r
+            TokenHelp = 0;\r
+          } else {\r
+            Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &TokenHelp, String);\r
+            if (Status == EFI_INVALID_PARAMETER) {\r
+              TokenHelp = 0;\r
+              Status    = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &TokenHelp, String);\r
+            }\r
+          }\r
+        }\r
+\r
+        gBS->FreePool (String);\r
+\r
+        CreateGotoOpCode (\r
+          0x1000,     // Device Manager Page\r
+          Token,      // Description String Token\r
+          TokenHelp,  // Description Help String Token\r
+          EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,  // Flag designating callback is active\r
+          (UINT16) Index,                                     // Callback key value\r
+          &UpdateData->Data                                   // Buffer to fill with op-code\r
+          );\r
+\r
+        //\r
+        // In the off-chance that we have lots of extra tokens allocated to the DeviceManager\r
+        // this ensures we are fairly re-using the tokens instead of constantly growing the token\r
+        // storage for this one handle.  If we incremented the token value beyond what it normally\r
+        // would use, we will fall back into the error path which seeds the token value with a 0\r
+        // so that we can correctly add a token value.\r
+        //\r
+        if (TokenHelp == 0) {\r
+          //\r
+          // Since we didn't add help, only advance Token by 1\r
+          //\r
+          Token++;\r
+        } else {\r
+          Token     = (UINT16) (Token + 2);\r
+          TokenHelp = (UINT16) (TokenHelp + 2);\r
+        }\r
+        //\r
+        // This for loop basically will take the Class value which is a bitmask and\r
+        // update the form for every active bit.  There will be a label at each bit\r
+        // location.  So if someone had a device which a class of EFI_DISK_DEVICE_CLASS |\r
+        // EFI_ON_BOARD_DEVICE_CLASS, this routine will unwind that mask and drop the menu entry\r
+        // on each corresponding label.\r
+        //\r
+        for (Count = 1; Count < 0x10000; Count <<= 1) {\r
+          //\r
+          // This is an active bit, so update the form\r
+          //\r
+          if (FormSetData->Class & Count) {\r
+            Hii->UpdateForm (\r
+                  Hii,\r
+                  FPCallbackInfo.DevMgrHiiHandle,\r
+                  (EFI_FORM_LABEL) (FormSetData->Class & Count),\r
+                  TRUE,\r
+                  UpdateData\r
+                  );\r
+          }\r
+        }\r
+      }\r
+\r
+      BufferSize = 0;\r
+      //\r
+      // Reset Buffer pointer to original location\r
+      //\r
+      gBS->FreePool (Buffer);\r
+    }\r
+  }\r
+  //\r
+  // Add oneof for video BIOS selection\r
+  //\r
+  VideoOption = BdsLibGetVariableAndSize (\r
+                  L"VBIOS",\r
+                  &gEfiGlobalVariableGuid,\r
+                  &VideoOptionSize\r
+                  );\r
+  if (NULL == VideoOption) {\r
+    FPCallbackInfo.Data.VideoBIOS = 0;\r
+  } else {\r
+    FPCallbackInfo.Data.VideoBIOS = VideoOption[0];\r
+    gBS->FreePool (VideoOption);\r
+  }\r
+\r
+  ASSERT (FPCallbackInfo.Data.VideoBIOS <= 1);\r
+\r
+  Status = gBS->AllocatePool (EfiBootServicesData, 2 * sizeof (IFR_OPTION), (VOID**) &IfrOptionList);\r
+  if (IfrOptionList != NULL) {\r
+    IfrOptionList[0].Flags        = EFI_IFR_FLAG_INTERACTIVE;\r
+    IfrOptionList[0].Key          = SET_VIDEO_BIOS_TYPE_QUESTION_ID + 0x2000;\r
+    IfrOptionList[0].StringToken  = STRING_TOKEN (STR_ONE_OF_PCI);\r
+    IfrOptionList[0].Value        = 0;\r
+    IfrOptionList[0].OptionString = NULL;\r
+    IfrOptionList[1].Flags        = EFI_IFR_FLAG_INTERACTIVE;\r
+    IfrOptionList[1].Key          = SET_VIDEO_BIOS_TYPE_QUESTION_ID + 0x2000;\r
+    IfrOptionList[1].StringToken  = STRING_TOKEN (STR_ONE_OF_AGP);\r
+    IfrOptionList[1].Value        = 1;\r
+    IfrOptionList[1].OptionString = NULL;\r
+    IfrOptionList[FPCallbackInfo.Data.VideoBIOS].Flags |= EFI_IFR_FLAG_DEFAULT;\r
+\r
+    CreateOneOfOpCode (\r
+      SET_VIDEO_BIOS_TYPE_QUESTION_ID,\r
+      (UINT8) 1,\r
+      STRING_TOKEN (STR_ONE_OF_VBIOS),\r
+      STRING_TOKEN (STR_ONE_OF_VBIOS_HELP),\r
+      IfrOptionList,\r
+      2,\r
+      &UpdateData->Data\r
+      );\r
+\r
+    UpdateData->DataCount = 4;\r
+    Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) EFI_VBIOS_CLASS, TRUE, UpdateData);\r
+    gBS->FreePool (IfrOptionList);\r
+  }\r
+\r
+  BootDeviceMngrMenuResetRequired = FALSE;\r
+  Status = gBrowser->SendForm (\r
+                      gBrowser,\r
+                      TRUE,                             // Use the database\r
+                      &FPCallbackInfo.DevMgrHiiHandle,  // The HII Handle\r
+                      1,\r
+                      NULL,\r
+                      FPCallbackInfo.CallbackHandle,\r
+                      (UINT8 *) &FPCallbackInfo.Data,\r
+                      NULL,\r
+                      &BootDeviceMngrMenuResetRequired\r
+                      );\r
+\r
+  if (BootDeviceMngrMenuResetRequired) {\r
+    EnableResetRequired ();\r
+  }\r
+\r
+  Hii->ResetStrings (Hii, FPCallbackInfo.DevMgrHiiHandle);\r
+\r
+  //\r
+  // We will have returned from processing a callback - user either hit ESC to exit, or selected\r
+  // a target to display\r
+  //\r
+  if (gCallbackKey != 0 && gCallbackKey < 0x2000) {\r
+    BootDeviceMngrMenuResetRequired = FALSE;\r
+    Status = gBrowser->SendForm (\r
+                        gBrowser,\r
+                        TRUE,                             // Use the database\r
+                        (EFI_HII_HANDLE *) &gCallbackKey, // The HII Handle\r
+                        1,\r
+                        NULL,\r
+                        NULL,                             // This is the handle that the interface to the callback was installed on\r
+                        NULL,\r
+                        NULL,\r
+                        &BootDeviceMngrMenuResetRequired\r
+                        );\r
+\r
+    if (BootDeviceMngrMenuResetRequired) {\r
+      EnableResetRequired ();\r
+    }\r
+    //\r
+    // Force return to Device Manager\r
+    //\r
+    gCallbackKey = 4;\r
+  }\r
+\r
+  if (gCallbackKey >= 0x2000) {\r
+    gCallbackKey = 4;\r
+  }\r
+\r
+  gBS->FreePool (UpdateData);\r
+  gBS->FreePool (HiiHandles);\r
+\r
+  return Status;\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManager.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManager.h
new file mode 100644 (file)
index 0000000..54aeb45
--- /dev/null
@@ -0,0 +1,59 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name: \r
+\r
+  DeviceManager.c\r
+\r
+Abstract:\r
+\r
+  The platform device manager reference implement\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _DEVICE_MANAGER_H\r
+#define _DEVICE_MANAGER_H\r
+\r
+#include "FrontPage.h"\r
+\r
+#define EFI_NON_DEVICE_CLASS              0x00  // Useful when you do not want something in the Device Manager\r
+#define EFI_DISK_DEVICE_CLASS             0x01\r
+#define EFI_VIDEO_DEVICE_CLASS            0x02\r
+#define EFI_NETWORK_DEVICE_CLASS          0x04\r
+#define EFI_INPUT_DEVICE_CLASS            0x08\r
+#define EFI_ON_BOARD_DEVICE_CLASS         0x10\r
+#define EFI_OTHER_DEVICE_CLASS            0x20\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceManagerCallbackRoutine (\r
+  IN EFI_FORM_CALLBACK_PROTOCOL       *This,\r
+  IN UINT16                           KeyValue,\r
+  IN EFI_IFR_DATA_ARRAY               *DataArray,\r
+  OUT EFI_HII_CALLBACK_PACKET         **Packet\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+InitializeDeviceManager (\r
+  VOID\r
+  )\r
+;\r
+\r
+EFI_STATUS\r
+CallDeviceManager (\r
+  VOID\r
+  )\r
+;\r
+\r
+#endif\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerStrings.uni b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerStrings.uni
new file mode 100644 (file)
index 0000000..f549ff2
Binary files /dev/null and b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerStrings.uni differ
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerVfr.Vfr b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/DeviceMngr/DeviceManagerVfr.Vfr
new file mode 100644 (file)
index 0000000..3419583
--- /dev/null
@@ -0,0 +1,75 @@
+// *++\r
+//\r
+// Copyright (c) 2006, Intel Corporation                                                         \r
+// All rights reserved. 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
+// Module Name:\r
+//\r
+//   DeviceManagerVfr.vfr \r
+// \r
+// Abstract:\r
+// \r
+//   Device Manager formset.\r
+// \r
+// Revision History: \r
+// \r
+// --*/\r
+\r
+#include "EdkGenericPlatformBdsLibStrDefs.h"\r
+\r
+#define FORMSET_GUID  { 0x3ebfa8e6, 0x511d, 0x4b5b, { 0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 } }\r
+\r
+#define EFI_DISK_DEVICE_CLASS              0x01\r
+#define EFI_VIDEO_DEVICE_CLASS             0x02\r
+#define EFI_NETWORK_DEVICE_CLASS           0x04\r
+#define EFI_INPUT_DEVICE_CLASS             0x08\r
+#define EFI_ON_BOARD_DEVICE_CLASS          0x10\r
+#define EFI_OTHER_DEVICE_CLASS             0x20\r
+#define EFI_VBIOS_CLASS                    0x40\r
+\r
+#define DEVICE_MANAGER_CLASS               0x0000\r
+#define FRONT_PAGE_SUBCLASS                         0x0003\r
+\r
+formset \r
+  guid     = FORMSET_GUID,\r
+  title    = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE),  \r
+  help     = STRING_TOKEN(STR_EMPTY_STRING),\r
+  class    = DEVICE_MANAGER_CLASS,      \r
+  subclass = FRONT_PAGE_SUBCLASS,\r
+\r
+  form formid = 0x1000,\r
+       title  = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE);\r
+\r
+    //\r
+    // This is where devices get added to the device manager hierarchy\r
+    //\r
+    subtitle text = STRING_TOKEN(STR_DISK_DEVICE);\r
+    label EFI_DISK_DEVICE_CLASS;\r
+\r
+    subtitle text = STRING_TOKEN(STR_VIDEO_DEVICE);\r
+    label EFI_VIDEO_DEVICE_CLASS;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NETWORK_DEVICE);\r
+    label EFI_NETWORK_DEVICE_CLASS;\r
+\r
+    subtitle text = STRING_TOKEN(STR_INPUT_DEVICE);\r
+    label EFI_INPUT_DEVICE_CLASS;\r
+\r
+    subtitle text = STRING_TOKEN(STR_ON_BOARD_DEVICE);\r
+    label EFI_ON_BOARD_DEVICE_CLASS;\r
+\r
+    subtitle text = STRING_TOKEN(STR_OTHER_DEVICE);\r
+    label EFI_OTHER_DEVICE_CLASS;\r
+    \r
+    subtitle text = STRING_TOKEN(STR_EMPTY_STRING);\r
+    label EFI_VBIOS_CLASS;\r
+    \r
+  endform;\r
+endformset;\r
+\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/EdkGenericPlatformBdsLib.msa b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/EdkGenericPlatformBdsLib.msa
new file mode 100644 (file)
index 0000000..828ab8d
--- /dev/null
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <MsaHeader>
+    <ModuleName>EdkPlatformGenericBdsLib</ModuleName>
+    <ModuleType>DXE_DRIVER</ModuleType>
+    <GuidValue>f392b762-8985-11db-be87-0040d02b1835</GuidValue>
+    <Version>1.0</Version>
+    <Abstract>Generic BDS library</Abstract>
+    <Description>Do generic action.</Description>
+    <Copyright>Copyright (c) 2006, Intel Corporation</Copyright>
+    <License>All rights reserved. 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.</License>
+    <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052</Specification>
+  </MsaHeader>
+  <ModuleDefinitions>
+    <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+    <BinaryModule>false</BinaryModule>
+    <OutputFileBasename>EdkGenericPlatformBdsLib</OutputFileBasename>
+  </ModuleDefinitions>
+  <LibraryClassDefinitions>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>DebugLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>UefiLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>UefiDriverEntryPoint</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>BaseLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>EdkGraphicsLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>DxeServicesTableLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>PerformanceLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>PrintLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>EdkIfrSupportLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>ReportStatusCodeLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>HobLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>EdkGenericBdsLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>MemoryAllocationLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>BaseMemoryLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>UefiBootServicesTableLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>UefiRuntimeServicesTableLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>DevicePathLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>HiiLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_PRODUCED">
+      <Keyword>EdkGenericPlatformBdsLib</Keyword>
+    </LibraryClass>
+    <LibraryClass Usage="ALWAYS_CONSUMED">
+      <Keyword>PeCoffLib</Keyword>
+    </LibraryClass>
+  </LibraryClassDefinitions>
+  <SourceFiles>
+    <Filename>Bds.h</Filename>
+    <Filename>BdsEntry.c</Filename>
+    <Filename>BdsBoot.c</Filename>
+    <Filename>FrontPage.h</Filename>
+    <Filename>FrontPage.c</Filename>
+    <Filename>FrontPageStrings.uni</Filename>
+    <Filename>FrontPageVfr.Vfr</Filename>
+    <Filename>Language.h</Filename>
+    <Filename>Language.c</Filename>
+    <Filename>String.h</Filename>
+    <Filename>String.c</Filename>
+    <Filename>Strings.uni</Filename>
+    <Filename>Capsules.c</Filename>
+    <Filename>MemoryTest.c</Filename>
+    <Filename>BootMaint/BmString.uni</Filename>
+    <Filename>BootMaint/Bm.vfr</Filename>
+    <Filename>BootMaint/BBSsupport.h</Filename>
+    <Filename>BootMaint/BootMaint.h</Filename>
+    <Filename>BootMaint/FormGuid.h</Filename>
+    <Filename>BootMaint/BmLib.c</Filename>
+    <Filename>BootMaint/BootOption.c</Filename>
+    <Filename>BootMaint/ConsoleOption.c</Filename>
+    <Filename>BootMaint/Data.c</Filename>
+    <Filename>BootMaint/Variable.c</Filename>
+    <Filename>BootMaint/UpdatePage.c</Filename>
+    <Filename>BootMaint/BBSsupport.c</Filename>
+    <Filename>BootMaint/BootMaint.c</Filename>
+    <Filename>BootMaint/FileExplorer.c</Filename>
+    <Filename>BootMaint/FE.vfr</Filename>
+    <Filename>BootMngr/BootManager.h</Filename>
+    <Filename>BootMngr/BootManager.c</Filename>
+    <Filename>BootMngr/BootManagerStrings.uni</Filename>
+    <Filename>BootMngr/BootManagerVfr.Vfr</Filename>
+    <Filename>DeviceMngr/DeviceManager.h</Filename>
+    <Filename>DeviceMngr/DeviceManager.c</Filename>
+    <Filename>DeviceMngr/DeviceManagerStrings.uni</Filename>
+    <Filename>DeviceMngr/DeviceManagerVfr.Vfr</Filename>
+    <!--<Filename>Bds.dxs</Filename>-->
+  </SourceFiles>
+  <PackageDependencies>
+    <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+    <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+  </PackageDependencies>
+  <Protocols>
+    <Protocol Usage="ALWAYS_PRODUCED">
+      <ProtocolCName>gEfiBdsArchProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiLegacyBiosProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiUgaSplashProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiHiiProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiFormCallbackProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiDataHubProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiFormBrowserProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiConsoleControlProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiCpuIoProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiUgaDrawProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiLoadFileProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiSimpleFileSystemProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiBlockIoProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiSerialIoProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="ALWAYS_CONSUMED">
+      <ProtocolCName>gEfiGenericMemTestProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="SOMETIMES_CONSUMED">
+      <ProtocolCName>gEfiCpuArchProtocolGuid</ProtocolCName>
+    </Protocol>
+    <Protocol Usage="SOMETIMES_CONSUMED">
+      <ProtocolCName>gEfiDriverBindingProtocolGuid</ProtocolCName>
+    </Protocol>
+  </Protocols>
+  <DataHubs>
+    <DataHubRecord Usage="SOMETIMES_CONSUMED">
+      <DataHubCName>BiosVendor</DataHubCName>
+    </DataHubRecord>
+    <DataHubRecord Usage="SOMETIMES_CONSUMED">
+      <DataHubCName>SystemManufacturer</DataHubCName>
+    </DataHubRecord>
+    <DataHubRecord Usage="SOMETIMES_CONSUMED">
+      <DataHubCName>ProcessorVersion</DataHubCName>
+    </DataHubRecord>
+    <DataHubRecord Usage="SOMETIMES_CONSUMED">
+      <DataHubCName>ProcessorFrequency</DataHubCName>
+    </DataHubRecord>
+    <DataHubRecord Usage="SOMETIMES_CONSUMED">
+      <DataHubCName>MemoryArray</DataHubCName>
+    </DataHubRecord>
+    <DataHubRecord Usage="SOMETIMES_CONSUMED">
+      <DataHubCName>SerialIoDevice</DataHubCName>
+    </DataHubRecord>
+    <DataHubRecord Usage="SOMETIMES_CONSUMED">
+      <DataHubCName>SerialIoPort</DataHubCName>
+    </DataHubRecord>
+  </DataHubs>
+  <Guids>
+    <GuidCNames Usage="ALWAYS_CONSUMED">
+      <GuidCName>gEfiBootStateGuid</GuidCName>
+    </GuidCNames>
+    <GuidCNames Usage="ALWAYS_CONSUMED">
+      <GuidCName>gEfiGlobalVariableGuid</GuidCName>
+    </GuidCNames>
+    <GuidCNames Usage="ALWAYS_CONSUMED">
+      <GuidCName>gEfiFlashMapHobGuid</GuidCName>
+    </GuidCNames>
+    <GuidCNames Usage="ALWAYS_CONSUMED">
+      <GuidCName>gEfiFileSystemVolumeLabelInfoIdGuid</GuidCName>
+    </GuidCNames>
+    <GuidCNames Usage="ALWAYS_CONSUMED">
+      <GuidCName>gEfiFileInfoGuid</GuidCName>
+    </GuidCNames>
+  </Guids>
+  <Externs>
+    <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+    <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+  </Externs>
+</ModuleSurfaceArea>
\ No newline at end of file
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPage.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPage.c
new file mode 100644 (file)
index 0000000..bcbde1a
--- /dev/null
@@ -0,0 +1,901 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  FrontPage.c\r
+\r
+Abstract:\r
+\r
+  FrontPage routines to handle the callbacks and browser calls\r
+  \r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+#include "String.h"\r
+\r
+EFI_GUID                    mProcessorSubClass  = EFI_PROCESSOR_SUBCLASS_GUID;\r
+EFI_GUID                    mMemorySubClass     = EFI_MEMORY_SUBCLASS_GUID;\r
+EFI_GUID                    mMiscSubClass       = EFI_MISC_SUBCLASS_GUID;\r
+\r
+UINT16                      mLastSelection;\r
+EFI_HII_HANDLE              gFrontPageHandle;\r
+EFI_HANDLE                  FrontPageCallbackHandle;\r
+EFI_FORM_CALLBACK_PROTOCOL  FrontPageCallback;\r
+EFI_FORM_BROWSER_PROTOCOL   *gBrowser;\r
+UINTN                       gCallbackKey;\r
+BOOLEAN                     gConnectAllHappened = FALSE;\r
+\r
+extern EFI_HII_HANDLE       gFrontPageHandle;\r
+extern EFI_GUID             gBdsStringPackGuid;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FrontPageCallbackRoutine (\r
+  IN EFI_FORM_CALLBACK_PROTOCOL       *This,\r
+  IN UINT16                           KeyValue,\r
+  IN EFI_IFR_DATA_ARRAY               *DataArray,\r
+  OUT EFI_HII_CALLBACK_PACKET         **Packet\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This is the function that is called to provide results data to the driver.  This data\r
+  consists of a unique key which is used to identify what data is either being passed back\r
+  or being asked for. \r
+\r
+Arguments:\r
+\r
+  KeyValue -        A unique value which is sent to the original exporting driver so that it\r
+                    can identify the type of data to expect.  The format of the data tends to\r
+                    vary based on the op-code that geerated the callback.\r
+\r
+  Data -            A pointer to the data being sent to the original exporting driver.\r
+\r
+Returns: \r
+\r
+--*/\r
+{\r
+  CHAR16        *LanguageString;\r
+  UINTN         Count;\r
+  CHAR16        UnicodeLang[3];\r
+  CHAR8         Lang[3];\r
+  EFI_STATUS    Status;\r
+  UINTN         Index;\r
+  CHAR16        *TmpStr;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+\r
+  SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+  SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+  SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+\r
+  Count = 0;\r
+\r
+  //\r
+  // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can\r
+  // describe to their customers in documentation how to find their setup information (namely\r
+  // under the device manager and specific buckets)\r
+  //\r
+  switch (KeyValue) {\r
+  case 0x0001:\r
+    //\r
+    // This is the continue - clear the screen and return an error to get out of FrontPage loop\r
+    //\r
+    gCallbackKey = 1;\r
+    break;\r
+\r
+  case 0x1234:\r
+    //\r
+    // Collect the languages from what our current Language support is based on our VFR\r
+    //\r
+    Hii->GetPrimaryLanguages (Hii, gFrontPageHandle, &LanguageString);\r
+\r
+    //\r
+    // Based on the DataArray->Data->Data value, we can determine\r
+    // which language was chosen by the user\r
+    //\r
+    for (Index = 0; Count != (UINTN) (((EFI_IFR_DATA_ENTRY *) (DataArray + 1))->Data); Index += 3) {\r
+      Count++;\r
+    }\r
+    //\r
+    // Preserve the choice the user made\r
+    //\r
+    mLastSelection = (UINT16) Count;\r
+\r
+    //\r
+    // The Language (in Unicode format) the user chose\r
+    //\r
+    CopyMem (UnicodeLang, &LanguageString[Index], 6);\r
+\r
+    //\r
+    // Convert Unicode to ASCII (Since the ISO standard assumes ASCII equivalent abbreviations\r
+    // we can be safe in converting this Unicode stream to ASCII without any loss in meaning.\r
+    //\r
+    for (Index = 0; Index < 3; Index++) {\r
+      Lang[Index] = (CHAR8) UnicodeLang[Index];\r
+    }\r
+\r
+    Status = gRT->SetVariable (\r
+                    L"Lang",\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    3,\r
+                    Lang\r
+                    );\r
+\r
+    gBS->FreePool (LanguageString);\r
+    gCallbackKey = 2;\r
+    break;\r
+\r
+  case 0x1064:\r
+    //\r
+    // Boot Manager\r
+    //\r
+    gCallbackKey = 3;\r
+    break;\r
+\r
+  case 0x8567:\r
+    //\r
+    // Device Manager\r
+    //\r
+    gCallbackKey = 4;\r
+    break;\r
+\r
+  case 0x9876:\r
+    //\r
+    // Boot Maintenance Manager\r
+    //\r
+    gCallbackKey = 5;\r
+    break;\r
+\r
+  case 0xFFFE:\r
+\r
+    break;\r
+\r
+  case 0xFFFF:\r
+    //\r
+    // FrontPage TimeOut Callback\r
+    //\r
+    TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));\r
+    if (TmpStr != NULL) {\r
+      PlatformBdsShowProgress (\r
+        Foreground,\r
+        Background,\r
+        TmpStr,\r
+        Color,\r
+        (UINTN) (((EFI_IFR_DATA_ENTRY *) (DataArray+1))->Data),\r
+        0\r
+        );\r
+      gBS->FreePool (TmpStr);\r
+    }\r
+    break;\r
+\r
+  default:\r
+    gCallbackKey = 0;\r
+    break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeFrontPage (\r
+  BOOLEAN                         ReInitializeStrings\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Initialize HII information for the FrontPage\r
+\r
+Arguments:\r
+  None\r
+            \r
+Returns:\r
+  EFI_SUCCESS       - The operation is successful.\r
+  EFI_DEVICE_ERROR  - If the dynamic opcode creation failed.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS          Status;\r
+  EFI_HII_PACKAGES    *PackageList;\r
+  EFI_HII_UPDATE_DATA *UpdateData;\r
+  IFR_OPTION          *OptionList;\r
+  CHAR16              *LanguageString;\r
+  UINTN               OptionCount;\r
+  UINTN               Index;\r
+  STRING_REF          Token;\r
+  UINT16              Key;\r
+  CHAR8               AsciiLang[4];\r
+  CHAR16              UnicodeLang[4];\r
+  CHAR16              Lang[4];\r
+  CHAR16              *StringBuffer;\r
+  UINTN               BufferSize;\r
+  UINT8               *TempBuffer;\r
+\r
+  UpdateData  = NULL;\r
+  OptionList  = NULL;\r
+\r
+  if (ReInitializeStrings) {\r
+    //\r
+    // BugBug: Dont' use a goto\r
+    //\r
+    goto ReInitStrings;\r
+  }\r
+  //\r
+  // Go ahead and initialize the Device Manager\r
+  //\r
+  InitializeDeviceManager ();\r
+\r
+  //\r
+  // BugBug: if FrontPageVfrBin is generated by a tool, why are we patching it here\r
+  //\r
+  TempBuffer    = (UINT8 *) FrontPageVfrBin;\r
+  TempBuffer    = TempBuffer + sizeof (EFI_HII_PACK_HEADER);\r
+  TempBuffer    = (UINT8 *) &((EFI_IFR_FORM_SET *) TempBuffer)->NvDataSize;\r
+  *TempBuffer   = 1;\r
+\r
+  gCallbackKey  = 0;\r
+\r
+  PackageList   = PreparePackages (1, &gBdsStringPackGuid, FrontPageVfrBin);\r
+\r
+  Status        = Hii->NewPack (Hii, PackageList, &gFrontPageHandle);\r
+\r
+  gBS->FreePool (PackageList);\r
+\r
+  //\r
+  // There will be only one FormConfig in the system\r
+  // If there is another out there, someone is trying to install us\r
+  // again.  Fail that scenario.\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiFormBrowserProtocolGuid,\r
+                  NULL,\r
+                  (VOID**)&gBrowser\r
+                  );\r
+\r
+  //\r
+  // This example does not implement worker functions\r
+  // for the NV accessor functions.  Only a callback evaluator\r
+  //\r
+  FrontPageCallback.NvRead    = NULL;\r
+  FrontPageCallback.NvWrite   = NULL;\r
+  FrontPageCallback.Callback  = FrontPageCallbackRoutine;\r
+\r
+  //\r
+  // Install protocol interface\r
+  //\r
+  FrontPageCallbackHandle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &FrontPageCallbackHandle,\r
+                  &gEfiFormCallbackProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &FrontPageCallback\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+ReInitStrings:\r
+  //\r
+  // BugBug: This logic is in BdsInitLanguage. It should not be in two places!\r
+  //\r
+  BufferSize = 4;\r
+  Status = gRT->GetVariable (\r
+                  L"Lang",\r
+                  &gEfiGlobalVariableGuid,\r
+                  NULL,\r
+                  &BufferSize,\r
+                  AsciiLang\r
+                  );\r
+\r
+  for (Index = 0; Index < 3; Index++) {\r
+    UnicodeLang[Index] = (CHAR16) AsciiLang[Index];\r
+  }\r
+\r
+  UnicodeLang[3] = 0;\r
+\r
+  //\r
+  // Allocate space for creation of UpdateData Buffer\r
+  //\r
+  UpdateData = AllocateZeroPool (0x1000);\r
+  ASSERT (UpdateData != NULL);\r
+\r
+  OptionList = AllocateZeroPool (0x1000);\r
+  ASSERT (OptionList != NULL);\r
+\r
+  //\r
+  // Flag update pending in FormSet\r
+  //\r
+  UpdateData->FormSetUpdate = TRUE;\r
+  //\r
+  // Register CallbackHandle data for FormSet\r
+  //\r
+  UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) FrontPageCallbackHandle;\r
+  UpdateData->FormUpdate  = FALSE;\r
+  UpdateData->FormTitle   = 0;\r
+  UpdateData->DataCount   = 1;\r
+\r
+  //\r
+  // Collect the languages from what our current Language support is based on our VFR\r
+  //\r
+  Hii->GetPrimaryLanguages (Hii, gFrontPageHandle, &LanguageString);\r
+\r
+  OptionCount = 0;\r
+\r
+  //\r
+  // Try for a 512 byte Buffer\r
+  //\r
+  BufferSize = 0x200;\r
+\r
+  //\r
+  // Allocate memory for our Form binary\r
+  //\r
+  StringBuffer = AllocateZeroPool (BufferSize);\r
+  ASSERT (StringBuffer != NULL);\r
+\r
+  for (Index = 0; LanguageString[Index] != 0; Index += 3) {\r
+    Token = 0;\r
+    CopyMem (Lang, &LanguageString[Index], 6);\r
+    Lang[3] = 0;\r
+\r
+    if (!StrCmp (Lang, UnicodeLang)) {\r
+      mLastSelection = (UINT16) OptionCount;\r
+    }\r
+\r
+    Status = Hii->GetString (Hii, gStringPackHandle, 1, TRUE, Lang, &BufferSize, StringBuffer);\r
+    Hii->NewString (Hii, NULL, gStringPackHandle, &Token, StringBuffer);\r
+    CopyMem (&OptionList[OptionCount].StringToken, &Token, sizeof (UINT16));\r
+    CopyMem (&OptionList[OptionCount].Value, &OptionCount, sizeof (UINT16));\r
+    Key = 0x1234;\r
+    CopyMem (&OptionList[OptionCount].Key, &Key, sizeof (UINT16));\r
+    OptionList[OptionCount].Flags = EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS;\r
+    OptionCount++;\r
+  }\r
+\r
+  gBS->FreePool (LanguageString);\r
+\r
+  if (ReInitializeStrings) {\r
+    gBS->FreePool (StringBuffer);\r
+    gBS->FreePool (OptionList);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = CreateOneOfOpCode (\r
+            FRONT_PAGE_QUESTION_ID,                               // Question ID\r
+            FRONT_PAGE_DATA_WIDTH,                                // Data Width\r
+            (STRING_REF) STRING_TOKEN (STR_LANGUAGE_SELECT),      // Prompt Token\r
+            (STRING_REF) STRING_TOKEN (STR_LANGUAGE_SELECT_HELP), // Help Token\r
+            OptionList,       // List of Options\r
+            OptionCount,      // Number of Options\r
+            &UpdateData->Data // Data Buffer\r
+            );\r
+\r
+  //\r
+  // Assign the number of options and the oneof and endoneof op-codes to count\r
+  //\r
+  UpdateData->DataCount = (UINT8) (OptionCount + 2);\r
+\r
+  Hii->UpdateForm (Hii, gFrontPageHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData);\r
+\r
+  gBS->FreePool (UpdateData);\r
+  //\r
+  // gBS->FreePool (OptionList);\r
+  //\r
+  gBS->FreePool (StringBuffer);\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+CallFrontPage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Call the browser and display the front page\r
+\r
+Arguments:\r
+  \r
+  None\r
+  \r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       FakeNvRamMap[1];\r
+  BOOLEAN     FrontPageMenuResetRequired;\r
+\r
+  //\r
+  // Begin waiting for USER INPUT\r
+  //\r
+  REPORT_STATUS_CODE (\r
+        EFI_PROGRESS_CODE,\r
+        (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT)\r
+        );\r
+\r
+  FakeNvRamMap[0] = (UINT8) mLastSelection;\r
+  FrontPageMenuResetRequired = FALSE;\r
+  Status = gBrowser->SendForm (\r
+                      gBrowser,\r
+                      TRUE,                     // Use the database\r
+                      &gFrontPageHandle,        // The HII Handle\r
+                      1,\r
+                      NULL,\r
+                      FrontPageCallbackHandle,  // This is the handle that the interface to the callback was installed on\r
+                      FakeNvRamMap,\r
+                      NULL,\r
+                      &FrontPageMenuResetRequired\r
+                      );\r
+  //\r
+  // Check whether user change any option setting which needs a reset to be effective\r
+  //                      \r
+  if (FrontPageMenuResetRequired) {\r
+    EnableResetRequired ();\r
+  }\r
+\r
+  Hii->ResetStrings (Hii, gFrontPageHandle);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+GetStringFromToken (\r
+  IN      EFI_GUID                  *ProducerGuid,\r
+  IN      STRING_REF                Token,\r
+  OUT     CHAR16                    **String\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Acquire the string associated with the ProducerGuid and return it.\r
+\r
+Arguments:\r
+  \r
+  ProducerGuid - The Guid to search the HII database for\r
+  Token - The token value of the string to extract\r
+  String - The string that is extracted\r
+  \r
+Returns:\r
+\r
+  EFI_SUCCESS - The function returns EFI_SUCCESS always.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS      Status;\r
+  UINT16          HandleBufferLength;\r
+  EFI_HII_HANDLE  *HiiHandleBuffer;\r
+  UINTN           StringBufferLength;\r
+  UINTN           NumberOfHiiHandles;\r
+  UINTN           Index;\r
+  UINT16          Length;\r
+  EFI_GUID        HiiGuid;\r
+\r
+  //\r
+  // Initialize params.\r
+  //\r
+  HandleBufferLength  = 0;\r
+  HiiHandleBuffer     = NULL;\r
+\r
+  //\r
+  // Get all the Hii handles\r
+  //\r
+  Status = BdsLibGetHiiHandles (Hii, &HandleBufferLength, &HiiHandleBuffer);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Get the Hii Handle that matches the StructureNode->ProducerName\r
+  //\r
+  NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);\r
+  for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
+    Length = 0;\r
+    Status = ExtractDataFromHiiHandle (\r
+              HiiHandleBuffer[Index],\r
+              &Length,\r
+              NULL,\r
+              &HiiGuid\r
+              );\r
+    if (CompareGuid (ProducerGuid, &HiiGuid)) {\r
+      break;\r
+    }\r
+  }\r
+  //\r
+  // Find the string based on the current language\r
+  //\r
+  StringBufferLength  = 0x100;\r
+  *String             = AllocateZeroPool (0x100);\r
+  Status = Hii->GetString (\r
+                  Hii,\r
+                  HiiHandleBuffer[Index],\r
+                  Token,\r
+                  FALSE,\r
+                  NULL,\r
+                  &StringBufferLength,\r
+                  *String\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (*String);\r
+    *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));\r
+  }\r
+\r
+  gBS->FreePool (HiiHandleBuffer);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+ConvertProcessorToString (\r
+  IN  EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency,\r
+  OUT CHAR16                            **String\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Convert Processor Frequency Data to a string\r
+\r
+Arguments:\r
+  \r
+  ProcessorFrequency - The frequency data to process\r
+  String - The string that is created\r
+  \r
+Returns:\r
+\r
+--*/\r
+{\r
+  CHAR16  *StringBuffer;\r
+  UINTN   Index;\r
+  UINT32  FreqMhz;\r
+\r
+  if (ProcessorFrequency->Exponent >= 6) {\r
+    FreqMhz = ProcessorFrequency->Value;\r
+    for (Index = 0; Index < (UINTN) (ProcessorFrequency->Exponent - 6); Index++) {\r
+      FreqMhz *= 10;\r
+    }\r
+  } else {\r
+    FreqMhz = 0;\r
+  }\r
+\r
+  StringBuffer = AllocateZeroPool (0x20);\r
+  ASSERT (StringBuffer != NULL);\r
+  Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3);\r
+  StrCat (StringBuffer, L".");\r
+  UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2);\r
+  StrCat (StringBuffer, L" GHz");\r
+\r
+  *String = (CHAR16 *) StringBuffer;\r
+\r
+  return ;\r
+}\r
+\r
+VOID\r
+ConvertMemorySizeToString (\r
+  IN  UINT32          MemorySize,\r
+  OUT CHAR16          **String\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Convert Memory Size to a string\r
+\r
+Arguments:\r
+  \r
+  MemorySize - The size of the memory to process\r
+  String - The string that is created\r
+  \r
+Returns:\r
+\r
+--*/\r
+{\r
+  CHAR16  *StringBuffer;\r
+\r
+  StringBuffer = AllocateZeroPool (0x20);\r
+  ASSERT (StringBuffer != NULL);\r
+  UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 6);\r
+  StrCat (StringBuffer, L" MB RAM");\r
+\r
+  *String = (CHAR16 *) StringBuffer;\r
+\r
+  return ;\r
+}\r
+\r
+VOID\r
+UpdateFrontPageStrings (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Update the banner information for the Front Page based on DataHub information\r
+\r
+Arguments:\r
+  \r
+  None\r
+  \r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                        Status;\r
+  STRING_REF                        TokenToUpdate;\r
+  CHAR16                            *NewString;\r
+  UINT64                            MonotonicCount;\r
+  EFI_DATA_HUB_PROTOCOL             *DataHub;\r
+  EFI_DATA_RECORD_HEADER            *Record;\r
+  EFI_SUBCLASS_TYPE1_HEADER         *DataHeader;\r
+  EFI_MISC_BIOS_VENDOR_DATA         *BiosVendor;\r
+  EFI_MISC_SYSTEM_MANUFACTURER_DATA *SystemManufacturer;\r
+  EFI_PROCESSOR_VERSION_DATA        *ProcessorVersion;\r
+  EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency;\r
+  EFI_MEMORY_ARRAY_START_ADDRESS_DATA *MemoryArray;\r
+  CHAR8                             LangCode[3];\r
+  CHAR16                            Lang[3];\r
+  UINTN                             Size;\r
+  UINTN                             Index;\r
+  BOOLEAN                           Find[5];\r
+\r
+  ZeroMem (Find, sizeof (Find));\r
+\r
+  //\r
+  // Update Front Page strings\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiDataHubProtocolGuid,\r
+                  NULL,\r
+                  (VOID**)&DataHub\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Size = 3;\r
+\r
+  Status = gRT->GetVariable (\r
+                  L"Lang",\r
+                  &gEfiGlobalVariableGuid,\r
+                  NULL,\r
+                  &Size,\r
+                  LangCode\r
+                  );\r
+\r
+  for (Index = 0; Index < 3; Index++) {\r
+    Lang[Index] = (CHAR16) LangCode[Index];\r
+  }\r
+\r
+  MonotonicCount  = 0;\r
+  Record          = NULL;\r
+  do {\r
+    Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);\r
+    if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {\r
+      DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
+      if (CompareGuid (&Record->DataRecordGuid, &mMiscSubClass) &&\r
+          (DataHeader->RecordType == EFI_MISC_BIOS_VENDOR_RECORD_NUMBER)\r
+          ) {\r
+        BiosVendor = (EFI_MISC_BIOS_VENDOR_DATA *) (DataHeader + 1);\r
+        GetStringFromToken (&Record->ProducerName, BiosVendor->BiosVersion, &NewString);\r
+        TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_BIOS_VERSION;\r
+        Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString);\r
+        gBS->FreePool (NewString);\r
+        Find[0] = TRUE;\r
+      }\r
+\r
+      if (CompareGuid (&Record->DataRecordGuid, &mMiscSubClass) &&\r
+          (DataHeader->RecordType == EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER)\r
+          ) {\r
+        SystemManufacturer = (EFI_MISC_SYSTEM_MANUFACTURER_DATA *) (DataHeader + 1);\r
+        GetStringFromToken (&Record->ProducerName, SystemManufacturer->SystemProductName, &NewString);\r
+        TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_COMPUTER_MODEL;\r
+        Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString);\r
+        gBS->FreePool (NewString);\r
+        Find[1] = TRUE;\r
+      }\r
+\r
+      if (CompareGuid (&Record->DataRecordGuid, &mProcessorSubClass) &&\r
+          (DataHeader->RecordType == ProcessorVersionRecordType)\r
+          ) {\r
+        ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *) (DataHeader + 1);\r
+        GetStringFromToken (&Record->ProducerName, *ProcessorVersion, &NewString);\r
+        TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_CPU_MODEL;\r
+        Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString);\r
+        gBS->FreePool (NewString);\r
+        Find[2] = TRUE;\r
+      }\r
+\r
+      if (CompareGuid (&Record->DataRecordGuid, &mProcessorSubClass) &&\r
+          (DataHeader->RecordType == ProcessorCoreFrequencyRecordType)\r
+          ) {\r
+        ProcessorFrequency = (EFI_PROCESSOR_CORE_FREQUENCY_DATA *) (DataHeader + 1);\r
+        ConvertProcessorToString (ProcessorFrequency, &NewString);\r
+        TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_CPU_SPEED;\r
+        Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString);\r
+        gBS->FreePool (NewString);\r
+        Find[3] = TRUE;\r
+      }\r
+\r
+      if (CompareGuid (&Record->DataRecordGuid, &mMemorySubClass) &&\r
+          (DataHeader->RecordType == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER)\r
+          ) {\r
+        MemoryArray = (EFI_MEMORY_ARRAY_START_ADDRESS_DATA *) (DataHeader + 1);\r
+        ConvertMemorySizeToString((UINT32)(RShiftU64((MemoryArray->MemoryArrayEndAddress - \r
+                                  MemoryArray->MemoryArrayStartAddress + 1), 20)),\r
+                                  &NewString);\r
+        TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_MEMORY_SIZE;\r
+        Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString);\r
+        gBS->FreePool (NewString);\r
+        Find[4] = TRUE;\r
+      }\r
+    }\r
+  } while (!EFI_ERROR (Status) && (MonotonicCount != 0) && !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4]));\r
+\r
+  return ;\r
+}\r
+\r
+VOID\r
+PlatformBdsEnterFrontPage (\r
+  IN UINT16                       TimeoutDefault,\r
+  IN BOOLEAN                      ConnectAllHappened\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  This function is the main entry of the platform setup entry.\r
+  The function will present the main menu of the system setup, \r
+  this is the platform reference part and can be customize.\r
+  \r
+Arguments:\r
+  TimeoutDefault     - The fault time out value before the system\r
+                       continue to boot.\r
+  ConnectAllHappened - The indicater to check if the connect all have\r
+                       already happended.\r
+  \r
+Returns:\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_HII_UPDATE_DATA           *UpdateData;\r
+  EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;\r
+\r
+  //\r
+  // Indicate if we need connect all in the platform setup\r
+  //\r
+  if (ConnectAllHappened) {\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+  //\r
+  // Allocate space for creation of Buffer\r
+  //\r
+  UpdateData = AllocateZeroPool (0x1000);\r
+  ASSERT (UpdateData != NULL);\r
+\r
+  UpdateData->FormSetUpdate       = FALSE;\r
+  UpdateData->FormCallbackHandle  = 0;\r
+  UpdateData->FormUpdate          = FALSE;\r
+  UpdateData->FormTitle           = 0;\r
+  UpdateData->DataCount           = 1;\r
+\r
+  //\r
+  // Remove Banner Op-code if any at this label\r
+  //\r
+  Hii->UpdateForm (Hii, gFrontPageHandle, (EFI_FORM_LABEL) 0xFFFF, FALSE, UpdateData);\r
+\r
+  //\r
+  // Create Banner Op-code which reflects correct timeout value\r
+  //\r
+  CreateBannerOpCode (\r
+    STRING_TOKEN (STR_TIME_OUT_PROMPT),\r
+    TimeoutDefault,\r
+    (UINT8) EFI_IFR_BANNER_TIMEOUT,\r
+    &UpdateData->Data\r
+    );\r
+\r
+  //\r
+  // Add Banner Op-code at this label\r
+  //\r
+  Hii->UpdateForm (Hii, gFrontPageHandle, (EFI_FORM_LABEL) 0xFFFF, TRUE, UpdateData);\r
+\r
+  do {\r
+\r
+    InitializeFrontPage (TRUE);\r
+\r
+    //\r
+    // Update Front Page strings\r
+    //\r
+    UpdateFrontPageStrings ();\r
+\r
+    gCallbackKey = 0;\r
+    PERF_START (0, "BdsTimeOut", "BDS", 0);\r
+    Status = CallFrontPage ();\r
+    PERF_END (0, "BdsTimeOut", "BDS", 0);\r
+\r
+    //\r
+    // If gCallbackKey is greater than 1 and less or equal to 5,\r
+    // it will lauch configuration utilities.\r
+    // 2 = set language\r
+    // 3 = boot manager\r
+    // 4 = device manager\r
+    // 5 = boot maintainenance manager\r
+    //\r
+    if ((gCallbackKey > 0x0001) && (gCallbackKey <= 0x0005)) {\r
+      REPORT_STATUS_CODE (\r
+            EFI_PROGRESS_CODE,\r
+            (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP)\r
+            );\r
+    }\r
+    //\r
+    // Based on the key that was set, we can determine what to do\r
+    //\r
+    switch (gCallbackKey) {\r
+    //\r
+    // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can\r
+    // describe to their customers in documentation how to find their setup information (namely\r
+    // under the device manager and specific buckets)\r
+    //\r
+    // These entries consist of the Continue, Select language, Boot Manager, and Device Manager\r
+    //\r
+    case 0x0001:\r
+      //\r
+      // User hit continue\r
+      //\r
+      break;\r
+\r
+    case 0x0002:\r
+      //\r
+      // User made a language setting change - display front page again\r
+      //\r
+      break;\r
+\r
+    case 0x0003:\r
+      //\r
+      // User chose to run the Boot Manager\r
+      //\r
+      CallBootManager ();\r
+      break;\r
+\r
+    case 0x0004:\r
+      //\r
+      // Display the Device Manager\r
+      //\r
+      do {\r
+        CallDeviceManager();\r
+      } while (gCallbackKey == 4);\r
+      break;\r
+\r
+    case 0x0005:\r
+      //\r
+      // Display the Boot Maintenance Manager\r
+      //\r
+      BdsStartBootMaint ();\r
+      break;\r
+    }\r
+\r
+  } while ((Status == EFI_SUCCESS) && (gCallbackKey != 1));\r
+\r
+  //\r
+  //Will leave browser, check any reset required change is applied? if yes, reset system\r
+  //\r
+  SetupResetReminder ();\r
+  \r
+  //\r
+  // Automatically load current entry\r
+  // Note: The following lines of code only execute when Auto boot\r
+  // takes affect\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID**)&ConsoleControl);\r
+  ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);\r
+\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPage.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPage.h
new file mode 100644 (file)
index 0000000..2899125
--- /dev/null
@@ -0,0 +1,94 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  FrontPage.h\r
+\r
+Abstract:\r
+\r
+  FrontPage routines to handle the callbacks and browser calls\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _FRONT_PAGE_H\r
+#define _FRONT_PAGE_H\r
+\r
+#include "DeviceMngr/DeviceManager.h"\r
+#include "BootMaint/BootMaint.h"\r
+#include "BootMngr/BootManager.h"\r
+\r
+//\r
+// This is the VFR compiler generated header file which defines the\r
+// string identifiers.\r
+//\r
+#include "EdkGenericPlatformBdsLibStrDefs.h"\r
+#define EFI_DISK_DEVICE_CLASS           0x01\r
+#define EFI_VIDEO_DEVICE_CLASS          0x02\r
+#define EFI_NETWORK_DEVICE_CLASS        0x04\r
+#define EFI_INPUT_DEVICE_CLASS          0x08\r
+#define EFI_ON_BOARD_DEVICE_CLASS       0x10\r
+#define EFI_OTHER_DEVICE_CLASS          0x20\r
+#define EFI_VBIOS_CLASS                 0x40\r
+\r
+#define SET_VIDEO_BIOS_TYPE_QUESTION_ID 0x00\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+  UINT8 VideoBIOS;\r
+} MyDevMgrIfrNVData;\r
+#pragma pack()\r
+\r
+#define EFI_FP_CALLBACK_DATA_SIGNATURE  EFI_SIGNATURE_32 ('F', 'P', 'C', 'B')\r
+#define EFI_FP_CALLBACK_DATA_FROM_THIS(a) \\r
+  CR (a, \\r
+      EFI_FRONTPAGE_CALLBACK_INFO, \\r
+      DevMgrCallback, \\r
+      EFI_FP_CALLBACK_DATA_SIGNATURE \\r
+      )\r
+\r
+typedef struct {\r
+  UINTN                       Signature;\r
+  MyDevMgrIfrNVData           Data;\r
+  EFI_HII_HANDLE              DevMgrHiiHandle;\r
+  EFI_HANDLE                  CallbackHandle;\r
+  EFI_FORM_CALLBACK_PROTOCOL  DevMgrCallback;\r
+} EFI_FRONTPAGE_CALLBACK_INFO;\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+// BugBug: we should put g in front of these tool generated globals.\r
+//         maybe even gVrf would be a better prefix\r
+//\r
+extern UINT8  FrontPageVfrBin[];\r
+extern UINT8  FrontPageStringsStr[];\r
+extern UINT8  DeviceManagerVfrBin[];\r
+extern UINT8  DeviceManagerStringsStr[];\r
+\r
+#define FRONT_PAGE_QUESTION_ID  0x0000\r
+#define FRONT_PAGE_DATA_WIDTH   0x01\r
+\r
+EFI_STATUS\r
+InitializeFrontPage (\r
+  IN BOOLEAN    ReInitializeStrings\r
+  );\r
+\r
+BOOLEAN\r
+TimeCompare (\r
+  IN EFI_TIME               *FirstTime,\r
+  IN EFI_TIME               *SecondTime\r
+  );\r
+\r
+#endif // _FRONT_PAGE_H_\r
+\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageStrings.uni b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageStrings.uni
new file mode 100644 (file)
index 0000000..76dbdcf
Binary files /dev/null and b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageStrings.uni differ
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageVfr.Vfr b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/FrontPageVfr.Vfr
new file mode 100644 (file)
index 0000000..8457784
--- /dev/null
@@ -0,0 +1,159 @@
+// *++\r
+//\r
+// Copyright (c) 2006, Intel Corporation                                                         \r
+// All rights reserved. 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
+// Module Name:\r
+//\r
+//   FrontPageVfr.vfr \r
+// \r
+// Abstract:\r
+// \r
+//   Browser formset.\r
+// \r
+// Revision History: \r
+// \r
+// --*/\r
+\r
+#include "EdkGenericPlatformBdsLibStrDefs.h"\r
+\r
+#define FORMSET_GUID  { 0x9e0c30bc, 0x3f06, 0x4ba6, { 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe } }\r
+\r
+#define FRONT_PAGE_ITEM_ONE    0x0001\r
+#define FRONT_PAGE_ITEM_TWO    0x0002\r
+#define FRONT_PAGE_ITEM_THREE  0x0003\r
+#define FRONT_PAGE_ITEM_FOUR   0x0004\r
+#define FRONT_PAGE_ITEM_FIVE   0x0005\r
+\r
+#define FRONT_PAGE_TIMEOUT     0xFFFF\r
+#define FRONT_PAGE_CLASS       0x0000\r
+#define FRONT_PAGE_SUBCLASS    0x0002\r
+\r
+formset \r
+  guid     = FORMSET_GUID,\r
+  title    = STRING_TOKEN(STR_FRONT_PAGE_TITLE),  \r
+  help     = STRING_TOKEN(STR_NULL_STRING),\r
+  class    = FRONT_PAGE_CLASS,      \r
+  subclass = FRONT_PAGE_SUBCLASS,\r
+\r
+  form formid = 0x1000,\r
+       title  = STRING_TOKEN(STR_FRONT_PAGE_TITLE);\r
+\r
+    banner \r
+      title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL),\r
+      line  0,\r
+      align left;\r
+    \r
+    banner \r
+      title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL),\r
+      line  1,\r
+      align left;\r
+    \r
+    banner \r
+      title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED),\r
+      line  1,\r
+      align right;\r
+    \r
+    banner \r
+      title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION),\r
+      line  2,\r
+      align left;\r
+    \r
+    banner \r
+      title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE),\r
+      line  2,\r
+      align right;\r
+\r
+//    banner \r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_LEFT),\r
+//      line  0,\r
+//      align left;\r
+    \r
+//    banner \r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_RIGHT),\r
+//      line  0,\r
+//      align right;\r
+    \r
+//    banner \r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_LEFT),\r
+//      line  1,\r
+//      align left;\r
+    \r
+//    banner \r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_RIGHT),\r
+//      line  1,\r
+//      align right;\r
+    \r
+//    banner \r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_2_LEFT),\r
+//      line  2,\r
+//      align left;\r
+    \r
+//    banner \r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_3_LEFT),\r
+//      line  3,\r
+//      align left;\r
+\r
+    goto FRONT_PAGE_ITEM_ONE, \r
+      prompt  = STRING_TOKEN(STR_CONTINUE_PROMPT), \r
+      help    = STRING_TOKEN(STR_CONTINUE_HELP),\r
+      flags   = INTERACTIVE | NV_ACCESS, \r
+      key     = 0x0001;\r
+\r
+    label FRONT_PAGE_ITEM_TWO;\r
+    //\r
+    // This is where we will dynamically add a OneOf type op-code to select Languages from the\r
+    // currently available choices\r
+    //\r
+\r
+    goto FRONT_PAGE_ITEM_THREE, \r
+      prompt  = STRING_TOKEN(STR_BOOT_MANAGER), \r
+      help    = STRING_TOKEN(STR_BOOT_MANAGER_HELP),\r
+      flags   = INTERACTIVE | NV_ACCESS, \r
+      key     = 0x1064;\r
+\r
+    goto FRONT_PAGE_ITEM_FOUR, \r
+      prompt  = STRING_TOKEN(STR_DEVICE_MANAGER), \r
+      help    = STRING_TOKEN(STR_DEVICE_MANAGER_HELP),\r
+      flags   = INTERACTIVE | NV_ACCESS, \r
+      key     = 0x8567;\r
+\r
+    goto FRONT_PAGE_ITEM_FIVE, \r
+      prompt  = STRING_TOKEN(STR_BOOT_MAINT_MANAGER), \r
+      help    = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP),\r
+      flags   = INTERACTIVE | NV_ACCESS, \r
+      key     = 0x9876;\r
+\r
+    label FRONT_PAGE_TIMEOUT;\r
+//  If one wanted to hard-code a value one could do it below, but our implementation follows EFI architecture\r
+//  and honors the TimeOut NV variable\r
+//\r
+//    banner\r
+//      title = STRING_TOKEN(STR_TIME_OUT_PROMPT),\r
+//      timeout = 0x000A;\r
+    \r
+  endform;\r
+\r
+  form formid = FRONT_PAGE_ITEM_ONE,\r
+       title  = STRING_TOKEN(STR_FRONT_PAGE_TITLE);  \r
+  endform;\r
+\r
+  form formid = FRONT_PAGE_ITEM_THREE,\r
+       title  = STRING_TOKEN(STR_FRONT_PAGE_TITLE);  \r
+  endform;\r
+\r
+  form formid = FRONT_PAGE_ITEM_FOUR,\r
+       title  = STRING_TOKEN(STR_FRONT_PAGE_TITLE);  \r
+  endform;\r
+\r
+  form formid = FRONT_PAGE_ITEM_FIVE,\r
+       title  = STRING_TOKEN(STR_FRONT_PAGE_TITLE);  \r
+  endform;\r
+\r
+endformset;\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Language.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Language.c
new file mode 100644 (file)
index 0000000..5091f20
--- /dev/null
@@ -0,0 +1,435 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  language.c\r
+\r
+Abstract:\r
+\r
+ Language settings\r
+  \r
+Revision History\r
+\r
+--*/\r
+\r
+#include "String.h"\r
+#include "Language.h"\r
+\r
+#define NARROW_GLYPH_NUMBER 8\r
+#define WIDE_GLYPH_NUMBER   75\r
+\r
+//\r
+// Default language code, currently is English\r
+//\r
+CHAR8 *mDefaultLangCode = "eng";\r
+\r
+typedef struct {\r
+  EFI_HII_FONT_PACK FixedLength;\r
+  EFI_NARROW_GLYPH  NarrowArray[NARROW_GLYPH_NUMBER];\r
+  EFI_WIDE_GLYPH    WideArray[WIDE_GLYPH_NUMBER];\r
+} FONT_PACK;\r
+\r
+FONT_PACK mFontPack = {\r
+  {\r
+    {\r
+      sizeof (EFI_HII_FONT_PACK) + (NARROW_GLYPH_NUMBER * sizeof (EFI_NARROW_GLYPH)) + (WIDE_GLYPH_NUMBER * sizeof (EFI_WIDE_GLYPH)),\r
+      EFI_HII_FONT\r
+    },\r
+    NARROW_GLYPH_NUMBER,\r
+    WIDE_GLYPH_NUMBER\r
+  },\r
+  {     // Narrow Glyphs\r
+    {\r
+      0x05d0,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x4E,\r
+        0x6E,\r
+        0x62,\r
+        0x32,\r
+        0x32,\r
+        0x3C,\r
+        0x68,\r
+        0x4C,\r
+        0x4C,\r
+        0x46,\r
+        0x76,\r
+        0x72,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d1,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x78,\r
+        0x7C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x7E,\r
+        0x7E,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d2,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x78,\r
+        0x7C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x1C,\r
+        0x3E,\r
+        0x66,\r
+        0x66,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d3,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x7E,\r
+        0x7E,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d4,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x7C,\r
+        0x7E,\r
+        0x06,\r
+        0x06,\r
+        0x06,\r
+        0x06,\r
+        0x66,\r
+        0x66,\r
+        0x66,\r
+        0x66,\r
+        0x66,\r
+        0x66,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d5,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x3C,\r
+        0x3C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d6,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x38,\r
+        0x38,\r
+        0x1E,\r
+        0x1E,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x0000,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    }\r
+  },\r
+  {     // Wide Glyphs\r
+    {\r
+      0x0020,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      },\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      },\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },  //\r
+  }\r
+};\r
+\r
+VOID\r
+ExportFonts (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Routine to export glyphs to the HII database.  This is in addition to whatever is defined in the Graphics Console driver.\r
+\r
+Arguments:\r
+  None\r
+            \r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_HII_HANDLE    HiiHandle;\r
+  EFI_HII_PACKAGES  *PackageList;\r
+\r
+  PackageList = PreparePackages (1, NULL, &mFontPack);\r
+  //\r
+  // Register our Fonts into the global database\r
+  //\r
+  HiiHandle = 0;\r
+  Hii->NewPack (Hii, PackageList, &HiiHandle);\r
+\r
+  gBS->FreePool (PackageList);\r
+}\r
+\r
+VOID\r
+InitializeLanguage (\r
+  BOOLEAN LangCodesSettingRequired\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Determine the current language that will be used \r
+  based on language related EFI Variables\r
+\r
+Arguments:\r
+  LangCodesSettingRequired - If required to set LangCode variable\r
+            \r
+Returns:\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Index;\r
+  UINTN       Size;\r
+  CHAR8       LangCode[ISO_639_2_ENTRY_SIZE];\r
+  CHAR8       *LangCodes;\r
+  CHAR16      *LanguageString;\r
+\r
+  LanguageString  = NULL;\r
+  LangCodes       = NULL;\r
+\r
+  ExportFonts ();\r
+\r
+  //\r
+  // Collect the languages from what our current Language support is based on our VFR\r
+  //\r
+  Hii->GetPrimaryLanguages (Hii, gStringPackHandle, &LanguageString);\r
+\r
+  LangCodes = AllocatePool (StrLen (LanguageString));\r
+  ASSERT (LangCodes);\r
+\r
+  //\r
+  // Convert LanguageString from Unicode to EFI defined ASCII LangCodes\r
+  //\r
+  for (Index = 0; LanguageString[Index] != 0x0000; Index++) {\r
+    LangCodes[Index] = (CHAR8) LanguageString[Index];\r
+  }\r
+\r
+  LangCodes[Index] = 0;\r
+\r
+  if (LangCodesSettingRequired) {\r
+    Status = gRT->SetVariable (\r
+                    L"LangCodes",\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    AsciiStrLen (LangCodes),\r
+                    LangCodes\r
+                    );\r
+  }\r
+  //\r
+  // Find current LangCode from Lang NV Variable\r
+  //\r
+  Size = ISO_639_2_ENTRY_SIZE;\r
+  Status = gRT->GetVariable (\r
+                  L"Lang",\r
+                  &gEfiGlobalVariableGuid,\r
+                  NULL,\r
+                  &Size,\r
+                  &LangCode\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = EFI_NOT_FOUND;\r
+    for (Index = 0; LangCodes[Index] != 0; Index += ISO_639_2_ENTRY_SIZE) {\r
+      if (CompareMem (&LangCodes[Index], LangCode, ISO_639_2_ENTRY_SIZE) == 0) {\r
+        Status = EFI_SUCCESS;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  //\r
+  // If we cannot get language code from Lang variable,\r
+  // or LangCode cannot be found from language table,\r
+  // set the mDefaultLangCode to Lang variable.\r
+  //\r
+  if (EFI_ERROR (Status)) {\r
+    Status = gRT->SetVariable (\r
+                    L"Lang",\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    ISO_639_2_ENTRY_SIZE,\r
+                    mDefaultLangCode\r
+                    );\r
+  }\r
+\r
+  if (LangCodes) {\r
+    gBS->FreePool (LangCodes);\r
+  }\r
+\r
+  if (LanguageString != NULL) {\r
+    gBS->FreePool (LanguageString);\r
+  }\r
+\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Language.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Language.h
new file mode 100644 (file)
index 0000000..6b6d887
--- /dev/null
@@ -0,0 +1,36 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  Language.h\r
+\r
+Abstract:\r
+  \r
+  Language setting\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _LANGUAGE_H\r
+#define _LANGUAGE_H\r
+\r
+#ifndef ISO_639_2_ENTRY_SIZE\r
+#define ISO_639_2_ENTRY_SIZE  3\r
+#endif\r
+\r
+VOID\r
+InitializeLanguage (\r
+  BOOLEAN LangCodesSettingRequired\r
+  );\r
+\r
+#endif // _LANGUAGE_H_\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/MemoryTest.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/MemoryTest.c
new file mode 100644 (file)
index 0000000..f4046b5
--- /dev/null
@@ -0,0 +1,430 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  MemoryTest.c\r
+\r
+Abstract:\r
+\r
+  Perform the platform memory test\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "String.h"\r
+\r
+//\r
+// BDS Platform Functions\r
+//\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+  IN CHAR16        *Title,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+  IN UINTN         Progress,\r
+  IN UINTN         PreviousValue\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Show progress bar with title above it. It only works in UGA mode.\r
+\r
+Arguments:\r
+  \r
+  TitleForeground - Foreground color for Title.\r
+  TitleBackground - Background color for Title.\r
+  Title           - Title above progress bar.\r
+  ProgressColor   - Progress bar color.\r
+  Progress        - Progress (0-100)\r
+\r
+Returns: \r
+  \r
+  EFI_STATUS      - Success update the progress bar\r
+\r
+--*/\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL   *GraphicsOutput;\r
+  EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
+  UINT32                SizeOfX;\r
+  UINT32                SizeOfY;\r
+  UINT32                ColorDepth;\r
+  UINT32                RefreshRate;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Color;\r
+  UINTN                 BlockHeight;\r
+  UINTN                 BlockWidth;\r
+  UINTN                 BlockNum;\r
+  UINTN                 PosX;\r
+  UINTN                 PosY;\r
+  UINTN                 Index;\r
+\r
+  if (Progress > 100) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  UgaDraw = NULL;\r
+  Status = gBS->HandleProtocol (\r
+                  gST->ConsoleOutHandle,\r
+                  &gEfiGraphicsOutputProtocolGuid,\r
+                  (VOID**)&GraphicsOutput\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    GraphicsOutput = NULL;\r
+\r
+    Status = gBS->HandleProtocol (\r
+                    gST->ConsoleOutHandle,\r
+                    &gEfiUgaDrawProtocolGuid,\r
+                    (VOID**)&UgaDraw\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  if (GraphicsOutput != NULL) {\r
+    SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+    SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
+  } else {\r
+    Status = UgaDraw->GetMode (\r
+                        UgaDraw,\r
+                        &SizeOfX,\r
+                        &SizeOfY,\r
+                        &ColorDepth,\r
+                        &RefreshRate\r
+                        );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  BlockWidth  = SizeOfX / 100;\r
+  BlockHeight = SizeOfY / 50;\r
+\r
+  BlockNum    = Progress;\r
+\r
+  PosX        = 0;\r
+  PosY        = SizeOfY * 48 / 50;\r
+\r
+  if (BlockNum == 0) {\r
+    //\r
+    // Clear progress area\r
+    //\r
+    SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+\r
+    if (GraphicsOutput != NULL) {\r
+      Status = GraphicsOutput->Blt (\r
+                          GraphicsOutput,\r
+                          &Color,\r
+                          EfiBltVideoFill,\r
+                          0,\r
+                          0,\r
+                          0,\r
+                          PosY - GLYPH_HEIGHT - 1,\r
+                          SizeOfX,\r
+                          SizeOfY - (PosY - GLYPH_HEIGHT - 1),\r
+                          SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+                          );\r
+    } else {\r
+      Status = UgaDraw->Blt (\r
+                          UgaDraw,\r
+                          (EFI_UGA_PIXEL *) &Color,\r
+                          EfiUgaVideoFill,\r
+                          0,\r
+                          0,\r
+                          0,\r
+                          PosY - GLYPH_HEIGHT - 1,\r
+                          SizeOfX,\r
+                          SizeOfY - (PosY - GLYPH_HEIGHT - 1),\r
+                          SizeOfX * sizeof (EFI_UGA_PIXEL)\r
+                          );\r
+    }\r
+  }\r
+  //\r
+  // Show progress by drawing blocks\r
+  //\r
+  for (Index = PreviousValue; Index < BlockNum; Index++) {\r
+    PosX = Index * BlockWidth;\r
+    if (GraphicsOutput != NULL) {\r
+      Status = GraphicsOutput->Blt (\r
+                          GraphicsOutput,\r
+                          &ProgressColor,\r
+                          EfiBltVideoFill,\r
+                          0,\r
+                          0,\r
+                          PosX,\r
+                          PosY,\r
+                          BlockWidth - 1,\r
+                          BlockHeight,\r
+                          (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+                          );\r
+    } else {\r
+      Status = UgaDraw->Blt (\r
+                          UgaDraw,\r
+                          (EFI_UGA_PIXEL *) &ProgressColor,\r
+                          EfiUgaVideoFill,\r
+                          0,\r
+                          0,\r
+                          PosX,\r
+                          PosY,\r
+                          BlockWidth - 1,\r
+                          BlockHeight,\r
+                          (BlockWidth) * sizeof (EFI_UGA_PIXEL)\r
+                          );\r
+    }\r
+  }\r
+\r
+  PrintXY (\r
+    (SizeOfX - StrLen (Title) * GLYPH_WIDTH) / 2,\r
+    PosY - GLYPH_HEIGHT - 1,\r
+    &TitleForeground,\r
+    &TitleBackground,\r
+    Title\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+BdsMemoryTest (\r
+  IN EXTENDMEM_COVERAGE_LEVEL Level\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Perform the memory test base on the memory test intensive level, \r
+  and update the memory resource.\r
+\r
+Arguments:\r
+  \r
+  Level  - The memory test intensive level.\r
+\r
+Returns: \r
+  \r
+  EFI_STATUS      - Success test all the system memory and update\r
+                    the memory resource\r
+                    \r
+--*/\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_STATUS                        InitStatus;\r
+  EFI_STATUS                        KeyStatus;\r
+  EFI_STATUS                        ReturnStatus;\r
+  BOOLEAN                           RequireSoftECCInit;\r
+  EFI_GENERIC_MEMORY_TEST_PROTOCOL  *GenMemoryTest;\r
+  UINT64                            TestedMemorySize;\r
+  UINT64                            TotalMemorySize;\r
+  UINTN                             TestPercent;\r
+  UINT64                            PreviousValue;\r
+  BOOLEAN                           ErrorOut;\r
+  BOOLEAN                           TestAbort;\r
+  EFI_INPUT_KEY                     Key;\r
+  CHAR16                            StrPercent[16];\r
+  CHAR16                            *StrTotalMemory;\r
+  CHAR16                            *Pos;\r
+  CHAR16                            *TmpStr;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     Foreground;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     Background;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     Color;\r
+  UINT8                             Value;\r
+  UINTN                             DataSize;\r
+\r
+  ReturnStatus = EFI_SUCCESS;\r
+  ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
+\r
+  Pos = AllocatePool (128);\r
+\r
+  if (Pos == NULL) {\r
+    return ReturnStatus;\r
+  }\r
+\r
+  StrTotalMemory    = Pos;\r
+\r
+  TestedMemorySize  = 0;\r
+  TotalMemorySize   = 0;\r
+  PreviousValue     = 0;\r
+  ErrorOut          = FALSE;\r
+  TestAbort         = FALSE;\r
+\r
+  SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+  SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+  SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+\r
+  RequireSoftECCInit = FALSE;\r
+\r
+  gST->ConOut->ClearScreen (gST->ConOut);\r
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiGenericMemTestProtocolGuid,\r
+                  NULL,\r
+                  (VOID**)&GenMemoryTest\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (Pos);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  InitStatus = GenMemoryTest->MemoryTestInit (\r
+                                GenMemoryTest,\r
+                                Level,\r
+                                &RequireSoftECCInit\r
+                                );\r
+  if (InitStatus == EFI_NO_MEDIA) {\r
+    //\r
+    // The PEI codes also have the relevant memory test code to check the memory,\r
+    // it can select to test some range of the memory or all of them. If PEI code\r
+    // checks all the memory, this BDS memory test will has no not-test memory to\r
+    // do the test, and then the status of EFI_NO_MEDIA will be returned by\r
+    // "MemoryTestInit". So it does not need to test memory again, just return.\r
+    //\r
+    gBS->FreePool (Pos);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2);\r
+  TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));\r
+\r
+  if (TmpStr != NULL) {\r
+    gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
+    gBS->FreePool (TmpStr);\r
+  }\r
+\r
+  do {\r
+    Status = GenMemoryTest->PerformMemoryTest (\r
+                              GenMemoryTest,\r
+                              &TestedMemorySize,\r
+                              &TotalMemorySize,\r
+                              &ErrorOut,\r
+                              TestAbort\r
+                              );\r
+    if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {\r
+      TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));\r
+      if (TmpStr != NULL) {\r
+        PrintXY (10, 10, NULL, NULL, TmpStr);\r
+        gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4);\r
+        gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
+        gBS->FreePool (TmpStr);\r
+      }\r
+\r
+      ASSERT (0);\r
+    }\r
+\r
+    TestPercent = (UINTN) DivU64x32 (\r
+                            DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),\r
+                            (UINTN)DivU64x32 (TotalMemorySize, 16)\r
+                            );\r
+    if (TestPercent != PreviousValue) {\r
+      UnicodeValueToString (StrPercent, 0, TestPercent, 0);\r
+      gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
+      TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));\r
+      if (TmpStr != NULL) {\r
+        BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL);\r
+        gBS->FreePool (TmpStr);\r
+      }\r
+\r
+      TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
+      if (TmpStr != NULL) {\r
+        PlatformBdsShowProgress (\r
+          Foreground,\r
+          Background,\r
+          TmpStr,\r
+          Color,\r
+          TestPercent,\r
+          (UINTN) PreviousValue\r
+          );\r
+        gBS->FreePool (TmpStr);\r
+      }\r
+    }\r
+\r
+    PreviousValue = TestPercent;\r
+\r
+    KeyStatus     = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+    if (Key.ScanCode == SCAN_ESC) {\r
+      if (!RequireSoftECCInit) {\r
+        TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
+        if (TmpStr != NULL) {\r
+          PlatformBdsShowProgress (\r
+            Foreground,\r
+            Background,\r
+            TmpStr,\r
+            Color,\r
+            100,\r
+            (UINTN) PreviousValue\r
+            );\r
+          gBS->FreePool (TmpStr);\r
+        }\r
+\r
+        gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
+        gST->ConOut->OutputString (gST->ConOut, L"100");\r
+        Status = GenMemoryTest->Finished (GenMemoryTest);\r
+        goto Done;\r
+      }\r
+\r
+      TestAbort = TRUE;\r
+    }\r
+  } while (Status != EFI_NOT_FOUND);\r
+\r
+  Status = GenMemoryTest->Finished (GenMemoryTest);\r
+\r
+Done:\r
+  UnicodeValueToString (StrTotalMemory, COMMA_TYPE, (UINTN) TotalMemorySize, 0);\r
+  if (StrTotalMemory[0] == L',') {\r
+    StrTotalMemory++;\r
+  }\r
+\r
+  TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));\r
+  if (TmpStr != NULL) {\r
+    StrCat (StrTotalMemory, TmpStr);\r
+    gBS->FreePool (TmpStr);\r
+  }\r
+\r
+  gST->ConOut->ClearScreen (gST->ConOut);\r
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+  gST->ConOut->OutputString (gST->ConOut, StrTotalMemory);\r
+  PlatformBdsShowProgress (\r
+    Foreground,\r
+    Background,\r
+    StrTotalMemory,\r
+    Color,\r
+    100,\r
+    (UINTN) PreviousValue\r
+    );\r
+\r
+  gBS->FreePool (Pos);\r
+\r
+  DataSize = sizeof (Value);\r
+  Status = gRT->GetVariable (\r
+                  L"BootState",\r
+                  &gEfiBootStateGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  &Value\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Value = 1;\r
+    gRT->SetVariable (\r
+          L"BootState",\r
+          &gEfiBootStateGuid,\r
+          EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+          sizeof (Value),\r
+          &Value\r
+          );\r
+  }\r
+\r
+  return ReturnStatus;\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/String.c b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/String.c
new file mode 100644 (file)
index 0000000..1b04f02
--- /dev/null
@@ -0,0 +1,136 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  string.c\r
+\r
+Abstract:\r
+\r
+  String support\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "String.h"\r
+#include "Language.h"\r
+\r
+extern UINT8  EdkGenericPlatformBdsLibStrings[];\r
+\r
+EFI_GUID      gBdsStringPackGuid = { 0x7bac95d3, 0xddf, 0x42f3, {0x9e, 0x24, 0x7c, 0x64, 0x49, 0x40, 0x37, 0x9a} };\r
+\r
+EFI_HII_HANDLE    gStringPackHandle;\r
+EFI_HII_PROTOCOL  *Hii;\r
+\r
+EFI_STATUS\r
+InitializeStringSupport (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Initialize HII global accessor for string support\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  String from ID.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS        Status;\r
+  EFI_HII_PACKAGES  *PackageList;\r
+  //\r
+  // There should only ever be one HII protocol\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiProtocolGuid,\r
+                  NULL,\r
+                  (VOID**)&Hii\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    PackageList = PreparePackages (1, &gBdsStringPackGuid, EdkGenericPlatformBdsLibStrings);\r
+    Status      = Hii->NewPack (Hii, PackageList, &gStringPackHandle);\r
+    gBS->FreePool (PackageList);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+CHAR16 *\r
+GetStringById (\r
+  IN  STRING_REF   Id\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Get string by string id from HII Interface\r
+\r
+Arguments:\r
+\r
+  Id       - String ID.\r
+           \r
+Returns:\r
+\r
+  CHAR16 * - String from ID.\r
+  NULL     - If error occurs.\r
+\r
+--*/\r
+{\r
+  CHAR16      *String;\r
+  UINTN       StringLength;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Set default string size assumption at no more than 256 bytes\r
+  //\r
+  StringLength  = 0x100;\r
+\r
+  String        = AllocateZeroPool (StringLength);\r
+  if (String == NULL) {\r
+    //\r
+    // If this happens, we are oh-so-dead, but return a NULL in any case.\r
+    //\r
+    return NULL;\r
+  }\r
+  //\r
+  // Get the current string for the current Language\r
+  //\r
+  Status = Hii->GetString (Hii, gStringPackHandle, Id, FALSE, NULL, &StringLength, String);\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      //\r
+      // Free the old pool\r
+      //\r
+      gBS->FreePool (String);\r
+\r
+      //\r
+      // Allocate new pool with correct value\r
+      //\r
+      String = AllocatePool (StringLength);\r
+      ASSERT (String != NULL);\r
+\r
+      Status = Hii->GetString (Hii, gStringPackHandle, Id, FALSE, NULL, &StringLength, String);\r
+      if (!EFI_ERROR (Status)) {\r
+        return String;\r
+      }\r
+    }\r
+\r
+    return NULL;\r
+  }\r
+\r
+  return String;\r
+}\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/String.h b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/String.h
new file mode 100644 (file)
index 0000000..da6a912
--- /dev/null
@@ -0,0 +1,59 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. 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
+Module Name:\r
+\r
+  string.h\r
+\r
+Abstract:\r
+  \r
+  String support\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _STRING_H_\r
+#define _STRING_H_\r
+\r
+//\r
+// This is the VFR compiler generated header file which defines the\r
+// string identifiers.\r
+//\r
+#include "EdkGenericPlatformBdsLibStrDefs.h"\r
+\r
+//\r
+// String Definition Guid for BDS Platform\r
+//\r
+#define EFI_BDS_PLATFORM_GUID \\r
+  { \\r
+    0x7777E939, 0xD57E, 0x4DCB, {0xA0, 0x8E, 0x64, 0xD7, 0x98, 0x57, 0x1E, 0x0F } \\r
+  }\r
+\r
+extern EFI_HII_HANDLE    gStringPackHandle;\r
+extern EFI_HII_PROTOCOL  *Hii;\r
+\r
+CHAR16            *\r
+GetStringById (\r
+  IN  STRING_REF   Id\r
+  );\r
+\r
+EFI_STATUS\r
+InitializeStringSupport (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+CallFrontPage (\r
+  VOID\r
+  );\r
+\r
+#endif // _STRING_H_\r
diff --git a/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Strings.uni b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Strings.uni
new file mode 100644 (file)
index 0000000..41a6b9a
Binary files /dev/null and b/EdkModulePkg/Library/EdkGenericPlatformBdsLib/Strings.uni differ