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