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