]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkNt32Pkg/Library/EdkGenericBdsLib/BdsMisc.c
add in FrameworkIfrSupportLib
[mirror_edk2.git] / EdkNt32Pkg / Library / EdkGenericBdsLib / BdsMisc.c
index 576ae7237f721dd065cb7d383d1ef3d4da21ac55..b8be94e74ddde08f9121b9b3bc4b84281d921bca 100644 (file)
@@ -1,13 +1,13 @@
 /*++\r
 \r
 /*++\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
+Copyright (c) 2006 - 2007, 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
 \r
 Module Name:\r
 \r
@@ -19,6 +19,9 @@ Abstract:
 \r
 --*/\r
 \r
 \r
 --*/\r
 \r
+#define MAX_STRING_LEN        200\r
+static BOOLEAN   mFeaturerSwitch = TRUE;\r
+static BOOLEAN   mResetRequired  = FALSE;\r
 extern UINT16 gPlatformBootTimeOutDefault;\r
 \r
 UINT16\r
 extern UINT16 gPlatformBootTimeOutDefault;\r
 \r
 UINT16\r
@@ -28,7 +31,7 @@ BdsLibGetTimeout (
 /*++\r
 \r
 Routine Description:\r
 /*++\r
 \r
 Routine Description:\r
-  \r
+\r
   Return the default value for system Timeout variable.\r
 \r
 Arguments:\r
   Return the default value for system Timeout variable.\r
 \r
 Arguments:\r
@@ -36,7 +39,7 @@ Arguments:
   None\r
 \r
 Returns:\r
   None\r
 \r
 Returns:\r
-  \r
+\r
   Timeout value.\r
 \r
 --*/\r
   Timeout value.\r
 \r
 --*/\r
@@ -82,7 +85,7 @@ BdsLibLoadDrivers (
 /*++\r
 \r
 Routine Description:\r
 /*++\r
 \r
 Routine Description:\r
-  \r
+\r
   The function will go through the driver optoin link list, load and start\r
   every driver the driver optoin device path point to.\r
 \r
   The function will go through the driver optoin link list, load and start\r
   every driver the driver optoin device path point to.\r
 \r
@@ -91,7 +94,7 @@ Arguments:
   BdsDriverLists   - The header of the current driver option link list\r
 \r
 Returns:\r
   BdsDriverLists   - The header of the current driver option link list\r
 \r
 Returns:\r
-  \r
+\r
   None\r
 \r
 --*/\r
   None\r
 \r
 --*/\r
@@ -195,7 +198,7 @@ BdsLibRegisterNewOption (
 /*++\r
 \r
 Routine Description:\r
 /*++\r
 \r
 Routine Description:\r
-  \r
+\r
   This function will register the new boot#### or driver#### option base on\r
   the VariableName. The new registered boot#### or driver#### will be linked\r
   to BdsOptionList and also update to the VariableName. After the boot#### or\r
   This function will register the new boot#### or driver#### option base on\r
   the VariableName. The new registered boot#### or driver#### will be linked\r
   to BdsOptionList and also update to the VariableName. After the boot#### or\r
@@ -204,18 +207,18 @@ Routine Description:
 Arguments:\r
 \r
   BdsOptionList    - The header of the boot#### or driver#### link list\r
 Arguments:\r
 \r
   BdsOptionList    - The header of the boot#### or driver#### link list\r
-  \r
+\r
   DevicePath       - The device path which the boot####\r
                      or driver#### option present\r
   DevicePath       - The device path which the boot####\r
                      or driver#### option present\r
-                     \r
+\r
   String           - The description of the boot#### or driver####\r
   String           - The description of the boot#### or driver####\r
-  \r
+\r
   VariableName     - Indicate if the boot#### or driver#### option\r
 \r
 Returns:\r
   VariableName     - Indicate if the boot#### or driver#### option\r
 \r
 Returns:\r
-  \r
+\r
   EFI_SUCCESS      - The boot#### or driver#### have been success registered\r
   EFI_SUCCESS      - The boot#### or driver#### have been success registered\r
-  \r
+\r
   EFI_STATUS       - Return the status of gRT->SetVariable ().\r
 \r
 --*/\r
   EFI_STATUS       - Return the status of gRT->SetVariable ().\r
 \r
 --*/\r
@@ -246,11 +249,13 @@ Returns:
   ZeroMem (OptionName, sizeof (OptionName));\r
 \r
   TempOptionSize = 0;\r
   ZeroMem (OptionName, sizeof (OptionName));\r
 \r
   TempOptionSize = 0;\r
+\r
   TempOptionPtr = BdsLibGetVariableAndSize (\r
                     VariableName,\r
                     &gEfiGlobalVariableGuid,\r
                     &TempOptionSize\r
                     );\r
   TempOptionPtr = BdsLibGetVariableAndSize (\r
                     VariableName,\r
                     &gEfiGlobalVariableGuid,\r
                     &TempOptionSize\r
                     );\r
+\r
   //\r
   // Compare with current option variable\r
   //\r
   //\r
   // Compare with current option variable\r
   //\r
@@ -287,8 +292,8 @@ Returns:
         //\r
         // Got the option, so just return\r
         //\r
         //\r
         // Got the option, so just return\r
         //\r
-        gBS->FreePool (OptionPtr);\r
-        gBS->FreePool (TempOptionPtr);\r
+        FreePool (OptionPtr);\r
+        FreePool (TempOptionPtr);\r
         return EFI_SUCCESS;\r
       } else {\r
         //\r
         return EFI_SUCCESS;\r
       } else {\r
         //\r
@@ -299,7 +304,7 @@ Returns:
       }\r
     }\r
 \r
       }\r
     }\r
 \r
-    gBS->FreePool (OptionPtr);\r
+    FreePool (OptionPtr);\r
   }\r
 \r
   OptionSize          = sizeof (UINT32) + sizeof (UINT16) + StrSize (String) + GetDevicePathSize (DevicePath);\r
   }\r
 \r
   OptionSize          = sizeof (UINT32) + sizeof (UINT16) + StrSize (String) + GetDevicePathSize (DevicePath);\r
@@ -339,12 +344,12 @@ Returns:
                   OptionPtr\r
                   );\r
   if (EFI_ERROR (Status) || UpdateBootDevicePath) {\r
                   OptionPtr\r
                   );\r
   if (EFI_ERROR (Status) || UpdateBootDevicePath) {\r
-    gBS->FreePool (OptionPtr);\r
-    gBS->FreePool (TempOptionPtr);\r
+    FreePool (OptionPtr);\r
+    FreePool (TempOptionPtr);\r
     return Status;\r
   }\r
 \r
     return Status;\r
   }\r
 \r
-  gBS->FreePool (OptionPtr);\r
+  FreePool (OptionPtr);\r
 \r
   //\r
   // Update the option order variable\r
 \r
   //\r
   // Update the option order variable\r
@@ -360,13 +365,15 @@ Returns:
                   OptionOrderPtr\r
                   );\r
   if (EFI_ERROR (Status)) {\r
                   OptionOrderPtr\r
                   );\r
   if (EFI_ERROR (Status)) {\r
-    gBS->FreePool (TempOptionPtr);\r
-    gBS->FreePool (OptionOrderPtr);\r
+    FreePool (TempOptionPtr);\r
+    FreePool (OptionOrderPtr);\r
     return Status;\r
   }\r
 \r
     return Status;\r
   }\r
 \r
-  gBS->FreePool (TempOptionPtr);\r
-  gBS->FreePool (OptionOrderPtr);\r
+  if (TempOptionPtr != NULL) {\r
+    FreePool (TempOptionPtr);\r
+  }\r
+  FreePool (OptionOrderPtr);\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -380,9 +387,9 @@ BdsLibVariableToOption (
 \r
 Routine Description:\r
 \r
 \r
 Routine Description:\r
 \r
-  Build the boot#### or driver#### option from the VariableName, the \r
+  Build the boot#### or driver#### option from the VariableName, the\r
   build boot#### or driver#### will also be linked to BdsCommonOptionList\r
   build boot#### or driver#### will also be linked to BdsCommonOptionList\r
-  \r
+\r
 Arguments:\r
 \r
   BdsCommonOptionList - The header of the boot#### or driver#### option link list\r
 Arguments:\r
 \r
   BdsCommonOptionList - The header of the boot#### or driver#### option link list\r
@@ -479,12 +486,12 @@ Returns:
   //\r
   if ((Option->Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE) {\r
     InsertTailList (BdsCommonOptionList, &Option->Link);\r
   //\r
   if ((Option->Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE) {\r
     InsertTailList (BdsCommonOptionList, &Option->Link);\r
-    gBS->FreePool (Variable);\r
+    FreePool (Variable);\r
     return Option;\r
   }\r
 \r
     return Option;\r
   }\r
 \r
-  gBS->FreePool (Variable);\r
-  gBS->FreePool (Option);\r
+  FreePool (Variable);\r
+  FreePool (Option);\r
   return NULL;\r
 \r
 }\r
   return NULL;\r
 \r
 }\r
@@ -550,38 +557,7 @@ Returns:
 \r
   }\r
 \r
 \r
   }\r
 \r
-  gBS->FreePool (OptionOrder);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-BdsLibGetBootMode (\r
-  OUT EFI_BOOT_MODE       *BootMode\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Get boot mode by looking up configuration table and parsing HOB list\r
-\r
-Arguments:\r
-\r
-  BootMode - Boot mode from PEI handoff HOB.\r
-\r
-Returns:\r
-\r
-  EFI_SUCCESS - Successfully get boot mode\r
-  \r
-  EFI_NOT_FOUND - Can not find the current system boot mode\r
-\r
---*/\r
-{\r
-  EFI_HOB_HANDOFF_INFO_TABLE        *HobList;\r
-\r
-  HobList = GetHobList ();\r
-  ASSERT (HobList->Header.HobType == EFI_HOB_TYPE_HANDOFF);\r
-  *BootMode = HobList->BootMode;\r
+  FreePool (OptionOrder);\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -648,6 +624,95 @@ Returns:
   return Buffer;\r
 }\r
 \r
   return Buffer;\r
 }\r
 \r
+VOID\r
+BdsLibSafeFreePool (\r
+  IN  VOID             *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Free pool safely.\r
+\r
+Arguments:\r
+\r
+  Buffer          - The allocated pool entry to free\r
+\r
+Returns:\r
+\r
+  Pointer of the buffer allocated.\r
+\r
+--*/\r
+{\r
+  if (Buffer != NULL) {\r
+    FreePool (Buffer);\r
+    Buffer = NULL;\r
+  }\r
+}\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BdsLibDelPartMatchInstance (\r
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Single\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Delete the instance in Multi which matches partly with Single instance\r
+\r
+Arguments:\r
+\r
+  Multi        - A pointer to a multi-instance device path data structure.\r
+\r
+  Single       - A pointer to a single-instance device path data structure.\r
+\r
+Returns:\r
+\r
+  This function will remove the device path instances in Multi which partly\r
+  match with the Single, and return the result device path. If there is no\r
+  remaining device path as a result, this function will return NULL.\r
+\r
+--*/\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;\r
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;\r
+  UINTN                     InstanceSize;\r
+  UINTN                     SingleDpSize;\r
+  UINTN                     Size;\r
+\r
+  NewDevicePath     = NULL;\r
+  TempNewDevicePath = NULL;\r
+\r
+  if (Multi == NULL || Single == NULL) {\r
+    return Multi;\r
+  }\r
+\r
+  Instance        =  GetNextDevicePathInstance (&Multi, &InstanceSize);\r
+  SingleDpSize    =  GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;\r
+  InstanceSize    -= END_DEVICE_PATH_LENGTH;\r
+\r
+  while (Instance != NULL) {\r
+\r
+    Size = (SingleDpSize < InstanceSize) ? SingleDpSize : InstanceSize;\r
+\r
+    if ((CompareMem (Instance, Single, Size) != 0)) {\r
+      //\r
+      // Append the device path instance which does not match with Single\r
+      //\r
+      TempNewDevicePath = NewDevicePath;\r
+      NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);\r
+      BdsLibSafeFreePool(TempNewDevicePath);\r
+    }\r
+    BdsLibSafeFreePool(Instance);\r
+    Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);\r
+    InstanceSize  -= END_DEVICE_PATH_LENGTH;\r
+  }\r
+\r
+  return NewDevicePath;\r
+}\r
+\r
 BOOLEAN\r
 BdsLibMatchDevicePaths (\r
   IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
 BOOLEAN\r
 BdsLibMatchDevicePaths (\r
   IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
@@ -669,9 +734,9 @@ Arguments:
 Returns:\r
 \r
   TRUE   - If the Single is contained within Multi\r
 Returns:\r
 \r
   TRUE   - If the Single is contained within Multi\r
-  \r
+\r
   FALSE  - The Single is not match within Multi\r
   FALSE  - The Single is not match within Multi\r
-  \r
+\r
 \r
 --*/\r
 {\r
 \r
 --*/\r
 {\r
@@ -685,7 +750,6 @@ Returns:
 \r
   DevicePath      = Multi;\r
   DevicePathInst  = GetNextDevicePathInstance (&DevicePath, &Size);\r
 \r
   DevicePath      = Multi;\r
   DevicePathInst  = GetNextDevicePathInstance (&DevicePath, &Size);\r
-  Size -= sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
 \r
   //\r
   // Search for the match of 'Single' in 'Multi'\r
 \r
   //\r
   // Search for the match of 'Single' in 'Multi'\r
@@ -695,17 +759,13 @@ Returns:
     // If the single device path is found in multiple device paths,\r
     // return success\r
     //\r
     // If the single device path is found in multiple device paths,\r
     // return success\r
     //\r
-    if (Size == 0) {\r
-      return FALSE;\r
-    }\r
-\r
     if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
     if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
+      FreePool (DevicePathInst);\r
       return TRUE;\r
     }\r
 \r
       return TRUE;\r
     }\r
 \r
-    gBS->FreePool (DevicePathInst);\r
+    FreePool (DevicePathInst);\r
     DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
     DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
-    Size -= sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
   }\r
 \r
   return FALSE;\r
   }\r
 \r
   return FALSE;\r
@@ -732,7 +792,7 @@ Arguments:
 Returns:\r
 \r
   EFI_SUCCESS          - Success print out the string using ConOut.\r
 Returns:\r
 \r
   EFI_SUCCESS          - Success print out the string using ConOut.\r
-  \r
+\r
   EFI_STATUS           - Return the status of the ConOut->OutputString ().\r
 \r
 --*/\r
   EFI_STATUS           - Return the status of the ConOut->OutputString ().\r
 \r
 --*/\r
@@ -762,3 +822,273 @@ Returns:
 \r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
+\r
+//\r
+//  Following are BDS Lib functions which  contain all the code about setup browser reset reminder feature.\r
+//  Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser  if\r
+//  user change any option setting which needs a reset to be effective, and  the reset will be applied according to  the user selection.\r
+//\r
+\r
+VOID\r
+EnableResetReminderFeature (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Enable the setup browser reset reminder feature.\r
+  This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.\r
+\r
+Arguments:\r
+\r
+  VOID\r
+\r
+Returns:\r
+\r
+  VOID\r
+\r
+--*/\r
+{\r
+  mFeaturerSwitch = TRUE;\r
+}\r
+\r
+VOID\r
+DisableResetReminderFeature (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Disable the setup browser reset reminder feature.\r
+  This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.\r
+\r
+Arguments:\r
+\r
+  VOID\r
+\r
+Returns:\r
+\r
+  VOID\r
+\r
+--*/\r
+{\r
+  mFeaturerSwitch = FALSE;\r
+}\r
+\r
+VOID\r
+EnableResetRequired (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+   Record the info that  a reset is required.\r
+   A  module boolean variable is used to record whether a reset is required.\r
+\r
+Arguments:\r
+\r
+  VOID\r
+\r
+Returns:\r
+\r
+  VOID\r
+\r
+--*/\r
+{\r
+  mResetRequired = TRUE;\r
+}\r
+\r
+VOID\r
+DisableResetRequired (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+   Record the info that  no reset is required.\r
+   A  module boolean variable is used to record whether a reset is required.\r
+\r
+Arguments:\r
+\r
+  VOID\r
+\r
+Returns:\r
+\r
+  VOID\r
+\r
+--*/\r
+{\r
+  mResetRequired = FALSE;\r
+}\r
+\r
+BOOLEAN\r
+IsResetReminderFeatureEnable (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Check whether platform policy enable the reset reminder feature. The default is enabled.\r
+\r
+Arguments:\r
+\r
+  VOID\r
+\r
+Returns:\r
+\r
+  VOID\r
+\r
+--*/\r
+{\r
+  return mFeaturerSwitch;\r
+}\r
+\r
+BOOLEAN\r
+IsResetRequired (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Check if  user changed any option setting which needs a system reset to be effective.\r
+\r
+Arguments:\r
+\r
+  VOID\r
+\r
+Returns:\r
+\r
+  VOID\r
+\r
+--*/\r
+{\r
+  return mResetRequired;\r
+}\r
+\r
+VOID\r
+SetupResetReminder (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Check whether a reset is needed, and finish the reset reminder feature.\r
+  If a reset is needed, Popup a menu to notice user, and finish the feature\r
+  according to the user selection.\r
+\r
+Arguments:\r
+\r
+  VOID\r
+\r
+Returns:\r
+\r
+  VOID\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_FORM_BROWSER_PROTOCOL     *Browser;\r
+  EFI_INPUT_KEY                 Key;\r
+  CHAR16                        *StringBuffer1;\r
+  CHAR16                        *StringBuffer2;\r
+\r
+\r
+  //\r
+  //check any reset required change is applied? if yes, reset system\r
+  //\r
+  if (IsResetReminderFeatureEnable ()) {\r
+    if (IsResetRequired ()) {\r
+\r
+      Status = gBS->LocateProtocol (\r
+                      &gEfiFormBrowserProtocolGuid,\r
+                      NULL,\r
+                      &Browser\r
+                      );\r
+\r
+      ASSERT (Status != EFI_SUCCESS);\r
+\r
+      StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
+      ASSERT (StringBuffer1 != NULL);\r
+      StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
+      ASSERT (StringBuffer2 != NULL);\r
+      StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now ? ");\r
+      StrCpy (StringBuffer2, L"Enter (YES)  /   Esc (NO)");\r
+      //\r
+      // Popup a menu to notice user\r
+      //\r
+      do {\r
+        Browser->CreatePopUp (2, TRUE, 0, NULL, &Key, StringBuffer1, StringBuffer2);\r
+      } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+      FreePool (StringBuffer1);\r
+      FreePool (StringBuffer2);\r
+      //\r
+      // If the user hits the YES Response key, reset\r
+      //\r
+      if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {\r
+        gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+      }\r
+      gST->ConOut->ClearScreen (gST->ConOut);\r
+    }\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+BdsLibGetHiiHandles (\r
+  IN     EFI_HII_PROTOCOL *Hii,\r
+  IN OUT UINT16           *HandleBufferLength,\r
+  OUT    EFI_HII_HANDLE   **HiiHandleBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Determines the handles that are currently active in the database.\r
+  It's the caller's responsibility to free handle buffer.\r
+\r
+Arguments:\r
+\r
+  This                  - A pointer to the EFI_HII_PROTOCOL instance.\r
+  HandleBufferLength    - On input, a pointer to the length of the handle buffer. On output,\r
+                          the length of the handle buffer that is required for the handles found.\r
+  HiiHandleBuffer       - Pointer to an array of EFI_HII_PROTOCOL instances returned.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS           - Get an array of EFI_HII_PROTOCOL instances successfully.\r
+  EFI_INVALID_PARAMETER - Hii is NULL.\r
+  EFI_NOT_FOUND         - Database not found.\r
+\r
+--*/\r
+{\r
+  UINT16      TempBufferLength;\r
+  EFI_STATUS  Status;\r
+\r
+  TempBufferLength = 0;\r
+\r
+  //\r
+  // Try to find the actual buffer size for HiiHandle Buffer.\r
+  //\r
+  Status = Hii->FindHandles (Hii, &TempBufferLength, *HiiHandleBuffer);\r
+\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    *HiiHandleBuffer = AllocateZeroPool (TempBufferLength);\r
+    Status = Hii->FindHandles (Hii, &TempBufferLength, *HiiHandleBuffer);\r
+    //\r
+    // we should not fail here.\r
+    //\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  *HandleBufferLength = TempBufferLength;\r
+\r
+  return Status;\r
+\r
+}\r