]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c
Introduce video resolution and text mode PCDs for BIOS setup in BDS module. User...
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / FrontPage.c
1 /** @file
2 FrontPage routines to handle the callbacks and browser calls
3
4 Copyright (c) 2004 - 2011, 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 "Bds.h"
16 #include "FrontPage.h"
17 #include "Language.h"
18 #include "Hotkey.h"
19
20 BOOLEAN gConnectAllHappened = FALSE;
21 UINTN gCallbackKey;
22
23 EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2;
24
25 FRONT_PAGE_CALLBACK_DATA gFrontPagePrivate = {
26 FRONT_PAGE_CALLBACK_DATA_SIGNATURE,
27 NULL,
28 NULL,
29 NULL,
30 {
31 FakeExtractConfig,
32 FakeRouteConfig,
33 FrontPageCallback
34 }
35 };
36
37 HII_VENDOR_DEVICE_PATH mFrontPageHiiVendorDevicePath = {
38 {
39 {
40 HARDWARE_DEVICE_PATH,
41 HW_VENDOR_DP,
42 {
43 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
44 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
45 }
46 },
47 FRONT_PAGE_FORMSET_GUID
48 },
49 {
50 END_DEVICE_PATH_TYPE,
51 END_ENTIRE_DEVICE_PATH_SUBTYPE,
52 {
53 (UINT8) (END_DEVICE_PATH_LENGTH),
54 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
55 }
56 }
57 };
58
59 /**
60 This function allows a caller to extract the current configuration for one
61 or more named elements from the target driver.
62
63
64 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
65 @param Request A null-terminated Unicode string in <ConfigRequest> format.
66 @param Progress On return, points to a character in the Request string.
67 Points to the string's null terminator if request was successful.
68 Points to the most recent '&' before the first failing name/value
69 pair (or the beginning of the string if the failure is in the
70 first name/value pair) if the request was not successful.
71 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
72 has all values filled in for the names in the Request string.
73 String to be allocated by the called function.
74
75 @retval EFI_SUCCESS The Results is filled with the requested values.
76 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
77 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
78 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
79
80 **/
81 EFI_STATUS
82 EFIAPI
83 FakeExtractConfig (
84 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
85 IN CONST EFI_STRING Request,
86 OUT EFI_STRING *Progress,
87 OUT EFI_STRING *Results
88 )
89 {
90 if (Progress == NULL || Results == NULL) {
91 return EFI_INVALID_PARAMETER;
92 }
93 *Progress = Request;
94 return EFI_NOT_FOUND;
95 }
96
97 /**
98 This function processes the results of changes in configuration.
99
100
101 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
102 @param Configuration A null-terminated Unicode string in <ConfigResp> format.
103 @param Progress A pointer to a string filled in with the offset of the most
104 recent '&' before the first failing name/value pair (or the
105 beginning of the string if the failure is in the first
106 name/value pair) or the terminating NULL if all was successful.
107
108 @retval EFI_SUCCESS The Results is processed successfully.
109 @retval EFI_INVALID_PARAMETER Configuration is NULL.
110 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
111
112 **/
113 EFI_STATUS
114 EFIAPI
115 FakeRouteConfig (
116 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
117 IN CONST EFI_STRING Configuration,
118 OUT EFI_STRING *Progress
119 )
120 {
121 if (Configuration == NULL || Progress == NULL) {
122 return EFI_INVALID_PARAMETER;
123 }
124
125 *Progress = Configuration;
126 if (!HiiIsConfigHdrMatch (Configuration, &gBootMaintFormSetGuid, mBootMaintStorageName)
127 && !HiiIsConfigHdrMatch (Configuration, &gFileExploreFormSetGuid, mFileExplorerStorageName)) {
128 return EFI_NOT_FOUND;
129 }
130
131 *Progress = Configuration + StrLen (Configuration);
132 return EFI_SUCCESS;
133 }
134
135 /**
136 This function processes the results of changes in configuration.
137
138
139 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
140 @param Action Specifies the type of action taken by the browser.
141 @param QuestionId A unique value which is sent to the original exporting driver
142 so that it can identify the type of data to expect.
143 @param Type The type of value for the question.
144 @param Value A pointer to the data being sent to the original exporting driver.
145 @param ActionRequest On return, points to the action requested by the callback function.
146
147 @retval EFI_SUCCESS The callback successfully handled the action.
148 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
149 @retval EFI_DEVICE_ERROR The variable could not be saved.
150 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.
151
152 **/
153 EFI_STATUS
154 EFIAPI
155 FrontPageCallback (
156 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
157 IN EFI_BROWSER_ACTION Action,
158 IN EFI_QUESTION_ID QuestionId,
159 IN UINT8 Type,
160 IN EFI_IFR_TYPE_VALUE *Value,
161 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
162 )
163 {
164 CHAR8 *LanguageString;
165 CHAR8 *LangCode;
166 CHAR8 *Lang;
167 UINTN Index;
168 EFI_STATUS Status;
169 CHAR8 *PlatformSupportedLanguages;
170 CHAR8 *BestLanguage;
171
172 if (Action == EFI_BROWSER_ACTION_CHANGING) {
173 if ((Value == NULL) || (ActionRequest == NULL)) {
174 return EFI_INVALID_PARAMETER;
175 }
176
177 gCallbackKey = QuestionId;
178
179 //
180 // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
181 // describe to their customers in documentation how to find their setup information (namely
182 // under the device manager and specific buckets)
183 //
184 switch (QuestionId) {
185 case FRONT_PAGE_KEY_CONTINUE:
186 //
187 // This is the continue - clear the screen and return an error to get out of FrontPage loop
188 //
189 break;
190
191 case FRONT_PAGE_KEY_LANGUAGE:
192 //
193 // Collect the languages from what our current Language support is based on our VFR
194 //
195 LanguageString = HiiGetSupportedLanguages (gFrontPagePrivate.HiiHandle);
196 ASSERT (LanguageString != NULL);
197 //
198 // Allocate working buffer for RFC 4646 language in supported LanguageString.
199 //
200 Lang = AllocatePool (AsciiStrSize (LanguageString));
201 ASSERT (Lang != NULL);
202
203 Index = 0;
204 LangCode = LanguageString;
205 while (*LangCode != 0) {
206 GetNextLanguage (&LangCode, Lang);
207
208 if (Index == Value->u8) {
209 break;
210 }
211
212 Index++;
213 }
214
215 PlatformSupportedLanguages = GetEfiGlobalVariable (L"PlatformLangCodes");
216 if (PlatformSupportedLanguages == NULL) {
217 PlatformSupportedLanguages = AllocateCopyPool (
218 AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)),
219 (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)
220 );
221 ASSERT (PlatformSupportedLanguages != NULL);
222 }
223
224 //
225 // Select the best language in platform supported Language.
226 //
227 BestLanguage = GetBestLanguage (
228 PlatformSupportedLanguages,
229 FALSE,
230 Lang,
231 NULL
232 );
233 if (BestLanguage != NULL) {
234 Status = gRT->SetVariable (
235 L"PlatformLang",
236 &gEfiGlobalVariableGuid,
237 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
238 AsciiStrSize (BestLanguage),
239 Lang
240 );
241 ASSERT_EFI_ERROR(Status);
242 FreePool (BestLanguage);
243 } else {
244 ASSERT (FALSE);
245 }
246
247 FreePool (PlatformSupportedLanguages);
248 FreePool (Lang);
249 FreePool (LanguageString);
250 break;
251
252 case FRONT_PAGE_KEY_BOOT_MANAGER:
253 //
254 // Boot Manager
255 //
256 break;
257
258 case FRONT_PAGE_KEY_DEVICE_MANAGER:
259 //
260 // Device Manager
261 //
262 break;
263
264 case FRONT_PAGE_KEY_BOOT_MAINTAIN:
265 //
266 // Boot Maintenance Manager
267 //
268 break;
269
270 default:
271 gCallbackKey = 0;
272 break;
273 }
274
275 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
276
277 return EFI_SUCCESS;
278 }
279
280 //
281 // All other action return unsupported.
282 //
283 return EFI_UNSUPPORTED;
284 }
285
286 /**
287 Initialize HII information for the FrontPage
288
289
290 @param InitializeHiiData TRUE if HII elements need to be initialized.
291
292 @retval EFI_SUCCESS The operation is successful.
293 @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed.
294
295 **/
296 EFI_STATUS
297 InitializeFrontPage (
298 IN BOOLEAN InitializeHiiData
299 )
300 {
301 EFI_STATUS Status;
302 CHAR8 *LanguageString;
303 CHAR8 *LangCode;
304 CHAR8 *Lang;
305 CHAR8 *CurrentLang;
306 CHAR8 *BestLanguage;
307 UINTN OptionCount;
308 CHAR16 *StringBuffer;
309 EFI_HII_HANDLE HiiHandle;
310 VOID *OptionsOpCodeHandle;
311 VOID *StartOpCodeHandle;
312 VOID *EndOpCodeHandle;
313 EFI_IFR_GUID_LABEL *StartLabel;
314 EFI_IFR_GUID_LABEL *EndLabel;
315 BOOLEAN FirstFlag;
316
317 if (InitializeHiiData) {
318 //
319 // Initialize the Device Manager
320 //
321 InitializeDeviceManager ();
322
323 //
324 // Initialize the Device Manager
325 //
326 InitializeBootManager ();
327
328 gCallbackKey = 0;
329
330 //
331 // Locate Hii relative protocols
332 //
333 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2);
334 if (EFI_ERROR (Status)) {
335 return Status;
336 }
337
338 //
339 // Install Device Path Protocol and Config Access protocol to driver handle
340 //
341 Status = gBS->InstallMultipleProtocolInterfaces (
342 &gFrontPagePrivate.DriverHandle,
343 &gEfiDevicePathProtocolGuid,
344 &mFrontPageHiiVendorDevicePath,
345 &gEfiHiiConfigAccessProtocolGuid,
346 &gFrontPagePrivate.ConfigAccess,
347 NULL
348 );
349 ASSERT_EFI_ERROR (Status);
350
351 //
352 // Publish our HII data
353 //
354 gFrontPagePrivate.HiiHandle = HiiAddPackages (
355 &gFrontPageFormSetGuid,
356 gFrontPagePrivate.DriverHandle,
357 FrontPageVfrBin,
358 BdsDxeStrings,
359 NULL
360 );
361 if (gFrontPagePrivate.HiiHandle == NULL) {
362 return EFI_OUT_OF_RESOURCES;
363 }
364 }
365
366
367 //
368 // Init OpCode Handle and Allocate space for creation of UpdateData Buffer
369 //
370 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
371 ASSERT (StartOpCodeHandle != NULL);
372
373 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
374 ASSERT (EndOpCodeHandle != NULL);
375
376 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
377 ASSERT (OptionsOpCodeHandle != NULL);
378 //
379 // Create Hii Extend Label OpCode as the start opcode
380 //
381 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
382 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
383 StartLabel->Number = LABEL_SELECT_LANGUAGE;
384
385 //
386 // Create Hii Extend Label OpCode as the end opcode
387 //
388 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
389 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
390 EndLabel->Number = LABEL_END;
391
392 //
393 // Collect the languages from what our current Language support is based on our VFR
394 //
395 HiiHandle = gFrontPagePrivate.HiiHandle;
396 LanguageString = HiiGetSupportedLanguages (HiiHandle);
397 ASSERT (LanguageString != NULL);
398 //
399 // Allocate working buffer for RFC 4646 language in supported LanguageString.
400 //
401 Lang = AllocatePool (AsciiStrSize (LanguageString));
402 ASSERT (Lang != NULL);
403
404 CurrentLang = GetEfiGlobalVariable (L"PlatformLang");
405 //
406 // Select the best language in LanguageString as the default one.
407 //
408 BestLanguage = GetBestLanguage (
409 LanguageString,
410 FALSE,
411 (CurrentLang != NULL) ? CurrentLang : "",
412 (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang),
413 LanguageString,
414 NULL
415 );
416 //
417 // BestLanguage must be selected as it is the first language in LanguageString by default
418 //
419 ASSERT (BestLanguage != NULL);
420
421 OptionCount = 0;
422 LangCode = LanguageString;
423 FirstFlag = FALSE;
424
425 if (gFrontPagePrivate.LanguageToken == NULL) {
426 while (*LangCode != 0) {
427 GetNextLanguage (&LangCode, Lang);
428 OptionCount ++;
429 }
430 gFrontPagePrivate.LanguageToken = AllocatePool (OptionCount * sizeof (EFI_STRING_ID));
431 ASSERT (gFrontPagePrivate.LanguageToken != NULL);
432 FirstFlag = TRUE;
433 }
434
435 OptionCount = 0;
436 LangCode = LanguageString;
437 while (*LangCode != 0) {
438 GetNextLanguage (&LangCode, Lang);
439
440 if (FirstFlag) {
441 StringBuffer = HiiGetString (HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, Lang);
442 ASSERT (StringBuffer != NULL);
443
444 //
445 // Save the string Id for each language
446 //
447 gFrontPagePrivate.LanguageToken[OptionCount] = HiiSetString (HiiHandle, 0, StringBuffer, NULL);
448 FreePool (StringBuffer);
449 }
450
451 if (AsciiStrCmp (Lang, BestLanguage) == 0) {
452 HiiCreateOneOfOptionOpCode (
453 OptionsOpCodeHandle,
454 gFrontPagePrivate.LanguageToken[OptionCount],
455 EFI_IFR_OPTION_DEFAULT,
456 EFI_IFR_NUMERIC_SIZE_1,
457 (UINT8) OptionCount
458 );
459 } else {
460 HiiCreateOneOfOptionOpCode (
461 OptionsOpCodeHandle,
462 gFrontPagePrivate.LanguageToken[OptionCount],
463 0,
464 EFI_IFR_NUMERIC_SIZE_1,
465 (UINT8) OptionCount
466 );
467 }
468
469 OptionCount++;
470 }
471
472 if (CurrentLang != NULL) {
473 FreePool (CurrentLang);
474 }
475 FreePool (BestLanguage);
476 FreePool (Lang);
477 FreePool (LanguageString);
478
479 HiiCreateOneOfOpCode (
480 StartOpCodeHandle,
481 FRONT_PAGE_KEY_LANGUAGE,
482 0,
483 0,
484 STRING_TOKEN (STR_LANGUAGE_SELECT),
485 STRING_TOKEN (STR_LANGUAGE_SELECT_HELP),
486 EFI_IFR_FLAG_CALLBACK,
487 EFI_IFR_NUMERIC_SIZE_1,
488 OptionsOpCodeHandle,
489 NULL
490 );
491
492 Status = HiiUpdateForm (
493 HiiHandle,
494 &gFrontPageFormSetGuid,
495 FRONT_PAGE_FORM_ID,
496 StartOpCodeHandle, // LABEL_SELECT_LANGUAGE
497 EndOpCodeHandle // LABEL_END
498 );
499
500 HiiFreeOpCodeHandle (StartOpCodeHandle);
501 HiiFreeOpCodeHandle (EndOpCodeHandle);
502 HiiFreeOpCodeHandle (OptionsOpCodeHandle);
503 return Status;
504 }
505
506 /**
507 Call the browser and display the front page
508
509 @return Status code that will be returned by
510 EFI_FORM_BROWSER2_PROTOCOL.SendForm ().
511
512 **/
513 EFI_STATUS
514 CallFrontPage (
515 VOID
516 )
517 {
518 EFI_STATUS Status;
519 EFI_BROWSER_ACTION_REQUEST ActionRequest;
520
521 //
522 // Begin waiting for USER INPUT
523 //
524 REPORT_STATUS_CODE (
525 EFI_PROGRESS_CODE,
526 (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT)
527 );
528
529 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
530 Status = gFormBrowser2->SendForm (
531 gFormBrowser2,
532 &gFrontPagePrivate.HiiHandle,
533 1,
534 &gFrontPageFormSetGuid,
535 0,
536 NULL,
537 &ActionRequest
538 );
539 //
540 // Check whether user change any option setting which needs a reset to be effective
541 //
542 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
543 EnableResetRequired ();
544 }
545
546 return Status;
547 }
548
549 /**
550 Acquire the string associated with the ProducerGuid and return it.
551
552
553 @param ProducerGuid The Guid to search the HII database for
554 @param Token The token value of the string to extract
555 @param String The string that is extracted
556
557 @retval EFI_SUCCESS The function returns EFI_SUCCESS always.
558
559 **/
560 EFI_STATUS
561 GetProducerString (
562 IN EFI_GUID *ProducerGuid,
563 IN EFI_STRING_ID Token,
564 OUT CHAR16 **String
565 )
566 {
567 EFI_STRING TmpString;
568
569 TmpString = HiiGetPackageString (ProducerGuid, Token, NULL);
570 if (TmpString == NULL) {
571 *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));
572 } else {
573 *String = TmpString;
574 }
575
576 return EFI_SUCCESS;
577 }
578
579 /**
580 Convert Processor Frequency Data to a string.
581
582 @param ProcessorFrequency The frequency data to process
583 @param Base10Exponent The exponent based on 10
584 @param String The string that is created
585
586 **/
587 VOID
588 ConvertProcessorToString (
589 IN UINT16 ProcessorFrequency,
590 IN UINT16 Base10Exponent,
591 OUT CHAR16 **String
592 )
593 {
594 CHAR16 *StringBuffer;
595 UINTN Index;
596 UINT32 FreqMhz;
597
598 if (Base10Exponent >= 6) {
599 FreqMhz = ProcessorFrequency;
600 for (Index = 0; Index < (UINTN) (Base10Exponent - 6); Index++) {
601 FreqMhz *= 10;
602 }
603 } else {
604 FreqMhz = 0;
605 }
606
607 StringBuffer = AllocateZeroPool (0x20);
608 ASSERT (StringBuffer != NULL);
609 Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3);
610 StrCat (StringBuffer, L".");
611 UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2);
612 StrCat (StringBuffer, L" GHz");
613 *String = (CHAR16 *) StringBuffer;
614 return ;
615 }
616
617
618 /**
619 Convert Memory Size to a string.
620
621 @param MemorySize The size of the memory to process
622 @param String The string that is created
623
624 **/
625 VOID
626 ConvertMemorySizeToString (
627 IN UINT32 MemorySize,
628 OUT CHAR16 **String
629 )
630 {
631 CHAR16 *StringBuffer;
632
633 StringBuffer = AllocateZeroPool (0x20);
634 ASSERT (StringBuffer != NULL);
635 UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 6);
636 StrCat (StringBuffer, L" MB RAM");
637
638 *String = (CHAR16 *) StringBuffer;
639
640 return ;
641 }
642
643 /**
644
645 Acquire the string associated with the Index from smbios structure and return it.
646 The caller is responsible for free the string buffer.
647
648 @param OptionalStrStart The start position to search the string
649 @param Index The index of the string to extract
650 @param String The string that is extracted
651
652 @retval EFI_SUCCESS The function returns EFI_SUCCESS always.
653
654 **/
655 EFI_STATUS
656 GetOptionalStringByIndex (
657 IN CHAR8 *OptionalStrStart,
658 IN UINT8 Index,
659 OUT CHAR16 **String
660 )
661 {
662 UINTN StrSize;
663
664 if (Index == 0) {
665 *String = AllocateZeroPool (sizeof (CHAR16));
666 return EFI_SUCCESS;
667 }
668
669 StrSize = 0;
670 do {
671 Index--;
672 OptionalStrStart += StrSize;
673 StrSize = AsciiStrSize (OptionalStrStart);
674 } while (OptionalStrStart[StrSize] != 0 && Index != 0);
675
676 if ((Index != 0) || (StrSize == 1)) {
677 //
678 // Meet the end of strings set but Index is non-zero, or
679 // Find an empty string
680 //
681 *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));
682 } else {
683 *String = AllocatePool (StrSize * sizeof (CHAR16));
684 AsciiStrToUnicodeStr (OptionalStrStart, *String);
685 }
686
687 return EFI_SUCCESS;
688 }
689
690
691 /**
692 Update the banner information for the Front Page based on DataHub information.
693
694 **/
695 VOID
696 UpdateFrontPageStrings (
697 VOID
698 )
699 {
700 UINT8 StrIndex;
701 CHAR16 *NewString;
702 BOOLEAN Find[5];
703 EFI_STATUS Status;
704 EFI_STRING_ID TokenToUpdate;
705 EFI_SMBIOS_HANDLE SmbiosHandle;
706 EFI_SMBIOS_PROTOCOL *Smbios;
707 SMBIOS_TABLE_TYPE0 *Type0Record;
708 SMBIOS_TABLE_TYPE1 *Type1Record;
709 SMBIOS_TABLE_TYPE4 *Type4Record;
710 SMBIOS_TABLE_TYPE19 *Type19Record;
711 EFI_SMBIOS_TABLE_HEADER *Record;
712
713 ZeroMem (Find, sizeof (Find));
714
715 //
716 // Update Front Page strings
717 //
718 Status = gBS->LocateProtocol (
719 &gEfiSmbiosProtocolGuid,
720 NULL,
721 (VOID **) &Smbios
722 );
723 ASSERT_EFI_ERROR (Status);
724
725 SmbiosHandle = 0;
726 do {
727 Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
728 if (EFI_ERROR(Status)) {
729 break;
730 }
731
732 if (Record->Type == EFI_SMBIOS_TYPE_BIOS_INFORMATION) {
733 Type0Record = (SMBIOS_TABLE_TYPE0 *) Record;
734 StrIndex = Type0Record->BiosVersion;
735 GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &NewString);
736 TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION);
737 HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
738 FreePool (NewString);
739 Find[0] = TRUE;
740 }
741
742 if (Record->Type == EFI_SMBIOS_TYPE_SYSTEM_INFORMATION) {
743 Type1Record = (SMBIOS_TABLE_TYPE1 *) Record;
744 StrIndex = Type1Record->ProductName;
745 GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type1Record + Type1Record->Hdr.Length), StrIndex, &NewString);
746 TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL);
747 HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
748 FreePool (NewString);
749 Find[1] = TRUE;
750 }
751
752 if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) {
753 Type4Record = (SMBIOS_TABLE_TYPE4 *) Record;
754 StrIndex = Type4Record->ProcessorVersion;
755 GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type4Record + Type4Record->Hdr.Length), StrIndex, &NewString);
756 TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL);
757 HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
758 FreePool (NewString);
759 Find[2] = TRUE;
760 }
761
762 if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) {
763 Type4Record = (SMBIOS_TABLE_TYPE4 *) Record;
764 ConvertProcessorToString(Type4Record->CurrentSpeed, 6, &NewString);
765 TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED);
766 HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
767 FreePool (NewString);
768 Find[3] = TRUE;
769 }
770
771 if ( Record->Type == EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS ) {
772 Type19Record = (SMBIOS_TABLE_TYPE19 *) Record;
773 ConvertMemorySizeToString (
774 (UINT32)(RShiftU64((Type19Record->EndingAddress - Type19Record->StartingAddress + 1), 10)),
775 &NewString
776 );
777 TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE);
778 HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
779 FreePool (NewString);
780 Find[4] = TRUE;
781 }
782 } while ( !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4]));
783 return ;
784 }
785
786
787 /**
788 Function waits for a given event to fire, or for an optional timeout to expire.
789
790 @param Event The event to wait for
791 @param Timeout An optional timeout value in 100 ns units.
792
793 @retval EFI_SUCCESS Event fired before Timeout expired.
794 @retval EFI_TIME_OUT Timout expired before Event fired..
795
796 **/
797 EFI_STATUS
798 WaitForSingleEvent (
799 IN EFI_EVENT Event,
800 IN UINT64 Timeout OPTIONAL
801 )
802 {
803 UINTN Index;
804 EFI_STATUS Status;
805 EFI_EVENT TimerEvent;
806 EFI_EVENT WaitList[2];
807
808 if (Timeout != 0) {
809 //
810 // Create a timer event
811 //
812 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
813 if (!EFI_ERROR (Status)) {
814 //
815 // Set the timer event
816 //
817 gBS->SetTimer (
818 TimerEvent,
819 TimerRelative,
820 Timeout
821 );
822
823 //
824 // Wait for the original event or the timer
825 //
826 WaitList[0] = Event;
827 WaitList[1] = TimerEvent;
828 Status = gBS->WaitForEvent (2, WaitList, &Index);
829 gBS->CloseEvent (TimerEvent);
830
831 //
832 // If the timer expired, change the return to timed out
833 //
834 if (!EFI_ERROR (Status) && Index == 1) {
835 Status = EFI_TIMEOUT;
836 }
837 }
838 } else {
839 //
840 // No timeout... just wait on the event
841 //
842 Status = gBS->WaitForEvent (1, &Event, &Index);
843 ASSERT (!EFI_ERROR (Status));
844 ASSERT (Index == 0);
845 }
846
847 return Status;
848 }
849
850 /**
851 Function show progress bar to wait for user input.
852
853
854 @param TimeoutDefault The fault time out value before the system continue to boot.
855
856 @retval EFI_SUCCESS User pressed some key except "Enter"
857 @retval EFI_TIME_OUT Timeout expired or user press "Enter"
858
859 **/
860 EFI_STATUS
861 ShowProgress (
862 IN UINT16 TimeoutDefault
863 )
864 {
865 CHAR16 *TmpStr;
866 UINT16 TimeoutRemain;
867 EFI_STATUS Status;
868 EFI_INPUT_KEY Key;
869 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
870 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
871 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
872
873 if (TimeoutDefault == 0) {
874 return EFI_TIMEOUT;
875 }
876
877 DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it! ...Zzz....\n"));
878
879 SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
880 SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
881 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
882
883 //
884 // Clear the progress status bar first
885 //
886 TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));
887 if (TmpStr != NULL) {
888 PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);
889 }
890
891 TimeoutRemain = TimeoutDefault;
892 while (TimeoutRemain != 0) {
893 DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain));
894
895 Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);
896 if (Status != EFI_TIMEOUT) {
897 break;
898 }
899 TimeoutRemain--;
900
901 //
902 // Show progress
903 //
904 if (TmpStr != NULL) {
905 PlatformBdsShowProgress (
906 Foreground,
907 Background,
908 TmpStr,
909 Color,
910 ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),
911 0
912 );
913 }
914 }
915 gBS->FreePool (TmpStr);
916
917 //
918 // Timeout expired
919 //
920 if (TimeoutRemain == 0) {
921 return EFI_TIMEOUT;
922 }
923
924 //
925 // User pressed some key
926 //
927 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
928 if (EFI_ERROR (Status)) {
929 return Status;
930 }
931
932 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
933 //
934 // User pressed enter, equivalent to select "continue"
935 //
936 return EFI_TIMEOUT;
937 }
938
939 return EFI_SUCCESS;
940 }
941
942 /**
943 This function will change video resolution and text mode for setup when setup is launched.
944
945 @param None.
946
947 @retval EFI_SUCCESS Mode is changed successfully.
948 @retval Others Mode failed to changed.
949
950 **/
951 EFI_STATUS
952 EFIAPI
953 ChangeModeForSetup (
954 VOID
955 )
956 {
957 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
958 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
959 UINTN SizeOfInfo;
960 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
961 UINT32 MaxGopMode;
962 UINT32 MaxTextMode;
963 UINT32 ModeNumber;
964 UINT32 SetupTextModeColumn;
965 UINT32 SetupTextModeRow;
966 UINT32 SetupHorizontalResolution;
967 UINT32 SetupVerticalResolution;
968 UINTN HandleCount;
969 EFI_HANDLE *HandleBuffer;
970 EFI_STATUS Status;
971 UINTN Index;
972 UINTN CurrentColumn;
973 UINTN CurrentRow;
974
975 Status = gBS->HandleProtocol (
976 gST->ConsoleOutHandle,
977 &gEfiGraphicsOutputProtocolGuid,
978 (VOID**)&GraphicsOutput
979 );
980 if (EFI_ERROR (Status)) {
981 GraphicsOutput = NULL;
982 }
983
984 Status = gBS->HandleProtocol (
985 gST->ConsoleOutHandle,
986 &gEfiSimpleTextOutProtocolGuid,
987 (VOID**)&SimpleTextOut
988 );
989 if (EFI_ERROR (Status)) {
990 SimpleTextOut = NULL;
991 }
992
993 if ((GraphicsOutput == NULL) && (SimpleTextOut == NULL)) {
994 return EFI_UNSUPPORTED;
995 }
996
997 //
998 // Get user defined text mode for setup.
999 //
1000 SetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
1001 SetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution);
1002 SetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn);
1003 SetupTextModeRow = PcdGet32 (PcdSetupConOutRow);
1004
1005 MaxGopMode = GraphicsOutput->Mode->MaxMode;
1006 MaxTextMode = SimpleTextOut->Mode->MaxMode;
1007
1008 //
1009 // 1. If current video resolution is same with setup video resolution,
1010 // video resolution need not be changed.
1011 // 1.1. If current text mode is same with setup text mode, text mode need not be changed.
1012 // 1.2. If current text mode is different with setup text mode, text mode need be changed to setup text mode.
1013 // 2. If current video resolution is different with setup video resolution, we need restart whole console drivers.
1014 //
1015 for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {
1016 Status = GraphicsOutput->QueryMode (
1017 GraphicsOutput,
1018 ModeNumber,
1019 &SizeOfInfo,
1020 &Info
1021 );
1022 if (!EFI_ERROR (Status)) {
1023 if ((Info->HorizontalResolution == SetupHorizontalResolution) &&
1024 (Info->VerticalResolution == SetupVerticalResolution)) {
1025 if ((GraphicsOutput->Mode->Info->HorizontalResolution == SetupHorizontalResolution) &&
1026 (GraphicsOutput->Mode->Info->VerticalResolution == SetupVerticalResolution)) {
1027 //
1028 // If current video resolution is same with setup video resolution,
1029 // then check if current text mode is same with setup text mode.
1030 //
1031 Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);
1032 ASSERT_EFI_ERROR (Status);
1033 if (CurrentColumn == SetupTextModeColumn && CurrentRow == SetupTextModeRow) {
1034 //
1035 // Current text mode is same with setup text mode, text mode need not be change.
1036 //
1037 FreePool (Info);
1038 return EFI_SUCCESS;
1039 } else {
1040 //
1041 // Current text mode is different with setup text mode, text mode need be change to new text mode.
1042 //
1043 for (Index = 0; Index < MaxTextMode; Index++) {
1044 Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);
1045 if (!EFI_ERROR(Status)) {
1046 if ((CurrentColumn == SetupTextModeColumn) && (CurrentRow == SetupTextModeRow)) {
1047 //
1048 // setup text mode is supported, set it.
1049 //
1050 Status = SimpleTextOut->SetMode (SimpleTextOut, Index);
1051 ASSERT_EFI_ERROR (Status);
1052 //
1053 // Update text mode PCD.
1054 //
1055 PcdSet32 (PcdConOutColumn, SetupTextModeColumn);
1056 PcdSet32 (PcdConOutRow, SetupTextModeRow);
1057 FreePool (Info);
1058 return EFI_SUCCESS;
1059 }
1060 }
1061 }
1062 if (Index == MaxTextMode) {
1063 //
1064 // If setup text mode is not supported, return error.
1065 //
1066 FreePool (Info);
1067 return EFI_UNSUPPORTED;
1068 }
1069 }
1070 } else {
1071 FreePool (Info);
1072 //
1073 // If current video resolution is not same with the setup video resolution, set new video resolution.
1074 // In this case, the drivers which produce simple text out need be restarted.
1075 //
1076 Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
1077 if (!EFI_ERROR (Status)) {
1078 //
1079 // Set PCD to restart GraphicsConsole and Consplitter to change video resolution
1080 // and produce new text mode based on new resolution.
1081 //
1082 PcdSet32 (PcdVideoHorizontalResolution, SetupHorizontalResolution);
1083 PcdSet32 (PcdVideoVerticalResolution, SetupVerticalResolution);
1084 PcdSet32 (PcdConOutColumn, SetupTextModeColumn);
1085 PcdSet32 (PcdConOutRow, SetupTextModeRow);
1086
1087 Status = gBS->LocateHandleBuffer (
1088 ByProtocol,
1089 &gEfiSimpleTextOutProtocolGuid,
1090 NULL,
1091 &HandleCount,
1092 &HandleBuffer
1093 );
1094 if (!EFI_ERROR (Status)) {
1095 for (Index = 0; Index < HandleCount; Index++) {
1096 gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
1097 }
1098 for (Index = 0; Index < HandleCount; Index++) {
1099 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
1100 }
1101 if (HandleBuffer != NULL) {
1102 FreePool (HandleBuffer);
1103 }
1104 break;
1105 }
1106 }
1107 }
1108 }
1109 FreePool (Info);
1110 }
1111 }
1112
1113 if (ModeNumber == MaxGopMode) {
1114 //
1115 // If the new resolution is not supported, return error.
1116 //
1117 return EFI_UNSUPPORTED;
1118 }
1119
1120 return EFI_SUCCESS;
1121 }
1122
1123 /**
1124 This function is the main entry of the platform setup entry.
1125 The function will present the main menu of the system setup,
1126 this is the platform reference part and can be customize.
1127
1128
1129 @param TimeoutDefault The fault time out value before the system
1130 continue to boot.
1131 @param ConnectAllHappened The indicater to check if the connect all have
1132 already happened.
1133
1134 **/
1135 VOID
1136 PlatformBdsEnterFrontPage (
1137 IN UINT16 TimeoutDefault,
1138 IN BOOLEAN ConnectAllHappened
1139 )
1140 {
1141 EFI_STATUS Status;
1142 EFI_BOOT_LOGO_PROTOCOL *BootLogo;
1143
1144 PERF_START (NULL, "BdsTimeOut", "BDS", 0);
1145 //
1146 // Indicate if we need connect all in the platform setup
1147 //
1148 if (ConnectAllHappened) {
1149 gConnectAllHappened = TRUE;
1150 }
1151
1152 HotkeyBoot ();
1153 if (TimeoutDefault != 0xffff) {
1154 Status = ShowProgress (TimeoutDefault);
1155 HotkeyBoot ();
1156
1157 //
1158 // Ensure screen is clear when switch Console from Graphics mode to Text mode
1159 //
1160 gST->ConOut->EnableCursor (gST->ConOut, TRUE);
1161 gST->ConOut->ClearScreen (gST->ConOut);
1162
1163 if (EFI_ERROR (Status)) {
1164 //
1165 // Timeout or user press enter to continue
1166 //
1167 goto Exit;
1168 }
1169 }
1170
1171 //
1172 // Boot Logo is corrupted, report it using Boot Logo protocol.
1173 //
1174 Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
1175 if (!EFI_ERROR (Status) && (BootLogo != NULL)) {
1176 BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);
1177 }
1178
1179 do {
1180 //
1181 // Set proper video resolution and text mode for setup
1182 //
1183 ChangeModeForSetup ();
1184
1185 InitializeFrontPage (FALSE);
1186
1187 //
1188 // Update Front Page strings
1189 //
1190 UpdateFrontPageStrings ();
1191
1192 gCallbackKey = 0;
1193 Status = CallFrontPage ();
1194
1195 //
1196 // If gCallbackKey is greater than 1 and less or equal to 5,
1197 // it will launch configuration utilities.
1198 // 2 = set language
1199 // 3 = boot manager
1200 // 4 = device manager
1201 // 5 = boot maintenance manager
1202 //
1203 if (gCallbackKey != 0) {
1204 REPORT_STATUS_CODE (
1205 EFI_PROGRESS_CODE,
1206 (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP)
1207 );
1208 }
1209 //
1210 // Based on the key that was set, we can determine what to do
1211 //
1212 switch (gCallbackKey) {
1213 //
1214 // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
1215 // describe to their customers in documentation how to find their setup information (namely
1216 // under the device manager and specific buckets)
1217 //
1218 // These entries consist of the Continue, Select language, Boot Manager, and Device Manager
1219 //
1220 case FRONT_PAGE_KEY_CONTINUE:
1221 //
1222 // User hit continue
1223 //
1224 break;
1225
1226 case FRONT_PAGE_KEY_LANGUAGE:
1227 //
1228 // User made a language setting change - display front page again
1229 //
1230 break;
1231
1232 case FRONT_PAGE_KEY_BOOT_MANAGER:
1233 //
1234 // User chose to run the Boot Manager
1235 //
1236 CallBootManager ();
1237 break;
1238
1239 case FRONT_PAGE_KEY_DEVICE_MANAGER:
1240 //
1241 // Display the Device Manager
1242 //
1243 do {
1244 CallDeviceManager ();
1245 } while (gCallbackKey == FRONT_PAGE_KEY_DEVICE_MANAGER);
1246 break;
1247
1248 case FRONT_PAGE_KEY_BOOT_MAINTAIN:
1249 //
1250 // Display the Boot Maintenance Manager
1251 //
1252 BdsStartBootMaint ();
1253 break;
1254 }
1255
1256 } while ((Status == EFI_SUCCESS) && (gCallbackKey != FRONT_PAGE_KEY_CONTINUE));
1257
1258 //
1259 //Will leave browser, check any reset required change is applied? if yes, reset system
1260 //
1261 SetupResetReminder ();
1262
1263 Exit:
1264 //
1265 // Automatically load current entry
1266 // Note: The following lines of code only execute when Auto boot
1267 // takes affect
1268 //
1269 PERF_END (NULL, "BdsTimeOut", "BDS", 0);
1270 }