3 This library class defines a set of interfaces to customize Ui module
5 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available under
7 the terms and conditions of the BSD License that accompanies this distribution.
8 The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Guid/MdeModuleHii.h>
18 #include <Guid/GlobalVariable.h>
20 #include <Protocol/HiiConfigAccess.h>
21 #include <Protocol/HiiString.h>
23 #include <Library/HiiLib.h>
24 #include <Library/DebugLib.h>
25 #include <Library/UefiLib.h>
26 #include <Library/BaseMemoryLib.h>
27 #include <Library/PcdLib.h>
28 #include <Library/MemoryAllocationLib.h>
29 #include <Library/UefiRuntimeServicesTableLib.h>
30 #include <Library/UefiHiiServicesLib.h>
31 #include <Library/DevicePathLib.h>
32 #include <Library/UefiBootServicesTableLib.h>
33 #include "FrontPageCustomizedUiSupport.h"
36 // This is the VFR compiler generated header file which defines the
37 // string identifiers.
39 #define PRINTABLE_LANGUAGE_NAME_STRING_ID 0x0001
41 #define UI_HII_DRIVER_LIST_SIZE 0x8
43 #define FRONT_PAGE_KEY_CONTINUE 0x1000
44 #define FRONT_PAGE_KEY_RESET 0x1001
45 #define FRONT_PAGE_KEY_LANGUAGE 0x1002
48 EFI_STRING_ID PromptId
;
50 EFI_STRING_ID DevicePathId
;
52 BOOLEAN EmptyLineAfter
;
53 } UI_HII_DRIVER_INSTANCE
;
55 CHAR8
*gLanguageString
;
56 EFI_STRING_ID
*gLanguageToken
;
57 UI_HII_DRIVER_INSTANCE
*gHiiDriverList
;
58 extern EFI_HII_HANDLE gStringPackHandle
;
59 UINT8 gCurrentLanguageIndex
;
63 Get next language from language code list (with separator ';').
65 If LangCode is NULL, then ASSERT.
66 If Lang is NULL, then ASSERT.
68 @param LangCode On input: point to first language in the list. On
69 output: point to next language in the list, or
70 NULL if no more language in the list.
71 @param Lang The first language in the list.
76 IN OUT CHAR8
**LangCode
,
83 ASSERT (LangCode
!= NULL
);
84 ASSERT (*LangCode
!= NULL
);
85 ASSERT (Lang
!= NULL
);
88 StringPtr
= *LangCode
;
89 while (StringPtr
[Index
] != 0 && StringPtr
[Index
] != ';') {
93 CopyMem (Lang
, StringPtr
, Index
);
96 if (StringPtr
[Index
] == ';') {
99 *LangCode
= StringPtr
+ Index
;
103 This function processes the language changes in configuration.
105 @param Value A pointer to the data being sent to the original exporting driver.
108 @retval TRUE The callback successfully handled the action.
109 @retval FALSE The callback not supported in this handler.
113 LanguageChangeHandler (
114 IN EFI_IFR_TYPE_VALUE
*Value
123 // Allocate working buffer for RFC 4646 language in supported LanguageString.
125 Lang
= AllocatePool (AsciiStrSize (gLanguageString
));
126 ASSERT (Lang
!= NULL
);
129 LangCode
= gLanguageString
;
130 while (*LangCode
!= 0) {
131 GetNextLanguage (&LangCode
, Lang
);
133 if (Index
== Value
->u8
) {
134 gCurrentLanguageIndex
= Value
->u8
;
141 if (Index
== Value
->u8
) {
142 Status
= gRT
->SetVariable (
144 &gEfiGlobalVariableGuid
,
145 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
149 if (EFI_ERROR (Status
)) {
151 return EFI_DEVICE_ERROR
;
162 This function processes the results of changes in configuration.
165 @param HiiHandle Points to the hii handle for this formset.
166 @param Action Specifies the type of action taken by the browser.
167 @param QuestionId A unique value which is sent to the original exporting driver
168 so that it can identify the type of data to expect.
169 @param Type The type of value for the question.
170 @param Value A pointer to the data being sent to the original exporting driver.
171 @param ActionRequest On return, points to the action requested by the callback function.
172 @param Status Return the handle status.
174 @retval TRUE The callback successfully handled the action.
175 @retval FALSE The callback not supported in this handler.
179 UiSupportLibCallbackHandler (
180 IN EFI_HII_HANDLE HiiHandle
,
181 IN EFI_BROWSER_ACTION Action
,
182 IN EFI_QUESTION_ID QuestionId
,
184 IN EFI_IFR_TYPE_VALUE
*Value
,
185 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
,
186 OUT EFI_STATUS
*Status
189 if (QuestionId
!= FRONT_PAGE_KEY_CONTINUE
&&
190 QuestionId
!= FRONT_PAGE_KEY_RESET
&&
191 QuestionId
!= FRONT_PAGE_KEY_LANGUAGE
) {
195 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
196 if (QuestionId
== FRONT_PAGE_KEY_LANGUAGE
) {
197 Value
->u8
= gCurrentLanguageIndex
;
198 *Status
= EFI_SUCCESS
;
200 *Status
= EFI_UNSUPPORTED
;
205 if (Action
!= EFI_BROWSER_ACTION_CHANGED
) {
207 // Do nothing for other UEFI Action. Only do call back when data is changed.
209 *Status
= EFI_UNSUPPORTED
;
213 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
214 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
215 *Status
= EFI_INVALID_PARAMETER
;
219 *Status
= EFI_SUCCESS
;
220 switch (QuestionId
) {
221 case FRONT_PAGE_KEY_CONTINUE
:
223 // This is the continue - clear the screen and return an error to get out of FrontPage loop
225 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
228 case FRONT_PAGE_KEY_LANGUAGE
:
229 *Status
= LanguageChangeHandler(Value
);
232 case FRONT_PAGE_KEY_RESET
:
236 gRT
->ResetSystem (EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
237 *Status
= EFI_UNSUPPORTED
;
248 Create Select language menu in the front page with oneof opcode.
250 @param[in] HiiHandle The hii handle for the Uiapp driver.
251 @param[in] StartOpCodeHandle The opcode handle to save the new opcode.
255 UiCreateLanguageMenu (
256 IN EFI_HII_HANDLE HiiHandle
,
257 IN VOID
*StartOpCodeHandle
264 CHAR16
*StringBuffer
;
265 VOID
*OptionsOpCodeHandle
;
268 EFI_HII_STRING_PROTOCOL
*HiiString
;
274 // Init OpCode Handle and Allocate space for creation of UpdateData Buffer
276 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
277 ASSERT (OptionsOpCodeHandle
!= NULL
);
279 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&CurrentLang
, NULL
);
282 // Get Support language list from variable.
284 GetEfiGlobalVariable2 (L
"PlatformLangCodes", (VOID
**)&gLanguageString
, NULL
);
285 if (gLanguageString
== NULL
) {
286 gLanguageString
= AllocateCopyPool (
287 AsciiStrSize ((CHAR8
*) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes
)),
288 (CHAR8
*) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes
)
290 ASSERT (gLanguageString
!= NULL
);
293 if (gLanguageToken
== NULL
) {
295 // Count the language list number.
297 LangCode
= gLanguageString
;
298 Lang
= AllocatePool (AsciiStrSize (gLanguageString
));
299 ASSERT (Lang
!= NULL
);
302 while (*LangCode
!= 0) {
303 GetNextLanguage (&LangCode
, Lang
);
308 // Allocate extra 1 as the end tag.
310 gLanguageToken
= AllocateZeroPool ((OptionCount
+ 1) * sizeof (EFI_STRING_ID
));
311 ASSERT (gLanguageToken
!= NULL
);
313 Status
= gBS
->LocateProtocol (&gEfiHiiStringProtocolGuid
, NULL
, (VOID
**) &HiiString
);
314 ASSERT_EFI_ERROR (Status
);
316 LangCode
= gLanguageString
;
318 while (*LangCode
!= 0) {
319 GetNextLanguage (&LangCode
, Lang
);
322 Status
= HiiString
->GetString (HiiString
, Lang
, HiiHandle
, PRINTABLE_LANGUAGE_NAME_STRING_ID
, StringBuffer
, &StringSize
, NULL
);
323 if (Status
== EFI_BUFFER_TOO_SMALL
) {
324 StringBuffer
= AllocateZeroPool (StringSize
);
325 ASSERT (StringBuffer
!= NULL
);
326 Status
= HiiString
->GetString (HiiString
, Lang
, HiiHandle
, PRINTABLE_LANGUAGE_NAME_STRING_ID
, StringBuffer
, &StringSize
, NULL
);
327 ASSERT_EFI_ERROR (Status
);
330 if (EFI_ERROR (Status
)) {
331 StringBuffer
= AllocatePool (AsciiStrSize (Lang
) * sizeof (CHAR16
));
332 ASSERT (StringBuffer
!= NULL
);
333 AsciiStrToUnicodeStr (Lang
, StringBuffer
);
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
);
351 while (*LangCode
!= 0) {
352 GetNextLanguage (&LangCode
, Lang
);
354 if (CurrentLang
!= NULL
&& AsciiStrCmp (Lang
, CurrentLang
) == 0) {
355 HiiCreateOneOfOptionOpCode (
357 gLanguageToken
[OptionCount
],
358 EFI_IFR_OPTION_DEFAULT
,
359 EFI_IFR_NUMERIC_SIZE_1
,
362 gCurrentLanguageIndex
= (UINT8
) OptionCount
;
364 HiiCreateOneOfOptionOpCode (
366 gLanguageToken
[OptionCount
],
368 EFI_IFR_NUMERIC_SIZE_1
,
376 if (CurrentLang
!= NULL
) {
377 FreePool (CurrentLang
);
381 HiiCreateOneOfOpCode (
383 FRONT_PAGE_KEY_LANGUAGE
,
386 STRING_TOKEN (STR_LANGUAGE_SELECT
),
387 STRING_TOKEN (STR_LANGUAGE_SELECT_HELP
),
388 EFI_IFR_FLAG_CALLBACK
,
389 EFI_IFR_NUMERIC_SIZE_1
,
396 Create continue menu in the front page.
398 @param[in] HiiHandle The hii handle for the Uiapp driver.
399 @param[in] StartOpCodeHandle The opcode handle to save the new opcode.
403 UiCreateContinueMenu (
404 IN EFI_HII_HANDLE HiiHandle
,
405 IN VOID
*StartOpCodeHandle
408 HiiCreateActionOpCode (
410 FRONT_PAGE_KEY_CONTINUE
,
411 STRING_TOKEN (STR_CONTINUE_PROMPT
),
412 STRING_TOKEN (STR_CONTINUE_PROMPT
),
413 EFI_IFR_FLAG_CALLBACK
,
419 Create empty line menu in the front page.
421 @param HiiHandle The hii handle for the Uiapp driver.
422 @param StartOpCodeHandle The opcode handle to save the new opcode.
427 IN EFI_HII_HANDLE HiiHandle
,
428 IN VOID
*StartOpCodeHandle
431 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_NULL_STRING
), 0, 0, 0);
435 Create Reset menu in the front page.
437 @param[in] HiiHandle The hii handle for the Uiapp driver.
438 @param[in] StartOpCodeHandle The opcode handle to save the new opcode.
443 IN EFI_HII_HANDLE HiiHandle
,
444 IN VOID
*StartOpCodeHandle
447 HiiCreateActionOpCode (
449 FRONT_PAGE_KEY_RESET
,
450 STRING_TOKEN (STR_RESET_STRING
),
451 STRING_TOKEN (STR_RESET_STRING
),
452 EFI_IFR_FLAG_CALLBACK
,
458 Extract device path for given HII handle and class guid.
460 @param Handle The HII handle.
462 @retval NULL Fail to get the device path string.
463 @return PathString Get the device path string.
467 ExtractDevicePathFromHiiHandle (
468 IN EFI_HII_HANDLE Handle
472 EFI_HANDLE DriverHandle
;
474 ASSERT (Handle
!= NULL
);
476 if (Handle
== NULL
) {
480 Status
= gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, Handle
, &DriverHandle
);
481 if (EFI_ERROR (Status
)) {
485 return ConvertDevicePathToText(DevicePathFromHandle (DriverHandle
), FALSE
, FALSE
);
489 Check whether this driver need to be shown in the front page.
491 @param HiiHandle The hii handle for the driver.
492 @param Guid The special guid for the driver which is the target.
493 @param PromptId Return the prompt string id.
494 @param HelpId Return the help string id.
495 @param FormsetGuid Return the formset guid info.
497 @retval EFI_SUCCESS Search the driver success
502 IN EFI_HII_HANDLE HiiHandle
,
504 OUT EFI_STRING_ID
*PromptId
,
505 OUT EFI_STRING_ID
*HelpId
,
506 OUT VOID
*FormsetGuid
512 EFI_IFR_FORM_SET
*Buffer
;
518 Status
= HiiGetFormSetFromHiiHandle(HiiHandle
, &Buffer
,&BufferSize
);
519 if (EFI_ERROR (Status
)) {
525 Ptr
= (UINT8
*) Buffer
;
526 while(TempSize
< BufferSize
) {
527 TempSize
+= ((EFI_IFR_OP_HEADER
*) Ptr
)->Length
;
529 if (((EFI_IFR_OP_HEADER
*) Ptr
)->Length
<= OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)){
530 Ptr
+= ((EFI_IFR_OP_HEADER
*) Ptr
)->Length
;
534 ClassGuidNum
= (UINT8
) (((EFI_IFR_FORM_SET
*)Ptr
)->Flags
& 0x3);
535 ClassGuid
= (EFI_GUID
*) (VOID
*)(Ptr
+ sizeof (EFI_IFR_FORM_SET
));
536 while (ClassGuidNum
-- > 0) {
537 if (!CompareGuid (Guid
, ClassGuid
)){
542 *PromptId
= ((EFI_IFR_FORM_SET
*)Ptr
)->FormSetTitle
;
543 *HelpId
= ((EFI_IFR_FORM_SET
*)Ptr
)->Help
;
544 CopyMem (FormsetGuid
, &((EFI_IFR_FORM_SET
*) Ptr
)->Guid
, sizeof (EFI_GUID
));
555 Search the drivers in the system which need to show in the front page
556 and insert the menu to the front page.
558 @param HiiHandle The hii handle for the Uiapp driver.
559 @param ClassGuid The class guid for the driver which is the target.
560 @param SpecialHandlerFn The pointer to the specail handler function, if any.
561 @param StartOpCodeHandle The opcode handle to save the new opcode.
563 @retval EFI_SUCCESS Search the driver success
567 UiListThirdPartyDrivers (
568 IN EFI_HII_HANDLE HiiHandle
,
569 IN EFI_GUID
*ClassGuid
,
570 IN DRIVER_SPECIAL_HANDLER SpecialHandlerFn
,
571 IN VOID
*StartOpCodeHandle
577 EFI_STRING_ID TokenHelp
;
578 EFI_HII_HANDLE
*HiiHandles
;
579 CHAR16
*DevicePathStr
;
582 UI_HII_DRIVER_INSTANCE
*DriverListPtr
;
584 BOOLEAN EmptyLineAfter
;
586 if (gHiiDriverList
!= NULL
) {
587 FreePool (gHiiDriverList
);
590 HiiHandles
= HiiGetHiiHandles (NULL
);
591 ASSERT (HiiHandles
!= NULL
);
593 gHiiDriverList
= AllocateZeroPool (UI_HII_DRIVER_LIST_SIZE
* sizeof (UI_HII_DRIVER_INSTANCE
));
594 ASSERT (gHiiDriverList
!= NULL
);
595 DriverListPtr
= gHiiDriverList
;
596 CurrentSize
= UI_HII_DRIVER_LIST_SIZE
;
598 for (Index
= 0, Count
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
599 if (!RequiredDriver (HiiHandles
[Index
], ClassGuid
, &Token
, &TokenHelp
, &gHiiDriverList
[Count
].FormSetGuid
)) {
603 String
= HiiGetString (HiiHandles
[Index
], Token
, NULL
);
604 if (String
== NULL
) {
605 String
= HiiGetString (gStringPackHandle
, STRING_TOKEN (STR_MISSING_STRING
), NULL
);
606 ASSERT (String
!= NULL
);
607 } else if (SpecialHandlerFn
!= NULL
) {
609 // Check whether need to rename the driver name.
611 EmptyLineAfter
= FALSE
;
612 if (SpecialHandlerFn (String
, &NewName
, &EmptyLineAfter
)) {
615 DriverListPtr
[Count
].EmptyLineAfter
= EmptyLineAfter
;
618 DriverListPtr
[Count
].PromptId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
621 String
= HiiGetString (HiiHandles
[Index
], TokenHelp
, NULL
);
622 if (String
== NULL
) {
623 String
= HiiGetString (gStringPackHandle
, STRING_TOKEN (STR_MISSING_STRING
), NULL
);
624 ASSERT (String
!= NULL
);
626 DriverListPtr
[Count
].HelpId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
629 DevicePathStr
= ExtractDevicePathFromHiiHandle(HiiHandles
[Index
]);
630 if (DevicePathStr
!= NULL
){
631 DriverListPtr
[Count
].DevicePathId
= HiiSetString (HiiHandle
, 0, DevicePathStr
, NULL
);
632 FreePool (DevicePathStr
);
634 DriverListPtr
[Count
].DevicePathId
= 0;
638 if (Count
>= CurrentSize
) {
639 DriverListPtr
= AllocateCopyPool ((Count
+ UI_HII_DRIVER_LIST_SIZE
) * sizeof (UI_HII_DRIVER_INSTANCE
), gHiiDriverList
);
640 ASSERT (DriverListPtr
!= NULL
);
641 FreePool (gHiiDriverList
);
642 gHiiDriverList
= DriverListPtr
;
643 CurrentSize
+= UI_HII_DRIVER_LIST_SIZE
;
647 FreePool (HiiHandles
);
650 while (gHiiDriverList
[Index
].PromptId
!= 0) {
651 HiiCreateGotoExOpCode (
654 gHiiDriverList
[Index
].PromptId
,
655 gHiiDriverList
[Index
].HelpId
,
659 &gHiiDriverList
[Index
].FormSetGuid
,
660 gHiiDriverList
[Index
].DevicePathId
663 if (gHiiDriverList
[Index
].EmptyLineAfter
) {
664 UiCreateEmptyLine (HiiHandle
, StartOpCodeHandle
);