1 /** @file
2   FrontPage routines to handle the callbacks and browser calls
3 
4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "FrontPage.h"
16 #include "Language.h"
17 #define MAX_STRING_LEN        200
18 
19 EFI_GUID   mFrontPageGuid      = FRONT_PAGE_FORMSET_GUID;
20 
21 BOOLEAN   gConnectAllHappened = FALSE;
22 BOOLEAN   mFeaturerSwitch = TRUE;
23 BOOLEAN   mResetRequired  = FALSE;
24 
25 EFI_FORM_BROWSER2_PROTOCOL      *gFormBrowser2;
26 CHAR8     *mLanguageString;
27 BOOLEAN   mModeInitialized = FALSE;
28 //
29 // Boot video resolution and text mode.
30 //
31 UINT32    mBootHorizontalResolution    = 0;
32 UINT32    mBootVerticalResolution      = 0;
33 UINT32    mBootTextModeColumn          = 0;
34 UINT32    mBootTextModeRow             = 0;
35 //
36 // BIOS setup video resolution and text mode.
37 //
38 UINT32    mSetupTextModeColumn         = 0;
39 UINT32    mSetupTextModeRow            = 0;
40 UINT32    mSetupHorizontalResolution   = 0;
41 UINT32    mSetupVerticalResolution     = 0;
42 
43 FRONT_PAGE_CALLBACK_DATA  gFrontPagePrivate = {
44   FRONT_PAGE_CALLBACK_DATA_SIGNATURE,
45   NULL,
46   NULL,
47   NULL,
48   {
49     FakeExtractConfig,
50     FakeRouteConfig,
51     FrontPageCallback
52   }
53 };
54 
55 HII_VENDOR_DEVICE_PATH  mFrontPageHiiVendorDevicePath = {
56   {
57     {
58       HARDWARE_DEVICE_PATH,
59       HW_VENDOR_DP,
60       {
61         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
62         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
63       }
64     },
65     //
66     // {8E6D99EE-7531-48f8-8745-7F6144468FF2}
67     //
68     { 0x8e6d99ee, 0x7531, 0x48f8, { 0x87, 0x45, 0x7f, 0x61, 0x44, 0x46, 0x8f, 0xf2 } }
69   },
70   {
71     END_DEVICE_PATH_TYPE,
72     END_ENTIRE_DEVICE_PATH_SUBTYPE,
73     {
74       (UINT8) (END_DEVICE_PATH_LENGTH),
75       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
76     }
77   }
78 };
79 
80 /**
81   Update the banner information for the Front Page based on Smbios information.
82 
83 **/
84 VOID
85 UpdateFrontPageStrings (
86   VOID
87   );
88 
89 /**
90   This function allows a caller to extract the current configuration for one
91   or more named elements from the target driver.
92 
93 
94   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
95   @param Request         A null-terminated Unicode string in <ConfigRequest> format.
96   @param Progress        On return, points to a character in the Request string.
97                          Points to the string's null terminator if request was successful.
98                          Points to the most recent '&' before the first failing name/value
99                          pair (or the beginning of the string if the failure is in the
100                          first name/value pair) if the request was not successful.
101   @param Results         A null-terminated Unicode string in <ConfigAltResp> format which
102                          has all values filled in for the names in the Request string.
103                          String to be allocated by the called function.
104 
105   @retval  EFI_SUCCESS            The Results is filled with the requested values.
106   @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
107   @retval  EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
108   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
109 
110 **/
111 EFI_STATUS
112 EFIAPI
FakeExtractConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Request,OUT EFI_STRING * Progress,OUT EFI_STRING * Results)113 FakeExtractConfig (
114   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
115   IN  CONST EFI_STRING                       Request,
116   OUT EFI_STRING                             *Progress,
117   OUT EFI_STRING                             *Results
118   )
119 {
120   if (Progress == NULL || Results == NULL) {
121     return EFI_INVALID_PARAMETER;
122   }
123   *Progress = Request;
124   return EFI_NOT_FOUND;
125 }
126 
127 /**
128   This function processes the results of changes in configuration.
129 
130 
131   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
132   @param Configuration   A null-terminated Unicode string in <ConfigResp> format.
133   @param Progress        A pointer to a string filled in with the offset of the most
134                          recent '&' before the first failing name/value pair (or the
135                          beginning of the string if the failure is in the first
136                          name/value pair) or the terminating NULL if all was successful.
137 
138   @retval  EFI_SUCCESS            The Results is processed successfully.
139   @retval  EFI_INVALID_PARAMETER  Configuration is NULL.
140   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
141 
142 **/
143 EFI_STATUS
144 EFIAPI
FakeRouteConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Configuration,OUT EFI_STRING * Progress)145 FakeRouteConfig (
146   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
147   IN  CONST EFI_STRING                       Configuration,
148   OUT EFI_STRING                             *Progress
149   )
150 {
151   if (Configuration == NULL || Progress == NULL) {
152     return EFI_INVALID_PARAMETER;
153   }
154 
155   return EFI_NOT_FOUND;
156 }
157 
158 /**
159   Create oneof options for language.
160 
161 **/
162 VOID
InitializeLanguage(VOID)163 InitializeLanguage (
164   VOID
165   )
166 {
167   EFI_STATUS                  Status;
168   CHAR8                       *LangCode;
169   CHAR8                       *Lang;
170   CHAR8                       *CurrentLang;
171   UINTN                       OptionCount;
172   CHAR16                      *StringBuffer;
173   EFI_HII_HANDLE              HiiHandle;
174   VOID                        *OptionsOpCodeHandle;
175   VOID                        *StartOpCodeHandle;
176   VOID                        *EndOpCodeHandle;
177   EFI_IFR_GUID_LABEL          *StartLabel;
178   EFI_IFR_GUID_LABEL          *EndLabel;
179   EFI_HII_STRING_PROTOCOL     *HiiString;
180   UINTN                       StringSize;
181 
182   Lang         = NULL;
183   StringBuffer = NULL;
184 
185   //
186   // Init OpCode Handle and Allocate space for creation of UpdateData Buffer
187   //
188   StartOpCodeHandle = HiiAllocateOpCodeHandle ();
189   ASSERT (StartOpCodeHandle != NULL);
190 
191   EndOpCodeHandle = HiiAllocateOpCodeHandle ();
192   ASSERT (EndOpCodeHandle != NULL);
193 
194   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
195   ASSERT (OptionsOpCodeHandle != NULL);
196   //
197   // Create Hii Extend Label OpCode as the start opcode
198   //
199   StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
200   StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
201   StartLabel->Number       = LABEL_SELECT_LANGUAGE;
202 
203   //
204   // Create Hii Extend Label OpCode as the end opcode
205   //
206   EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
207   EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
208   EndLabel->Number       = LABEL_END;
209   //
210   // Collect the languages from what our current Language support is based on our VFR
211   //
212   HiiHandle = gFrontPagePrivate.HiiHandle;
213 
214   GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&CurrentLang, NULL);
215 
216   if (mLanguageString == NULL) {
217     //
218     // Get Support language list from variable.
219     //
220     GetEfiGlobalVariable2 (L"PlatformLangCodes", (VOID**)&mLanguageString, NULL);
221     if (mLanguageString == NULL) {
222       mLanguageString = AllocateCopyPool (
223                                  AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)),
224                                  (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)
225                                  );
226       ASSERT (mLanguageString != NULL);
227     }
228   }
229 
230   if (gFrontPagePrivate.LanguageToken == NULL) {
231     //
232     // Count the language list number.
233     //
234     LangCode      = mLanguageString;
235     Lang          = AllocatePool (AsciiStrSize (mLanguageString));
236     ASSERT (Lang != NULL);
237     OptionCount = 0;
238     while (*LangCode != 0) {
239       GetNextLanguage (&LangCode, Lang);
240       OptionCount ++;
241     }
242 
243     //
244     // Allocate extra 1 as the end tag.
245     //
246     gFrontPagePrivate.LanguageToken = AllocateZeroPool ((OptionCount + 1) * sizeof (EFI_STRING_ID));
247     ASSERT (gFrontPagePrivate.LanguageToken != NULL);
248 
249     Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
250     ASSERT_EFI_ERROR (Status);
251 
252     LangCode     = mLanguageString;
253     OptionCount  = 0;
254     while (*LangCode != 0) {
255       GetNextLanguage (&LangCode, Lang);
256 
257       StringSize = 0;
258       Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL);
259       if (Status == EFI_BUFFER_TOO_SMALL) {
260         StringBuffer = AllocateZeroPool (StringSize);
261         ASSERT (StringBuffer != NULL);
262         Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL);
263         ASSERT_EFI_ERROR (Status);
264       }
265 
266       if (EFI_ERROR (Status)) {
267         StringBuffer = AllocatePool (AsciiStrSize (Lang) * sizeof (CHAR16));
268         ASSERT (StringBuffer != NULL);
269         AsciiStrToUnicodeStr (Lang, StringBuffer);
270       }
271 
272       ASSERT (StringBuffer != NULL);
273       gFrontPagePrivate.LanguageToken[OptionCount] = HiiSetString (HiiHandle, 0, StringBuffer, NULL);
274       FreePool (StringBuffer);
275 
276       OptionCount++;
277     }
278   }
279 
280   ASSERT (gFrontPagePrivate.LanguageToken != NULL);
281   LangCode     = mLanguageString;
282   OptionCount  = 0;
283   if (Lang == NULL) {
284     Lang = AllocatePool (AsciiStrSize (mLanguageString));
285     ASSERT (Lang != NULL);
286   }
287   while (*LangCode != 0) {
288     GetNextLanguage (&LangCode, Lang);
289 
290     if (CurrentLang != NULL && AsciiStrCmp (Lang, CurrentLang) == 0) {
291       HiiCreateOneOfOptionOpCode (
292         OptionsOpCodeHandle,
293         gFrontPagePrivate.LanguageToken[OptionCount],
294         EFI_IFR_OPTION_DEFAULT,
295         EFI_IFR_NUMERIC_SIZE_1,
296         (UINT8) OptionCount
297         );
298     } else {
299       HiiCreateOneOfOptionOpCode (
300         OptionsOpCodeHandle,
301         gFrontPagePrivate.LanguageToken[OptionCount],
302         0,
303         EFI_IFR_NUMERIC_SIZE_1,
304         (UINT8) OptionCount
305         );
306     }
307 
308     OptionCount++;
309   }
310 
311   if (CurrentLang != NULL) {
312     FreePool (CurrentLang);
313   }
314   FreePool (Lang);
315 
316   HiiCreateOneOfOpCode (
317     StartOpCodeHandle,
318     FRONT_PAGE_KEY_LANGUAGE,
319     0,
320     0,
321     STRING_TOKEN (STR_LANGUAGE_SELECT),
322     STRING_TOKEN (STR_LANGUAGE_SELECT_HELP),
323     EFI_IFR_FLAG_CALLBACK,
324     EFI_IFR_NUMERIC_SIZE_1,
325     OptionsOpCodeHandle,
326     NULL
327     );
328 
329   Status = HiiUpdateForm (
330              HiiHandle,
331              &mFrontPageGuid,
332              FRONT_PAGE_FORM_ID,
333              StartOpCodeHandle, // LABEL_SELECT_LANGUAGE
334              EndOpCodeHandle    // LABEL_END
335              );
336 
337   HiiFreeOpCodeHandle (StartOpCodeHandle);
338   HiiFreeOpCodeHandle (EndOpCodeHandle);
339   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
340 }
341 
342 /**
343   This function processes the results of changes in configuration.
344 
345 
346   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
347   @param Action          Specifies the type of action taken by the browser.
348   @param QuestionId      A unique value which is sent to the original exporting driver
349                          so that it can identify the type of data to expect.
350   @param Type            The type of value for the question.
351   @param Value           A pointer to the data being sent to the original exporting driver.
352   @param ActionRequest   On return, points to the action requested by the callback function.
353 
354   @retval  EFI_SUCCESS           The callback successfully handled the action.
355   @retval  EFI_OUT_OF_RESOURCES  Not enough storage is available to hold the variable and its data.
356   @retval  EFI_DEVICE_ERROR      The variable could not be saved.
357   @retval  EFI_UNSUPPORTED       The specified Action is not supported by the callback.
358 
359 **/
360 EFI_STATUS
361 EFIAPI
FrontPageCallback(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,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)362 FrontPageCallback (
363   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
364   IN  EFI_BROWSER_ACTION                     Action,
365   IN  EFI_QUESTION_ID                        QuestionId,
366   IN  UINT8                                  Type,
367   IN  EFI_IFR_TYPE_VALUE                     *Value,
368   OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
369   )
370 {
371   CHAR8                         *LangCode;
372   CHAR8                         *Lang;
373   UINTN                         Index;
374   EFI_STATUS                    Status;
375 
376   if (Action != EFI_BROWSER_ACTION_CHANGED) {
377     //
378     // Do nothing for other UEFI Action. Only do call back when data is changed.
379     //
380     return EFI_UNSUPPORTED;
381   }
382 
383   if (Action == EFI_BROWSER_ACTION_CHANGED) {
384     if ((Value == NULL) || (ActionRequest == NULL)) {
385       return EFI_INVALID_PARAMETER;
386     }
387 
388     switch (QuestionId) {
389     case FRONT_PAGE_KEY_CONTINUE:
390       //
391       // This is the continue - clear the screen and return an error to get out of FrontPage loop
392       //
393       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
394       break;
395 
396     case FRONT_PAGE_KEY_LANGUAGE:
397       //
398       // Allocate working buffer for RFC 4646 language in supported LanguageString.
399       //
400       Lang = AllocatePool (AsciiStrSize (mLanguageString));
401       ASSERT (Lang != NULL);
402 
403       Index = 0;
404       LangCode = mLanguageString;
405       while (*LangCode != 0) {
406         GetNextLanguage (&LangCode, Lang);
407 
408         if (Index == Value->u8) {
409           break;
410         }
411 
412         Index++;
413       }
414 
415       if (Index == Value->u8) {
416         Status = gRT->SetVariable (
417                         L"PlatformLang",
418                         &gEfiGlobalVariableGuid,
419                         EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
420                         AsciiStrSize (Lang),
421                         Lang
422                         );
423         ASSERT_EFI_ERROR(Status);
424       } else {
425         ASSERT (FALSE);
426       }
427       FreePool (Lang);
428       //
429       //Current language of platform is changed,recreate oneof options for language.
430       //
431       InitializeLanguage();
432       break;
433 
434     default:
435       break;
436     }
437   }
438 
439   return EFI_SUCCESS;
440 }
441 
442 /**
443 Update front page form base on the ClassGuid in the formset in other modules.
444 
445 **/
446 VOID
UpdateFrontPageForm(VOID)447 UpdateFrontPageForm (
448   VOID
449   )
450 {
451   EFI_STATUS                  Status;
452   EFI_HII_HANDLE              HiiHandle;
453   VOID                        *StartOpCodeHandle;
454   VOID                        *EndOpCodeHandle;
455   EFI_IFR_GUID_LABEL          *StartLabel;
456   EFI_IFR_GUID_LABEL          *EndLabel;
457   UINTN                       Index;
458   EFI_STRING                  String;
459   EFI_STRING_ID               Token;
460   EFI_STRING_ID               TokenHelp;
461   EFI_HII_HANDLE              *HiiHandles;
462   EFI_GUID                    FormSetGuid;
463   CHAR16                      *DevicePathStr;
464   EFI_STRING_ID               DevicePathId;
465   EFI_IFR_FORM_SET            *Buffer;
466   UINTN                       BufferSize;
467   UINT8                       ClassGuidNum;
468   EFI_GUID                    *ClassGuid;
469   UINTN                       TempSize;
470   UINT8                       *Ptr;
471 
472   TempSize =0;
473   BufferSize = 0;
474   Buffer = NULL;
475 
476   HiiHandle = gFrontPagePrivate.HiiHandle;
477 
478   //
479   // Allocate space for creation of UpdateData Buffer
480   //
481   StartOpCodeHandle = HiiAllocateOpCodeHandle ();
482   ASSERT (StartOpCodeHandle != NULL);
483 
484   EndOpCodeHandle = HiiAllocateOpCodeHandle ();
485   ASSERT (EndOpCodeHandle != NULL);
486   //
487   // Create Hii Extend Label OpCode as the start opcode
488   //
489   StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
490   StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
491   StartLabel->Number       = LABEL_PLATFORM_INFORMATION;
492   //
493   // Create Hii Extend Label OpCode as the end opcode
494   //
495   EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
496   EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
497   EndLabel->Number       = LABEL_END;
498 
499   //
500   // Get all the Hii handles
501   //
502   HiiHandles = HiiGetHiiHandles (NULL);
503   ASSERT (HiiHandles != NULL);
504   //
505   // Search for formset of each class type
506   //
507   for (Index = 0; HiiHandles[Index] != NULL; Index++) {
508     Status = HiiGetFormSetFromHiiHandle(HiiHandles[Index], &Buffer,&BufferSize);
509     if (EFI_ERROR (Status)) {
510       continue;
511     }
512 
513     Ptr = (UINT8 *)Buffer;
514     while(TempSize < BufferSize)  {
515       TempSize += ((EFI_IFR_OP_HEADER *) Ptr)->Length;
516 
517       if (((EFI_IFR_OP_HEADER *) Ptr)->Length <= OFFSET_OF (EFI_IFR_FORM_SET, Flags)){
518         Ptr += ((EFI_IFR_OP_HEADER *) Ptr)->Length;
519         continue;
520       }
521 
522       //
523       // Find Class Guid
524       //
525       ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *)Ptr)->Flags & 0x3);
526       ClassGuid = (EFI_GUID *) (VOID *)(Ptr + sizeof (EFI_IFR_FORM_SET));
527       while (ClassGuidNum-- > 0) {
528         if (CompareGuid (&gEfiIfrFrontPageGuid, ClassGuid) == 0){
529           ClassGuid ++;
530           continue;
531         }
532 
533         String = HiiGetString (HiiHandles[Index], ((EFI_IFR_FORM_SET *)Ptr)->FormSetTitle, NULL);
534         if (String == NULL) {
535           String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);
536           ASSERT (String != NULL);
537         }
538         Token = HiiSetString (HiiHandle, 0, String, NULL);
539         FreePool (String);
540 
541         String = HiiGetString (HiiHandles[Index], ((EFI_IFR_FORM_SET *)Ptr)->Help, NULL);
542 
543         if (String == NULL) {
544           String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);
545           ASSERT (String != NULL);
546         }
547         TokenHelp = HiiSetString (HiiHandle, 0, String, NULL);
548         FreePool (String);
549 
550         FormSetGuid = ((EFI_IFR_FORM_SET *)Ptr)->Guid;
551 
552         DevicePathStr = ExtractDevicePathFromHiiHandle(HiiHandles[Index]);
553         DevicePathId  = 0;
554         if (DevicePathStr != NULL){
555           DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL);
556           FreePool (DevicePathStr);
557         }
558         HiiCreateGotoExOpCode (
559           StartOpCodeHandle,
560           0,
561           Token,
562           TokenHelp,
563           0,
564           (EFI_QUESTION_ID) (Index + FRONT_PAGE_KEY_OFFSET),
565           0,
566           &FormSetGuid,
567           DevicePathId
568         );
569         break;
570       }
571       Ptr += ((EFI_IFR_OP_HEADER *) Ptr)->Length;
572     }
573 
574     FreePool(Buffer);
575     Buffer = NULL;
576     TempSize = 0;
577     BufferSize = 0;
578   }
579 
580   HiiUpdateForm (
581     HiiHandle,
582     &mFrontPageGuid,
583     FRONT_PAGE_FORM_ID,
584     StartOpCodeHandle,
585     EndOpCodeHandle
586     );
587 
588   HiiFreeOpCodeHandle (StartOpCodeHandle);
589   HiiFreeOpCodeHandle (EndOpCodeHandle);
590   FreePool (HiiHandles);
591 }
592 
593 /**
594   Initialize HII information for the FrontPage
595 
596 
597   @retval  EFI_SUCCESS        The operation is successful.
598   @retval  EFI_DEVICE_ERROR   If the dynamic opcode creation failed.
599 
600 **/
601 EFI_STATUS
InitializeFrontPage(VOID)602 InitializeFrontPage (
603   VOID
604   )
605 {
606   EFI_STATUS                  Status;
607   //
608   // Locate Hii relative protocols
609   //
610   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2);
611   if (EFI_ERROR (Status)) {
612     return Status;
613   }
614 
615   //
616   // Install Device Path Protocol and Config Access protocol to driver handle
617   //
618   gFrontPagePrivate.DriverHandle = NULL;
619   Status = gBS->InstallMultipleProtocolInterfaces (
620                   &gFrontPagePrivate.DriverHandle,
621                   &gEfiDevicePathProtocolGuid,
622                   &mFrontPageHiiVendorDevicePath,
623                   &gEfiHiiConfigAccessProtocolGuid,
624                   &gFrontPagePrivate.ConfigAccess,
625                   NULL
626                   );
627   ASSERT_EFI_ERROR (Status);
628 
629   //
630   // Publish our HII data
631   //
632   gFrontPagePrivate.HiiHandle = HiiAddPackages (
633                                   &mFrontPageGuid,
634                                   gFrontPagePrivate.DriverHandle,
635                                   FrontPageVfrBin,
636                                   UiAppStrings,
637                                   NULL
638                                   );
639   ASSERT (gFrontPagePrivate.HiiHandle != NULL);
640 
641   //
642   //Updata Front Page strings
643   //
644   UpdateFrontPageStrings ();
645 
646   //
647   // Initialize laguage options
648   //
649   InitializeLanguage ();
650 
651   //
652   //Updata Front Page form
653   //
654   UpdateFrontPageForm();
655 
656   return Status;
657 }
658 
659 /**
660   Call the browser and display the front page
661 
662   @return   Status code that will be returned by
663             EFI_FORM_BROWSER2_PROTOCOL.SendForm ().
664 
665 **/
666 EFI_STATUS
CallFrontPage(VOID)667 CallFrontPage (
668   VOID
669   )
670 {
671   EFI_STATUS                  Status;
672   EFI_BROWSER_ACTION_REQUEST  ActionRequest;
673 
674   //
675   // Begin waiting for USER INPUT
676   //
677   REPORT_STATUS_CODE (
678     EFI_PROGRESS_CODE,
679     (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT)
680     );
681 
682   ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
683   Status = gFormBrowser2->SendForm (
684                             gFormBrowser2,
685                             &gFrontPagePrivate.HiiHandle,
686                             1,
687                             &mFrontPageGuid,
688                             0,
689                             NULL,
690                             &ActionRequest
691                             );
692   //
693   // Check whether user change any option setting which needs a reset to be effective
694   //
695   if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
696     EnableResetRequired ();
697   }
698 
699   return Status;
700 }
701 
702 /**
703   Remove the installed packages from the HiiDatabase.
704 
705 **/
706 VOID
FreeFrontPage(VOID)707 FreeFrontPage(
708   VOID
709   )
710 {
711   EFI_STATUS                  Status;
712   Status = gBS->UninstallMultipleProtocolInterfaces (
713                   gFrontPagePrivate.DriverHandle,
714                   &gEfiDevicePathProtocolGuid,
715                   &mFrontPageHiiVendorDevicePath,
716                   &gEfiHiiConfigAccessProtocolGuid,
717                   &gFrontPagePrivate.ConfigAccess,
718                   NULL
719                   );
720   ASSERT_EFI_ERROR (Status);
721 
722   //
723   // Publish our HII data
724   //
725   HiiRemovePackages (gFrontPagePrivate.HiiHandle);
726   if (gFrontPagePrivate.LanguageToken != NULL) {
727     FreePool (gFrontPagePrivate.LanguageToken);
728     gFrontPagePrivate.LanguageToken = NULL;
729   }
730 }
731 
732 /**
733   Convert Processor Frequency Data to a string.
734 
735   @param ProcessorFrequency The frequency data to process
736   @param Base10Exponent     The exponent based on 10
737   @param String             The string that is created
738 
739 **/
740 VOID
ConvertProcessorToString(IN UINT16 ProcessorFrequency,IN UINT16 Base10Exponent,OUT CHAR16 ** String)741 ConvertProcessorToString (
742   IN  UINT16                               ProcessorFrequency,
743   IN  UINT16                               Base10Exponent,
744   OUT CHAR16                               **String
745   )
746 {
747   CHAR16  *StringBuffer;
748   UINTN   Index;
749   UINTN   DestMax;
750   UINT32  FreqMhz;
751 
752   if (Base10Exponent >= 6) {
753     FreqMhz = ProcessorFrequency;
754     for (Index = 0; Index < (UINTN) (Base10Exponent - 6); Index++) {
755       FreqMhz *= 10;
756     }
757   } else {
758     FreqMhz = 0;
759   }
760   DestMax = 0x20 / sizeof (CHAR16);
761   StringBuffer = AllocateZeroPool (0x20);
762   ASSERT (StringBuffer != NULL);
763   Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3);
764   StrCatS (StringBuffer, DestMax, L".");
765   UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2);
766   StrCatS (StringBuffer, DestMax, L" GHz");
767   *String = (CHAR16 *) StringBuffer;
768   return ;
769 }
770 
771 
772 /**
773   Convert Memory Size to a string.
774 
775   @param MemorySize      The size of the memory to process
776   @param String          The string that is created
777 
778 **/
779 VOID
ConvertMemorySizeToString(IN UINT32 MemorySize,OUT CHAR16 ** String)780 ConvertMemorySizeToString (
781   IN  UINT32          MemorySize,
782   OUT CHAR16          **String
783   )
784 {
785   CHAR16  *StringBuffer;
786 
787   StringBuffer = AllocateZeroPool (0x24);
788   ASSERT (StringBuffer != NULL);
789   UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 10);
790   StrCatS (StringBuffer, 0x24 / sizeof (CHAR16), L" MB RAM");
791 
792   *String = (CHAR16 *) StringBuffer;
793 
794   return ;
795 }
796 
797 /**
798 
799   Acquire the string associated with the Index from smbios structure and return it.
800   The caller is responsible for free the string buffer.
801 
802   @param    OptionalStrStart  The start position to search the string
803   @param    Index             The index of the string to extract
804   @param    String            The string that is extracted
805 
806   @retval   EFI_SUCCESS       The function returns EFI_SUCCESS always.
807 
808 **/
809 EFI_STATUS
GetOptionalStringByIndex(IN CHAR8 * OptionalStrStart,IN UINT8 Index,OUT CHAR16 ** String)810 GetOptionalStringByIndex (
811   IN      CHAR8                   *OptionalStrStart,
812   IN      UINT8                   Index,
813   OUT     CHAR16                  **String
814   )
815 {
816   UINTN          StrSize;
817 
818   if (Index == 0) {
819     *String = AllocateZeroPool (sizeof (CHAR16));
820     return EFI_SUCCESS;
821   }
822 
823   StrSize = 0;
824   do {
825     Index--;
826     OptionalStrStart += StrSize;
827     StrSize           = AsciiStrSize (OptionalStrStart);
828   } while (OptionalStrStart[StrSize] != 0 && Index != 0);
829 
830   if ((Index != 0) || (StrSize == 1)) {
831     //
832     // Meet the end of strings set but Index is non-zero, or
833     // Find an empty string
834     //
835     *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));
836   } else {
837     *String = AllocatePool (StrSize * sizeof (CHAR16));
838     AsciiStrToUnicodeStr (OptionalStrStart, *String);
839   }
840 
841   return EFI_SUCCESS;
842 }
843 
844 
845 /**
846   Update the banner information for the Front Page based on Smbios information.
847 **/
848 VOID
UpdateFrontPageStrings(VOID)849 UpdateFrontPageStrings (
850   VOID
851   )
852 {
853   UINT8                             StrIndex;
854   CHAR16                            *NewString;
855   CHAR16                            *FirmwareVersionString;
856   BOOLEAN                           Find[5];
857   EFI_STATUS                        Status;
858   EFI_STRING_ID                     TokenToUpdate;
859   EFI_SMBIOS_HANDLE                 SmbiosHandle;
860   EFI_SMBIOS_PROTOCOL               *Smbios;
861   SMBIOS_TABLE_TYPE0                *Type0Record;
862   SMBIOS_TABLE_TYPE1                *Type1Record;
863   SMBIOS_TABLE_TYPE4                *Type4Record;
864   SMBIOS_TABLE_TYPE19               *Type19Record;
865   EFI_SMBIOS_TABLE_HEADER           *Record;
866 
867   ZeroMem (Find, sizeof (Find));
868 
869   //
870   // Update Front Page strings
871   //
872   Status = gBS->LocateProtocol (
873                   &gEfiSmbiosProtocolGuid,
874                   NULL,
875                   (VOID **) &Smbios
876                   );
877   if (EFI_ERROR (Status)) {
878     return ;
879   }
880 
881   SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
882   do {
883     Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
884     if (EFI_ERROR(Status)) {
885       break;
886     }
887 
888     if (Record->Type == EFI_SMBIOS_TYPE_BIOS_INFORMATION) {
889       Type0Record = (SMBIOS_TABLE_TYPE0 *) Record;
890       StrIndex = Type0Record->BiosVersion;
891       GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &NewString);
892       TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION);
893       FirmwareVersionString = (CHAR16 *) PcdGetPtr (PcdFirmwareVersionString);
894       if (*FirmwareVersionString != 0x0000 ) {
895         FreePool (NewString);
896         NewString = (CHAR16 *) PcdGetPtr (PcdFirmwareVersionString);
897         HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
898       } else {
899         HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
900         FreePool (NewString);
901       }
902       Find[0] = TRUE;
903     }
904 
905     if (Record->Type == EFI_SMBIOS_TYPE_SYSTEM_INFORMATION) {
906       Type1Record = (SMBIOS_TABLE_TYPE1 *) Record;
907       StrIndex = Type1Record->ProductName;
908       GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type1Record + Type1Record->Hdr.Length), StrIndex, &NewString);
909       TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL);
910       HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
911       FreePool (NewString);
912       Find[1] = TRUE;
913     }
914 
915     if ((Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) && !Find[2]) {
916       Type4Record = (SMBIOS_TABLE_TYPE4 *) Record;
917       //
918       // The information in the record should be only valid when the CPU Socket is populated.
919       //
920       if ((Type4Record->Status & SMBIOS_TYPE4_CPU_SOCKET_POPULATED) == SMBIOS_TYPE4_CPU_SOCKET_POPULATED) {
921         StrIndex = Type4Record->ProcessorVersion;
922         GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type4Record + Type4Record->Hdr.Length), StrIndex, &NewString);
923         TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL);
924         HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
925         FreePool (NewString);
926         Find[2] = TRUE;
927       }
928     }
929 
930     if ((Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) && !Find[3]) {
931       Type4Record = (SMBIOS_TABLE_TYPE4 *) Record;
932       //
933       // The information in the record should be only valid when the CPU Socket is populated.
934       //
935       if ((Type4Record->Status & SMBIOS_TYPE4_CPU_SOCKET_POPULATED) == SMBIOS_TYPE4_CPU_SOCKET_POPULATED) {
936         ConvertProcessorToString(Type4Record->CurrentSpeed, 6, &NewString);
937         TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED);
938         HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
939         FreePool (NewString);
940         Find[3] = TRUE;
941       }
942     }
943 
944     if ( Record->Type == EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS ) {
945       Type19Record = (SMBIOS_TABLE_TYPE19 *) Record;
946       ConvertMemorySizeToString (
947         (UINT32)(RShiftU64((Type19Record->EndingAddress - Type19Record->StartingAddress + 1), 10)),
948         &NewString
949         );
950       TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE);
951       HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
952       FreePool (NewString);
953       Find[4] = TRUE;
954     }
955   } while ( !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4]));
956   return ;
957 }
958 
959 /**
960   This function will change video resolution and text mode
961   according to defined setup mode or defined boot mode
962 
963   @param  IsSetupMode   Indicate mode is changed to setup mode or boot mode.
964 
965   @retval  EFI_SUCCESS  Mode is changed successfully.
966   @retval  Others             Mode failed to be changed.
967 
968 **/
969 EFI_STATUS
970 EFIAPI
BdsSetConsoleMode(BOOLEAN IsSetupMode)971 BdsSetConsoleMode (
972   BOOLEAN  IsSetupMode
973   )
974 {
975   EFI_GRAPHICS_OUTPUT_PROTOCOL          *GraphicsOutput;
976   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL       *SimpleTextOut;
977   UINTN                                 SizeOfInfo;
978   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
979   UINT32                                MaxGopMode;
980   UINT32                                MaxTextMode;
981   UINT32                                ModeNumber;
982   UINT32                                NewHorizontalResolution;
983   UINT32                                NewVerticalResolution;
984   UINT32                                NewColumns;
985   UINT32                                NewRows;
986   UINTN                                 HandleCount;
987   EFI_HANDLE                            *HandleBuffer;
988   EFI_STATUS                            Status;
989   UINTN                                 Index;
990   UINTN                                 CurrentColumn;
991   UINTN                                 CurrentRow;
992 
993   MaxGopMode  = 0;
994   MaxTextMode = 0;
995 
996   //
997   // Get current video resolution and text mode
998   //
999   Status = gBS->HandleProtocol (
1000                   gST->ConsoleOutHandle,
1001                   &gEfiGraphicsOutputProtocolGuid,
1002                   (VOID**)&GraphicsOutput
1003                   );
1004   if (EFI_ERROR (Status)) {
1005     GraphicsOutput = NULL;
1006   }
1007 
1008   Status = gBS->HandleProtocol (
1009                   gST->ConsoleOutHandle,
1010                   &gEfiSimpleTextOutProtocolGuid,
1011                   (VOID**)&SimpleTextOut
1012                   );
1013   if (EFI_ERROR (Status)) {
1014     SimpleTextOut = NULL;
1015   }
1016 
1017   if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {
1018     return EFI_UNSUPPORTED;
1019   }
1020 
1021   if (IsSetupMode) {
1022     //
1023     // The requried resolution and text mode is setup mode.
1024     //
1025     NewHorizontalResolution = mSetupHorizontalResolution;
1026     NewVerticalResolution   = mSetupVerticalResolution;
1027     NewColumns              = mSetupTextModeColumn;
1028     NewRows                 = mSetupTextModeRow;
1029   } else {
1030     //
1031     // The required resolution and text mode is boot mode.
1032     //
1033     NewHorizontalResolution = mBootHorizontalResolution;
1034     NewVerticalResolution   = mBootVerticalResolution;
1035     NewColumns              = mBootTextModeColumn;
1036     NewRows                 = mBootTextModeRow;
1037   }
1038 
1039   if (GraphicsOutput != NULL) {
1040     MaxGopMode  = GraphicsOutput->Mode->MaxMode;
1041   }
1042 
1043   if (SimpleTextOut != NULL) {
1044     MaxTextMode = SimpleTextOut->Mode->MaxMode;
1045   }
1046 
1047   //
1048   // 1. If current video resolution is same with required video resolution,
1049   //    video resolution need not be changed.
1050   //    1.1. If current text mode is same with required text mode, text mode need not be changed.
1051   //    1.2. If current text mode is different from required text mode, text mode need be changed.
1052   // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
1053   //
1054   for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {
1055     Status = GraphicsOutput->QueryMode (
1056                        GraphicsOutput,
1057                        ModeNumber,
1058                        &SizeOfInfo,
1059                        &Info
1060                        );
1061     if (!EFI_ERROR (Status)) {
1062       if ((Info->HorizontalResolution == NewHorizontalResolution) &&
1063           (Info->VerticalResolution == NewVerticalResolution)) {
1064         if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) &&
1065             (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) {
1066           //
1067           // Current resolution is same with required resolution, check if text mode need be set
1068           //
1069           Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);
1070           ASSERT_EFI_ERROR (Status);
1071           if (CurrentColumn == NewColumns && CurrentRow == NewRows) {
1072             //
1073             // If current text mode is same with required text mode. Do nothing
1074             //
1075             FreePool (Info);
1076             return EFI_SUCCESS;
1077           } else {
1078             //
1079             // If current text mode is different from requried text mode.  Set new video mode
1080             //
1081             for (Index = 0; Index < MaxTextMode; Index++) {
1082               Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);
1083               if (!EFI_ERROR(Status)) {
1084                 if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) {
1085                   //
1086                   // Required text mode is supported, set it.
1087                   //
1088                   Status = SimpleTextOut->SetMode (SimpleTextOut, Index);
1089                   ASSERT_EFI_ERROR (Status);
1090                   //
1091                   // Update text mode PCD.
1092                   //
1093                   Status = PcdSet32S (PcdConOutColumn, mSetupTextModeColumn);
1094                   ASSERT_EFI_ERROR (Status);
1095                   Status = PcdSet32S (PcdConOutRow, mSetupTextModeRow);
1096                   ASSERT_EFI_ERROR (Status);
1097                   FreePool (Info);
1098                   return EFI_SUCCESS;
1099                 }
1100               }
1101             }
1102             if (Index == MaxTextMode) {
1103               //
1104               // If requried text mode is not supported, return error.
1105               //
1106               FreePool (Info);
1107               return EFI_UNSUPPORTED;
1108             }
1109           }
1110         } else {
1111           //
1112           // If current video resolution is not same with the new one, set new video resolution.
1113           // In this case, the driver which produces simple text out need be restarted.
1114           //
1115           Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
1116           if (!EFI_ERROR (Status)) {
1117             FreePool (Info);
1118             break;
1119           }
1120         }
1121       }
1122       FreePool (Info);
1123     }
1124   }
1125 
1126   if (ModeNumber == MaxGopMode) {
1127     //
1128     // If the resolution is not supported, return error.
1129     //
1130     return EFI_UNSUPPORTED;
1131   }
1132 
1133   //
1134   // Set PCD to Inform GraphicsConsole to change video resolution.
1135   // Set PCD to Inform Consplitter to change text mode.
1136   //
1137   Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution);
1138   ASSERT_EFI_ERROR (Status);
1139   Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution);
1140   ASSERT_EFI_ERROR (Status);
1141   Status = PcdSet32S (PcdConOutColumn, NewColumns);
1142   ASSERT_EFI_ERROR (Status);
1143   Status = PcdSet32S (PcdConOutRow, NewRows);
1144   ASSERT_EFI_ERROR (Status);
1145 
1146 
1147   //
1148   // Video mode is changed, so restart graphics console driver and higher level driver.
1149   // Reconnect graphics console driver and higher level driver.
1150   // Locate all the handles with GOP protocol and reconnect it.
1151   //
1152   Status = gBS->LocateHandleBuffer (
1153                    ByProtocol,
1154                    &gEfiSimpleTextOutProtocolGuid,
1155                    NULL,
1156                    &HandleCount,
1157                    &HandleBuffer
1158                    );
1159   if (!EFI_ERROR (Status)) {
1160     for (Index = 0; Index < HandleCount; Index++) {
1161       gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
1162     }
1163     for (Index = 0; Index < HandleCount; Index++) {
1164       gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
1165     }
1166     if (HandleBuffer != NULL) {
1167       FreePool (HandleBuffer);
1168     }
1169   }
1170 
1171   return EFI_SUCCESS;
1172 }
1173 
1174 /**
1175   The user Entry Point for Application. The user code starts with this function
1176   as the real entry point for the image goes into a library that calls this
1177   function.
1178 
1179   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
1180   @param[in] SystemTable    A pointer to the EFI System Table.
1181 
1182   @retval EFI_SUCCESS       The entry point is executed successfully.
1183   @retval other             Some error occurs when executing this entry point.
1184 
1185 **/
1186 EFI_STATUS
1187 EFIAPI
InitializeUserInterface(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1188 InitializeUserInterface (
1189   IN EFI_HANDLE        ImageHandle,
1190   IN EFI_SYSTEM_TABLE  *SystemTable
1191   )
1192 {
1193   EFI_HII_HANDLE                     HiiHandle;
1194   EFI_STATUS                         Status;
1195   EFI_GRAPHICS_OUTPUT_PROTOCOL       *GraphicsOutput;
1196   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *SimpleTextOut;
1197   UINTN                              BootTextColumn;
1198   UINTN                              BootTextRow;
1199 
1200   if (!mModeInitialized) {
1201     //
1202     // After the console is ready, get current video resolution
1203     // and text mode before launching setup at first time.
1204     //
1205     Status = gBS->HandleProtocol (
1206                     gST->ConsoleOutHandle,
1207                     &gEfiGraphicsOutputProtocolGuid,
1208                     (VOID**)&GraphicsOutput
1209                     );
1210     if (EFI_ERROR (Status)) {
1211       GraphicsOutput = NULL;
1212     }
1213 
1214     Status = gBS->HandleProtocol (
1215                     gST->ConsoleOutHandle,
1216                     &gEfiSimpleTextOutProtocolGuid,
1217                     (VOID**)&SimpleTextOut
1218                     );
1219     if (EFI_ERROR (Status)) {
1220       SimpleTextOut = NULL;
1221     }
1222 
1223     if (GraphicsOutput != NULL) {
1224       //
1225       // Get current video resolution and text mode.
1226       //
1227       mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
1228       mBootVerticalResolution   = GraphicsOutput->Mode->Info->VerticalResolution;
1229     }
1230 
1231     if (SimpleTextOut != NULL) {
1232       Status = SimpleTextOut->QueryMode (
1233                                 SimpleTextOut,
1234                                 SimpleTextOut->Mode->Mode,
1235                                 &BootTextColumn,
1236                                 &BootTextRow
1237                                 );
1238       mBootTextModeColumn = (UINT32)BootTextColumn;
1239       mBootTextModeRow    = (UINT32)BootTextRow;
1240     }
1241 
1242     //
1243     // Get user defined text mode for setup.
1244     //
1245     mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
1246     mSetupVerticalResolution   = PcdGet32 (PcdSetupVideoVerticalResolution);
1247     mSetupTextModeColumn       = PcdGet32 (PcdSetupConOutColumn);
1248     mSetupTextModeRow          = PcdGet32 (PcdSetupConOutRow);
1249 
1250     mModeInitialized           = TRUE;
1251   }
1252 
1253   gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
1254   gST->ConOut->ClearScreen (gST->ConOut);
1255 
1256   //
1257   // Install customized fonts needed by Front Page
1258   //
1259 
1260   HiiHandle = ExportFonts ();
1261   ASSERT (HiiHandle != NULL);
1262 
1263   InitializeStringSupport ();
1264 
1265   BdsSetConsoleMode (TRUE);
1266   UiEntry (FALSE);
1267   BdsSetConsoleMode (FALSE);
1268 
1269   UninitializeStringSupport ();
1270   HiiRemovePackages (HiiHandle);
1271 
1272   return EFI_SUCCESS;
1273 }
1274 
1275 /**
1276   This function is the main entry of the UI entry.
1277   The function will present the main menu of the system UI.
1278 
1279   @param ConnectAllHappened Caller passes the value to UI to avoid unnecessary connect-all.
1280 
1281 **/
1282 VOID
1283 EFIAPI
UiEntry(IN BOOLEAN ConnectAllHappened)1284 UiEntry (
1285   IN BOOLEAN                      ConnectAllHappened
1286   )
1287 {
1288   EFI_STATUS                    Status;
1289   EFI_BOOT_LOGO_PROTOCOL        *BootLogo;
1290 
1291   //
1292   // Indicate if the connect all has been performed before.
1293   //
1294   if (ConnectAllHappened) {
1295     gConnectAllHappened = TRUE;
1296   }
1297 
1298   //
1299   // The boot option enumeration time is acceptable in Ui driver
1300   //
1301   EfiBootManagerRefreshAllBootOption ();
1302 
1303   //
1304   // Boot Logo is corrupted, report it using Boot Logo protocol.
1305   //
1306   Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
1307   if (!EFI_ERROR (Status) && (BootLogo != NULL)) {
1308     BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);
1309   }
1310 
1311   InitializeFrontPage ();
1312 
1313   CallFrontPage ();
1314 
1315   FreeFrontPage ();
1316 
1317   if (mLanguageString != NULL) {
1318     FreePool (mLanguageString);
1319     mLanguageString = NULL;
1320   }
1321 
1322   //
1323   //Will leave browser, check any reset required change is applied? if yes, reset system
1324   //
1325   SetupResetReminder ();
1326 }
1327 
1328 /**
1329   Extract device path for given HII handle and class guid.
1330 
1331   @param Handle          The HII handle.
1332 
1333   @retval  NULL          Fail to get the device path string.
1334   @return  PathString    Get the device path string.
1335 
1336 **/
1337 CHAR16 *
ExtractDevicePathFromHiiHandle(IN EFI_HII_HANDLE Handle)1338 ExtractDevicePathFromHiiHandle (
1339   IN      EFI_HII_HANDLE      Handle
1340   )
1341 {
1342   EFI_STATUS                       Status;
1343   EFI_HANDLE                       DriverHandle;
1344 
1345   ASSERT (Handle != NULL);
1346 
1347   if (Handle == NULL) {
1348     return NULL;
1349   }
1350 
1351   Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle);
1352   if (EFI_ERROR (Status)) {
1353     return NULL;
1354   }
1355 
1356  return ConvertDevicePathToText(DevicePathFromHandle (DriverHandle), FALSE, FALSE);
1357 
1358 }
1359 
1360 //
1361 //  Following are BDS Lib functions which contain all the code about setup browser reset reminder feature.
1362 //  Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser  if
1363 //  user change any option setting which needs a reset to be effective, and  the reset will be applied according to  the user selection.
1364 //
1365 
1366 
1367 /**
1368   Enable the setup browser reset reminder feature.
1369   This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.
1370 
1371 **/
1372 VOID
1373 EFIAPI
EnableResetReminderFeature(VOID)1374 EnableResetReminderFeature (
1375   VOID
1376   )
1377 {
1378   mFeaturerSwitch = TRUE;
1379 }
1380 
1381 
1382 /**
1383   Disable the setup browser reset reminder feature.
1384   This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.
1385 
1386 **/
1387 VOID
1388 EFIAPI
DisableResetReminderFeature(VOID)1389 DisableResetReminderFeature (
1390   VOID
1391   )
1392 {
1393   mFeaturerSwitch = FALSE;
1394 }
1395 
1396 
1397 /**
1398   Record the info that  a reset is required.
1399   A  module boolean variable is used to record whether a reset is required.
1400 
1401 **/
1402 VOID
1403 EFIAPI
EnableResetRequired(VOID)1404 EnableResetRequired (
1405   VOID
1406   )
1407 {
1408   mResetRequired = TRUE;
1409 }
1410 
1411 
1412 /**
1413   Record the info that  no reset is required.
1414   A  module boolean variable is used to record whether a reset is required.
1415 
1416 **/
1417 VOID
1418 EFIAPI
DisableResetRequired(VOID)1419 DisableResetRequired (
1420   VOID
1421   )
1422 {
1423   mResetRequired = FALSE;
1424 }
1425 
1426 
1427 /**
1428   Check whether platform policy enable the reset reminder feature. The default is enabled.
1429 
1430 **/
1431 BOOLEAN
1432 EFIAPI
IsResetReminderFeatureEnable(VOID)1433 IsResetReminderFeatureEnable (
1434   VOID
1435   )
1436 {
1437   return mFeaturerSwitch;
1438 }
1439 
1440 
1441 /**
1442   Check if  user changed any option setting which needs a system reset to be effective.
1443 
1444 **/
1445 BOOLEAN
1446 EFIAPI
IsResetRequired(VOID)1447 IsResetRequired (
1448   VOID
1449   )
1450 {
1451   return mResetRequired;
1452 }
1453 
1454 
1455 /**
1456   Check whether a reset is needed, and finish the reset reminder feature.
1457   If a reset is needed, Popup a menu to notice user, and finish the feature
1458   according to the user selection.
1459 
1460 **/
1461 VOID
1462 EFIAPI
SetupResetReminder(VOID)1463 SetupResetReminder (
1464   VOID
1465   )
1466 {
1467   EFI_INPUT_KEY                 Key;
1468   CHAR16                        *StringBuffer1;
1469   CHAR16                        *StringBuffer2;
1470 
1471 
1472   //
1473   //check any reset required change is applied? if yes, reset system
1474   //
1475   if (IsResetReminderFeatureEnable ()) {
1476     if (IsResetRequired ()) {
1477 
1478       StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
1479       ASSERT (StringBuffer1 != NULL);
1480       StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
1481       ASSERT (StringBuffer2 != NULL);
1482       StrCpyS (StringBuffer1, MAX_STRING_LEN, L"Configuration changed. Reset to apply it Now.");
1483       StrCpyS (StringBuffer2, MAX_STRING_LEN, L"Press ENTER to reset");
1484       //
1485       // Popup a menu to notice user
1486       //
1487       do {
1488         CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL);
1489       } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1490 
1491       FreePool (StringBuffer1);
1492       FreePool (StringBuffer2);
1493 
1494       gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
1495     }
1496   }
1497 }
1498 
1499