3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 FrontPage routines to handle the callbacks and browser calls
23 #include "BdsPlatform.h"
24 #include "FrontPage.h"
27 EFI_GUID mProcessorSubClass
= EFI_PROCESSOR_SUBCLASS_GUID
;
28 EFI_GUID mMemorySubClass
= EFI_MEMORY_SUBCLASS_GUID
;
29 EFI_GUID mMiscSubClass
= EFI_MISC_SUBCLASS_GUID
;
31 UINT16 mLastSelection
;
32 EFI_HII_HANDLE gFrontPageHandle
;
33 EFI_HANDLE FrontPageCallbackHandle
;
34 EFI_FORM_CALLBACK_PROTOCOL FrontPageCallback
;
35 EFI_FORM_BROWSER_PROTOCOL
*gBrowser
;
37 BOOLEAN gConnectAllHappened
= FALSE
;
39 extern EFI_HII_HANDLE gFrontPageHandle
;
40 extern EFI_GUID gBdsStringPackGuid
;
44 FrontPageCallbackRoutine (
45 IN EFI_FORM_CALLBACK_PROTOCOL
*This
,
47 IN EFI_IFR_DATA_ARRAY
*DataArray
,
48 OUT EFI_HII_CALLBACK_PACKET
**Packet
54 This is the function that is called to provide results data to the driver. This data
55 consists of a unique key which is used to identify what data is either being passed back
60 KeyValue - A unique value which is sent to the original exporting driver so that it
61 can identify the type of data to expect. The format of the data tends to
62 vary based on the op-code that geerated the callback.
64 Data - A pointer to the data being sent to the original exporting driver.
70 CHAR16
*LanguageString
;
72 CHAR16 UnicodeLang
[3];
77 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
78 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
79 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color
;
81 SetMem (&Foreground
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
), 0xff);
82 SetMem (&Background
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
), 0x0);
83 SetMem (&Color
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
), 0xff);
88 // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
89 // describe to their customers in documentation how to find their setup information (namely
90 // under the device manager and specific buckets)
95 // This is the continue - clear the screen and return an error to get out of FrontPage loop
102 // Collect the languages from what our current Language support is based on our VFR
104 Hii
->GetPrimaryLanguages (Hii
, gFrontPageHandle
, &LanguageString
);
107 // Based on the DataArray->Data->Data value, we can determine
108 // which language was chosen by the user
110 for (Index
= 0; Count
!= (UINTN
) (((EFI_IFR_DATA_ENTRY
*) (DataArray
+ 1))->Data
); Index
+= 3) {
114 // Preserve the choice the user made
116 mLastSelection
= (UINT16
) Count
;
119 // The Language (in Unicode format) the user chose
121 CopyMem (UnicodeLang
, &LanguageString
[Index
], 6);
124 // Convert Unicode to ASCII (Since the ISO standard assumes ASCII equivalent abbreviations
125 // we can be safe in converting this Unicode stream to ASCII without any loss in meaning.
127 for (Index
= 0; Index
< 3; Index
++) {
128 Lang
[Index
] = (CHAR8
) UnicodeLang
[Index
];
131 Status
= gRT
->SetVariable (
133 &gEfiGlobalVariableGuid
,
134 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
139 gBS
->FreePool (LanguageString
);
159 // Boot Maintenance Manager
170 // FrontPage TimeOut Callback
172 TmpStr
= GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION
));
173 if (TmpStr
!= NULL
) {
174 PlatformBdsShowProgress (
179 (UINTN
) (((EFI_IFR_DATA_ENTRY
*) (DataArray
+1))->Data
),
182 gBS
->FreePool (TmpStr
);
195 InitializeFrontPage (
196 BOOLEAN ReInitializeStrings
202 Initialize HII information for the FrontPage
208 EFI_SUCCESS - The operation is successful.
209 EFI_DEVICE_ERROR - If the dynamic opcode creation failed.
214 EFI_HII_PACKAGES
*PackageList
;
215 EFI_HII_UPDATE_DATA
*UpdateData
;
216 IFR_OPTION
*OptionList
;
217 CHAR16
*LanguageString
;
223 CHAR16 UnicodeLang
[4];
225 CHAR16
*StringBuffer
;
232 if (ReInitializeStrings
) {
234 // BugBug: Dont' use a goto
239 // Go ahead and initialize the Device Manager
241 InitializeDeviceManager ();
244 // BugBug: if FrontPageVfrBin is generated by a tool, why are we patching it here
246 TempBuffer
= (UINT8
*) FrontPageVfrBin
;
247 TempBuffer
= TempBuffer
+ sizeof (EFI_HII_PACK_HEADER
);
248 TempBuffer
= (UINT8
*) &((EFI_IFR_FORM_SET
*) TempBuffer
)->NvDataSize
;
253 PackageList
= PreparePackages (1, &gBdsStringPackGuid
, FrontPageVfrBin
);
255 Status
= Hii
->NewPack (Hii
, PackageList
, &gFrontPageHandle
);
257 gBS
->FreePool (PackageList
);
260 // There will be only one FormConfig in the system
261 // If there is another out there, someone is trying to install us
262 // again. Fail that scenario.
264 Status
= gBS
->LocateProtocol (
265 &gEfiFormBrowserProtocolGuid
,
271 // This example does not implement worker functions
272 // for the NV accessor functions. Only a callback evaluator
274 FrontPageCallback
.NvRead
= NULL
;
275 FrontPageCallback
.NvWrite
= NULL
;
276 FrontPageCallback
.Callback
= FrontPageCallbackRoutine
;
279 // Install protocol interface
281 FrontPageCallbackHandle
= NULL
;
282 Status
= gBS
->InstallProtocolInterface (
283 &FrontPageCallbackHandle
,
284 &gEfiFormCallbackProtocolGuid
,
285 EFI_NATIVE_INTERFACE
,
288 ASSERT_EFI_ERROR (Status
);
292 // BugBug: This logic is in BdsInitLanguage. It should not be in two places!
295 Status
= gRT
->GetVariable (
297 &gEfiGlobalVariableGuid
,
303 for (Index
= 0; Index
< 3; Index
++) {
304 UnicodeLang
[Index
] = (CHAR16
) AsciiLang
[Index
];
310 // Allocate space for creation of UpdateData Buffer
312 UpdateData
= AllocateZeroPool (0x1000);
313 ASSERT (UpdateData
!= NULL
);
315 OptionList
= AllocateZeroPool (0x1000);
316 ASSERT (OptionList
!= NULL
);
319 // Flag update pending in FormSet
321 UpdateData
->FormSetUpdate
= TRUE
;
323 // Register CallbackHandle data for FormSet
325 UpdateData
->FormCallbackHandle
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) FrontPageCallbackHandle
;
326 UpdateData
->FormUpdate
= FALSE
;
327 UpdateData
->FormTitle
= 0;
328 UpdateData
->DataCount
= 1;
331 // Collect the languages from what our current Language support is based on our VFR
333 Hii
->GetPrimaryLanguages (Hii
, gFrontPageHandle
, &LanguageString
);
338 // Try for a 512 byte Buffer
343 // Allocate memory for our Form binary
345 StringBuffer
= AllocateZeroPool (BufferSize
);
346 ASSERT (StringBuffer
!= NULL
);
348 for (Index
= 0; LanguageString
[Index
] != 0; Index
+= 3) {
350 CopyMem (Lang
, &LanguageString
[Index
], 6);
353 if (!StrCmp (Lang
, UnicodeLang
)) {
354 mLastSelection
= (UINT16
) OptionCount
;
357 Status
= Hii
->GetString (Hii
, gStringPackHandle
, 1, TRUE
, Lang
, &BufferSize
, StringBuffer
);
358 Hii
->NewString (Hii
, NULL
, gStringPackHandle
, &Token
, StringBuffer
);
359 CopyMem (&OptionList
[OptionCount
].StringToken
, &Token
, sizeof (UINT16
));
360 CopyMem (&OptionList
[OptionCount
].Value
, &OptionCount
, sizeof (UINT16
));
362 CopyMem (&OptionList
[OptionCount
].Key
, &Key
, sizeof (UINT16
));
363 OptionList
[OptionCount
].Flags
= EFI_IFR_FLAG_INTERACTIVE
| EFI_IFR_FLAG_NV_ACCESS
;
367 gBS
->FreePool (LanguageString
);
369 if (ReInitializeStrings
) {
370 gBS
->FreePool (StringBuffer
);
371 gBS
->FreePool (OptionList
);
375 Status
= CreateOneOfOpCode (
376 FRONT_PAGE_QUESTION_ID
, // Question ID
377 FRONT_PAGE_DATA_WIDTH
, // Data Width
378 (STRING_REF
) STRING_TOKEN (STR_LANGUAGE_SELECT
), // Prompt Token
379 (STRING_REF
) STRING_TOKEN (STR_LANGUAGE_SELECT_HELP
), // Help Token
380 OptionList
, // List of Options
381 OptionCount
, // Number of Options
382 &UpdateData
->Data
// Data Buffer
386 // Assign the number of options and the oneof and endoneof op-codes to count
388 UpdateData
->DataCount
= (UINT8
) (OptionCount
+ 2);
390 Hii
->UpdateForm (Hii
, gFrontPageHandle
, (EFI_FORM_LABEL
) 0x0002, TRUE
, UpdateData
);
392 gBS
->FreePool (UpdateData
);
394 // gBS->FreePool (OptionList);
396 gBS
->FreePool (StringBuffer
);
408 Call the browser and display the front page
419 UINT8 FakeNvRamMap
[1];
420 BOOLEAN FrontPageMenuResetRequired
;
423 // Begin waiting for USER INPUT
427 (EFI_SOFTWARE_DXE_BS_DRIVER
| EFI_SW_PC_INPUT_WAIT
)
430 FakeNvRamMap
[0] = (UINT8
) mLastSelection
;
431 FrontPageMenuResetRequired
= FALSE
;
432 Status
= gBrowser
->SendForm (
434 TRUE
, // Use the database
435 &gFrontPageHandle
, // The HII Handle
438 FrontPageCallbackHandle
, // This is the handle that the interface to the callback was installed on
441 &FrontPageMenuResetRequired
444 // Check whether user change any option setting which needs a reset to be effective
446 if (FrontPageMenuResetRequired
) {
447 EnableResetRequired ();
450 Hii
->ResetStrings (Hii
, gFrontPageHandle
);
457 IN EFI_GUID
*ProducerGuid
,
465 Acquire the string associated with the ProducerGuid and return it.
469 ProducerGuid - The Guid to search the HII database for
470 Token - The token value of the string to extract
471 String - The string that is extracted
475 EFI_SUCCESS - The function returns EFI_SUCCESS always.
480 UINT16 HandleBufferLength
;
481 EFI_HII_HANDLE
*HiiHandleBuffer
;
482 UINTN StringBufferLength
;
483 UINTN NumberOfHiiHandles
;
488 HandleBufferLength
= 0x1000;
489 HiiHandleBuffer
= NULL
;
492 // Get all the Hii handles
494 HiiHandleBuffer
= AllocateZeroPool (HandleBufferLength
);
496 Status
= Hii
->FindHandles (Hii
, &HandleBufferLength
, HiiHandleBuffer
);
497 ASSERT_EFI_ERROR (Status
);
500 // Get the Hii Handle that matches the StructureNode->ProducerName
502 NumberOfHiiHandles
= HandleBufferLength
/ sizeof (EFI_HII_HANDLE
);
503 for (Index
= 0; Index
< NumberOfHiiHandles
; Index
++) {
505 Status
= ExtractDataFromHiiHandle (
506 HiiHandleBuffer
[Index
],
511 if (CompareGuid (ProducerGuid
, &HiiGuid
)) {
516 // Find the string based on the current language
518 StringBufferLength
= 0x100;
519 *String
= AllocateZeroPool (0x100);
520 Status
= Hii
->GetString (
522 HiiHandleBuffer
[Index
],
530 if (EFI_ERROR (Status
)) {
531 gBS
->FreePool (*String
);
532 *String
= GetStringById (STRING_TOKEN (STR_MISSING_STRING
));
535 gBS
->FreePool (HiiHandleBuffer
);
540 ConvertProcessorToString (
541 IN EFI_PROCESSOR_CORE_FREQUENCY_DATA
*ProcessorFrequency
,
548 Convert Processor Frequency Data to a string
552 ProcessorFrequency - The frequency data to process
553 String - The string that is created
559 CHAR16
*StringBuffer
;
563 if (ProcessorFrequency
->Exponent
>= 6) {
564 FreqMhz
= ProcessorFrequency
->Value
;
565 for (Index
= 0; Index
< (UINTN
) (ProcessorFrequency
->Exponent
- 6); Index
++) {
572 StringBuffer
= AllocateZeroPool (0x20);
573 ASSERT (StringBuffer
!= NULL
);
574 Index
= UnicodeValueToString (StringBuffer
, LEFT_JUSTIFY
, FreqMhz
/ 1000, 3);
575 StrCat (StringBuffer
, L
".");
576 UnicodeValueToString (StringBuffer
+ Index
+ 1, PREFIX_ZERO
, (FreqMhz
% 1000) / 10, 2);
577 StrCat (StringBuffer
, L
" GHz");
579 *String
= (CHAR16
*) StringBuffer
;
585 ConvertMemorySizeToString (
586 IN UINT32 MemorySize
,
593 Convert Memory Size to a string
597 MemorySize - The size of the memory to process
598 String - The string that is created
604 CHAR16
*StringBuffer
;
606 StringBuffer
= AllocateZeroPool (0x20);
607 ASSERT (StringBuffer
!= NULL
);
608 UnicodeValueToString (StringBuffer
, LEFT_JUSTIFY
, MemorySize
, 6);
609 StrCat (StringBuffer
, L
" MB RAM");
611 *String
= (CHAR16
*) StringBuffer
;
617 UpdateFrontPageStrings (
624 Update the banner information for the Front Page based on DataHub information
635 STRING_REF TokenToUpdate
;
637 UINT64 MonotonicCount
;
638 EFI_DATA_HUB_PROTOCOL
*DataHub
;
639 EFI_DATA_RECORD_HEADER
*Record
;
640 EFI_SUBCLASS_TYPE1_HEADER
*DataHeader
;
641 EFI_MISC_BIOS_VENDOR_DATA
*BiosVendor
;
642 EFI_MISC_SYSTEM_MANUFACTURER_DATA
*SystemManufacturer
;
643 EFI_PROCESSOR_VERSION_DATA
*ProcessorVersion
;
644 EFI_PROCESSOR_CORE_FREQUENCY_DATA
*ProcessorFrequency
;
645 EFI_MEMORY_ARRAY_START_ADDRESS_DATA
*MemoryArray
;
652 ZeroMem (Find
, sizeof (Find
));
655 // Update Front Page strings
657 Status
= gBS
->LocateProtocol (
658 &gEfiDataHubProtocolGuid
,
662 ASSERT_EFI_ERROR (Status
);
666 Status
= gRT
->GetVariable (
668 &gEfiGlobalVariableGuid
,
674 for (Index
= 0; Index
< 3; Index
++) {
675 Lang
[Index
] = (CHAR16
) LangCode
[Index
];
681 Status
= DataHub
->GetNextRecord (DataHub
, &MonotonicCount
, NULL
, &Record
);
682 if (Record
->DataRecordClass
== EFI_DATA_RECORD_CLASS_DATA
) {
683 DataHeader
= (EFI_SUBCLASS_TYPE1_HEADER
*) (Record
+ 1);
684 if (CompareGuid (&Record
->DataRecordGuid
, &mMiscSubClass
) &&
685 (DataHeader
->RecordType
== EFI_MISC_BIOS_VENDOR_RECORD_NUMBER
)
687 BiosVendor
= (EFI_MISC_BIOS_VENDOR_DATA
*) (DataHeader
+ 1);
688 GetStringFromToken (&Record
->ProducerName
, BiosVendor
->BiosVersion
, &NewString
);
689 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_BIOS_VERSION
;
690 Hii
->NewString (Hii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
691 gBS
->FreePool (NewString
);
695 if (CompareGuid (&Record
->DataRecordGuid
, &mMiscSubClass
) &&
696 (DataHeader
->RecordType
== EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER
)
698 SystemManufacturer
= (EFI_MISC_SYSTEM_MANUFACTURER_DATA
*) (DataHeader
+ 1);
699 GetStringFromToken (&Record
->ProducerName
, SystemManufacturer
->SystemProductName
, &NewString
);
700 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_COMPUTER_MODEL
;
701 Hii
->NewString (Hii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
702 gBS
->FreePool (NewString
);
706 if (CompareGuid (&Record
->DataRecordGuid
, &mProcessorSubClass
) &&
707 (DataHeader
->RecordType
== ProcessorVersionRecordType
)
709 ProcessorVersion
= (EFI_PROCESSOR_VERSION_DATA
*) (DataHeader
+ 1);
710 GetStringFromToken (&Record
->ProducerName
, *ProcessorVersion
, &NewString
);
711 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_CPU_MODEL
;
712 Hii
->NewString (Hii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
713 gBS
->FreePool (NewString
);
717 if (CompareGuid (&Record
->DataRecordGuid
, &mProcessorSubClass
) &&
718 (DataHeader
->RecordType
== ProcessorCoreFrequencyRecordType
)
720 ProcessorFrequency
= (EFI_PROCESSOR_CORE_FREQUENCY_DATA
*) (DataHeader
+ 1);
721 ConvertProcessorToString (ProcessorFrequency
, &NewString
);
722 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_CPU_SPEED
;
723 Hii
->NewString (Hii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
724 gBS
->FreePool (NewString
);
728 if (CompareGuid (&Record
->DataRecordGuid
, &mMemorySubClass
) &&
729 (DataHeader
->RecordType
== EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER
)
731 MemoryArray
= (EFI_MEMORY_ARRAY_START_ADDRESS_DATA
*) (DataHeader
+ 1);
732 ConvertMemorySizeToString((UINT32
)(RShiftU64((MemoryArray
->MemoryArrayEndAddress
-
733 MemoryArray
->MemoryArrayStartAddress
+ 1), 20)),
735 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_MEMORY_SIZE
;
736 Hii
->NewString (Hii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
737 gBS
->FreePool (NewString
);
741 } while (!EFI_ERROR (Status
) && (MonotonicCount
!= 0) && !(Find
[0] && Find
[1] && Find
[2] && Find
[3] && Find
[4]));
747 PlatformBdsEnterFrontPage (
748 IN UINT16 TimeoutDefault
,
749 IN BOOLEAN ConnectAllHappened
754 This function is the main entry of the platform setup entry.
755 The function will present the main menu of the system setup,
756 this is the platform reference part and can be customize.
759 TimeoutDefault - The fault time out value before the system
761 ConnectAllHappened - The indicater to check if the connect all have
770 EFI_HII_UPDATE_DATA
*UpdateData
;
771 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
774 // Indicate if we need connect all in the platform setup
776 if (ConnectAllHappened
) {
777 gConnectAllHappened
= TRUE
;
780 // Allocate space for creation of Buffer
782 UpdateData
= AllocateZeroPool (0x1000);
783 ASSERT (UpdateData
!= NULL
);
785 UpdateData
->FormSetUpdate
= FALSE
;
786 UpdateData
->FormCallbackHandle
= 0;
787 UpdateData
->FormUpdate
= FALSE
;
788 UpdateData
->FormTitle
= 0;
789 UpdateData
->DataCount
= 1;
792 // Remove Banner Op-code if any at this label
794 Hii
->UpdateForm (Hii
, gFrontPageHandle
, (EFI_FORM_LABEL
) 0xFFFF, FALSE
, UpdateData
);
797 // Create Banner Op-code which reflects correct timeout value
800 STRING_TOKEN (STR_TIME_OUT_PROMPT
),
802 (UINT8
) EFI_IFR_BANNER_TIMEOUT
,
807 // Add Banner Op-code at this label
809 Hii
->UpdateForm (Hii
, gFrontPageHandle
, (EFI_FORM_LABEL
) 0xFFFF, TRUE
, UpdateData
);
813 InitializeFrontPage (TRUE
);
816 // Update Front Page strings
818 UpdateFrontPageStrings ();
821 PERF_START (0, "BdsTimeOut", "BDS", 0);
822 Status
= CallFrontPage ();
823 PERF_END (0, "BdsTimeOut", "BDS", 0);
826 // If gCallbackKey is greater than 1 and less or equal to 5,
827 // it will lauch configuration utilities.
830 // 4 = device manager
831 // 5 = boot maintainenance manager
833 if ((gCallbackKey
> 0x0001) && (gCallbackKey
<= 0x0005)) {
836 (EFI_SOFTWARE_DXE_BS_DRIVER
| EFI_SW_PC_USER_SETUP
)
840 // Based on the key that was set, we can determine what to do
842 switch (gCallbackKey
) {
844 // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
845 // describe to their customers in documentation how to find their setup information (namely
846 // under the device manager and specific buckets)
848 // These entries consist of the Continue, Select language, Boot Manager, and Device Manager
858 // User made a language setting change - display front page again
864 // User chose to run the Boot Manager
871 // Display the Device Manager
875 } while (gCallbackKey
== 4);
880 // Display the Boot Maintenance Manager
882 BdsStartBootMaint ();
886 } while ((Status
== EFI_SUCCESS
) && (gCallbackKey
!= 1));
889 //Will leave browser, check any reset required change is applied? if yes, reset system
891 SetupResetReminder ();
894 // Automatically load current entry
895 // Note: The following lines of code only execute when Auto boot
898 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, &ConsoleControl
);
899 ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);