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
;
57 Get next language from language code list (with separator ';').
59 If LangCode is NULL, then ASSERT.
60 If Lang is NULL, then ASSERT.
62 @param LangCode On input: point to first language in the list. On
63 output: point to next language in the list, or
64 NULL if no more language in the list.
65 @param Lang The first language in the list.
70 IN OUT CHAR8
**LangCode
,
77 ASSERT (LangCode
!= NULL
);
78 ASSERT (*LangCode
!= NULL
);
79 ASSERT (Lang
!= NULL
);
82 StringPtr
= *LangCode
;
83 while (StringPtr
[Index
] != 0 && StringPtr
[Index
] != ';') {
87 CopyMem (Lang
, StringPtr
, Index
);
90 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
;
158 This function processes the results of changes in configuration.
161 @param HiiHandle Points to the hii handle for this formset.
162 @param Action Specifies the type of action taken by the browser.
163 @param QuestionId A unique value which is sent to the original exporting driver
164 so that it can identify the type of data to expect.
165 @param Type The type of value for the question.
166 @param Value A pointer to the data being sent to the original exporting driver.
167 @param ActionRequest On return, points to the action requested by the callback function.
168 @param Status Return the handle status.
170 @retval TRUE The callback successfully handled the action.
171 @retval FALSE The callback not supported in this handler.
175 UiSupportLibCallbackHandler (
176 IN EFI_HII_HANDLE HiiHandle
,
177 IN EFI_BROWSER_ACTION Action
,
178 IN EFI_QUESTION_ID QuestionId
,
180 IN EFI_IFR_TYPE_VALUE
*Value
,
181 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
,
182 OUT EFI_STATUS
*Status
185 if ((QuestionId
!= FRONT_PAGE_KEY_CONTINUE
) &&
186 (QuestionId
!= FRONT_PAGE_KEY_RESET
) &&
187 (QuestionId
!= FRONT_PAGE_KEY_LANGUAGE
))
192 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
193 if (QuestionId
== FRONT_PAGE_KEY_LANGUAGE
) {
194 Value
->u8
= gCurrentLanguageIndex
;
195 *Status
= EFI_SUCCESS
;
197 *Status
= EFI_UNSUPPORTED
;
203 if (Action
!= EFI_BROWSER_ACTION_CHANGED
) {
205 // Do nothing for other UEFI Action. Only do call back when data is changed.
207 *Status
= EFI_UNSUPPORTED
;
211 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
212 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
213 *Status
= EFI_INVALID_PARAMETER
;
217 *Status
= EFI_SUCCESS
;
218 switch (QuestionId
) {
219 case FRONT_PAGE_KEY_CONTINUE
:
221 // This is the continue - clear the screen and return an error to get out of FrontPage loop
223 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
226 case FRONT_PAGE_KEY_LANGUAGE
:
227 *Status
= LanguageChangeHandler (Value
);
230 case FRONT_PAGE_KEY_RESET
:
234 gRT
->ResetSystem (EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
235 *Status
= EFI_UNSUPPORTED
;
246 Create Select language menu in the front page with oneof opcode.
248 @param[in] HiiHandle The hii handle for the Uiapp driver.
249 @param[in] StartOpCodeHandle The opcode handle to save the new opcode.
253 UiCreateLanguageMenu (
254 IN EFI_HII_HANDLE HiiHandle
,
255 IN VOID
*StartOpCodeHandle
263 CHAR16
*StringBuffer
;
264 VOID
*OptionsOpCodeHandle
;
267 EFI_HII_STRING_PROTOCOL
*HiiString
;
273 // Init OpCode Handle and Allocate space for creation of UpdateData Buffer
275 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
276 ASSERT (OptionsOpCodeHandle
!= NULL
);
278 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&CurrentLang
, NULL
);
281 // Get Support language list from variable.
283 GetEfiGlobalVariable2 (L
"PlatformLangCodes", (VOID
**)&gLanguageString
, NULL
);
284 if (gLanguageString
== NULL
) {
285 gLanguageString
= AllocateCopyPool (
286 AsciiStrSize ((CHAR8
*)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes
)),
287 (CHAR8
*)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes
)
289 ASSERT (gLanguageString
!= NULL
);
292 if (gLanguageToken
== NULL
) {
294 // Count the language list number.
296 LangCode
= gLanguageString
;
297 Lang
= AllocatePool (AsciiStrSize (gLanguageString
));
298 ASSERT (Lang
!= NULL
);
301 while (*LangCode
!= 0) {
302 GetNextLanguage (&LangCode
, Lang
);
307 // Allocate extra 1 as the end tag.
309 gLanguageToken
= AllocateZeroPool ((OptionCount
+ 1) * sizeof (EFI_STRING_ID
));
310 ASSERT (gLanguageToken
!= NULL
);
312 Status
= gBS
->LocateProtocol (&gEfiHiiStringProtocolGuid
, NULL
, (VOID
**)&HiiString
);
313 ASSERT_EFI_ERROR (Status
);
315 LangCode
= gLanguageString
;
317 while (*LangCode
!= 0) {
318 GetNextLanguage (&LangCode
, Lang
);
321 Status
= HiiString
->GetString (HiiString
, Lang
, HiiHandle
, PRINTABLE_LANGUAGE_NAME_STRING_ID
, StringBuffer
, &StringSize
, NULL
);
322 if (Status
== EFI_BUFFER_TOO_SMALL
) {
323 StringBuffer
= AllocateZeroPool (StringSize
);
324 ASSERT (StringBuffer
!= NULL
);
325 Status
= HiiString
->GetString (HiiString
, Lang
, HiiHandle
, PRINTABLE_LANGUAGE_NAME_STRING_ID
, StringBuffer
, &StringSize
, NULL
);
326 ASSERT_EFI_ERROR (Status
);
329 if (EFI_ERROR (Status
)) {
330 LangSize
= AsciiStrSize (Lang
);
331 StringBuffer
= AllocatePool (LangSize
* sizeof (CHAR16
));
332 ASSERT (StringBuffer
!= NULL
);
333 AsciiStrToUnicodeStrS (Lang
, StringBuffer
, LangSize
);
336 ASSERT (StringBuffer
!= NULL
);
337 gLanguageToken
[OptionCount
] = HiiSetString (HiiHandle
, 0, StringBuffer
, NULL
);
338 FreePool (StringBuffer
);
344 ASSERT (gLanguageToken
!= NULL
);
345 LangCode
= gLanguageString
;
348 Lang
= AllocatePool (AsciiStrSize (gLanguageString
));
349 ASSERT (Lang
!= NULL
);
352 while (*LangCode
!= 0) {
353 GetNextLanguage (&LangCode
, Lang
);
355 if ((CurrentLang
!= NULL
) && (AsciiStrCmp (Lang
, CurrentLang
) == 0)) {
356 HiiCreateOneOfOptionOpCode (
358 gLanguageToken
[OptionCount
],
359 EFI_IFR_OPTION_DEFAULT
,
360 EFI_IFR_NUMERIC_SIZE_1
,
363 gCurrentLanguageIndex
= (UINT8
)OptionCount
;
365 HiiCreateOneOfOptionOpCode (
367 gLanguageToken
[OptionCount
],
369 EFI_IFR_NUMERIC_SIZE_1
,
377 if (CurrentLang
!= NULL
) {
378 FreePool (CurrentLang
);
383 HiiCreateOneOfOpCode (
385 FRONT_PAGE_KEY_LANGUAGE
,
388 STRING_TOKEN (STR_LANGUAGE_SELECT
),
389 STRING_TOKEN (STR_LANGUAGE_SELECT_HELP
),
390 EFI_IFR_FLAG_CALLBACK
,
391 EFI_IFR_NUMERIC_SIZE_1
,
398 Create continue menu in the front page.
400 @param[in] HiiHandle The hii handle for the Uiapp driver.
401 @param[in] StartOpCodeHandle The opcode handle to save the new opcode.
405 UiCreateContinueMenu (
406 IN EFI_HII_HANDLE HiiHandle
,
407 IN VOID
*StartOpCodeHandle
410 HiiCreateActionOpCode (
412 FRONT_PAGE_KEY_CONTINUE
,
413 STRING_TOKEN (STR_CONTINUE_PROMPT
),
414 STRING_TOKEN (STR_CONTINUE_PROMPT
),
415 EFI_IFR_FLAG_CALLBACK
,
421 Create empty line menu in the front page.
423 @param HiiHandle The hii handle for the Uiapp driver.
424 @param StartOpCodeHandle The opcode handle to save the new opcode.
429 IN EFI_HII_HANDLE HiiHandle
,
430 IN VOID
*StartOpCodeHandle
433 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_NULL_STRING
), 0, 0, 0);
437 Create Reset menu in the front page.
439 @param[in] HiiHandle The hii handle for the Uiapp driver.
440 @param[in] StartOpCodeHandle The opcode handle to save the new opcode.
445 IN EFI_HII_HANDLE HiiHandle
,
446 IN VOID
*StartOpCodeHandle
449 HiiCreateActionOpCode (
451 FRONT_PAGE_KEY_RESET
,
452 STRING_TOKEN (STR_RESET_STRING
),
453 STRING_TOKEN (STR_RESET_STRING
),
454 EFI_IFR_FLAG_CALLBACK
,
460 Extract device path for given HII handle and class guid.
462 @param Handle The HII handle.
464 @retval NULL Fail to get the device path string.
465 @return PathString Get the device path string.
469 ExtractDevicePathFromHiiHandle (
470 IN EFI_HII_HANDLE Handle
474 EFI_HANDLE DriverHandle
;
476 ASSERT (Handle
!= NULL
);
478 if (Handle
== NULL
) {
482 Status
= gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, Handle
, &DriverHandle
);
483 if (EFI_ERROR (Status
)) {
487 return ConvertDevicePathToText (DevicePathFromHandle (DriverHandle
), FALSE
, FALSE
);
491 Check whether this driver need to be shown in the front page.
493 @param HiiHandle The hii handle for the driver.
494 @param Guid The special guid for the driver which is the target.
495 @param PromptId Return the prompt string id.
496 @param HelpId Return the help string id.
497 @param FormsetGuid Return the formset guid info.
499 @retval EFI_SUCCESS Search the driver success
504 IN EFI_HII_HANDLE HiiHandle
,
506 OUT EFI_STRING_ID
*PromptId
,
507 OUT EFI_STRING_ID
*HelpId
,
508 OUT VOID
*FormsetGuid
514 EFI_IFR_FORM_SET
*Buffer
;
520 Status
= HiiGetFormSetFromHiiHandle (HiiHandle
, &Buffer
, &BufferSize
);
521 if (EFI_ERROR (Status
)) {
527 Ptr
= (UINT8
*)Buffer
;
528 while (TempSize
< BufferSize
) {
529 TempSize
+= ((EFI_IFR_OP_HEADER
*)Ptr
)->Length
;
531 if (((EFI_IFR_OP_HEADER
*)Ptr
)->Length
<= OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
532 Ptr
+= ((EFI_IFR_OP_HEADER
*)Ptr
)->Length
;
536 ClassGuidNum
= (UINT8
)(((EFI_IFR_FORM_SET
*)Ptr
)->Flags
& 0x3);
537 ClassGuid
= (EFI_GUID
*)(VOID
*)(Ptr
+ sizeof (EFI_IFR_FORM_SET
));
538 while (ClassGuidNum
-- > 0) {
539 if (!CompareGuid (Guid
, ClassGuid
)) {
544 *PromptId
= ((EFI_IFR_FORM_SET
*)Ptr
)->FormSetTitle
;
545 *HelpId
= ((EFI_IFR_FORM_SET
*)Ptr
)->Help
;
546 CopyMem (FormsetGuid
, &((EFI_IFR_FORM_SET
*)Ptr
)->Guid
, sizeof (EFI_GUID
));
557 Search the drivers in the system which need to show in the front page
558 and insert the menu to the front page.
560 @param HiiHandle The hii handle for the Uiapp driver.
561 @param ClassGuid The class guid for the driver which is the target.
562 @param SpecialHandlerFn The pointer to the special handler function, if any.
563 @param StartOpCodeHandle The opcode handle to save the new opcode.
565 @retval EFI_SUCCESS Search the driver success
569 UiListThirdPartyDrivers (
570 IN EFI_HII_HANDLE HiiHandle
,
571 IN EFI_GUID
*ClassGuid
,
572 IN DRIVER_SPECIAL_HANDLER SpecialHandlerFn
,
573 IN VOID
*StartOpCodeHandle
579 EFI_STRING_ID TokenHelp
;
580 EFI_HII_HANDLE
*HiiHandles
;
581 CHAR16
*DevicePathStr
;
584 UI_HII_DRIVER_INSTANCE
*DriverListPtr
;
586 BOOLEAN EmptyLineAfter
;
588 if (gHiiDriverList
!= NULL
) {
589 FreePool (gHiiDriverList
);
592 HiiHandles
= HiiGetHiiHandles (NULL
);
593 ASSERT (HiiHandles
!= NULL
);
595 gHiiDriverList
= AllocateZeroPool (UI_HII_DRIVER_LIST_SIZE
* sizeof (UI_HII_DRIVER_INSTANCE
));
596 ASSERT (gHiiDriverList
!= NULL
);
597 DriverListPtr
= gHiiDriverList
;
598 CurrentSize
= UI_HII_DRIVER_LIST_SIZE
;
600 for (Index
= 0, Count
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
601 if (!RequiredDriver (HiiHandles
[Index
], ClassGuid
, &Token
, &TokenHelp
, &gHiiDriverList
[Count
].FormSetGuid
)) {
605 String
= HiiGetString (HiiHandles
[Index
], Token
, NULL
);
606 if (String
== NULL
) {
607 String
= HiiGetString (gStringPackHandle
, STRING_TOKEN (STR_MISSING_STRING
), NULL
);
608 ASSERT (String
!= NULL
);
609 } else if (SpecialHandlerFn
!= NULL
) {
611 // Check whether need to rename the driver name.
613 EmptyLineAfter
= FALSE
;
614 if (SpecialHandlerFn (String
, &NewName
, &EmptyLineAfter
)) {
617 DriverListPtr
[Count
].EmptyLineAfter
= EmptyLineAfter
;
621 DriverListPtr
[Count
].PromptId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
624 String
= HiiGetString (HiiHandles
[Index
], TokenHelp
, NULL
);
625 if (String
== NULL
) {
626 String
= HiiGetString (gStringPackHandle
, STRING_TOKEN (STR_MISSING_STRING
), NULL
);
627 ASSERT (String
!= NULL
);
630 DriverListPtr
[Count
].HelpId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
633 DevicePathStr
= ExtractDevicePathFromHiiHandle (HiiHandles
[Index
]);
634 if (DevicePathStr
!= NULL
) {
635 DriverListPtr
[Count
].DevicePathId
= HiiSetString (HiiHandle
, 0, DevicePathStr
, NULL
);
636 FreePool (DevicePathStr
);
638 DriverListPtr
[Count
].DevicePathId
= 0;
642 if (Count
>= CurrentSize
) {
643 DriverListPtr
= ReallocatePool (
644 CurrentSize
* sizeof (UI_HII_DRIVER_INSTANCE
),
645 (Count
+ UI_HII_DRIVER_LIST_SIZE
)
646 * sizeof (UI_HII_DRIVER_INSTANCE
),
649 ASSERT (DriverListPtr
!= NULL
);
650 gHiiDriverList
= DriverListPtr
;
651 CurrentSize
+= UI_HII_DRIVER_LIST_SIZE
;
655 FreePool (HiiHandles
);
658 while (gHiiDriverList
[Index
].PromptId
!= 0) {
659 HiiCreateGotoExOpCode (
662 gHiiDriverList
[Index
].PromptId
,
663 gHiiDriverList
[Index
].HelpId
,
665 (EFI_QUESTION_ID
)(Index
+ FRONT_PAGE_KEY_DRIVER
),
667 &gHiiDriverList
[Index
].FormSetGuid
,
668 gHiiDriverList
[Index
].DevicePathId
671 if (gHiiDriverList
[Index
].EmptyLineAfter
) {
672 UiCreateEmptyLine (HiiHandle
, StartOpCodeHandle
);