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