3 Copyright (c) 2006 - 2007, 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
22 #include "BdsPlatform.h"
23 #include "FrontPage.h"
24 #include "BdsString.h"
26 EFI_GUID mProcessorSubClass
= EFI_PROCESSOR_SUBCLASS_GUID
;
27 EFI_GUID mMemorySubClass
= EFI_MEMORY_SUBCLASS_GUID
;
28 EFI_GUID mMiscSubClass
= EFI_MISC_SUBCLASS_GUID
;
30 UINT16 mLastSelection
;
31 FRAMEWORK_EFI_HII_HANDLE gFrontPageHandle
;
32 EFI_HANDLE FrontPageCallbackHandle
;
33 EFI_FORM_CALLBACK_PROTOCOL FrontPageCallback
;
34 EFI_FORM_BROWSER_PROTOCOL
*gBrowser
;
36 BOOLEAN gConnectAllHappened
= FALSE
;
38 extern FRAMEWORK_EFI_HII_HANDLE gFrontPageHandle
;
42 FrontPageCallbackRoutine (
43 IN EFI_FORM_CALLBACK_PROTOCOL
*This
,
45 IN FRAMEWORK_EFI_IFR_DATA_ARRAY
*DataArray
,
46 OUT EFI_HII_CALLBACK_PACKET
**Packet
52 This is the function that is called to provide results data to the driver. This data
53 consists of a unique key which is used to identify what data is either being passed back
58 KeyValue - A unique value which is sent to the original exporting driver so that it
59 can identify the type of data to expect. The format of the data tends to
60 vary based on the op-code that geerated the callback.
62 Data - A pointer to the data being sent to the original exporting driver.
68 CHAR16
*LanguageString
;
70 CHAR16 UnicodeLang
[3];
75 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground
;
76 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
77 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color
;
79 SetMem (&Foreground
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
), 0xff);
80 SetMem (&Background
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
), 0x0);
81 SetMem (&Color
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
), 0xff);
86 // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
87 // describe to their customers in documentation how to find their setup information (namely
88 // under the device manager and specific buckets)
93 // This is the continue - clear the screen and return an error to get out of FrontPage loop
100 // Collect the languages from what our current Language support is based on our VFR
102 gHii
->GetPrimaryLanguages (gHii
, gFrontPageHandle
, &LanguageString
);
105 // Based on the DataArray->Data->Data value, we can determine
106 // which language was chosen by the user
108 for (Index
= 0; Count
!= (UINTN
) (((FRAMEWORK_EFI_IFR_DATA_ENTRY
*) (DataArray
+ 1))->Data
); Index
+= 3) {
112 // Preserve the choice the user made
114 mLastSelection
= (UINT16
) Count
;
117 // The Language (in Unicode format) the user chose
119 CopyMem (UnicodeLang
, &LanguageString
[Index
], 6);
122 // Convert Unicode to ASCII (Since the ISO standard assumes ASCII equivalent abbreviations
123 // we can be safe in converting this Unicode stream to ASCII without any loss in meaning.
125 for (Index
= 0; Index
< 3; Index
++) {
126 Lang
[Index
] = (CHAR8
) UnicodeLang
[Index
];
129 Status
= gRT
->SetVariable (
131 &gEfiGlobalVariableGuid
,
132 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
137 FreePool (LanguageString
);
157 // Boot Maintenance Manager
168 // FrontPage TimeOut Callback
170 TmpStr
= GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION
));
171 if (TmpStr
!= NULL
) {
172 PlatformBdsShowProgress (
177 (UINTN
) (((FRAMEWORK_EFI_IFR_DATA_ENTRY
*) (DataArray
+1))->Data
),
193 InitializeFrontPage (
194 BOOLEAN ReInitializeStrings
200 Initialize HII information for the FrontPage
206 EFI_SUCCESS - The operation is successful.
207 EFI_DEVICE_ERROR - If the dynamic opcode creation failed.
212 EFI_HII_PACKAGES
*PackageList
;
213 EFI_HII_UPDATE_DATA
*UpdateData
;
214 IFR_OPTION
*OptionList
;
215 CHAR16
*LanguageString
;
221 CHAR16 UnicodeLang
[4];
223 CHAR16
*StringBuffer
;
230 if (ReInitializeStrings
) {
232 // BugBug: Dont' use a goto
237 // Go ahead and initialize the Device Manager
239 InitializeDeviceManager ();
242 // BugBug: if FrontPageVfrBin is generated by a tool, why are we patching it here
244 TempBuffer
= (UINT8
*) FrontPageVfrBin
;
245 TempBuffer
= TempBuffer
+ sizeof (EFI_HII_PACK_HEADER
);
246 TempBuffer
= (UINT8
*) &((FRAMEWORK_EFI_IFR_FORM_SET
*) TempBuffer
)->NvDataSize
;
251 PackageList
= PreparePackages (1, &gEfiCallerIdGuid
, FrontPageVfrBin
);
253 Status
= gHii
->NewPack (gHii
, PackageList
, &gFrontPageHandle
);
255 FreePool (PackageList
);
258 // There will be only one FormConfig in the system
259 // If there is another out there, someone is trying to install us
260 // again. Fail that scenario.
262 Status
= gBS
->LocateProtocol (
263 &gEfiFormBrowserProtocolGuid
,
269 // This example does not implement worker functions
270 // for the NV accessor functions. Only a callback evaluator
272 FrontPageCallback
.NvRead
= NULL
;
273 FrontPageCallback
.NvWrite
= NULL
;
274 FrontPageCallback
.Callback
= FrontPageCallbackRoutine
;
277 // Install protocol interface
279 FrontPageCallbackHandle
= NULL
;
280 Status
= gBS
->InstallProtocolInterface (
281 &FrontPageCallbackHandle
,
282 &gEfiFormCallbackProtocolGuid
,
283 EFI_NATIVE_INTERFACE
,
286 ASSERT_EFI_ERROR (Status
);
290 // BugBug: This logic is in BdsInitLanguage. It should not be in two places!
293 Status
= gRT
->GetVariable (
295 &gEfiGlobalVariableGuid
,
301 for (Index
= 0; Index
< 3; Index
++) {
302 UnicodeLang
[Index
] = (CHAR16
) AsciiLang
[Index
];
308 // Allocate space for creation of UpdateData Buffer
310 UpdateData
= AllocateZeroPool (0x1000);
311 ASSERT (UpdateData
!= NULL
);
313 OptionList
= AllocateZeroPool (0x1000);
314 ASSERT (OptionList
!= NULL
);
317 // Flag update pending in FormSet
319 UpdateData
->FormSetUpdate
= TRUE
;
321 // Register CallbackHandle data for FormSet
323 UpdateData
->FormCallbackHandle
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) FrontPageCallbackHandle
;
324 UpdateData
->FormUpdate
= FALSE
;
325 UpdateData
->FormTitle
= 0;
326 UpdateData
->DataCount
= 1;
329 // Collect the languages from what our current Language support is based on our VFR
331 gHii
->GetPrimaryLanguages (gHii
, gFrontPageHandle
, &LanguageString
);
335 for (Index
= 0; LanguageString
[Index
] != 0; Index
+= 3) {
337 CopyMem (Lang
, &LanguageString
[Index
], 6);
340 if (!StrCmp (Lang
, UnicodeLang
)) {
341 mLastSelection
= (UINT16
) OptionCount
;
345 Status
= gHii
->GetString (gHii
, gStringPackHandle
, 1, TRUE
, Lang
, &BufferSize
, NULL
);
346 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
347 StringBuffer
= AllocateZeroPool (BufferSize
);
348 ASSERT (StringBuffer
!= NULL
);
349 Status
= gHii
->GetString (gHii
, gStringPackHandle
, 1, TRUE
, Lang
, &BufferSize
, StringBuffer
);
350 ASSERT_EFI_ERROR (Status
);
351 gHii
->NewString (gHii
, NULL
, gStringPackHandle
, &Token
, StringBuffer
);
352 FreePool (StringBuffer
);
353 CopyMem (&OptionList
[OptionCount
].StringToken
, &Token
, sizeof (UINT16
));
354 CopyMem (&OptionList
[OptionCount
].Value
, &OptionCount
, sizeof (UINT16
));
356 CopyMem (&OptionList
[OptionCount
].Key
, &Key
, sizeof (UINT16
));
357 OptionList
[OptionCount
].Flags
= FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE
| FRAMEWORK_EFI_IFR_FLAG_NV_ACCESS
;
361 FreePool (LanguageString
);
363 if (ReInitializeStrings
) {
364 FreePool (OptionList
);
368 Status
= CreateOneOfOpCode (
369 FRONT_PAGE_QUESTION_ID
, // Question ID
370 FRONT_PAGE_DATA_WIDTH
, // Data Width
371 (STRING_REF
) STRING_TOKEN (STR_LANGUAGE_SELECT
), // Prompt Token
372 (STRING_REF
) STRING_TOKEN (STR_LANGUAGE_SELECT_HELP
), // Help Token
373 OptionList
, // List of Options
374 OptionCount
, // Number of Options
375 &UpdateData
->Data
// Data Buffer
379 // Assign the number of options and the oneof and endoneof op-codes to count
381 UpdateData
->DataCount
= (UINT8
) (OptionCount
+ 2);
383 gHii
->UpdateForm (gHii
, gFrontPageHandle
, (EFI_FORM_LABEL
) 0x0002, TRUE
, UpdateData
);
385 FreePool (UpdateData
);
386 FreePool (OptionList
);
398 Call the browser and display the front page
409 UINT8 FakeNvRamMap
[1];
410 BOOLEAN FrontPageMenuResetRequired
;
413 // Begin waiting for USER INPUT
417 (EFI_SOFTWARE_DXE_BS_DRIVER
| EFI_SW_PC_INPUT_WAIT
)
420 FakeNvRamMap
[0] = (UINT8
) mLastSelection
;
421 FrontPageMenuResetRequired
= FALSE
;
422 Status
= gBrowser
->SendForm (
424 TRUE
, // Use the database
425 &gFrontPageHandle
, // The HII Handle
428 FrontPageCallbackHandle
, // This is the handle that the interface to the callback was installed on
431 &FrontPageMenuResetRequired
434 // Check whether user change any option setting which needs a reset to be effective
436 if (FrontPageMenuResetRequired
) {
437 EnableResetRequired ();
440 gHii
->ResetStrings (gHii
, gFrontPageHandle
);
447 IN EFI_GUID
*ProducerGuid
,
455 Acquire the string associated with the ProducerGuid and return it.
459 ProducerGuid - The Guid to search the HII database for
460 Token - The token value of the string to extract
461 String - The string that is extracted
465 EFI_SUCCESS - The function returns EFI_SUCCESS always.
470 UINT16 HandleBufferLength
;
471 FRAMEWORK_EFI_HII_HANDLE
*HiiHandleBuffer
;
472 UINTN StringBufferLength
;
473 UINTN NumberOfHiiHandles
;
479 // Initialize params.
481 HandleBufferLength
= 0;
482 HiiHandleBuffer
= NULL
;
485 // Get all the Hii handles
487 Status
= BdsLibGetHiiHandles (gHii
, &HandleBufferLength
, &HiiHandleBuffer
);
488 ASSERT_EFI_ERROR (Status
);
491 // Get the gHii Handle that matches the StructureNode->ProducerName
493 NumberOfHiiHandles
= HandleBufferLength
/ sizeof (FRAMEWORK_EFI_HII_HANDLE
);
494 for (Index
= 0; Index
< NumberOfHiiHandles
; Index
++) {
496 Status
= ExtractDataFromHiiHandle (
497 HiiHandleBuffer
[Index
],
502 if (CompareGuid (ProducerGuid
, &HiiGuid
)) {
507 // Find the string based on the current language
509 StringBufferLength
= 0x100;
510 *String
= AllocateZeroPool (0x100);
511 Status
= gHii
->GetString (
513 HiiHandleBuffer
[Index
],
521 if (EFI_ERROR (Status
)) {
523 *String
= GetStringById (STRING_TOKEN (STR_MISSING_STRING
));
526 FreePool (HiiHandleBuffer
);
531 ConvertProcessorToString (
532 IN EFI_PROCESSOR_CORE_FREQUENCY_DATA
*ProcessorFrequency
,
539 Convert Processor Frequency Data to a string
543 ProcessorFrequency - The frequency data to process
544 String - The string that is created
550 CHAR16
*StringBuffer
;
554 if (ProcessorFrequency
->Exponent
>= 6) {
555 FreqMhz
= ProcessorFrequency
->Value
;
556 for (Index
= 0; Index
< (UINTN
) (ProcessorFrequency
->Exponent
- 6); Index
++) {
563 StringBuffer
= AllocateZeroPool (0x20);
564 ASSERT (StringBuffer
!= NULL
);
565 Index
= UnicodeValueToString (StringBuffer
, LEFT_JUSTIFY
, FreqMhz
/ 1000, 3);
566 StrCat (StringBuffer
, L
".");
567 UnicodeValueToString (StringBuffer
+ Index
+ 1, PREFIX_ZERO
, (FreqMhz
% 1000) / 10, 2);
568 StrCat (StringBuffer
, L
" GHz");
570 *String
= (CHAR16
*) StringBuffer
;
576 ConvertMemorySizeToString (
577 IN UINT32 MemorySize
,
584 Convert Memory Size to a string
588 MemorySize - The size of the memory to process
589 String - The string that is created
595 CHAR16
*StringBuffer
;
597 StringBuffer
= AllocateZeroPool (0x20);
598 ASSERT (StringBuffer
!= NULL
);
599 UnicodeValueToString (StringBuffer
, LEFT_JUSTIFY
, MemorySize
, 6);
600 StrCat (StringBuffer
, L
" MB RAM");
602 *String
= (CHAR16
*) StringBuffer
;
608 UpdateFrontPageStrings (
615 Update the banner information for the Front Page based on DataHub information
626 STRING_REF TokenToUpdate
;
628 UINT64 MonotonicCount
;
629 EFI_DATA_HUB_PROTOCOL
*DataHub
;
630 EFI_DATA_RECORD_HEADER
*Record
;
631 EFI_SUBCLASS_TYPE1_HEADER
*DataHeader
;
632 EFI_MISC_BIOS_VENDOR_DATA
*BiosVendor
;
633 EFI_MISC_SYSTEM_MANUFACTURER_DATA
*SystemManufacturer
;
634 EFI_PROCESSOR_VERSION_DATA
*ProcessorVersion
;
635 EFI_PROCESSOR_CORE_FREQUENCY_DATA
*ProcessorFrequency
;
636 EFI_MEMORY_ARRAY_START_ADDRESS_DATA
*MemoryArray
;
643 ZeroMem (Find
, sizeof (Find
));
646 // Update Front Page strings
648 Status
= gBS
->LocateProtocol (
649 &gEfiDataHubProtocolGuid
,
653 ASSERT_EFI_ERROR (Status
);
657 Status
= gRT
->GetVariable (
659 &gEfiGlobalVariableGuid
,
665 for (Index
= 0; Index
< 3; Index
++) {
666 Lang
[Index
] = (CHAR16
) LangCode
[Index
];
672 Status
= DataHub
->GetNextRecord (DataHub
, &MonotonicCount
, NULL
, &Record
);
673 if (Record
->DataRecordClass
== EFI_DATA_RECORD_CLASS_DATA
) {
674 DataHeader
= (EFI_SUBCLASS_TYPE1_HEADER
*) (Record
+ 1);
675 if (CompareGuid (&Record
->DataRecordGuid
, &mMiscSubClass
) &&
676 (DataHeader
->RecordType
== EFI_MISC_BIOS_VENDOR_RECORD_NUMBER
)
678 BiosVendor
= (EFI_MISC_BIOS_VENDOR_DATA
*) (DataHeader
+ 1);
679 GetStringFromToken (&Record
->ProducerName
, BiosVendor
->BiosVersion
, &NewString
);
680 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_BIOS_VERSION
;
681 gHii
->NewString (gHii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
682 FreePool (NewString
);
686 if (CompareGuid (&Record
->DataRecordGuid
, &mMiscSubClass
) &&
687 (DataHeader
->RecordType
== EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER
)
689 SystemManufacturer
= (EFI_MISC_SYSTEM_MANUFACTURER_DATA
*) (DataHeader
+ 1);
690 GetStringFromToken (&Record
->ProducerName
, SystemManufacturer
->SystemProductName
, &NewString
);
691 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_COMPUTER_MODEL
;
692 gHii
->NewString (gHii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
693 FreePool (NewString
);
697 if (CompareGuid (&Record
->DataRecordGuid
, &mProcessorSubClass
) &&
698 (DataHeader
->RecordType
== ProcessorVersionRecordType
)
700 ProcessorVersion
= (EFI_PROCESSOR_VERSION_DATA
*) (DataHeader
+ 1);
701 GetStringFromToken (&Record
->ProducerName
, *ProcessorVersion
, &NewString
);
702 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_CPU_MODEL
;
703 gHii
->NewString (gHii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
704 FreePool (NewString
);
708 if (CompareGuid (&Record
->DataRecordGuid
, &mProcessorSubClass
) &&
709 (DataHeader
->RecordType
== ProcessorCoreFrequencyRecordType
)
711 ProcessorFrequency
= (EFI_PROCESSOR_CORE_FREQUENCY_DATA
*) (DataHeader
+ 1);
712 ConvertProcessorToString (ProcessorFrequency
, &NewString
);
713 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_CPU_SPEED
;
714 gHii
->NewString (gHii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
715 FreePool (NewString
);
719 if (CompareGuid (&Record
->DataRecordGuid
, &mMemorySubClass
) &&
720 (DataHeader
->RecordType
== EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER
)
722 MemoryArray
= (EFI_MEMORY_ARRAY_START_ADDRESS_DATA
*) (DataHeader
+ 1);
723 ConvertMemorySizeToString((UINT32
)(RShiftU64((MemoryArray
->MemoryArrayEndAddress
-
724 MemoryArray
->MemoryArrayStartAddress
+ 1), 20)),
726 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_MEMORY_SIZE
;
727 gHii
->NewString (gHii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
728 FreePool (NewString
);
732 } while (!EFI_ERROR (Status
) && (MonotonicCount
!= 0) && !(Find
[0] && Find
[1] && Find
[2] && Find
[3] && Find
[4]));
738 PlatformBdsEnterFrontPage (
739 IN UINT16 TimeoutDefault
,
740 IN BOOLEAN ConnectAllHappened
745 This function is the main entry of the platform setup entry.
746 The function will present the main menu of the system setup,
747 this is the platform reference part and can be customize.
750 TimeoutDefault - The fault time out value before the system
752 ConnectAllHappened - The indicater to check if the connect all have
761 EFI_HII_UPDATE_DATA
*UpdateData
;
762 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
765 // Indicate if we need connect all in the platform setup
767 if (ConnectAllHappened
) {
768 gConnectAllHappened
= TRUE
;
771 // Allocate space for creation of Buffer
773 UpdateData
= AllocateZeroPool (0x1000);
774 ASSERT (UpdateData
!= NULL
);
776 UpdateData
->FormSetUpdate
= FALSE
;
777 UpdateData
->FormCallbackHandle
= 0;
778 UpdateData
->FormUpdate
= FALSE
;
779 UpdateData
->FormTitle
= 0;
780 UpdateData
->DataCount
= 1;
783 // Remove Banner Op-code if any at this label
785 gHii
->UpdateForm (gHii
, gFrontPageHandle
, (EFI_FORM_LABEL
) 0xFFFF, FALSE
, UpdateData
);
788 // Create Banner Op-code which reflects correct timeout value
791 STRING_TOKEN (STR_TIME_OUT_PROMPT
),
793 (UINT8
) FRAMEWORK_EFI_IFR_BANNER_TIMEOUT
,
798 // Add Banner Op-code at this label
800 gHii
->UpdateForm (gHii
, gFrontPageHandle
, (EFI_FORM_LABEL
) 0xFFFF, TRUE
, UpdateData
);
804 InitializeFrontPage (TRUE
);
807 // Update Front Page strings
809 UpdateFrontPageStrings ();
812 PERF_START (0, "BdsTimeOut", "BDS", 0);
813 Status
= CallFrontPage ();
814 PERF_END (0, "BdsTimeOut", "BDS", 0);
817 // If gCallbackKey is greater than 1 and less or equal to 5,
818 // it will lauch configuration utilities.
821 // 4 = device manager
822 // 5 = boot maintainenance manager
824 if ((gCallbackKey
> 0x0001) && (gCallbackKey
<= 0x0005)) {
827 (EFI_SOFTWARE_DXE_BS_DRIVER
| EFI_SW_PC_USER_SETUP
)
831 // Based on the key that was set, we can determine what to do
833 switch (gCallbackKey
) {
835 // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
836 // describe to their customers in documentation how to find their setup information (namely
837 // under the device manager and specific buckets)
839 // These entries consist of the Continue, Select language, Boot Manager, and Device Manager
849 // User made a language setting change - display front page again
855 // User chose to run the Boot Manager
862 // Display the Device Manager
866 } while (gCallbackKey
== 4);
871 // Display the Boot Maintenance Manager
873 BdsStartBootMaint ();
877 } while ((Status
== EFI_SUCCESS
) && (gCallbackKey
!= 1));
880 //Will leave browser, check any reset required change is applied? if yes, reset system
882 SetupResetReminder ();
885 // Automatically load current entry
886 // Note: The following lines of code only execute when Auto boot
889 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, &ConsoleControl
);
890 ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);