]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c
Update HiiConfigAccess.ExtractConfig interface to support NULL request string and...
[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 - 2009, Intel Corporation. <BR>
5 All rights reserved. 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
19 EFI_GUID mFrontPageGuid = FRONT_PAGE_FORMSET_GUID;
20
21 BOOLEAN gConnectAllHappened = FALSE;
22 UINTN gCallbackKey;
23
24 EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2;
25
26 FRONT_PAGE_CALLBACK_DATA gFrontPagePrivate = {
27 FRONT_PAGE_CALLBACK_DATA_SIGNATURE,
28 NULL,
29 NULL,
30 NULL,
31 {
32 FakeExtractConfig,
33 FakeRouteConfig,
34 FrontPageCallback
35 }
36 };
37
38 HII_VENDOR_DEVICE_PATH mFrontPageHiiVendorDevicePath = {
39 {
40 {
41 HARDWARE_DEVICE_PATH,
42 HW_VENDOR_DP,
43 {
44 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
45 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
46 }
47 },
48 //
49 // {8E6D99EE-7531-48f8-8745-7F6144468FF2}
50 //
51 { 0x8e6d99ee, 0x7531, 0x48f8, { 0x87, 0x45, 0x7f, 0x61, 0x44, 0x46, 0x8f, 0xf2 } }
52 },
53 {
54 END_DEVICE_PATH_TYPE,
55 END_ENTIRE_DEVICE_PATH_SUBTYPE,
56 {
57 (UINT8) (END_DEVICE_PATH_LENGTH),
58 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
59 }
60 }
61 };
62
63 /**
64 This function allows a caller to extract the current configuration for one
65 or more named elements from the target driver.
66
67
68 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
69 @param Request A null-terminated Unicode string in <ConfigRequest> format.
70 @param Progress On return, points to a character in the Request string.
71 Points to the string's null terminator if request was successful.
72 Points to the most recent '&' before the first failing name/value
73 pair (or the beginning of the string if the failure is in the
74 first name/value pair) if the request was not successful.
75 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
76 has all values filled in for the names in the Request string.
77 String to be allocated by the called function.
78
79 @retval EFI_SUCCESS The Results is filled with the requested values.
80 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
81 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
82 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
83
84 **/
85 EFI_STATUS
86 EFIAPI
87 FakeExtractConfig (
88 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
89 IN CONST EFI_STRING Request,
90 OUT EFI_STRING *Progress,
91 OUT EFI_STRING *Results
92 )
93 {
94 if (Progress == NULL || Results == NULL) {
95 return EFI_INVALID_PARAMETER;
96 }
97 *Progress = Request;
98 return EFI_NOT_FOUND;
99 }
100
101 /**
102 This function processes the results of changes in configuration.
103
104
105 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
106 @param Configuration A null-terminated Unicode string in <ConfigResp> format.
107 @param Progress A pointer to a string filled in with the offset of the most
108 recent '&' before the first failing name/value pair (or the
109 beginning of the string if the failure is in the first
110 name/value pair) or the terminating NULL if all was successful.
111
112 @retval EFI_SUCCESS The Results is processed successfully.
113 @retval EFI_INVALID_PARAMETER Configuration is NULL.
114 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
115
116 **/
117 EFI_STATUS
118 EFIAPI
119 FakeRouteConfig (
120 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
121 IN CONST EFI_STRING Configuration,
122 OUT EFI_STRING *Progress
123 )
124 {
125 if (Configuration == NULL || Progress == NULL) {
126 return EFI_INVALID_PARAMETER;
127 }
128
129 *Progress = Configuration;
130 if (!HiiIsConfigHdrMatch (Configuration, &mBootMaintGuid, mBootMaintStorageName)
131 && !HiiIsConfigHdrMatch (Configuration, &mFileExplorerGuid, mFileExplorerStorageName)) {
132 return EFI_NOT_FOUND;
133 }
134
135 *Progress = Configuration + StrLen (Configuration);
136 return EFI_SUCCESS;
137 }
138
139 /**
140 This function processes the results of changes in configuration.
141
142
143 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
144 @param Action Specifies the type of action taken by the browser.
145 @param QuestionId A unique value which is sent to the original exporting driver
146 so that it can identify the type of data to expect.
147 @param Type The type of value for the question.
148 @param Value A pointer to the data being sent to the original exporting driver.
149 @param ActionRequest On return, points to the action requested by the callback function.
150
151 @retval EFI_SUCCESS The callback successfully handled the action.
152 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
153 @retval EFI_DEVICE_ERROR The variable could not be saved.
154 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.
155
156 **/
157 EFI_STATUS
158 EFIAPI
159 FrontPageCallback (
160 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
161 IN EFI_BROWSER_ACTION Action,
162 IN EFI_QUESTION_ID QuestionId,
163 IN UINT8 Type,
164 IN EFI_IFR_TYPE_VALUE *Value,
165 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
166 )
167 {
168 CHAR8 *LanguageString;
169 CHAR8 *LangCode;
170 CHAR8 *Lang;
171 UINTN Index;
172 EFI_STATUS Status;
173 CHAR8 *PlatformSupportedLanguages;
174 CHAR8 *BestLanguage;
175
176 if ((Value == NULL) || (ActionRequest == NULL)) {
177 return EFI_INVALID_PARAMETER;
178 }
179
180 gCallbackKey = QuestionId;
181
182 //
183 // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
184 // describe to their customers in documentation how to find their setup information (namely
185 // under the device manager and specific buckets)
186 //
187 switch (QuestionId) {
188 case FRONT_PAGE_KEY_CONTINUE:
189 //
190 // This is the continue - clear the screen and return an error to get out of FrontPage loop
191 //
192 break;
193
194 case FRONT_PAGE_KEY_LANGUAGE:
195 //
196 // Collect the languages from what our current Language support is based on our VFR
197 //
198 LanguageString = HiiGetSupportedLanguages (gFrontPagePrivate.HiiHandle);
199 ASSERT (LanguageString != NULL);
200 //
201 // Allocate working buffer for RFC 4646 language in supported LanguageString.
202 //
203 Lang = AllocatePool (AsciiStrSize (LanguageString));
204 ASSERT (Lang != NULL);
205
206 Index = 0;
207 LangCode = LanguageString;
208 while (*LangCode != 0) {
209 GetNextLanguage (&LangCode, Lang);
210
211 if (Index == Value->u8) {
212 break;
213 }
214
215 Index++;
216 }
217
218 PlatformSupportedLanguages = GetEfiGlobalVariable (L"PlatformLangCodes");
219 if (PlatformSupportedLanguages == NULL) {
220 PlatformSupportedLanguages = AllocateCopyPool (
221 AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)),
222 (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)
223 );
224 ASSERT (PlatformSupportedLanguages != NULL);
225 }
226
227 //
228 // Select the best language in platform supported Language.
229 //
230 BestLanguage = GetBestLanguage (
231 PlatformSupportedLanguages,
232 FALSE,
233 Lang,
234 NULL
235 );
236 if (BestLanguage != NULL) {
237 Status = gRT->SetVariable (
238 L"PlatformLang",
239 &gEfiGlobalVariableGuid,
240 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
241 AsciiStrSize (BestLanguage),
242 Lang
243 );
244 ASSERT_EFI_ERROR(Status);
245 FreePool (BestLanguage);
246 } else {
247 ASSERT (FALSE);
248 }
249
250 FreePool (PlatformSupportedLanguages);
251 FreePool (Lang);
252 FreePool (LanguageString);
253 break;
254
255 case FRONT_PAGE_KEY_BOOT_MANAGER:
256 //
257 // Boot Manager
258 //
259 break;
260
261 case FRONT_PAGE_KEY_DEVICE_MANAGER:
262 //
263 // Device Manager
264 //
265 break;
266
267 case FRONT_PAGE_KEY_BOOT_MAINTAIN:
268 //
269 // Boot Maintenance Manager
270 //
271 break;
272
273 default:
274 gCallbackKey = 0;
275 break;
276 }
277
278 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
279
280 return EFI_SUCCESS;
281 }
282
283 /**
284 Initialize HII information for the FrontPage
285
286
287 @param InitializeHiiData TRUE if HII elements need to be initialized.
288
289 @retval EFI_SUCCESS The operation is successful.
290 @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed.
291
292 **/
293 EFI_STATUS
294 InitializeFrontPage (
295 IN BOOLEAN InitializeHiiData
296 )
297 {
298 EFI_STATUS Status;
299 CHAR8 *LanguageString;
300 CHAR8 *LangCode;
301 CHAR8 *Lang;
302 CHAR8 *CurrentLang;
303 CHAR8 *BestLanguage;
304 UINTN OptionCount;
305 CHAR16 *StringBuffer;
306 EFI_HII_HANDLE HiiHandle;
307 VOID *OptionsOpCodeHandle;
308 VOID *StartOpCodeHandle;
309 VOID *EndOpCodeHandle;
310 EFI_IFR_GUID_LABEL *StartLabel;
311 EFI_IFR_GUID_LABEL *EndLabel;
312 BOOLEAN FirstFlag;
313 EFI_STRING_ID Temp;
314
315 if (InitializeHiiData) {
316 //
317 // Initialize the Device Manager
318 //
319 InitializeDeviceManager ();
320
321 //
322 // Initialize the Device Manager
323 //
324 InitializeBootManager ();
325
326 gCallbackKey = 0;
327
328 //
329 // Locate Hii relative protocols
330 //
331 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2);
332 if (EFI_ERROR (Status)) {
333 return Status;
334 }
335
336 //
337 // Install Device Path Protocol and Config Access protocol to driver handle
338 //
339 Status = gBS->InstallMultipleProtocolInterfaces (
340 &gFrontPagePrivate.DriverHandle,
341 &gEfiDevicePathProtocolGuid,
342 &mFrontPageHiiVendorDevicePath,
343 &gEfiHiiConfigAccessProtocolGuid,
344 &gFrontPagePrivate.ConfigAccess,
345 NULL
346 );
347 ASSERT_EFI_ERROR (Status);
348
349 //
350 // Publish our HII data
351 //
352 gFrontPagePrivate.HiiHandle = HiiAddPackages (
353 &mFrontPageGuid,
354 gFrontPagePrivate.DriverHandle,
355 FrontPageVfrBin,
356 BdsDxeStrings,
357 NULL
358 );
359 if (gFrontPagePrivate.HiiHandle == NULL) {
360 return EFI_OUT_OF_RESOURCES;
361 }
362 }
363
364
365 //
366 // Init OpCode Handle and Allocate space for creation of UpdateData Buffer
367 //
368 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
369 ASSERT (StartOpCodeHandle != NULL);
370
371 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
372 ASSERT (EndOpCodeHandle != NULL);
373
374 OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
375 ASSERT (OptionsOpCodeHandle != NULL);
376 //
377 // Create Hii Extend Label OpCode as the start opcode
378 //
379 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
380 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
381 StartLabel->Number = LABEL_SELECT_LANGUAGE;
382
383 //
384 // Create Hii Extend Label OpCode as the end opcode
385 //
386 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
387 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
388 EndLabel->Number = LABEL_END;
389
390 //
391 // Collect the languages from what our current Language support is based on our VFR
392 //
393 HiiHandle = gFrontPagePrivate.HiiHandle;
394 LanguageString = HiiGetSupportedLanguages (HiiHandle);
395 ASSERT (LanguageString != NULL);
396 //
397 // Allocate working buffer for RFC 4646 language in supported LanguageString.
398 //
399 Lang = AllocatePool (AsciiStrSize (LanguageString));
400 ASSERT (Lang != NULL);
401
402 CurrentLang = GetEfiGlobalVariable (L"PlatformLang");
403 //
404 // Select the best language in LanguageString as the default one.
405 //
406 BestLanguage = GetBestLanguage (
407 LanguageString,
408 FALSE,
409 (CurrentLang != NULL) ? CurrentLang : "",
410 (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang),
411 LanguageString,
412 NULL
413 );
414 //
415 // BestLanguage must be selected as it is the first language in LanguageString by default
416 //
417 ASSERT (BestLanguage != NULL);
418
419 OptionCount = 0;
420 LangCode = LanguageString;
421 FirstFlag = FALSE;
422
423 if (gFrontPagePrivate.LanguageToken == NULL) {
424 while (*LangCode != 0) {
425 GetNextLanguage (&LangCode, Lang);
426 OptionCount ++;
427 }
428 gFrontPagePrivate.LanguageToken = AllocatePool ((OptionCount + 1) * sizeof (EFI_STRING_ID));
429 ASSERT (gFrontPagePrivate.LanguageToken != NULL);
430 FirstFlag = TRUE;
431 }
432
433 Status = gHiiString->NewString (gHiiString, HiiHandle, &Temp, "de-DE", L"Dedede", L"TEST", NULL);
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_EFI_ERROR (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 &mFrontPageGuid,
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 &mFrontPageGuid,
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 UINT8 StrNum;
663 UINTN CurrentStrLen;
664 CHAR8* CharInStr;
665 EFI_STATUS Status;
666
667 StrNum = 0;
668 Status = EFI_NOT_FOUND;
669 CharInStr = OptionalStrStart;
670
671 if (Index != 1) {
672 CurrentStrLen = 0;
673 //
674 // look for the two consecutive zeros, check the string limit by the way.
675 //
676 while (*CharInStr != 0 || *(CharInStr+1) != 0) {
677 if (*CharInStr == 0) {
678 StrNum += 1;
679 CharInStr++;
680 }
681
682 if (StrNum == Index) {
683 Status = EFI_SUCCESS;
684 break;
685 }
686
687 CurrentStrLen = AsciiStrLen(CharInStr);
688
689 //
690 // forward the pointer
691 //
692 OptionalStrStart = CharInStr;
693 CharInStr += CurrentStrLen;
694 }
695
696 if (EFI_ERROR (Status)) {
697 *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));
698 return Status;
699 }
700 } else {
701 CurrentStrLen = AsciiStrLen(CharInStr);
702 }
703
704 *String = AllocatePool((CurrentStrLen + 1)*sizeof(CHAR16));
705 AsciiStrToUnicodeStr(OptionalStrStart, *String);
706
707 return EFI_SUCCESS;
708 }
709
710
711 /**
712 Update the banner information for the Front Page based on DataHub information.
713
714 **/
715 VOID
716 UpdateFrontPageStrings (
717 VOID
718 )
719 {
720 UINT8 StrIndex;
721 CHAR16 *NewString;
722 BOOLEAN Find[5];
723 EFI_STATUS Status;
724 EFI_STRING_ID TokenToUpdate;
725 EFI_SMBIOS_HANDLE SmbiosHandle;
726 EFI_SMBIOS_PROTOCOL *Smbios;
727 SMBIOS_TABLE_TYPE0 *Type0Record;
728 SMBIOS_TABLE_TYPE1 *Type1Record;
729 SMBIOS_TABLE_TYPE4 *Type4Record;
730 SMBIOS_TABLE_TYPE19 *Type19Record;
731 EFI_SMBIOS_TABLE_HEADER *Record;
732
733 ZeroMem (Find, sizeof (Find));
734
735 //
736 // Update Front Page strings
737 //
738 Status = gBS->LocateProtocol (
739 &gEfiSmbiosProtocolGuid,
740 NULL,
741 (VOID **) &Smbios
742 );
743 ASSERT_EFI_ERROR (Status);
744
745 SmbiosHandle = 0;
746 do {
747 Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
748 if (EFI_ERROR(Status)) {
749 break;
750 }
751
752 if (Record->Type == EFI_SMBIOS_TYPE_BIOS_INFORMATION) {
753 Type0Record = (SMBIOS_TABLE_TYPE0 *) Record;
754 StrIndex = Type0Record->BiosVersion;
755 GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &NewString);
756 TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION);
757 HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
758 FreePool (NewString);
759 Find[0] = TRUE;
760 }
761
762 if (Record->Type == EFI_SMBIOS_TYPE_SYSTEM_INFORMATION) {
763 Type1Record = (SMBIOS_TABLE_TYPE1 *) Record;
764 StrIndex = Type1Record->ProductName;
765 GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type1Record + Type1Record->Hdr.Length), StrIndex, &NewString);
766 TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL);
767 HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
768 FreePool (NewString);
769 Find[1] = TRUE;
770 }
771
772 if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) {
773 Type4Record = (SMBIOS_TABLE_TYPE4 *) Record;
774 StrIndex = Type4Record->ProcessorVersion;
775 GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type4Record + Type4Record->Hdr.Length), StrIndex, &NewString);
776 TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL);
777 HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
778 FreePool (NewString);
779 Find[2] = TRUE;
780 }
781
782 if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) {
783 Type4Record = (SMBIOS_TABLE_TYPE4 *) Record;
784 ConvertProcessorToString(Type4Record->CurrentSpeed, 6, &NewString);
785 TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED);
786 HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
787 FreePool (NewString);
788 Find[3] = TRUE;
789 }
790
791 if ( Record->Type == EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS ) {
792 Type19Record = (SMBIOS_TABLE_TYPE19 *) Record;
793 ConvertMemorySizeToString (
794 (UINT32)(RShiftU64((Type19Record->EndingAddress - Type19Record->StartingAddress + 1), 10)),
795 &NewString
796 );
797 TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE);
798 HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
799 FreePool (NewString);
800 Find[4] = TRUE;
801 }
802 } while ( !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4]));
803 return ;
804 }
805
806
807 /**
808 Function waits for a given event to fire, or for an optional timeout to expire.
809
810 @param Event The event to wait for
811 @param Timeout An optional timeout value in 100 ns units.
812
813 @retval EFI_SUCCESS Event fired before Timeout expired.
814 @retval EFI_TIME_OUT Timout expired before Event fired..
815
816 **/
817 EFI_STATUS
818 WaitForSingleEvent (
819 IN EFI_EVENT Event,
820 IN UINT64 Timeout OPTIONAL
821 )
822 {
823 UINTN Index;
824 EFI_STATUS Status;
825 EFI_EVENT TimerEvent;
826 EFI_EVENT WaitList[2];
827
828 if (Timeout != 0) {
829 //
830 // Create a timer event
831 //
832 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
833 if (!EFI_ERROR (Status)) {
834 //
835 // Set the timer event
836 //
837 gBS->SetTimer (
838 TimerEvent,
839 TimerRelative,
840 Timeout
841 );
842
843 //
844 // Wait for the original event or the timer
845 //
846 WaitList[0] = Event;
847 WaitList[1] = TimerEvent;
848 Status = gBS->WaitForEvent (2, WaitList, &Index);
849 gBS->CloseEvent (TimerEvent);
850
851 //
852 // If the timer expired, change the return to timed out
853 //
854 if (!EFI_ERROR (Status) && Index == 1) {
855 Status = EFI_TIMEOUT;
856 }
857 }
858 } else {
859 //
860 // No timeout... just wait on the event
861 //
862 Status = gBS->WaitForEvent (1, &Event, &Index);
863 ASSERT (!EFI_ERROR (Status));
864 ASSERT (Index == 0);
865 }
866
867 return Status;
868 }
869
870 /**
871 Function show progress bar to wait for user input.
872
873
874 @param TimeoutDefault The fault time out value before the system continue to boot.
875
876 @retval EFI_SUCCESS User pressed some key except "Enter"
877 @retval EFI_TIME_OUT Timeout expired or user press "Enter"
878
879 **/
880 EFI_STATUS
881 ShowProgress (
882 IN UINT16 TimeoutDefault
883 )
884 {
885 CHAR16 *TmpStr;
886 UINT16 TimeoutRemain;
887 EFI_STATUS Status;
888 EFI_INPUT_KEY Key;
889 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
890 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
891 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
892
893 if (TimeoutDefault == 0) {
894 return EFI_TIMEOUT;
895 }
896
897 DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it! ...Zzz....\n"));
898
899 SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
900 SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
901 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
902
903 //
904 // Clear the progress status bar first
905 //
906 TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));
907 if (TmpStr != NULL) {
908 PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);
909 }
910
911 TimeoutRemain = TimeoutDefault;
912 while (TimeoutRemain != 0) {
913 DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain));
914
915 Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);
916 if (Status != EFI_TIMEOUT) {
917 break;
918 }
919 TimeoutRemain--;
920
921 //
922 // Show progress
923 //
924 if (TmpStr != NULL) {
925 PlatformBdsShowProgress (
926 Foreground,
927 Background,
928 TmpStr,
929 Color,
930 ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),
931 0
932 );
933 }
934 }
935 gBS->FreePool (TmpStr);
936
937 //
938 // Timeout expired
939 //
940 if (TimeoutRemain == 0) {
941 return EFI_TIMEOUT;
942 }
943
944 //
945 // User pressed some key
946 //
947 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
948 if (EFI_ERROR (Status)) {
949 return Status;
950 }
951
952 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
953 //
954 // User pressed enter, equivalent to select "continue"
955 //
956 return EFI_TIMEOUT;
957 }
958
959 return EFI_SUCCESS;
960 }
961
962 /**
963 This function is the main entry of the platform setup entry.
964 The function will present the main menu of the system setup,
965 this is the platform reference part and can be customize.
966
967
968 @param TimeoutDefault The fault time out value before the system
969 continue to boot.
970 @param ConnectAllHappened The indicater to check if the connect all have
971 already happened.
972
973 **/
974 VOID
975 PlatformBdsEnterFrontPage (
976 IN UINT16 TimeoutDefault,
977 IN BOOLEAN ConnectAllHappened
978 )
979 {
980 EFI_STATUS Status;
981
982 PERF_START (NULL, "BdsTimeOut", "BDS", 0);
983 //
984 // Indicate if we need connect all in the platform setup
985 //
986 if (ConnectAllHappened) {
987 gConnectAllHappened = TRUE;
988 }
989
990 if (TimeoutDefault != 0xffff) {
991 Status = ShowProgress (TimeoutDefault);
992
993 //
994 // Ensure screen is clear when switch Console from Graphics mode to Text mode
995 //
996 gST->ConOut->EnableCursor (gST->ConOut, TRUE);
997 gST->ConOut->ClearScreen (gST->ConOut);
998
999 if (EFI_ERROR (Status)) {
1000 //
1001 // Timeout or user press enter to continue
1002 //
1003 goto Exit;
1004 }
1005 }
1006
1007 do {
1008
1009 InitializeFrontPage (FALSE);
1010
1011 //
1012 // Update Front Page strings
1013 //
1014 UpdateFrontPageStrings ();
1015
1016 gCallbackKey = 0;
1017 Status = CallFrontPage ();
1018
1019 //
1020 // If gCallbackKey is greater than 1 and less or equal to 5,
1021 // it will launch configuration utilities.
1022 // 2 = set language
1023 // 3 = boot manager
1024 // 4 = device manager
1025 // 5 = boot maintenance manager
1026 //
1027 if (gCallbackKey != 0) {
1028 REPORT_STATUS_CODE (
1029 EFI_PROGRESS_CODE,
1030 (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP)
1031 );
1032 }
1033 //
1034 // Based on the key that was set, we can determine what to do
1035 //
1036 switch (gCallbackKey) {
1037 //
1038 // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
1039 // describe to their customers in documentation how to find their setup information (namely
1040 // under the device manager and specific buckets)
1041 //
1042 // These entries consist of the Continue, Select language, Boot Manager, and Device Manager
1043 //
1044 case FRONT_PAGE_KEY_CONTINUE:
1045 //
1046 // User hit continue
1047 //
1048 break;
1049
1050 case FRONT_PAGE_KEY_LANGUAGE:
1051 //
1052 // User made a language setting change - display front page again
1053 //
1054 break;
1055
1056 case FRONT_PAGE_KEY_BOOT_MANAGER:
1057 //
1058 // User chose to run the Boot Manager
1059 //
1060 CallBootManager ();
1061 break;
1062
1063 case FRONT_PAGE_KEY_DEVICE_MANAGER:
1064 //
1065 // Display the Device Manager
1066 //
1067 do {
1068 CallDeviceManager ();
1069 } while (gCallbackKey == FRONT_PAGE_KEY_DEVICE_MANAGER);
1070 break;
1071
1072 case FRONT_PAGE_KEY_BOOT_MAINTAIN:
1073 //
1074 // Display the Boot Maintenance Manager
1075 //
1076 BdsStartBootMaint ();
1077 break;
1078 }
1079
1080 } while ((Status == EFI_SUCCESS) && (gCallbackKey != FRONT_PAGE_KEY_CONTINUE));
1081
1082 //
1083 //Will leave browser, check any reset required change is applied? if yes, reset system
1084 //
1085 SetupResetReminder ();
1086
1087 Exit:
1088 //
1089 // Automatically load current entry
1090 // Note: The following lines of code only execute when Auto boot
1091 // takes affect
1092 //
1093 PERF_END (NULL, "BdsTimeOut", "BDS", 0);
1094 }