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