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_UGA_PIXEL Foreground
;
78 EFI_UGA_PIXEL Background
;
81 SetMem (&Foreground
, sizeof (EFI_UGA_PIXEL
), 0xff);
82 SetMem (&Background
, sizeof (EFI_UGA_PIXEL
), 0x0);
83 SetMem (&Color
, sizeof (EFI_UGA_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];
422 // Begin waiting for USER INPUT
426 (EFI_SOFTWARE_DXE_BS_DRIVER
| EFI_SW_PC_INPUT_WAIT
)
429 FakeNvRamMap
[0] = (UINT8
) mLastSelection
;
430 Status
= gBrowser
->SendForm (
432 TRUE
, // Use the database
433 &gFrontPageHandle
, // The HII Handle
436 FrontPageCallbackHandle
, // This is the handle that the interface to the callback was installed on
442 Hii
->ResetStrings (Hii
, gFrontPageHandle
);
449 IN EFI_GUID
*ProducerGuid
,
457 Acquire the string associated with the ProducerGuid and return it.
461 ProducerGuid - The Guid to search the HII database for
462 Token - The token value of the string to extract
463 String - The string that is extracted
467 EFI_SUCCESS - The function returns EFI_SUCCESS always.
472 UINT16 HandleBufferLength
;
473 EFI_HII_HANDLE
*HiiHandleBuffer
;
474 UINTN StringBufferLength
;
475 UINTN NumberOfHiiHandles
;
480 HandleBufferLength
= 0x1000;
481 HiiHandleBuffer
= NULL
;
484 // Get all the Hii handles
486 HiiHandleBuffer
= AllocateZeroPool (HandleBufferLength
);
488 Status
= Hii
->FindHandles (Hii
, &HandleBufferLength
, HiiHandleBuffer
);
489 ASSERT_EFI_ERROR (Status
);
492 // Get the Hii Handle that matches the StructureNode->ProducerName
494 NumberOfHiiHandles
= HandleBufferLength
/ sizeof (EFI_HII_HANDLE
);
495 for (Index
= 0; Index
< NumberOfHiiHandles
; Index
++) {
497 Status
= ExtractDataFromHiiHandle (
498 HiiHandleBuffer
[Index
],
503 if (CompareGuid (ProducerGuid
, &HiiGuid
)) {
508 // Find the string based on the current language
510 StringBufferLength
= 0x100;
511 *String
= AllocateZeroPool (0x100);
512 Status
= Hii
->GetString (
514 HiiHandleBuffer
[Index
],
522 if (EFI_ERROR (Status
)) {
523 gBS
->FreePool (*String
);
524 *String
= GetStringById (STRING_TOKEN (STR_MISSING_STRING
));
527 gBS
->FreePool (HiiHandleBuffer
);
532 ConvertProcessorToString (
533 IN EFI_PROCESSOR_CORE_FREQUENCY_DATA
*ProcessorFrequency
,
540 Convert Processor Frequency Data to a string
544 ProcessorFrequency - The frequency data to process
545 String - The string that is created
551 CHAR16
*StringBuffer
;
555 if (ProcessorFrequency
->Exponent
>= 6) {
556 FreqMhz
= ProcessorFrequency
->Value
;
557 for (Index
= 0; Index
< (UINTN
) (ProcessorFrequency
->Exponent
- 6); Index
++) {
564 StringBuffer
= AllocateZeroPool (0x20);
565 ASSERT (StringBuffer
!= NULL
);
566 Index
= UnicodeValueToString (StringBuffer
, LEFT_JUSTIFY
, FreqMhz
/ 1000, 3);
567 StrCat (StringBuffer
, L
".");
568 UnicodeValueToString (StringBuffer
+ Index
+ 1, PREFIX_ZERO
, (FreqMhz
% 1000) / 10, 2);
569 StrCat (StringBuffer
, L
" GHz");
571 *String
= (CHAR16
*) StringBuffer
;
577 ConvertMemorySizeToString (
578 IN UINT32 MemorySize
,
585 Convert Memory Size to a string
589 MemorySize - The size of the memory to process
590 String - The string that is created
596 CHAR16
*StringBuffer
;
598 StringBuffer
= AllocateZeroPool (0x20);
599 ASSERT (StringBuffer
!= NULL
);
600 UnicodeValueToString (StringBuffer
, LEFT_JUSTIFY
, MemorySize
, 6);
601 StrCat (StringBuffer
, L
" MB RAM");
603 *String
= (CHAR16
*) StringBuffer
;
609 UpdateFrontPageStrings (
616 Update the banner information for the Front Page based on DataHub information
627 STRING_REF TokenToUpdate
;
629 UINT64 MonotonicCount
;
630 EFI_DATA_HUB_PROTOCOL
*DataHub
;
631 EFI_DATA_RECORD_HEADER
*Record
;
632 EFI_SUBCLASS_TYPE1_HEADER
*DataHeader
;
633 EFI_MISC_BIOS_VENDOR_DATA
*BiosVendor
;
634 EFI_MISC_SYSTEM_MANUFACTURER_DATA
*SystemManufacturer
;
635 EFI_PROCESSOR_VERSION_DATA
*ProcessorVersion
;
636 EFI_PROCESSOR_CORE_FREQUENCY_DATA
*ProcessorFrequency
;
637 EFI_MEMORY_ARRAY_START_ADDRESS_DATA
*MemoryArray
;
644 ZeroMem (Find
, sizeof (Find
));
647 // Update Front Page strings
649 Status
= gBS
->LocateProtocol (
650 &gEfiDataHubProtocolGuid
,
654 ASSERT_EFI_ERROR (Status
);
658 Status
= gRT
->GetVariable (
660 &gEfiGlobalVariableGuid
,
666 for (Index
= 0; Index
< 3; Index
++) {
667 Lang
[Index
] = (CHAR16
) LangCode
[Index
];
673 Status
= DataHub
->GetNextRecord (DataHub
, &MonotonicCount
, NULL
, &Record
);
674 if (Record
->DataRecordClass
== EFI_DATA_RECORD_CLASS_DATA
) {
675 DataHeader
= (EFI_SUBCLASS_TYPE1_HEADER
*) (Record
+ 1);
676 if (CompareGuid (&Record
->DataRecordGuid
, &mMiscSubClass
) &&
677 (DataHeader
->RecordType
== EFI_MISC_BIOS_VENDOR_RECORD_NUMBER
)
679 BiosVendor
= (EFI_MISC_BIOS_VENDOR_DATA
*) (DataHeader
+ 1);
680 GetStringFromToken (&Record
->ProducerName
, BiosVendor
->BiosVersion
, &NewString
);
681 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_BIOS_VERSION
;
682 Hii
->NewString (Hii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
683 gBS
->FreePool (NewString
);
687 if (CompareGuid (&Record
->DataRecordGuid
, &mMiscSubClass
) &&
688 (DataHeader
->RecordType
== EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER
)
690 SystemManufacturer
= (EFI_MISC_SYSTEM_MANUFACTURER_DATA
*) (DataHeader
+ 1);
691 GetStringFromToken (&Record
->ProducerName
, SystemManufacturer
->SystemProductName
, &NewString
);
692 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_COMPUTER_MODEL
;
693 Hii
->NewString (Hii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
694 gBS
->FreePool (NewString
);
698 if (CompareGuid (&Record
->DataRecordGuid
, &mProcessorSubClass
) &&
699 (DataHeader
->RecordType
== ProcessorVersionRecordType
)
701 ProcessorVersion
= (EFI_PROCESSOR_VERSION_DATA
*) (DataHeader
+ 1);
702 GetStringFromToken (&Record
->ProducerName
, *ProcessorVersion
, &NewString
);
703 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_CPU_MODEL
;
704 Hii
->NewString (Hii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
705 gBS
->FreePool (NewString
);
709 if (CompareGuid (&Record
->DataRecordGuid
, &mProcessorSubClass
) &&
710 (DataHeader
->RecordType
== ProcessorCoreFrequencyRecordType
)
712 ProcessorFrequency
= (EFI_PROCESSOR_CORE_FREQUENCY_DATA
*) (DataHeader
+ 1);
713 ConvertProcessorToString (ProcessorFrequency
, &NewString
);
714 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_CPU_SPEED
;
715 Hii
->NewString (Hii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
716 gBS
->FreePool (NewString
);
720 if (CompareGuid (&Record
->DataRecordGuid
, &mMemorySubClass
) &&
721 (DataHeader
->RecordType
== EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER
)
723 MemoryArray
= (EFI_MEMORY_ARRAY_START_ADDRESS_DATA
*) (DataHeader
+ 1);
724 ConvertMemorySizeToString((UINT32
)(RShiftU64((MemoryArray
->MemoryArrayEndAddress
-
725 MemoryArray
->MemoryArrayStartAddress
+ 1), 20)),
727 TokenToUpdate
= (STRING_REF
) STR_FRONT_PAGE_MEMORY_SIZE
;
728 Hii
->NewString (Hii
, Lang
, gFrontPageHandle
, &TokenToUpdate
, NewString
);
729 gBS
->FreePool (NewString
);
733 } while (!EFI_ERROR (Status
) && (MonotonicCount
!= 0) && !(Find
[0] && Find
[1] && Find
[2] && Find
[3] && Find
[4]));
739 PlatformBdsEnterFrontPage (
740 IN UINT16 TimeoutDefault
,
741 IN BOOLEAN ConnectAllHappened
746 This function is the main entry of the platform setup entry.
747 The function will present the main menu of the system setup,
748 this is the platform reference part and can be customize.
751 TimeoutDefault - The fault time out value before the system
753 ConnectAllHappened - The indicater to check if the connect all have
762 EFI_HII_UPDATE_DATA
*UpdateData
;
763 EFI_CONSOLE_CONTROL_PROTOCOL
*ConsoleControl
;
766 // Indicate if we need connect all in the platform setup
768 if (ConnectAllHappened
) {
769 gConnectAllHappened
= TRUE
;
772 // Allocate space for creation of Buffer
774 UpdateData
= AllocateZeroPool (0x1000);
775 ASSERT (UpdateData
!= NULL
);
777 UpdateData
->FormSetUpdate
= FALSE
;
778 UpdateData
->FormCallbackHandle
= 0;
779 UpdateData
->FormUpdate
= FALSE
;
780 UpdateData
->FormTitle
= 0;
781 UpdateData
->DataCount
= 1;
784 // Remove Banner Op-code if any at this label
786 Hii
->UpdateForm (Hii
, gFrontPageHandle
, (EFI_FORM_LABEL
) 0xFFFF, FALSE
, UpdateData
);
789 // Create Banner Op-code which reflects correct timeout value
792 STRING_TOKEN (STR_TIME_OUT_PROMPT
),
794 (UINT8
) EFI_IFR_BANNER_TIMEOUT
,
799 // Add Banner Op-code at this label
801 Hii
->UpdateForm (Hii
, gFrontPageHandle
, (EFI_FORM_LABEL
) 0xFFFF, TRUE
, UpdateData
);
805 InitializeFrontPage (TRUE
);
808 // Update Front Page strings
810 UpdateFrontPageStrings ();
813 PERF_START (0, "BdsTimeOut", "BDS", 0);
814 Status
= CallFrontPage ();
815 PERF_END (0, "BdsTimeOut", "BDS", 0);
818 // If gCallbackKey is greater than 1 and less or equal to 5,
819 // it will lauch configuration utilities.
822 // 4 = device manager
823 // 5 = boot maintainenance manager
825 if ((gCallbackKey
> 0x0001) && (gCallbackKey
<= 0x0005)) {
828 (EFI_SOFTWARE_DXE_BS_DRIVER
| EFI_SW_PC_USER_SETUP
)
832 // Based on the key that was set, we can determine what to do
834 switch (gCallbackKey
) {
836 // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
837 // describe to their customers in documentation how to find their setup information (namely
838 // under the device manager and specific buckets)
840 // These entries consist of the Continue, Select language, Boot Manager, and Device Manager
850 // User made a language setting change - display front page again
856 // User chose to run the Boot Manager
863 // Display the Device Manager
867 } while (gCallbackKey
== 4);
872 // Display the Boot Maintenance Manager
874 BdsStartBootMaint ();
878 } while ((Status
== EFI_SUCCESS
) && (gCallbackKey
!= 1));
881 // Automatically load current entry
882 // Note: The following lines of code only execute when Auto boot
885 Status
= gBS
->LocateProtocol (&gEfiConsoleControlProtocolGuid
, NULL
, &ConsoleControl
);
886 ConsoleControl
->SetMode (ConsoleControl
, EfiConsoleControlScreenText
);