3 This library class defines a set of interfaces to customize Ui module
5 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Guid/MdeModuleHii.h>
12 #include <Guid/GlobalVariable.h>
14 #include <Protocol/HiiConfigAccess.h>
15 #include <Protocol/HiiString.h>
17 #include <Library/HiiLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/UefiLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/PcdLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/UefiRuntimeServicesTableLib.h>
24 #include <Library/UefiHiiServicesLib.h>
25 #include <Library/DevicePathLib.h>
26 #include <Library/UefiBootServicesTableLib.h>
27 #include "FrontPageCustomizedUiSupport.h"
30 // This is the VFR compiler generated header file which defines the
31 // string identifiers.
33 #define PRINTABLE_LANGUAGE_NAME_STRING_ID 0x0001
35 #define UI_HII_DRIVER_LIST_SIZE 0x8
37 #define FRONT_PAGE_KEY_CONTINUE 0x1000
38 #define FRONT_PAGE_KEY_RESET 0x1001
39 #define FRONT_PAGE_KEY_LANGUAGE 0x1002
40 #define FRONT_PAGE_KEY_DRIVER 0x2000
43 EFI_STRING_ID PromptId
;
45 EFI_STRING_ID DevicePathId
;
47 BOOLEAN EmptyLineAfter
;
48 } UI_HII_DRIVER_INSTANCE
;
50 CHAR8
*gLanguageString
;
51 EFI_STRING_ID
*gLanguageToken
;
52 UI_HII_DRIVER_INSTANCE
*gHiiDriverList
;
53 extern EFI_HII_HANDLE gStringPackHandle
;
54 UINT8 gCurrentLanguageIndex
;
58 Get next language from language code list (with separator ';').
60 If LangCode is NULL, then ASSERT.
61 If Lang is NULL, then ASSERT.
63 @param LangCode On input: point to first language in the list. On
64 output: point to next language in the list, or
65 NULL if no more language in the list.
66 @param Lang The first language in the list.
71 IN OUT CHAR8
**LangCode
,
78 ASSERT (LangCode
!= NULL
);
79 ASSERT (*LangCode
!= NULL
);
80 ASSERT (Lang
!= NULL
);
83 StringPtr
= *LangCode
;
84 while (StringPtr
[Index
] != 0 && StringPtr
[Index
] != ';') {
88 CopyMem (Lang
, StringPtr
, Index
);
91 if (StringPtr
[Index
] == ';') {
94 *LangCode
= StringPtr
+ Index
;
98 This function processes the language changes in configuration.
100 @param Value A pointer to the data being sent to the original exporting driver.
103 @retval TRUE The callback successfully handled the action.
104 @retval FALSE The callback not supported in this handler.
108 LanguageChangeHandler (
109 IN EFI_IFR_TYPE_VALUE
*Value
118 // Allocate working buffer for RFC 4646 language in supported LanguageString.
120 Lang
= AllocatePool (AsciiStrSize (gLanguageString
));
121 ASSERT (Lang
!= NULL
);
124 LangCode
= gLanguageString
;
125 while (*LangCode
!= 0) {
126 GetNextLanguage (&LangCode
, Lang
);
128 if (Index
== Value
->u8
) {
129 gCurrentLanguageIndex
= Value
->u8
;
136 if (Index
== Value
->u8
) {
137 Status
= gRT
->SetVariable (
139 &gEfiGlobalVariableGuid
,
140 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
144 if (EFI_ERROR (Status
)) {
146 return EFI_DEVICE_ERROR
;
157 This function processes the results of changes in configuration.
160 @param HiiHandle Points to the hii handle for this formset.
161 @param Action Specifies the type of action taken by the browser.
162 @param QuestionId A unique value which is sent to the original exporting driver
163 so that it can identify the type of data to expect.
164 @param Type The type of value for the question.
165 @param Value A pointer to the data being sent to the original exporting driver.
166 @param ActionRequest On return, points to the action requested by the callback function.
167 @param Status Return the handle status.
169 @retval TRUE The callback successfully handled the action.
170 @retval FALSE The callback not supported in this handler.
174 UiSupportLibCallbackHandler (
175 IN EFI_HII_HANDLE HiiHandle
,
176 IN EFI_BROWSER_ACTION Action
,
177 IN EFI_QUESTION_ID QuestionId
,
179 IN EFI_IFR_TYPE_VALUE
*Value
,
180 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
,
181 OUT EFI_STATUS
*Status
184 if (QuestionId
!= FRONT_PAGE_KEY_CONTINUE
&&
185 QuestionId
!= FRONT_PAGE_KEY_RESET
&&
186 QuestionId
!= FRONT_PAGE_KEY_LANGUAGE
) {
190 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
191 if (QuestionId
== FRONT_PAGE_KEY_LANGUAGE
) {
192 Value
->u8
= gCurrentLanguageIndex
;
193 *Status
= EFI_SUCCESS
;
195 *Status
= EFI_UNSUPPORTED
;
200 if (Action
!= EFI_BROWSER_ACTION_CHANGED
) {
202 // Do nothing for other UEFI Action. Only do call back when data is changed.
204 *Status
= EFI_UNSUPPORTED
;
208 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
209 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
210 *Status
= EFI_INVALID_PARAMETER
;
214 *Status
= EFI_SUCCESS
;
215 switch (QuestionId
) {
216 case FRONT_PAGE_KEY_CONTINUE
:
218 // This is the continue - clear the screen and return an error to get out of FrontPage loop
220 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
223 case FRONT_PAGE_KEY_LANGUAGE
:
224 *Status
= LanguageChangeHandler(Value
);
227 case FRONT_PAGE_KEY_RESET
:
231 gRT
->ResetSystem (EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
232 *Status
= EFI_UNSUPPORTED
;
243 Create Select language menu in the front page with oneof opcode.
245 @param[in] HiiHandle The hii handle for the Uiapp driver.
246 @param[in] StartOpCodeHandle The opcode handle to save the new opcode.
250 UiCreateLanguageMenu (
251 IN EFI_HII_HANDLE HiiHandle
,
252 IN VOID
*StartOpCodeHandle
260 CHAR16
*StringBuffer
;
261 VOID
*OptionsOpCodeHandle
;
264 EFI_HII_STRING_PROTOCOL
*HiiString
;
270 // Init OpCode Handle and Allocate space for creation of UpdateData Buffer
272 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
273 ASSERT (OptionsOpCodeHandle
!= NULL
);
275 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&CurrentLang
, NULL
);
278 // Get Support language list from variable.
280 GetEfiGlobalVariable2 (L
"PlatformLangCodes", (VOID
**)&gLanguageString
, NULL
);
281 if (gLanguageString
== NULL
) {
282 gLanguageString
= AllocateCopyPool (
283 AsciiStrSize ((CHAR8
*) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes
)),
284 (CHAR8
*) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes
)
286 ASSERT (gLanguageString
!= NULL
);
289 if (gLanguageToken
== NULL
) {
291 // Count the language list number.
293 LangCode
= gLanguageString
;
294 Lang
= AllocatePool (AsciiStrSize (gLanguageString
));
295 ASSERT (Lang
!= NULL
);
298 while (*LangCode
!= 0) {
299 GetNextLanguage (&LangCode
, Lang
);
304 // Allocate extra 1 as the end tag.
306 gLanguageToken
= AllocateZeroPool ((OptionCount
+ 1) * sizeof (EFI_STRING_ID
));
307 ASSERT (gLanguageToken
!= NULL
);
309 Status
= gBS
->LocateProtocol (&gEfiHiiStringProtocolGuid
, NULL
, (VOID
**) &HiiString
);
310 ASSERT_EFI_ERROR (Status
);
312 LangCode
= gLanguageString
;
314 while (*LangCode
!= 0) {
315 GetNextLanguage (&LangCode
, Lang
);
318 Status
= HiiString
->GetString (HiiString
, Lang
, HiiHandle
, PRINTABLE_LANGUAGE_NAME_STRING_ID
, StringBuffer
, &StringSize
, NULL
);
319 if (Status
== EFI_BUFFER_TOO_SMALL
) {
320 StringBuffer
= AllocateZeroPool (StringSize
);
321 ASSERT (StringBuffer
!= NULL
);
322 Status
= HiiString
->GetString (HiiString
, Lang
, HiiHandle
, PRINTABLE_LANGUAGE_NAME_STRING_ID
, StringBuffer
, &StringSize
, NULL
);
323 ASSERT_EFI_ERROR (Status
);
326 if (EFI_ERROR (Status
)) {
327 LangSize
= AsciiStrSize (Lang
);
328 StringBuffer
= AllocatePool (LangSize
* sizeof (CHAR16
));
329 ASSERT (StringBuffer
!= NULL
);
330 AsciiStrToUnicodeStrS (Lang
, StringBuffer
, LangSize
);
333 ASSERT (StringBuffer
!= NULL
);
334 gLanguageToken
[OptionCount
] = HiiSetString (HiiHandle
, 0, StringBuffer
, NULL
);
335 FreePool (StringBuffer
);
341 ASSERT (gLanguageToken
!= NULL
);
342 LangCode
= gLanguageString
;
345 Lang
= AllocatePool (AsciiStrSize (gLanguageString
));
346 ASSERT (Lang
!= NULL
);
348 while (*LangCode
!= 0) {
349 GetNextLanguage (&LangCode
, Lang
);
351 if (CurrentLang
!= NULL
&& AsciiStrCmp (Lang
, CurrentLang
) == 0) {
352 HiiCreateOneOfOptionOpCode (
354 gLanguageToken
[OptionCount
],
355 EFI_IFR_OPTION_DEFAULT
,
356 EFI_IFR_NUMERIC_SIZE_1
,
359 gCurrentLanguageIndex
= (UINT8
) OptionCount
;
361 HiiCreateOneOfOptionOpCode (
363 gLanguageToken
[OptionCount
],
365 EFI_IFR_NUMERIC_SIZE_1
,
373 if (CurrentLang
!= NULL
) {
374 FreePool (CurrentLang
);
378 HiiCreateOneOfOpCode (
380 FRONT_PAGE_KEY_LANGUAGE
,
383 STRING_TOKEN (STR_LANGUAGE_SELECT
),
384 STRING_TOKEN (STR_LANGUAGE_SELECT_HELP
),
385 EFI_IFR_FLAG_CALLBACK
,
386 EFI_IFR_NUMERIC_SIZE_1
,
393 Create continue menu in the front page.
395 @param[in] HiiHandle The hii handle for the Uiapp driver.
396 @param[in] StartOpCodeHandle The opcode handle to save the new opcode.
400 UiCreateContinueMenu (
401 IN EFI_HII_HANDLE HiiHandle
,
402 IN VOID
*StartOpCodeHandle
405 HiiCreateActionOpCode (
407 FRONT_PAGE_KEY_CONTINUE
,
408 STRING_TOKEN (STR_CONTINUE_PROMPT
),
409 STRING_TOKEN (STR_CONTINUE_PROMPT
),
410 EFI_IFR_FLAG_CALLBACK
,
416 Create empty line menu in the front page.
418 @param HiiHandle The hii handle for the Uiapp driver.
419 @param StartOpCodeHandle The opcode handle to save the new opcode.
424 IN EFI_HII_HANDLE HiiHandle
,
425 IN VOID
*StartOpCodeHandle
428 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_NULL_STRING
), 0, 0, 0);
432 Create Reset menu in the front page.
434 @param[in] HiiHandle The hii handle for the Uiapp driver.
435 @param[in] StartOpCodeHandle The opcode handle to save the new opcode.
440 IN EFI_HII_HANDLE HiiHandle
,
441 IN VOID
*StartOpCodeHandle
444 HiiCreateActionOpCode (
446 FRONT_PAGE_KEY_RESET
,
447 STRING_TOKEN (STR_RESET_STRING
),
448 STRING_TOKEN (STR_RESET_STRING
),
449 EFI_IFR_FLAG_CALLBACK
,
455 Extract device path for given HII handle and class guid.
457 @param Handle The HII handle.
459 @retval NULL Fail to get the device path string.
460 @return PathString Get the device path string.
464 ExtractDevicePathFromHiiHandle (
465 IN EFI_HII_HANDLE Handle
469 EFI_HANDLE DriverHandle
;
471 ASSERT (Handle
!= NULL
);
473 if (Handle
== NULL
) {
477 Status
= gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, Handle
, &DriverHandle
);
478 if (EFI_ERROR (Status
)) {
482 return ConvertDevicePathToText(DevicePathFromHandle (DriverHandle
), FALSE
, FALSE
);
486 Check whether this driver need to be shown in the front page.
488 @param HiiHandle The hii handle for the driver.
489 @param Guid The special guid for the driver which is the target.
490 @param PromptId Return the prompt string id.
491 @param HelpId Return the help string id.
492 @param FormsetGuid Return the formset guid info.
494 @retval EFI_SUCCESS Search the driver success
499 IN EFI_HII_HANDLE HiiHandle
,
501 OUT EFI_STRING_ID
*PromptId
,
502 OUT EFI_STRING_ID
*HelpId
,
503 OUT VOID
*FormsetGuid
509 EFI_IFR_FORM_SET
*Buffer
;
515 Status
= HiiGetFormSetFromHiiHandle(HiiHandle
, &Buffer
,&BufferSize
);
516 if (EFI_ERROR (Status
)) {
522 Ptr
= (UINT8
*) Buffer
;
523 while(TempSize
< BufferSize
) {
524 TempSize
+= ((EFI_IFR_OP_HEADER
*) Ptr
)->Length
;
526 if (((EFI_IFR_OP_HEADER
*) Ptr
)->Length
<= OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)){
527 Ptr
+= ((EFI_IFR_OP_HEADER
*) Ptr
)->Length
;
531 ClassGuidNum
= (UINT8
) (((EFI_IFR_FORM_SET
*)Ptr
)->Flags
& 0x3);
532 ClassGuid
= (EFI_GUID
*) (VOID
*)(Ptr
+ sizeof (EFI_IFR_FORM_SET
));
533 while (ClassGuidNum
-- > 0) {
534 if (!CompareGuid (Guid
, ClassGuid
)){
539 *PromptId
= ((EFI_IFR_FORM_SET
*)Ptr
)->FormSetTitle
;
540 *HelpId
= ((EFI_IFR_FORM_SET
*)Ptr
)->Help
;
541 CopyMem (FormsetGuid
, &((EFI_IFR_FORM_SET
*) Ptr
)->Guid
, sizeof (EFI_GUID
));
552 Search the drivers in the system which need to show in the front page
553 and insert the menu to the front page.
555 @param HiiHandle The hii handle for the Uiapp driver.
556 @param ClassGuid The class guid for the driver which is the target.
557 @param SpecialHandlerFn The pointer to the special handler function, if any.
558 @param StartOpCodeHandle The opcode handle to save the new opcode.
560 @retval EFI_SUCCESS Search the driver success
564 UiListThirdPartyDrivers (
565 IN EFI_HII_HANDLE HiiHandle
,
566 IN EFI_GUID
*ClassGuid
,
567 IN DRIVER_SPECIAL_HANDLER SpecialHandlerFn
,
568 IN VOID
*StartOpCodeHandle
574 EFI_STRING_ID TokenHelp
;
575 EFI_HII_HANDLE
*HiiHandles
;
576 CHAR16
*DevicePathStr
;
579 UI_HII_DRIVER_INSTANCE
*DriverListPtr
;
581 BOOLEAN EmptyLineAfter
;
583 if (gHiiDriverList
!= NULL
) {
584 FreePool (gHiiDriverList
);
587 HiiHandles
= HiiGetHiiHandles (NULL
);
588 ASSERT (HiiHandles
!= NULL
);
590 gHiiDriverList
= AllocateZeroPool (UI_HII_DRIVER_LIST_SIZE
* sizeof (UI_HII_DRIVER_INSTANCE
));
591 ASSERT (gHiiDriverList
!= NULL
);
592 DriverListPtr
= gHiiDriverList
;
593 CurrentSize
= UI_HII_DRIVER_LIST_SIZE
;
595 for (Index
= 0, Count
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
596 if (!RequiredDriver (HiiHandles
[Index
], ClassGuid
, &Token
, &TokenHelp
, &gHiiDriverList
[Count
].FormSetGuid
)) {
600 String
= HiiGetString (HiiHandles
[Index
], Token
, NULL
);
601 if (String
== NULL
) {
602 String
= HiiGetString (gStringPackHandle
, STRING_TOKEN (STR_MISSING_STRING
), NULL
);
603 ASSERT (String
!= NULL
);
604 } else if (SpecialHandlerFn
!= NULL
) {
606 // Check whether need to rename the driver name.
608 EmptyLineAfter
= FALSE
;
609 if (SpecialHandlerFn (String
, &NewName
, &EmptyLineAfter
)) {
612 DriverListPtr
[Count
].EmptyLineAfter
= EmptyLineAfter
;
615 DriverListPtr
[Count
].PromptId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
618 String
= HiiGetString (HiiHandles
[Index
], TokenHelp
, NULL
);
619 if (String
== NULL
) {
620 String
= HiiGetString (gStringPackHandle
, STRING_TOKEN (STR_MISSING_STRING
), NULL
);
621 ASSERT (String
!= NULL
);
623 DriverListPtr
[Count
].HelpId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
626 DevicePathStr
= ExtractDevicePathFromHiiHandle(HiiHandles
[Index
]);
627 if (DevicePathStr
!= NULL
){
628 DriverListPtr
[Count
].DevicePathId
= HiiSetString (HiiHandle
, 0, DevicePathStr
, NULL
);
629 FreePool (DevicePathStr
);
631 DriverListPtr
[Count
].DevicePathId
= 0;
635 if (Count
>= CurrentSize
) {
636 DriverListPtr
= ReallocatePool (
637 CurrentSize
* sizeof (UI_HII_DRIVER_INSTANCE
),
638 (Count
+ UI_HII_DRIVER_LIST_SIZE
)
639 * sizeof (UI_HII_DRIVER_INSTANCE
),
642 ASSERT (DriverListPtr
!= NULL
);
643 gHiiDriverList
= DriverListPtr
;
644 CurrentSize
+= UI_HII_DRIVER_LIST_SIZE
;
648 FreePool (HiiHandles
);
651 while (gHiiDriverList
[Index
].PromptId
!= 0) {
652 HiiCreateGotoExOpCode (
655 gHiiDriverList
[Index
].PromptId
,
656 gHiiDriverList
[Index
].HelpId
,
658 (EFI_QUESTION_ID
) (Index
+ FRONT_PAGE_KEY_DRIVER
),
660 &gHiiDriverList
[Index
].FormSetGuid
,
661 gHiiDriverList
[Index
].DevicePathId
664 if (gHiiDriverList
[Index
].EmptyLineAfter
) {
665 UiCreateEmptyLine (HiiHandle
, StartOpCodeHandle
);