1 /** @file
2   FrontPage routines to handle the callbacks and browser calls
3 
4 Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "FrontPage.h"
11 #include "FrontPageCustomizedUi.h"
12 
13 #define MAX_STRING_LEN            200
14 
15 EFI_GUID   mFrontPageGuid      = FRONT_PAGE_FORMSET_GUID;
16 
17 BOOLEAN   mResetRequired  = FALSE;
18 
19 EFI_FORM_BROWSER2_PROTOCOL      *gFormBrowser2;
20 CHAR8     *mLanguageString;
21 BOOLEAN   mModeInitialized = FALSE;
22 //
23 // Boot video resolution and text mode.
24 //
25 UINT32    mBootHorizontalResolution    = 0;
26 UINT32    mBootVerticalResolution      = 0;
27 UINT32    mBootTextModeColumn          = 0;
28 UINT32    mBootTextModeRow             = 0;
29 //
30 // BIOS setup video resolution and text mode.
31 //
32 UINT32    mSetupTextModeColumn         = 0;
33 UINT32    mSetupTextModeRow            = 0;
34 UINT32    mSetupHorizontalResolution   = 0;
35 UINT32    mSetupVerticalResolution     = 0;
36 
37 FRONT_PAGE_CALLBACK_DATA  gFrontPagePrivate = {
38   FRONT_PAGE_CALLBACK_DATA_SIGNATURE,
39   NULL,
40   NULL,
41   NULL,
42   {
43     FakeExtractConfig,
44     FakeRouteConfig,
45     FrontPageCallback
46   }
47 };
48 
49 HII_VENDOR_DEVICE_PATH  mFrontPageHiiVendorDevicePath = {
50   {
51     {
52       HARDWARE_DEVICE_PATH,
53       HW_VENDOR_DP,
54       {
55         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
56         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
57       }
58     },
59     //
60     // {8E6D99EE-7531-48f8-8745-7F6144468FF2}
61     //
62     { 0x8e6d99ee, 0x7531, 0x48f8, { 0x87, 0x45, 0x7f, 0x61, 0x44, 0x46, 0x8f, 0xf2 } }
63   },
64   {
65     END_DEVICE_PATH_TYPE,
66     END_ENTIRE_DEVICE_PATH_SUBTYPE,
67     {
68       (UINT8) (END_DEVICE_PATH_LENGTH),
69       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
70     }
71   }
72 };
73 
74 /**
75   Update the banner information for the Front Page based on Smbios information.
76 
77 **/
78 VOID
79 UpdateFrontPageBannerStrings (
80   VOID
81   );
82 
83 /**
84   This function allows a caller to extract the current configuration for one
85   or more named elements from the target driver.
86 
87 
88   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
89   @param Request         A null-terminated Unicode string in <ConfigRequest> format.
90   @param Progress        On return, points to a character in the Request string.
91                          Points to the string's null terminator if request was successful.
92                          Points to the most recent '&' before the first failing name/value
93                          pair (or the beginning of the string if the failure is in the
94                          first name/value pair) if the request was not successful.
95   @param Results         A null-terminated Unicode string in <ConfigAltResp> format which
96                          has all values filled in for the names in the Request string.
97                          String to be allocated by the called function.
98 
99   @retval  EFI_SUCCESS            The Results is filled with the requested values.
100   @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
101   @retval  EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
102   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
103 
104 **/
105 EFI_STATUS
106 EFIAPI
FakeExtractConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Request,OUT EFI_STRING * Progress,OUT EFI_STRING * Results)107 FakeExtractConfig (
108   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
109   IN  CONST EFI_STRING                       Request,
110   OUT EFI_STRING                             *Progress,
111   OUT EFI_STRING                             *Results
112   )
113 {
114   if (Progress == NULL || Results == NULL) {
115     return EFI_INVALID_PARAMETER;
116   }
117   *Progress = Request;
118   return EFI_NOT_FOUND;
119 }
120 
121 /**
122   This function processes the results of changes in configuration.
123 
124 
125   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
126   @param Configuration   A null-terminated Unicode string in <ConfigResp> format.
127   @param Progress        A pointer to a string filled in with the offset of the most
128                          recent '&' before the first failing name/value pair (or the
129                          beginning of the string if the failure is in the first
130                          name/value pair) or the terminating NULL if all was successful.
131 
132   @retval  EFI_SUCCESS            The Results is processed successfully.
133   @retval  EFI_INVALID_PARAMETER  Configuration is NULL.
134   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
135 
136 **/
137 EFI_STATUS
138 EFIAPI
FakeRouteConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Configuration,OUT EFI_STRING * Progress)139 FakeRouteConfig (
140   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
141   IN  CONST EFI_STRING                       Configuration,
142   OUT EFI_STRING                             *Progress
143   )
144 {
145   if (Configuration == NULL || Progress == NULL) {
146     return EFI_INVALID_PARAMETER;
147   }
148 
149   *Progress = Configuration;
150 
151   return EFI_NOT_FOUND;
152 }
153 
154 /**
155   This function processes the results of changes in configuration.
156 
157 
158   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
159   @param Action          Specifies the type of action taken by the browser.
160   @param QuestionId      A unique value which is sent to the original exporting driver
161                          so that it can identify the type of data to expect.
162   @param Type            The type of value for the question.
163   @param Value           A pointer to the data being sent to the original exporting driver.
164   @param ActionRequest   On return, points to the action requested by the callback function.
165 
166   @retval  EFI_SUCCESS           The callback successfully handled the action.
167   @retval  EFI_OUT_OF_RESOURCES  Not enough storage is available to hold the variable and its data.
168   @retval  EFI_DEVICE_ERROR      The variable could not be saved.
169   @retval  EFI_UNSUPPORTED       The specified Action is not supported by the callback.
170 
171 **/
172 EFI_STATUS
173 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)174 FrontPageCallback (
175   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
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   )
182 {
183   return UiFrontPageCallbackHandler (gFrontPagePrivate.HiiHandle, Action, QuestionId, Type, Value, ActionRequest);
184 }
185 
186 /**
187 
188   Update the menus in the front page.
189 
190 **/
191 VOID
UpdateFrontPageForm(VOID)192 UpdateFrontPageForm (
193   VOID
194   )
195 {
196   VOID                        *StartOpCodeHandle;
197   VOID                        *EndOpCodeHandle;
198   EFI_IFR_GUID_LABEL          *StartGuidLabel;
199   EFI_IFR_GUID_LABEL          *EndGuidLabel;
200 
201   //
202   // Allocate space for creation of UpdateData Buffer
203   //
204   StartOpCodeHandle = HiiAllocateOpCodeHandle ();
205   ASSERT (StartOpCodeHandle != NULL);
206 
207   EndOpCodeHandle = HiiAllocateOpCodeHandle ();
208   ASSERT (EndOpCodeHandle != NULL);
209   //
210   // Create Hii Extend Label OpCode as the start opcode
211   //
212   StartGuidLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
213   StartGuidLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
214   StartGuidLabel->Number       = LABEL_FRANTPAGE_INFORMATION;
215   //
216   // Create Hii Extend Label OpCode as the end opcode
217   //
218   EndGuidLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
219   EndGuidLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
220   EndGuidLabel->Number       = LABEL_END;
221 
222   //
223   //Updata Front Page form
224   //
225   UiCustomizeFrontPage (
226     gFrontPagePrivate.HiiHandle,
227     StartOpCodeHandle
228     );
229 
230   HiiUpdateForm (
231     gFrontPagePrivate.HiiHandle,
232     &mFrontPageGuid,
233     FRONT_PAGE_FORM_ID,
234     StartOpCodeHandle,
235     EndOpCodeHandle
236     );
237 
238   HiiFreeOpCodeHandle (StartOpCodeHandle);
239   HiiFreeOpCodeHandle (EndOpCodeHandle);
240 }
241 
242 /**
243   Initialize HII information for the FrontPage
244 
245 
246   @retval  EFI_SUCCESS        The operation is successful.
247   @retval  EFI_DEVICE_ERROR   If the dynamic opcode creation failed.
248 
249 **/
250 EFI_STATUS
InitializeFrontPage(VOID)251 InitializeFrontPage (
252   VOID
253   )
254 {
255   EFI_STATUS                  Status;
256   //
257   // Locate Hii relative protocols
258   //
259   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2);
260   if (EFI_ERROR (Status)) {
261     return Status;
262   }
263 
264   //
265   // Install Device Path Protocol and Config Access protocol to driver handle
266   //
267   gFrontPagePrivate.DriverHandle = NULL;
268   Status = gBS->InstallMultipleProtocolInterfaces (
269                   &gFrontPagePrivate.DriverHandle,
270                   &gEfiDevicePathProtocolGuid,
271                   &mFrontPageHiiVendorDevicePath,
272                   &gEfiHiiConfigAccessProtocolGuid,
273                   &gFrontPagePrivate.ConfigAccess,
274                   NULL
275                   );
276   ASSERT_EFI_ERROR (Status);
277 
278   //
279   // Publish our HII data
280   //
281   gFrontPagePrivate.HiiHandle = HiiAddPackages (
282                                   &mFrontPageGuid,
283                                   gFrontPagePrivate.DriverHandle,
284                                   FrontPageVfrBin,
285                                   UiAppStrings,
286                                   NULL
287                                   );
288   ASSERT (gFrontPagePrivate.HiiHandle != NULL);
289 
290   //
291   //Updata Front Page banner strings
292   //
293   UpdateFrontPageBannerStrings ();
294 
295   //
296   // Update front page menus.
297   //
298   UpdateFrontPageForm();
299 
300   return Status;
301 }
302 
303 /**
304   Call the browser and display the front page
305 
306   @return   Status code that will be returned by
307             EFI_FORM_BROWSER2_PROTOCOL.SendForm ().
308 
309 **/
310 EFI_STATUS
CallFrontPage(VOID)311 CallFrontPage (
312   VOID
313   )
314 {
315   EFI_STATUS                  Status;
316   EFI_BROWSER_ACTION_REQUEST  ActionRequest;
317 
318   //
319   // Begin waiting for USER INPUT
320   //
321   REPORT_STATUS_CODE (
322     EFI_PROGRESS_CODE,
323     (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT)
324     );
325 
326   ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
327   Status = gFormBrowser2->SendForm (
328                             gFormBrowser2,
329                             &gFrontPagePrivate.HiiHandle,
330                             1,
331                             &mFrontPageGuid,
332                             0,
333                             NULL,
334                             &ActionRequest
335                             );
336   //
337   // Check whether user change any option setting which needs a reset to be effective
338   //
339   if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
340     EnableResetRequired ();
341   }
342 
343   return Status;
344 }
345 
346 /**
347   Remove the installed packages from the HiiDatabase.
348 
349 **/
350 VOID
FreeFrontPage(VOID)351 FreeFrontPage(
352   VOID
353   )
354 {
355   EFI_STATUS                  Status;
356   Status = gBS->UninstallMultipleProtocolInterfaces (
357                   gFrontPagePrivate.DriverHandle,
358                   &gEfiDevicePathProtocolGuid,
359                   &mFrontPageHiiVendorDevicePath,
360                   &gEfiHiiConfigAccessProtocolGuid,
361                   &gFrontPagePrivate.ConfigAccess,
362                   NULL
363                   );
364   ASSERT_EFI_ERROR (Status);
365 
366   //
367   // Publish our HII data
368   //
369   HiiRemovePackages (gFrontPagePrivate.HiiHandle);
370   if (gFrontPagePrivate.LanguageToken != NULL) {
371     FreePool (gFrontPagePrivate.LanguageToken);
372     gFrontPagePrivate.LanguageToken = NULL;
373   }
374 }
375 
376 /**
377   Convert Processor Frequency Data to a string.
378 
379   @param ProcessorFrequency The frequency data to process
380   @param Base10Exponent     The exponent based on 10
381   @param String             The string that is created
382 
383 **/
384 VOID
ConvertProcessorToString(IN UINT16 ProcessorFrequency,IN UINT16 Base10Exponent,OUT CHAR16 ** String)385 ConvertProcessorToString (
386   IN  UINT16                               ProcessorFrequency,
387   IN  UINT16                               Base10Exponent,
388   OUT CHAR16                               **String
389   )
390 {
391   CHAR16  *StringBuffer;
392   UINTN   Index;
393   UINTN   DestMax;
394   UINT32  FreqMhz;
395 
396   if (Base10Exponent >= 6) {
397     FreqMhz = ProcessorFrequency;
398     for (Index = 0; Index < (UINT32) Base10Exponent - 6; Index++) {
399       FreqMhz *= 10;
400     }
401   } else {
402     FreqMhz = 0;
403   }
404   DestMax = 0x20 / sizeof (CHAR16);
405   StringBuffer = AllocateZeroPool (0x20);
406   ASSERT (StringBuffer != NULL);
407   UnicodeValueToStringS (StringBuffer, sizeof (CHAR16) * DestMax, LEFT_JUSTIFY, FreqMhz / 1000, 3);
408   Index = StrnLenS (StringBuffer, DestMax);
409   StrCatS (StringBuffer, DestMax, L".");
410   UnicodeValueToStringS (
411     StringBuffer + Index + 1,
412     sizeof (CHAR16) * (DestMax - (Index + 1)),
413     PREFIX_ZERO,
414     (FreqMhz % 1000) / 10,
415     2
416     );
417   StrCatS (StringBuffer, DestMax, L" GHz");
418   *String = (CHAR16 *) StringBuffer;
419   return ;
420 }
421 
422 
423 /**
424   Convert Memory Size to a string.
425 
426   @param MemorySize      The size of the memory to process
427   @param String          The string that is created
428 
429 **/
430 VOID
ConvertMemorySizeToString(IN UINT32 MemorySize,OUT CHAR16 ** String)431 ConvertMemorySizeToString (
432   IN  UINT32          MemorySize,
433   OUT CHAR16          **String
434   )
435 {
436   CHAR16  *StringBuffer;
437 
438   StringBuffer = AllocateZeroPool (0x24);
439   ASSERT (StringBuffer != NULL);
440   UnicodeValueToStringS (StringBuffer, 0x24, LEFT_JUSTIFY, MemorySize, 10);
441   StrCatS (StringBuffer, 0x24 / sizeof (CHAR16), L" MB RAM");
442 
443   *String = (CHAR16 *) StringBuffer;
444 
445   return ;
446 }
447 
448 /**
449 
450   Acquire the string associated with the Index from smbios structure and return it.
451   The caller is responsible for free the string buffer.
452 
453   @param    OptionalStrStart  The start position to search the string
454   @param    Index             The index of the string to extract
455   @param    String            The string that is extracted
456 
457   @retval   EFI_SUCCESS       The function returns EFI_SUCCESS always.
458 
459 **/
460 EFI_STATUS
GetOptionalStringByIndex(IN CHAR8 * OptionalStrStart,IN UINT8 Index,OUT CHAR16 ** String)461 GetOptionalStringByIndex (
462   IN      CHAR8                   *OptionalStrStart,
463   IN      UINT8                   Index,
464   OUT     CHAR16                  **String
465   )
466 {
467   UINTN          StrSize;
468 
469   if (Index == 0) {
470     *String = AllocateZeroPool (sizeof (CHAR16));
471     return EFI_SUCCESS;
472   }
473 
474   StrSize = 0;
475   do {
476     Index--;
477     OptionalStrStart += StrSize;
478     StrSize           = AsciiStrSize (OptionalStrStart);
479   } while (OptionalStrStart[StrSize] != 0 && Index != 0);
480 
481   if ((Index != 0) || (StrSize == 1)) {
482     //
483     // Meet the end of strings set but Index is non-zero, or
484     // Find an empty string
485     //
486     *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));
487   } else {
488     *String = AllocatePool (StrSize * sizeof (CHAR16));
489     AsciiStrToUnicodeStrS (OptionalStrStart, *String, StrSize);
490   }
491 
492   return EFI_SUCCESS;
493 }
494 
495 
496 /**
497 
498   Update the banner information for the Front Page based on Smbios information.
499 
500 **/
501 VOID
UpdateFrontPageBannerStrings(VOID)502 UpdateFrontPageBannerStrings (
503   VOID
504   )
505 {
506   UINT8                             StrIndex;
507   CHAR16                            *NewString;
508   CHAR16                            *FirmwareVersionString;
509   EFI_STATUS                        Status;
510   EFI_SMBIOS_HANDLE                 SmbiosHandle;
511   EFI_SMBIOS_PROTOCOL               *Smbios;
512   SMBIOS_TABLE_TYPE0                *Type0Record;
513   SMBIOS_TABLE_TYPE1                *Type1Record;
514   SMBIOS_TABLE_TYPE4                *Type4Record;
515   SMBIOS_TABLE_TYPE19               *Type19Record;
516   EFI_SMBIOS_TABLE_HEADER           *Record;
517   UINT64                            InstalledMemory;
518   BOOLEAN                           FoundCpu;
519 
520   InstalledMemory = 0;
521   FoundCpu = 0;
522 
523   //
524   // Update default banner string.
525   //
526   NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE4_LEFT), NULL);
527   UiCustomizeFrontPageBanner (4, TRUE, &NewString);
528   HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE4_LEFT), NewString, NULL);
529   FreePool (NewString);
530 
531   NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE4_RIGHT), NULL);
532   UiCustomizeFrontPageBanner (4, FALSE, &NewString);
533   HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE4_RIGHT), NewString, NULL);
534   FreePool (NewString);
535 
536   NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE5_LEFT), NULL);
537   UiCustomizeFrontPageBanner (5, TRUE, &NewString);
538   HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE5_LEFT), NewString, NULL);
539   FreePool (NewString);
540 
541   NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE5_RIGHT), NULL);
542   UiCustomizeFrontPageBanner (5, FALSE, &NewString);
543   HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_CUSTOMIZE_BANNER_LINE5_RIGHT), NewString, NULL);
544   FreePool (NewString);
545 
546   //
547   // Update Front Page banner strings base on SmBios Table.
548   //
549   Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &Smbios);
550   if (EFI_ERROR (Status)) {
551     //
552     // Smbios protocol not found, get the default value.
553     //
554     NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL), NULL);
555     UiCustomizeFrontPageBanner (1, TRUE, &NewString);
556     HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL), NewString, NULL);
557     FreePool (NewString);
558 
559     NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL), NULL);
560     UiCustomizeFrontPageBanner (2, TRUE, &NewString);
561     HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL), NewString, NULL);
562     FreePool (NewString);
563 
564     NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED), NULL);
565     UiCustomizeFrontPageBanner (2, FALSE, &NewString);
566     HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED), NewString, NULL);
567     FreePool (NewString);
568 
569     NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION), NULL);
570     UiCustomizeFrontPageBanner (3, TRUE, &NewString);
571     HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION), NewString, NULL);
572     FreePool (NewString);
573 
574     NewString = HiiGetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE), NULL);
575     UiCustomizeFrontPageBanner (3, FALSE, &NewString);
576     HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE), NewString, NULL);
577     FreePool (NewString);
578 
579     return;
580   }
581 
582   SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
583   Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
584   while (!EFI_ERROR(Status)) {
585     if (Record->Type == SMBIOS_TYPE_BIOS_INFORMATION) {
586       Type0Record = (SMBIOS_TABLE_TYPE0 *) Record;
587       StrIndex = Type0Record->BiosVersion;
588       GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &NewString);
589 
590       FirmwareVersionString = (CHAR16 *) PcdGetPtr (PcdFirmwareVersionString);
591       if (*FirmwareVersionString != 0x0000 ) {
592         FreePool (NewString);
593         NewString = (CHAR16 *) PcdGetPtr (PcdFirmwareVersionString);
594         UiCustomizeFrontPageBanner (3, TRUE, &NewString);
595         HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION), NewString, NULL);
596       } else {
597         UiCustomizeFrontPageBanner (3, TRUE, &NewString);
598         HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION), NewString, NULL);
599         FreePool (NewString);
600       }
601     }
602 
603     if (Record->Type == SMBIOS_TYPE_SYSTEM_INFORMATION) {
604       Type1Record = (SMBIOS_TABLE_TYPE1 *) Record;
605       StrIndex = Type1Record->ProductName;
606       GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type1Record + Type1Record->Hdr.Length), StrIndex, &NewString);
607       UiCustomizeFrontPageBanner (1, TRUE, &NewString);
608       HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL), NewString, NULL);
609       FreePool (NewString);
610     }
611 
612     if ((Record->Type == SMBIOS_TYPE_PROCESSOR_INFORMATION) && !FoundCpu) {
613       Type4Record = (SMBIOS_TABLE_TYPE4 *) Record;
614       //
615       // The information in the record should be only valid when the CPU Socket is populated.
616       //
617       if ((Type4Record->Status & SMBIOS_TYPE4_CPU_SOCKET_POPULATED) == SMBIOS_TYPE4_CPU_SOCKET_POPULATED) {
618         StrIndex = Type4Record->ProcessorVersion;
619         GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type4Record + Type4Record->Hdr.Length), StrIndex, &NewString);
620         UiCustomizeFrontPageBanner (2, TRUE, &NewString);
621         HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL), NewString, NULL);
622         FreePool (NewString);
623 
624         ConvertProcessorToString(Type4Record->CurrentSpeed, 6, &NewString);
625         UiCustomizeFrontPageBanner (2, FALSE, &NewString);
626         HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED), NewString, NULL);
627         FreePool (NewString);
628 
629         FoundCpu = TRUE;
630       }
631     }
632 
633     if ( Record->Type == SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS ) {
634       Type19Record = (SMBIOS_TABLE_TYPE19 *) Record;
635       if (Type19Record->StartingAddress != 0xFFFFFFFF ) {
636         InstalledMemory += RShiftU64(Type19Record->EndingAddress -
637                                      Type19Record->StartingAddress + 1, 10);
638       } else {
639         InstalledMemory += RShiftU64(Type19Record->ExtendedEndingAddress -
640                                      Type19Record->ExtendedStartingAddress + 1, 20);
641       }
642     }
643 
644     Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
645   }
646 
647   //
648   // Now update the total installed RAM size
649   //
650   ConvertMemorySizeToString ((UINT32)InstalledMemory, &NewString );
651   UiCustomizeFrontPageBanner (3, FALSE, &NewString);
652   HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE), NewString, NULL);
653   FreePool (NewString);
654 }
655 
656 /**
657   This function will change video resolution and text mode
658   according to defined setup mode or defined boot mode
659 
660   @param  IsSetupMode   Indicate mode is changed to setup mode or boot mode.
661 
662   @retval  EFI_SUCCESS  Mode is changed successfully.
663   @retval  Others             Mode failed to be changed.
664 
665 **/
666 EFI_STATUS
UiSetConsoleMode(BOOLEAN IsSetupMode)667 UiSetConsoleMode (
668   BOOLEAN  IsSetupMode
669   )
670 {
671   EFI_GRAPHICS_OUTPUT_PROTOCOL          *GraphicsOutput;
672   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL       *SimpleTextOut;
673   UINTN                                 SizeOfInfo;
674   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
675   UINT32                                MaxGopMode;
676   UINT32                                MaxTextMode;
677   UINT32                                ModeNumber;
678   UINT32                                NewHorizontalResolution;
679   UINT32                                NewVerticalResolution;
680   UINT32                                NewColumns;
681   UINT32                                NewRows;
682   UINTN                                 HandleCount;
683   EFI_HANDLE                            *HandleBuffer;
684   EFI_STATUS                            Status;
685   UINTN                                 Index;
686   UINTN                                 CurrentColumn;
687   UINTN                                 CurrentRow;
688 
689   MaxGopMode  = 0;
690   MaxTextMode = 0;
691 
692   //
693   // Get current video resolution and text mode
694   //
695   Status = gBS->HandleProtocol (
696                   gST->ConsoleOutHandle,
697                   &gEfiGraphicsOutputProtocolGuid,
698                   (VOID**)&GraphicsOutput
699                   );
700   if (EFI_ERROR (Status)) {
701     GraphicsOutput = NULL;
702   }
703 
704   Status = gBS->HandleProtocol (
705                   gST->ConsoleOutHandle,
706                   &gEfiSimpleTextOutProtocolGuid,
707                   (VOID**)&SimpleTextOut
708                   );
709   if (EFI_ERROR (Status)) {
710     SimpleTextOut = NULL;
711   }
712 
713   if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {
714     return EFI_UNSUPPORTED;
715   }
716 
717   if (IsSetupMode) {
718     //
719     // The required resolution and text mode is setup mode.
720     //
721     NewHorizontalResolution = mSetupHorizontalResolution;
722     NewVerticalResolution   = mSetupVerticalResolution;
723     NewColumns              = mSetupTextModeColumn;
724     NewRows                 = mSetupTextModeRow;
725   } else {
726     //
727     // The required resolution and text mode is boot mode.
728     //
729     NewHorizontalResolution = mBootHorizontalResolution;
730     NewVerticalResolution   = mBootVerticalResolution;
731     NewColumns              = mBootTextModeColumn;
732     NewRows                 = mBootTextModeRow;
733   }
734 
735   if (GraphicsOutput != NULL) {
736     MaxGopMode  = GraphicsOutput->Mode->MaxMode;
737   }
738 
739   if (SimpleTextOut != NULL) {
740     MaxTextMode = SimpleTextOut->Mode->MaxMode;
741   }
742 
743   //
744   // 1. If current video resolution is same with required video resolution,
745   //    video resolution need not be changed.
746   //    1.1. If current text mode is same with required text mode, text mode need not be changed.
747   //    1.2. If current text mode is different from required text mode, text mode need be changed.
748   // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
749   //
750   for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {
751     Status = GraphicsOutput->QueryMode (
752                        GraphicsOutput,
753                        ModeNumber,
754                        &SizeOfInfo,
755                        &Info
756                        );
757     if (!EFI_ERROR (Status)) {
758       if ((Info->HorizontalResolution == NewHorizontalResolution) &&
759           (Info->VerticalResolution == NewVerticalResolution)) {
760         if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) &&
761             (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) {
762           //
763           // Current resolution is same with required resolution, check if text mode need be set
764           //
765           Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);
766           ASSERT_EFI_ERROR (Status);
767           if (CurrentColumn == NewColumns && CurrentRow == NewRows) {
768             //
769             // If current text mode is same with required text mode. Do nothing
770             //
771             FreePool (Info);
772             return EFI_SUCCESS;
773           } else {
774             //
775             // If current text mode is different from required text mode.  Set new video mode
776             //
777             for (Index = 0; Index < MaxTextMode; Index++) {
778               Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);
779               if (!EFI_ERROR(Status)) {
780                 if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) {
781                   //
782                   // Required text mode is supported, set it.
783                   //
784                   Status = SimpleTextOut->SetMode (SimpleTextOut, Index);
785                   ASSERT_EFI_ERROR (Status);
786                   //
787                   // Update text mode PCD.
788                   //
789                   Status = PcdSet32S (PcdConOutColumn, mSetupTextModeColumn);
790                   ASSERT_EFI_ERROR (Status);
791                   Status = PcdSet32S (PcdConOutRow, mSetupTextModeRow);
792                   ASSERT_EFI_ERROR (Status);
793                   FreePool (Info);
794                   return EFI_SUCCESS;
795                 }
796               }
797             }
798             if (Index == MaxTextMode) {
799               //
800               // If required text mode is not supported, return error.
801               //
802               FreePool (Info);
803               return EFI_UNSUPPORTED;
804             }
805           }
806         } else {
807           //
808           // If current video resolution is not same with the new one, set new video resolution.
809           // In this case, the driver which produces simple text out need be restarted.
810           //
811           Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
812           if (!EFI_ERROR (Status)) {
813             FreePool (Info);
814             break;
815           }
816         }
817       }
818       FreePool (Info);
819     }
820   }
821 
822   if (ModeNumber == MaxGopMode) {
823     //
824     // If the resolution is not supported, return error.
825     //
826     return EFI_UNSUPPORTED;
827   }
828 
829   //
830   // Set PCD to Inform GraphicsConsole to change video resolution.
831   // Set PCD to Inform Consplitter to change text mode.
832   //
833   Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution);
834   ASSERT_EFI_ERROR (Status);
835   Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution);
836   ASSERT_EFI_ERROR (Status);
837   Status = PcdSet32S (PcdConOutColumn, NewColumns);
838   ASSERT_EFI_ERROR (Status);
839   Status = PcdSet32S (PcdConOutRow, NewRows);
840   ASSERT_EFI_ERROR (Status);
841 
842   //
843   // Video mode is changed, so restart graphics console driver and higher level driver.
844   // Reconnect graphics console driver and higher level driver.
845   // Locate all the handles with GOP protocol and reconnect it.
846   //
847   Status = gBS->LocateHandleBuffer (
848                    ByProtocol,
849                    &gEfiSimpleTextOutProtocolGuid,
850                    NULL,
851                    &HandleCount,
852                    &HandleBuffer
853                    );
854   if (!EFI_ERROR (Status)) {
855     for (Index = 0; Index < HandleCount; Index++) {
856       gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
857     }
858     for (Index = 0; Index < HandleCount; Index++) {
859       gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
860     }
861     if (HandleBuffer != NULL) {
862       FreePool (HandleBuffer);
863     }
864   }
865 
866   return EFI_SUCCESS;
867 }
868 
869 /**
870   The user Entry Point for Application. The user code starts with this function
871   as the real entry point for the image goes into a library that calls this
872   function.
873 
874   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
875   @param[in] SystemTable    A pointer to the EFI System Table.
876 
877   @retval EFI_SUCCESS       The entry point is executed successfully.
878   @retval other             Some error occurs when executing this entry point.
879 
880 **/
881 EFI_STATUS
882 EFIAPI
InitializeUserInterface(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)883 InitializeUserInterface (
884   IN EFI_HANDLE        ImageHandle,
885   IN EFI_SYSTEM_TABLE  *SystemTable
886   )
887 {
888   EFI_HII_HANDLE                     HiiHandle;
889   EFI_STATUS                         Status;
890   EFI_GRAPHICS_OUTPUT_PROTOCOL       *GraphicsOutput;
891   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *SimpleTextOut;
892   UINTN                              BootTextColumn;
893   UINTN                              BootTextRow;
894 
895   if (!mModeInitialized) {
896     //
897     // After the console is ready, get current video resolution
898     // and text mode before launching setup at first time.
899     //
900     Status = gBS->HandleProtocol (
901                     gST->ConsoleOutHandle,
902                     &gEfiGraphicsOutputProtocolGuid,
903                     (VOID**)&GraphicsOutput
904                     );
905     if (EFI_ERROR (Status)) {
906       GraphicsOutput = NULL;
907     }
908 
909     Status = gBS->HandleProtocol (
910                     gST->ConsoleOutHandle,
911                     &gEfiSimpleTextOutProtocolGuid,
912                     (VOID**)&SimpleTextOut
913                     );
914     if (EFI_ERROR (Status)) {
915       SimpleTextOut = NULL;
916     }
917 
918     if (GraphicsOutput != NULL) {
919       //
920       // Get current video resolution and text mode.
921       //
922       mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
923       mBootVerticalResolution   = GraphicsOutput->Mode->Info->VerticalResolution;
924     }
925 
926     if (SimpleTextOut != NULL) {
927       Status = SimpleTextOut->QueryMode (
928                                 SimpleTextOut,
929                                 SimpleTextOut->Mode->Mode,
930                                 &BootTextColumn,
931                                 &BootTextRow
932                                 );
933       mBootTextModeColumn = (UINT32)BootTextColumn;
934       mBootTextModeRow    = (UINT32)BootTextRow;
935     }
936 
937     //
938     // Get user defined text mode for setup.
939     //
940     mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
941     mSetupVerticalResolution   = PcdGet32 (PcdSetupVideoVerticalResolution);
942     mSetupTextModeColumn       = PcdGet32 (PcdSetupConOutColumn);
943     mSetupTextModeRow          = PcdGet32 (PcdSetupConOutRow);
944 
945     mModeInitialized           = TRUE;
946   }
947 
948   gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
949   gST->ConOut->ClearScreen (gST->ConOut);
950 
951   //
952   // Install customized fonts needed by Front Page
953   //
954   HiiHandle = ExportFonts ();
955   ASSERT (HiiHandle != NULL);
956 
957   InitializeStringSupport ();
958 
959   UiSetConsoleMode (TRUE);
960   UiEntry (FALSE);
961   UiSetConsoleMode (FALSE);
962 
963   UninitializeStringSupport ();
964   HiiRemovePackages (HiiHandle);
965 
966   return EFI_SUCCESS;
967 }
968 
969 /**
970   This function is the main entry of the UI entry.
971   The function will present the main menu of the system UI.
972 
973   @param ConnectAllHappened Caller passes the value to UI to avoid unnecessary connect-all.
974 
975 **/
976 VOID
977 EFIAPI
UiEntry(IN BOOLEAN ConnectAllHappened)978 UiEntry (
979   IN BOOLEAN                      ConnectAllHappened
980   )
981 {
982   EFI_STATUS                    Status;
983   EFI_BOOT_LOGO_PROTOCOL        *BootLogo;
984 
985   //
986   // Enter Setup page.
987   //
988   REPORT_STATUS_CODE (
989     EFI_PROGRESS_CODE,
990     (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP)
991     );
992 
993   //
994   // Indicate if the connect all has been performed before.
995   // If has not been performed before, do here.
996   //
997   if (!ConnectAllHappened) {
998     EfiBootManagerConnectAll ();
999   }
1000 
1001   //
1002   // The boot option enumeration time is acceptable in Ui driver
1003   //
1004   EfiBootManagerRefreshAllBootOption ();
1005 
1006   //
1007   // Boot Logo is corrupted, report it using Boot Logo protocol.
1008   //
1009   Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
1010   if (!EFI_ERROR (Status) && (BootLogo != NULL)) {
1011     BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);
1012   }
1013 
1014   InitializeFrontPage ();
1015 
1016   CallFrontPage ();
1017 
1018   FreeFrontPage ();
1019 
1020   if (mLanguageString != NULL) {
1021     FreePool (mLanguageString);
1022     mLanguageString = NULL;
1023   }
1024 
1025   //
1026   //Will leave browser, check any reset required change is applied? if yes, reset system
1027   //
1028   SetupResetReminder ();
1029 }
1030 
1031 //
1032 //  Following are BDS Lib functions which contain all the code about setup browser reset reminder feature.
1033 //  Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser  if
1034 //  user change any option setting which needs a reset to be effective, and  the reset will be applied according to  the user selection.
1035 //
1036 
1037 
1038 
1039 
1040 
1041 /**
1042   Record the info that  a reset is required.
1043   A  module boolean variable is used to record whether a reset is required.
1044 
1045 **/
1046 VOID
1047 EFIAPI
EnableResetRequired(VOID)1048 EnableResetRequired (
1049   VOID
1050   )
1051 {
1052   mResetRequired = TRUE;
1053 }
1054 
1055 
1056 
1057 
1058 
1059 /**
1060   Check if  user changed any option setting which needs a system reset to be effective.
1061 
1062 **/
1063 BOOLEAN
1064 EFIAPI
IsResetRequired(VOID)1065 IsResetRequired (
1066   VOID
1067   )
1068 {
1069   return mResetRequired;
1070 }
1071 
1072 
1073 /**
1074   Check whether a reset is needed, and finish the reset reminder feature.
1075   If a reset is needed, Popup a menu to notice user, and finish the feature
1076   according to the user selection.
1077 
1078 **/
1079 VOID
1080 EFIAPI
SetupResetReminder(VOID)1081 SetupResetReminder (
1082   VOID
1083   )
1084 {
1085   EFI_INPUT_KEY                 Key;
1086   CHAR16                        *StringBuffer1;
1087   CHAR16                        *StringBuffer2;
1088 
1089   //
1090   //check any reset required change is applied? if yes, reset system
1091   //
1092   if (IsResetRequired ()) {
1093 
1094     StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
1095     ASSERT (StringBuffer1 != NULL);
1096     StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));
1097     ASSERT (StringBuffer2 != NULL);
1098     StrCpyS (StringBuffer1, MAX_STRING_LEN, L"Configuration changed. Reset to apply it Now.");
1099     StrCpyS (StringBuffer2, MAX_STRING_LEN, L"Press ENTER to reset");
1100     //
1101     // Popup a menu to notice user
1102     //
1103     do {
1104       CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL);
1105     } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1106 
1107     FreePool (StringBuffer1);
1108     FreePool (StringBuffer2);
1109 
1110     gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
1111   }
1112 }
1113 
1114