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
46 #define FRONT_PAGE_KEY_DRIVER 0x2000
49 EFI_STRING_ID PromptId
;
51 EFI_STRING_ID DevicePathId
;
53 BOOLEAN EmptyLineAfter
;
54 } UI_HII_DRIVER_INSTANCE
;
56 CHAR8
*gLanguageString
;
57 EFI_STRING_ID
*gLanguageToken
;
58 UI_HII_DRIVER_INSTANCE
*gHiiDriverList
;
59 extern EFI_HII_HANDLE gStringPackHandle
;
60 UINT8 gCurrentLanguageIndex
;
64 Get next language from language code list (with separator ';').
66 If LangCode is NULL, then ASSERT.
67 If Lang is NULL, then ASSERT.
69 @param LangCode On input: point to first language in the list. On
70 output: point to next language in the list, or
71 NULL if no more language in the list.
72 @param Lang The first language in the list.
77 IN OUT CHAR8
**LangCode
,
84 ASSERT (LangCode
!= NULL
);
85 ASSERT (*LangCode
!= NULL
);
86 ASSERT (Lang
!= NULL
);
89 StringPtr
= *LangCode
;
90 while (StringPtr
[Index
] != 0 && StringPtr
[Index
] != ';') {
94 CopyMem (Lang
, StringPtr
, Index
);
97 if (StringPtr
[Index
] == ';') {
100 *LangCode
= StringPtr
+ Index
;
104 This function processes the language changes in configuration.
106 @param Value A pointer to the data being sent to the original exporting driver.
109 @retval TRUE The callback successfully handled the action.
110 @retval FALSE The callback not supported in this handler.
114 LanguageChangeHandler (
115 IN EFI_IFR_TYPE_VALUE
*Value
124 // Allocate working buffer for RFC 4646 language in supported LanguageString.
126 Lang
= AllocatePool (AsciiStrSize (gLanguageString
));
127 ASSERT (Lang
!= NULL
);
130 LangCode
= gLanguageString
;
131 while (*LangCode
!= 0) {
132 GetNextLanguage (&LangCode
, Lang
);
134 if (Index
== Value
->u8
) {
135 gCurrentLanguageIndex
= Value
->u8
;
142 if (Index
== Value
->u8
) {
143 Status
= gRT
->SetVariable (
145 &gEfiGlobalVariableGuid
,
146 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
150 if (EFI_ERROR (Status
)) {
152 return EFI_DEVICE_ERROR
;
163 This function processes the results of changes in configuration.
166 @param HiiHandle Points to the hii handle for this formset.
167 @param Action Specifies the type of action taken by the browser.
168 @param QuestionId A unique value which is sent to the original exporting driver
169 so that it can identify the type of data to expect.
170 @param Type The type of value for the question.
171 @param Value A pointer to the data being sent to the original exporting driver.
172 @param ActionRequest On return, points to the action requested by the callback function.
173 @param Status Return the handle status.
175 @retval TRUE The callback successfully handled the action.
176 @retval FALSE The callback not supported in this handler.
180 UiSupportLibCallbackHandler (
181 IN EFI_HII_HANDLE HiiHandle
,
182 IN EFI_BROWSER_ACTION Action
,
183 IN EFI_QUESTION_ID QuestionId
,
185 IN EFI_IFR_TYPE_VALUE
*Value
,
186 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
,
187 OUT EFI_STATUS
*Status
190 if (QuestionId
!= FRONT_PAGE_KEY_CONTINUE
&&
191 QuestionId
!= FRONT_PAGE_KEY_RESET
&&
192 QuestionId
!= FRONT_PAGE_KEY_LANGUAGE
) {
196 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
197 if (QuestionId
== FRONT_PAGE_KEY_LANGUAGE
) {
198 Value
->u8
= gCurrentLanguageIndex
;
199 *Status
= EFI_SUCCESS
;
201 *Status
= EFI_UNSUPPORTED
;
206 if (Action
!= EFI_BROWSER_ACTION_CHANGED
) {
208 // Do nothing for other UEFI Action. Only do call back when data is changed.
210 *Status
= EFI_UNSUPPORTED
;
214 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
215 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
216 *Status
= EFI_INVALID_PARAMETER
;
220 *Status
= EFI_SUCCESS
;
221 switch (QuestionId
) {
222 case FRONT_PAGE_KEY_CONTINUE
:
224 // This is the continue - clear the screen and return an error to get out of FrontPage loop
226 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
229 case FRONT_PAGE_KEY_LANGUAGE
:
230 *Status
= LanguageChangeHandler(Value
);
233 case FRONT_PAGE_KEY_RESET
:
237 gRT
->ResetSystem (EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
238 *Status
= EFI_UNSUPPORTED
;
249 Create Select language menu in the front page with oneof opcode.
251 @param[in] HiiHandle The hii handle for the Uiapp driver.
252 @param[in] StartOpCodeHandle The opcode handle to save the new opcode.
256 UiCreateLanguageMenu (
257 IN EFI_HII_HANDLE HiiHandle
,
258 IN VOID
*StartOpCodeHandle
266 CHAR16
*StringBuffer
;
267 VOID
*OptionsOpCodeHandle
;
270 EFI_HII_STRING_PROTOCOL
*HiiString
;
276 // Init OpCode Handle and Allocate space for creation of UpdateData Buffer
278 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
279 ASSERT (OptionsOpCodeHandle
!= NULL
);
281 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&CurrentLang
, NULL
);
284 // Get Support language list from variable.
286 GetEfiGlobalVariable2 (L
"PlatformLangCodes", (VOID
**)&gLanguageString
, NULL
);
287 if (gLanguageString
== NULL
) {
288 gLanguageString
= AllocateCopyPool (
289 AsciiStrSize ((CHAR8
*) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes
)),
290 (CHAR8
*) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes
)
292 ASSERT (gLanguageString
!= NULL
);
295 if (gLanguageToken
== NULL
) {
297 // Count the language list number.
299 LangCode
= gLanguageString
;
300 Lang
= AllocatePool (AsciiStrSize (gLanguageString
));
301 ASSERT (Lang
!= NULL
);
304 while (*LangCode
!= 0) {
305 GetNextLanguage (&LangCode
, Lang
);
310 // Allocate extra 1 as the end tag.
312 gLanguageToken
= AllocateZeroPool ((OptionCount
+ 1) * sizeof (EFI_STRING_ID
));
313 ASSERT (gLanguageToken
!= NULL
);
315 Status
= gBS
->LocateProtocol (&gEfiHiiStringProtocolGuid
, NULL
, (VOID
**) &HiiString
);
316 ASSERT_EFI_ERROR (Status
);
318 LangCode
= gLanguageString
;
320 while (*LangCode
!= 0) {
321 GetNextLanguage (&LangCode
, Lang
);
324 Status
= HiiString
->GetString (HiiString
, Lang
, HiiHandle
, PRINTABLE_LANGUAGE_NAME_STRING_ID
, StringBuffer
, &StringSize
, NULL
);
325 if (Status
== EFI_BUFFER_TOO_SMALL
) {
326 StringBuffer
= AllocateZeroPool (StringSize
);
327 ASSERT (StringBuffer
!= NULL
);
328 Status
= HiiString
->GetString (HiiString
, Lang
, HiiHandle
, PRINTABLE_LANGUAGE_NAME_STRING_ID
, StringBuffer
, &StringSize
, NULL
);
329 ASSERT_EFI_ERROR (Status
);
332 if (EFI_ERROR (Status
)) {
333 LangSize
= AsciiStrSize (Lang
);
334 StringBuffer
= AllocatePool (LangSize
* sizeof (CHAR16
));
335 ASSERT (StringBuffer
!= NULL
);
336 AsciiStrToUnicodeStrS (Lang
, StringBuffer
, LangSize
);
339 ASSERT (StringBuffer
!= NULL
);
340 gLanguageToken
[OptionCount
] = HiiSetString (HiiHandle
, 0, StringBuffer
, NULL
);
341 FreePool (StringBuffer
);
347 ASSERT (gLanguageToken
!= NULL
);
348 LangCode
= gLanguageString
;
351 Lang
= AllocatePool (AsciiStrSize (gLanguageString
));
352 ASSERT (Lang
!= NULL
);
354 while (*LangCode
!= 0) {
355 GetNextLanguage (&LangCode
, Lang
);
357 if (CurrentLang
!= NULL
&& AsciiStrCmp (Lang
, CurrentLang
) == 0) {
358 HiiCreateOneOfOptionOpCode (
360 gLanguageToken
[OptionCount
],
361 EFI_IFR_OPTION_DEFAULT
,
362 EFI_IFR_NUMERIC_SIZE_1
,
365 gCurrentLanguageIndex
= (UINT8
) OptionCount
;
367 HiiCreateOneOfOptionOpCode (
369 gLanguageToken
[OptionCount
],
371 EFI_IFR_NUMERIC_SIZE_1
,
379 if (CurrentLang
!= NULL
) {
380 FreePool (CurrentLang
);
384 HiiCreateOneOfOpCode (
386 FRONT_PAGE_KEY_LANGUAGE
,
389 STRING_TOKEN (STR_LANGUAGE_SELECT
),
390 STRING_TOKEN (STR_LANGUAGE_SELECT_HELP
),
391 EFI_IFR_FLAG_CALLBACK
,
392 EFI_IFR_NUMERIC_SIZE_1
,
399 Create continue menu in the front page.
401 @param[in] HiiHandle The hii handle for the Uiapp driver.
402 @param[in] StartOpCodeHandle The opcode handle to save the new opcode.
406 UiCreateContinueMenu (
407 IN EFI_HII_HANDLE HiiHandle
,
408 IN VOID
*StartOpCodeHandle
411 HiiCreateActionOpCode (
413 FRONT_PAGE_KEY_CONTINUE
,
414 STRING_TOKEN (STR_CONTINUE_PROMPT
),
415 STRING_TOKEN (STR_CONTINUE_PROMPT
),
416 EFI_IFR_FLAG_CALLBACK
,
422 Create empty line menu in the front page.
424 @param HiiHandle The hii handle for the Uiapp driver.
425 @param StartOpCodeHandle The opcode handle to save the new opcode.
430 IN EFI_HII_HANDLE HiiHandle
,
431 IN VOID
*StartOpCodeHandle
434 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_NULL_STRING
), 0, 0, 0);
438 Create Reset menu in the front page.
440 @param[in] HiiHandle The hii handle for the Uiapp driver.
441 @param[in] StartOpCodeHandle The opcode handle to save the new opcode.
446 IN EFI_HII_HANDLE HiiHandle
,
447 IN VOID
*StartOpCodeHandle
450 HiiCreateActionOpCode (
452 FRONT_PAGE_KEY_RESET
,
453 STRING_TOKEN (STR_RESET_STRING
),
454 STRING_TOKEN (STR_RESET_STRING
),
455 EFI_IFR_FLAG_CALLBACK
,
461 Extract device path for given HII handle and class guid.
463 @param Handle The HII handle.
465 @retval NULL Fail to get the device path string.
466 @return PathString Get the device path string.
470 ExtractDevicePathFromHiiHandle (
471 IN EFI_HII_HANDLE Handle
475 EFI_HANDLE DriverHandle
;
477 ASSERT (Handle
!= NULL
);
479 if (Handle
== NULL
) {
483 Status
= gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, Handle
, &DriverHandle
);
484 if (EFI_ERROR (Status
)) {
488 return ConvertDevicePathToText(DevicePathFromHandle (DriverHandle
), FALSE
, FALSE
);
492 Check whether this driver need to be shown in the front page.
494 @param HiiHandle The hii handle for the driver.
495 @param Guid The special guid for the driver which is the target.
496 @param PromptId Return the prompt string id.
497 @param HelpId Return the help string id.
498 @param FormsetGuid Return the formset guid info.
500 @retval EFI_SUCCESS Search the driver success
505 IN EFI_HII_HANDLE HiiHandle
,
507 OUT EFI_STRING_ID
*PromptId
,
508 OUT EFI_STRING_ID
*HelpId
,
509 OUT VOID
*FormsetGuid
515 EFI_IFR_FORM_SET
*Buffer
;
521 Status
= HiiGetFormSetFromHiiHandle(HiiHandle
, &Buffer
,&BufferSize
);
522 if (EFI_ERROR (Status
)) {
528 Ptr
= (UINT8
*) Buffer
;
529 while(TempSize
< BufferSize
) {
530 TempSize
+= ((EFI_IFR_OP_HEADER
*) Ptr
)->Length
;
532 if (((EFI_IFR_OP_HEADER
*) Ptr
)->Length
<= OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)){
533 Ptr
+= ((EFI_IFR_OP_HEADER
*) Ptr
)->Length
;
537 ClassGuidNum
= (UINT8
) (((EFI_IFR_FORM_SET
*)Ptr
)->Flags
& 0x3);
538 ClassGuid
= (EFI_GUID
*) (VOID
*)(Ptr
+ sizeof (EFI_IFR_FORM_SET
));
539 while (ClassGuidNum
-- > 0) {
540 if (!CompareGuid (Guid
, ClassGuid
)){
545 *PromptId
= ((EFI_IFR_FORM_SET
*)Ptr
)->FormSetTitle
;
546 *HelpId
= ((EFI_IFR_FORM_SET
*)Ptr
)->Help
;
547 CopyMem (FormsetGuid
, &((EFI_IFR_FORM_SET
*) Ptr
)->Guid
, sizeof (EFI_GUID
));
558 Search the drivers in the system which need to show in the front page
559 and insert the menu to the front page.
561 @param HiiHandle The hii handle for the Uiapp driver.
562 @param ClassGuid The class guid for the driver which is the target.
563 @param SpecialHandlerFn The pointer to the specail handler function, if any.
564 @param StartOpCodeHandle The opcode handle to save the new opcode.
566 @retval EFI_SUCCESS Search the driver success
570 UiListThirdPartyDrivers (
571 IN EFI_HII_HANDLE HiiHandle
,
572 IN EFI_GUID
*ClassGuid
,
573 IN DRIVER_SPECIAL_HANDLER SpecialHandlerFn
,
574 IN VOID
*StartOpCodeHandle
580 EFI_STRING_ID TokenHelp
;
581 EFI_HII_HANDLE
*HiiHandles
;
582 CHAR16
*DevicePathStr
;
585 UI_HII_DRIVER_INSTANCE
*DriverListPtr
;
587 BOOLEAN EmptyLineAfter
;
589 if (gHiiDriverList
!= NULL
) {
590 FreePool (gHiiDriverList
);
593 HiiHandles
= HiiGetHiiHandles (NULL
);
594 ASSERT (HiiHandles
!= NULL
);
596 gHiiDriverList
= AllocateZeroPool (UI_HII_DRIVER_LIST_SIZE
* sizeof (UI_HII_DRIVER_INSTANCE
));
597 ASSERT (gHiiDriverList
!= NULL
);
598 DriverListPtr
= gHiiDriverList
;
599 CurrentSize
= UI_HII_DRIVER_LIST_SIZE
;
601 for (Index
= 0, Count
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
602 if (!RequiredDriver (HiiHandles
[Index
], ClassGuid
, &Token
, &TokenHelp
, &gHiiDriverList
[Count
].FormSetGuid
)) {
606 String
= HiiGetString (HiiHandles
[Index
], Token
, NULL
);
607 if (String
== NULL
) {
608 String
= HiiGetString (gStringPackHandle
, STRING_TOKEN (STR_MISSING_STRING
), NULL
);
609 ASSERT (String
!= NULL
);
610 } else if (SpecialHandlerFn
!= NULL
) {
612 // Check whether need to rename the driver name.
614 EmptyLineAfter
= FALSE
;
615 if (SpecialHandlerFn (String
, &NewName
, &EmptyLineAfter
)) {
618 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
);
629 DriverListPtr
[Count
].HelpId
= HiiSetString (HiiHandle
, 0, String
, NULL
);
632 DevicePathStr
= ExtractDevicePathFromHiiHandle(HiiHandles
[Index
]);
633 if (DevicePathStr
!= NULL
){
634 DriverListPtr
[Count
].DevicePathId
= HiiSetString (HiiHandle
, 0, DevicePathStr
, NULL
);
635 FreePool (DevicePathStr
);
637 DriverListPtr
[Count
].DevicePathId
= 0;
641 if (Count
>= CurrentSize
) {
642 DriverListPtr
= ReallocatePool (
643 CurrentSize
* sizeof (UI_HII_DRIVER_INSTANCE
),
644 (Count
+ UI_HII_DRIVER_LIST_SIZE
)
645 * sizeof (UI_HII_DRIVER_INSTANCE
),
648 ASSERT (DriverListPtr
!= NULL
);
649 gHiiDriverList
= DriverListPtr
;
650 CurrentSize
+= UI_HII_DRIVER_LIST_SIZE
;
654 FreePool (HiiHandles
);
657 while (gHiiDriverList
[Index
].PromptId
!= 0) {
658 HiiCreateGotoExOpCode (
661 gHiiDriverList
[Index
].PromptId
,
662 gHiiDriverList
[Index
].HelpId
,
664 (EFI_QUESTION_ID
) (Index
+ FRONT_PAGE_KEY_DRIVER
),
666 &gHiiDriverList
[Index
].FormSetGuid
,
667 gHiiDriverList
[Index
].DevicePathId
670 if (gHiiDriverList
[Index
].EmptyLineAfter
) {
671 UiCreateEmptyLine (HiiHandle
, StartOpCodeHandle
);