Home | History | Annotate | Download | only in UiApp
      1 /** @file
      2 
      3   This library class defines a set of interfaces to customize Ui module
      4 
      5 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials are licensed and made available under
      7 the terms and conditions of the BSD License that accompanies this distribution.
      8 The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php.
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 #include <Uefi.h>
     16 
     17 #include <Guid/MdeModuleHii.h>
     18 #include <Guid/GlobalVariable.h>
     19 
     20 #include <Protocol/HiiConfigAccess.h>
     21 #include <Protocol/HiiString.h>
     22 
     23 #include <Library/HiiLib.h>
     24 #include <Library/DebugLib.h>
     25 #include <Library/UefiLib.h>
     26 #include <Library/BaseMemoryLib.h>
     27 #include <Library/PcdLib.h>
     28 #include <Library/MemoryAllocationLib.h>
     29 #include <Library/UefiRuntimeServicesTableLib.h>
     30 #include <Library/UefiHiiServicesLib.h>
     31 #include <Library/DevicePathLib.h>
     32 #include <Library/UefiBootServicesTableLib.h>
     33 #include "FrontPageCustomizedUiSupport.h"
     34 
     35 //
     36 // This is the VFR compiler generated header file which defines the
     37 // string identifiers.
     38 //
     39 #define PRINTABLE_LANGUAGE_NAME_STRING_ID     0x0001
     40 
     41 #define UI_HII_DRIVER_LIST_SIZE               0x8
     42 
     43 #define FRONT_PAGE_KEY_CONTINUE               0x1000
     44 #define FRONT_PAGE_KEY_RESET                  0x1001
     45 #define FRONT_PAGE_KEY_LANGUAGE               0x1002
     46 #define FRONT_PAGE_KEY_DRIVER                 0x2000
     47 
     48 typedef struct {
     49   EFI_STRING_ID   PromptId;
     50   EFI_STRING_ID   HelpId;
     51   EFI_STRING_ID   DevicePathId;
     52   EFI_GUID        FormSetGuid;
     53   BOOLEAN         EmptyLineAfter;
     54 } UI_HII_DRIVER_INSTANCE;
     55 
     56 CHAR8                        *gLanguageString;
     57 EFI_STRING_ID                *gLanguageToken;
     58 UI_HII_DRIVER_INSTANCE       *gHiiDriverList;
     59 extern EFI_HII_HANDLE        gStringPackHandle;
     60 UINT8                        gCurrentLanguageIndex;
     61 
     62 
     63 /**
     64   Get next language from language code list (with separator ';').
     65 
     66   If LangCode is NULL, then ASSERT.
     67   If Lang is NULL, then ASSERT.
     68 
     69   @param  LangCode    On input: point to first language in the list. On
     70                                  output: point to next language in the list, or
     71                                  NULL if no more language in the list.
     72   @param  Lang           The first language in the list.
     73 
     74 **/
     75 VOID
     76 GetNextLanguage (
     77   IN OUT CHAR8      **LangCode,
     78   OUT CHAR8         *Lang
     79   )
     80 {
     81   UINTN  Index;
     82   CHAR8  *StringPtr;
     83 
     84   ASSERT (LangCode != NULL);
     85   ASSERT (*LangCode != NULL);
     86   ASSERT (Lang != NULL);
     87 
     88   Index = 0;
     89   StringPtr = *LangCode;
     90   while (StringPtr[Index] != 0 && StringPtr[Index] != ';') {
     91     Index++;
     92   }
     93 
     94   CopyMem (Lang, StringPtr, Index);
     95   Lang[Index] = 0;
     96 
     97   if (StringPtr[Index] == ';') {
     98     Index++;
     99   }
    100   *LangCode = StringPtr + Index;
    101 }
    102 
    103 /**
    104   This function processes the language changes in configuration.
    105 
    106   @param Value           A pointer to the data being sent to the original exporting driver.
    107 
    108 
    109   @retval  TRUE          The callback successfully handled the action.
    110   @retval  FALSE         The callback not supported in this handler.
    111 
    112 **/
    113 EFI_STATUS
    114 LanguageChangeHandler (
    115   IN  EFI_IFR_TYPE_VALUE                     *Value
    116   )
    117 {
    118   CHAR8                         *LangCode;
    119   CHAR8                         *Lang;
    120   UINTN                         Index;
    121   EFI_STATUS                    Status;
    122 
    123   //
    124   // Allocate working buffer for RFC 4646 language in supported LanguageString.
    125   //
    126   Lang = AllocatePool (AsciiStrSize (gLanguageString));
    127   ASSERT (Lang != NULL);
    128 
    129   Index = 0;
    130   LangCode = gLanguageString;
    131   while (*LangCode != 0) {
    132     GetNextLanguage (&LangCode, Lang);
    133 
    134     if (Index == Value->u8) {
    135       gCurrentLanguageIndex = Value->u8;
    136       break;
    137     }
    138 
    139     Index++;
    140   }
    141 
    142   if (Index == Value->u8) {
    143     Status = gRT->SetVariable (
    144                     L"PlatformLang",
    145                     &gEfiGlobalVariableGuid,
    146                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    147                     AsciiStrSize (Lang),
    148                     Lang
    149                     );
    150     if (EFI_ERROR (Status)) {
    151       FreePool (Lang);
    152       return EFI_DEVICE_ERROR;
    153     }
    154   } else {
    155     ASSERT (FALSE);
    156   }
    157   FreePool (Lang);
    158 
    159   return EFI_SUCCESS;
    160 }
    161 
    162 /**
    163   This function processes the results of changes in configuration.
    164 
    165 
    166   @param HiiHandle       Points to the hii handle for this formset.
    167   @param Action          Specifies the type of action taken by the browser.
    168   @param QuestionId      A unique value which is sent to the original exporting driver
    169                          so that it can identify the type of data to expect.
    170   @param Type            The type of value for the question.
    171   @param Value           A pointer to the data being sent to the original exporting driver.
    172   @param ActionRequest   On return, points to the action requested by the callback function.
    173   @param Status          Return the handle status.
    174 
    175   @retval  TRUE          The callback successfully handled the action.
    176   @retval  FALSE         The callback not supported in this handler.
    177 
    178 **/
    179 BOOLEAN
    180 UiSupportLibCallbackHandler (
    181   IN  EFI_HII_HANDLE                         HiiHandle,
    182   IN  EFI_BROWSER_ACTION                     Action,
    183   IN  EFI_QUESTION_ID                        QuestionId,
    184   IN  UINT8                                  Type,
    185   IN  EFI_IFR_TYPE_VALUE                     *Value,
    186   OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest,
    187   OUT EFI_STATUS                             *Status
    188   )
    189 {
    190   if (QuestionId != FRONT_PAGE_KEY_CONTINUE &&
    191       QuestionId != FRONT_PAGE_KEY_RESET &&
    192       QuestionId != FRONT_PAGE_KEY_LANGUAGE) {
    193     return FALSE;
    194   }
    195 
    196   if (Action == EFI_BROWSER_ACTION_RETRIEVE) {
    197     if (QuestionId == FRONT_PAGE_KEY_LANGUAGE) {
    198       Value->u8 = gCurrentLanguageIndex;
    199       *Status = EFI_SUCCESS;
    200     } else {
    201       *Status = EFI_UNSUPPORTED;
    202     }
    203     return TRUE;
    204   }
    205 
    206   if (Action != EFI_BROWSER_ACTION_CHANGED) {
    207     //
    208     // Do nothing for other UEFI Action. Only do call back when data is changed.
    209     //
    210     *Status = EFI_UNSUPPORTED;
    211     return TRUE;
    212   }
    213 
    214   if (Action == EFI_BROWSER_ACTION_CHANGED) {
    215     if ((Value == NULL) || (ActionRequest == NULL)) {
    216       *Status = EFI_INVALID_PARAMETER;
    217       return TRUE;
    218     }
    219 
    220     *Status = EFI_SUCCESS;
    221     switch (QuestionId) {
    222     case FRONT_PAGE_KEY_CONTINUE:
    223       //
    224       // This is the continue - clear the screen and return an error to get out of FrontPage loop
    225       //
    226       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
    227       break;
    228 
    229     case FRONT_PAGE_KEY_LANGUAGE:
    230       *Status = LanguageChangeHandler(Value);
    231       break;
    232 
    233     case FRONT_PAGE_KEY_RESET:
    234       //
    235       // Reset
    236       //
    237       gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
    238       *Status = EFI_UNSUPPORTED;
    239 
    240     default:
    241       break;
    242     }
    243   }
    244 
    245   return TRUE;
    246 }
    247 
    248 /**
    249   Create Select language menu in the front page with oneof opcode.
    250 
    251   @param[in]    HiiHandle           The hii handle for the Uiapp driver.
    252   @param[in]    StartOpCodeHandle   The opcode handle to save the new opcode.
    253 
    254 **/
    255 VOID
    256 UiCreateLanguageMenu (
    257   IN EFI_HII_HANDLE              HiiHandle,
    258   IN VOID                        *StartOpCodeHandle
    259   )
    260 {
    261   CHAR8                       *LangCode;
    262   CHAR8                       *Lang;
    263   UINTN                       LangSize;
    264   CHAR8                       *CurrentLang;
    265   UINTN                       OptionCount;
    266   CHAR16                      *StringBuffer;
    267   VOID                        *OptionsOpCodeHandle;
    268   UINTN                       StringSize;
    269   EFI_STATUS                  Status;
    270   EFI_HII_STRING_PROTOCOL     *HiiString;
    271 
    272   Lang         = NULL;
    273   StringBuffer = NULL;
    274 
    275   //
    276   // Init OpCode Handle and Allocate space for creation of UpdateData Buffer
    277   //
    278   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    279   ASSERT (OptionsOpCodeHandle != NULL);
    280 
    281   GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&CurrentLang, NULL);
    282 
    283   //
    284   // Get Support language list from variable.
    285   //
    286   GetEfiGlobalVariable2 (L"PlatformLangCodes", (VOID**)&gLanguageString, NULL);
    287   if (gLanguageString == NULL) {
    288     gLanguageString = AllocateCopyPool (
    289                                AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)),
    290                                (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)
    291                                );
    292     ASSERT (gLanguageString != NULL);
    293   }
    294 
    295   if (gLanguageToken == NULL) {
    296     //
    297     // Count the language list number.
    298     //
    299     LangCode = gLanguageString;
    300     Lang = AllocatePool (AsciiStrSize (gLanguageString));
    301     ASSERT (Lang != NULL);
    302 
    303     OptionCount = 0;
    304     while (*LangCode != 0) {
    305       GetNextLanguage (&LangCode, Lang);
    306       OptionCount ++;
    307     }
    308 
    309     //
    310     // Allocate extra 1 as the end tag.
    311     //
    312     gLanguageToken = AllocateZeroPool ((OptionCount + 1) * sizeof (EFI_STRING_ID));
    313     ASSERT (gLanguageToken != NULL);
    314 
    315     Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
    316     ASSERT_EFI_ERROR (Status);
    317 
    318     LangCode     = gLanguageString;
    319     OptionCount  = 0;
    320     while (*LangCode != 0) {
    321       GetNextLanguage (&LangCode, Lang);
    322 
    323       StringSize = 0;
    324       Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL);
    325       if (Status == EFI_BUFFER_TOO_SMALL) {
    326         StringBuffer = AllocateZeroPool (StringSize);
    327         ASSERT (StringBuffer != NULL);
    328         Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL);
    329         ASSERT_EFI_ERROR (Status);
    330       }
    331 
    332       if (EFI_ERROR (Status)) {
    333         LangSize = AsciiStrSize (Lang);
    334         StringBuffer = AllocatePool (LangSize * sizeof (CHAR16));
    335         ASSERT (StringBuffer != NULL);
    336         AsciiStrToUnicodeStrS (Lang, StringBuffer, LangSize);
    337       }
    338 
    339       ASSERT (StringBuffer != NULL);
    340       gLanguageToken[OptionCount] = HiiSetString (HiiHandle, 0, StringBuffer, NULL);
    341       FreePool (StringBuffer);
    342 
    343       OptionCount++;
    344     }
    345   }
    346 
    347   ASSERT (gLanguageToken != NULL);
    348   LangCode = gLanguageString;
    349   OptionCount = 0;
    350   if (Lang == NULL) {
    351     Lang = AllocatePool (AsciiStrSize (gLanguageString));
    352     ASSERT (Lang != NULL);
    353   }
    354   while (*LangCode != 0) {
    355     GetNextLanguage (&LangCode, Lang);
    356 
    357     if (CurrentLang != NULL && AsciiStrCmp (Lang, CurrentLang) == 0) {
    358       HiiCreateOneOfOptionOpCode (
    359         OptionsOpCodeHandle,
    360         gLanguageToken[OptionCount],
    361         EFI_IFR_OPTION_DEFAULT,
    362         EFI_IFR_NUMERIC_SIZE_1,
    363         (UINT8) OptionCount
    364         );
    365       gCurrentLanguageIndex = (UINT8) OptionCount;
    366     } else {
    367       HiiCreateOneOfOptionOpCode (
    368         OptionsOpCodeHandle,
    369         gLanguageToken[OptionCount],
    370         0,
    371         EFI_IFR_NUMERIC_SIZE_1,
    372         (UINT8) OptionCount
    373         );
    374     }
    375 
    376     OptionCount++;
    377   }
    378 
    379   if (CurrentLang != NULL) {
    380     FreePool (CurrentLang);
    381   }
    382   FreePool (Lang);
    383 
    384   HiiCreateOneOfOpCode (
    385     StartOpCodeHandle,
    386     FRONT_PAGE_KEY_LANGUAGE,
    387     0,
    388     0,
    389     STRING_TOKEN (STR_LANGUAGE_SELECT),
    390     STRING_TOKEN (STR_LANGUAGE_SELECT_HELP),
    391     EFI_IFR_FLAG_CALLBACK,
    392     EFI_IFR_NUMERIC_SIZE_1,
    393     OptionsOpCodeHandle,
    394     NULL
    395     );
    396 }
    397 
    398 /**
    399   Create continue menu in the front page.
    400 
    401   @param[in]    HiiHandle           The hii handle for the Uiapp driver.
    402   @param[in]    StartOpCodeHandle   The opcode handle to save the new opcode.
    403 
    404 **/
    405 VOID
    406 UiCreateContinueMenu (
    407   IN EFI_HII_HANDLE              HiiHandle,
    408   IN VOID                        *StartOpCodeHandle
    409   )
    410 {
    411   HiiCreateActionOpCode (
    412     StartOpCodeHandle,
    413     FRONT_PAGE_KEY_CONTINUE,
    414     STRING_TOKEN (STR_CONTINUE_PROMPT),
    415     STRING_TOKEN (STR_CONTINUE_PROMPT),
    416     EFI_IFR_FLAG_CALLBACK,
    417     0
    418     );
    419 }
    420 
    421 /**
    422   Create empty line menu in the front page.
    423 
    424   @param    HiiHandle           The hii handle for the Uiapp driver.
    425   @param    StartOpCodeHandle   The opcode handle to save the new opcode.
    426 
    427 **/
    428 VOID
    429 UiCreateEmptyLine (
    430   IN EFI_HII_HANDLE              HiiHandle,
    431   IN VOID                        *StartOpCodeHandle
    432   )
    433 {
    434   HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_NULL_STRING), 0, 0, 0);
    435 }
    436 
    437 /**
    438   Create Reset menu in the front page.
    439 
    440   @param[in]    HiiHandle           The hii handle for the Uiapp driver.
    441   @param[in]    StartOpCodeHandle   The opcode handle to save the new opcode.
    442 
    443 **/
    444 VOID
    445 UiCreateResetMenu (
    446   IN EFI_HII_HANDLE              HiiHandle,
    447   IN VOID                        *StartOpCodeHandle
    448   )
    449 {
    450   HiiCreateActionOpCode (
    451     StartOpCodeHandle,
    452     FRONT_PAGE_KEY_RESET,
    453     STRING_TOKEN (STR_RESET_STRING),
    454     STRING_TOKEN (STR_RESET_STRING),
    455     EFI_IFR_FLAG_CALLBACK,
    456     0
    457     );
    458 }
    459 
    460 /**
    461   Extract device path for given HII handle and class guid.
    462 
    463   @param Handle          The HII handle.
    464 
    465   @retval  NULL          Fail to get the device path string.
    466   @return  PathString    Get the device path string.
    467 
    468 **/
    469 CHAR16 *
    470 ExtractDevicePathFromHiiHandle (
    471   IN      EFI_HII_HANDLE      Handle
    472   )
    473 {
    474   EFI_STATUS                       Status;
    475   EFI_HANDLE                       DriverHandle;
    476 
    477   ASSERT (Handle != NULL);
    478 
    479   if (Handle == NULL) {
    480     return NULL;
    481   }
    482 
    483   Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle);
    484   if (EFI_ERROR (Status)) {
    485     return NULL;
    486   }
    487 
    488   return ConvertDevicePathToText(DevicePathFromHandle (DriverHandle), FALSE, FALSE);
    489 }
    490 
    491 /**
    492   Check whether this driver need to be shown in the front page.
    493 
    494   @param    HiiHandle           The hii handle for the driver.
    495   @param    Guid                The special guid for the driver which is the target.
    496   @param    PromptId            Return the prompt string id.
    497   @param    HelpId              Return the help string id.
    498   @param    FormsetGuid         Return the formset guid info.
    499 
    500   @retval   EFI_SUCCESS         Search the driver success
    501 
    502 **/
    503 BOOLEAN
    504 RequiredDriver (
    505   IN  EFI_HII_HANDLE              HiiHandle,
    506   IN  EFI_GUID                    *Guid,
    507   OUT EFI_STRING_ID               *PromptId,
    508   OUT EFI_STRING_ID               *HelpId,
    509   OUT VOID                        *FormsetGuid
    510   )
    511 {
    512   EFI_STATUS                  Status;
    513   UINT8                       ClassGuidNum;
    514   EFI_GUID                    *ClassGuid;
    515   EFI_IFR_FORM_SET            *Buffer;
    516   UINTN                       BufferSize;
    517   UINT8                       *Ptr;
    518   UINTN                       TempSize;
    519   BOOLEAN                     RetVal;
    520 
    521   Status = HiiGetFormSetFromHiiHandle(HiiHandle, &Buffer,&BufferSize);
    522   if (EFI_ERROR (Status)) {
    523     return FALSE;
    524   }
    525 
    526   RetVal = FALSE;
    527   TempSize = 0;
    528   Ptr = (UINT8 *) Buffer;
    529   while(TempSize < BufferSize)  {
    530     TempSize += ((EFI_IFR_OP_HEADER *) Ptr)->Length;
    531 
    532     if (((EFI_IFR_OP_HEADER *) Ptr)->Length <= OFFSET_OF (EFI_IFR_FORM_SET, Flags)){
    533       Ptr += ((EFI_IFR_OP_HEADER *) Ptr)->Length;
    534       continue;
    535     }
    536 
    537     ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *)Ptr)->Flags & 0x3);
    538     ClassGuid = (EFI_GUID *) (VOID *)(Ptr + sizeof (EFI_IFR_FORM_SET));
    539     while (ClassGuidNum-- > 0) {
    540       if (!CompareGuid (Guid, ClassGuid)){
    541         ClassGuid ++;
    542         continue;
    543       }
    544 
    545       *PromptId = ((EFI_IFR_FORM_SET *)Ptr)->FormSetTitle;
    546       *HelpId = ((EFI_IFR_FORM_SET *)Ptr)->Help;
    547       CopyMem (FormsetGuid, &((EFI_IFR_FORM_SET *) Ptr)->Guid, sizeof (EFI_GUID));
    548       RetVal = TRUE;
    549     }
    550   }
    551 
    552   FreePool (Buffer);
    553 
    554   return RetVal;
    555 }
    556 
    557 /**
    558   Search the drivers in the system which need to show in the front page
    559   and insert the menu to the front page.
    560 
    561   @param    HiiHandle           The hii handle for the Uiapp driver.
    562   @param    ClassGuid           The class guid for the driver which is the target.
    563   @param    SpecialHandlerFn    The pointer to the specail handler function, if any.
    564   @param    StartOpCodeHandle   The opcode handle to save the new opcode.
    565 
    566   @retval   EFI_SUCCESS         Search the driver success
    567 
    568 **/
    569 EFI_STATUS
    570 UiListThirdPartyDrivers (
    571   IN EFI_HII_HANDLE              HiiHandle,
    572   IN EFI_GUID                    *ClassGuid,
    573   IN DRIVER_SPECIAL_HANDLER      SpecialHandlerFn,
    574   IN VOID                        *StartOpCodeHandle
    575   )
    576 {
    577   UINTN                       Index;
    578   EFI_STRING                  String;
    579   EFI_STRING_ID               Token;
    580   EFI_STRING_ID               TokenHelp;
    581   EFI_HII_HANDLE              *HiiHandles;
    582   CHAR16                      *DevicePathStr;
    583   UINTN                       Count;
    584   UINTN                       CurrentSize;
    585   UI_HII_DRIVER_INSTANCE      *DriverListPtr;
    586   EFI_STRING                  NewName;
    587   BOOLEAN                     EmptyLineAfter;
    588 
    589   if (gHiiDriverList != NULL) {
    590     FreePool (gHiiDriverList);
    591   }
    592 
    593   HiiHandles = HiiGetHiiHandles (NULL);
    594   ASSERT (HiiHandles != NULL);
    595 
    596   gHiiDriverList = AllocateZeroPool (UI_HII_DRIVER_LIST_SIZE * sizeof (UI_HII_DRIVER_INSTANCE));
    597   ASSERT (gHiiDriverList != NULL);
    598   DriverListPtr = gHiiDriverList;
    599   CurrentSize = UI_HII_DRIVER_LIST_SIZE;
    600 
    601   for (Index = 0, Count = 0; HiiHandles[Index] != NULL; Index++) {
    602     if (!RequiredDriver (HiiHandles[Index], ClassGuid, &Token, &TokenHelp, &gHiiDriverList[Count].FormSetGuid)) {
    603       continue;
    604     }
    605 
    606     String = HiiGetString (HiiHandles[Index], Token, NULL);
    607     if (String == NULL) {
    608       String = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);
    609       ASSERT (String != NULL);
    610     } else if (SpecialHandlerFn != NULL) {
    611       //
    612       // Check whether need to rename the driver name.
    613       //
    614       EmptyLineAfter = FALSE;
    615       if (SpecialHandlerFn (String, &NewName, &EmptyLineAfter)) {
    616         FreePool (String);
    617         String = NewName;
    618         DriverListPtr[Count].EmptyLineAfter = EmptyLineAfter;
    619       }
    620     }
    621     DriverListPtr[Count].PromptId = HiiSetString (HiiHandle, 0, String, NULL);
    622     FreePool (String);
    623 
    624     String = HiiGetString (HiiHandles[Index], TokenHelp, NULL);
    625     if (String == NULL) {
    626       String = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);
    627       ASSERT (String != NULL);
    628     }
    629     DriverListPtr[Count].HelpId = HiiSetString (HiiHandle, 0, String, NULL);
    630     FreePool (String);
    631 
    632     DevicePathStr = ExtractDevicePathFromHiiHandle(HiiHandles[Index]);
    633     if (DevicePathStr != NULL){
    634       DriverListPtr[Count].DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL);
    635       FreePool (DevicePathStr);
    636     } else {
    637       DriverListPtr[Count].DevicePathId = 0;
    638     }
    639 
    640     Count++;
    641     if (Count >= CurrentSize) {
    642       DriverListPtr = AllocateCopyPool ((Count + UI_HII_DRIVER_LIST_SIZE) * sizeof (UI_HII_DRIVER_INSTANCE), gHiiDriverList);
    643       ASSERT (DriverListPtr != NULL);
    644       FreePool (gHiiDriverList);
    645       gHiiDriverList = DriverListPtr;
    646       CurrentSize += UI_HII_DRIVER_LIST_SIZE;
    647     }
    648   }
    649 
    650   FreePool (HiiHandles);
    651 
    652   Index = 0;
    653   while (gHiiDriverList[Index].PromptId != 0) {
    654     HiiCreateGotoExOpCode (
    655       StartOpCodeHandle,
    656       0,
    657       gHiiDriverList[Index].PromptId,
    658       gHiiDriverList[Index].HelpId,
    659       0,
    660       (EFI_QUESTION_ID) (Index + FRONT_PAGE_KEY_DRIVER),
    661       0,
    662       &gHiiDriverList[Index].FormSetGuid,
    663       gHiiDriverList[Index].DevicePathId
    664     );
    665 
    666     if (gHiiDriverList[Index].EmptyLineAfter) {
    667       UiCreateEmptyLine (HiiHandle, StartOpCodeHandle);
    668     }
    669 
    670     Index ++;
    671   }
    672 
    673   return EFI_SUCCESS;
    674 }
    675