2 This file contains functions related to Config Access Protocols installed by
3 by HII Thunk Modules which is used to thunk UEFI Config Access Callback to
4 Framework HII Callback.
6 Copyright (c) 2008, Intel Corporation
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "HiiDatabase.h"
19 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE ConfigAccessProtocolInstanceTempate
= {
20 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_SIGNATURE
,
25 }, //ConfigAccessProtocol
26 NULL
, //FrameworkFormCallbackProtocol
27 {NULL
, NULL
} //ConfigAccessStorageListHead
31 Find and return the pointer to Package Header of the Form package
32 in the Framework Package List. The Framework Package List is created
33 by a module calling the Framework HII interface.
34 The Framwork Package List contains package data
35 generated by Intel's UEFI VFR Compiler and String gather tool. The data format
36 of the package data is defined by TIANO_AUTOGEN_PACKAGES_HEADER.
38 If the package list contains other type of packages such as KEYBOARD_LAYOUT,
39 FONTS and IMAGES, the ASSERT. This is to make sure the caller is a
40 Framework Module which does not include packages introduced by UEFI Specification
41 or packages that is not supported by Thunk layer.
43 @param Packages The Framework Package List
45 @retval EFI_HII_PACKAGE_HEADER* Return the Package Header of
47 @retval NULL If no Form Package is found.
49 EFI_HII_PACKAGE_HEADER
*
51 IN CONST EFI_HII_PACKAGES
*Packages
54 TIANO_AUTOGEN_PACKAGES_HEADER
**TianoAutogenPackageHdrArray
;
55 EFI_HII_PACKAGE_HEADER
*IfrPackage
;
58 ASSERT (Packages
!= NULL
);
62 TianoAutogenPackageHdrArray
= (TIANO_AUTOGEN_PACKAGES_HEADER
**) (((UINT8
*) &Packages
->GuidId
) + sizeof (Packages
->GuidId
));
63 for (Index
= 0; Index
< Packages
->NumberOfPackages
; Index
++) {
65 // BugBug: The current UEFI HII build tool generate a binary in the format defined in:
66 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
67 // this binary is with same package type. So the returned IfrPackNum and StringPackNum
68 // may not be the exact number of valid package number in the binary generated
71 switch (TianoAutogenPackageHdrArray
[Index
]->PackageHeader
.Type
) {
72 case EFI_HII_PACKAGE_FORM
:
73 return &TianoAutogenPackageHdrArray
[Index
]->PackageHeader
;
76 case EFI_HII_PACKAGE_STRINGS
:
77 case EFI_HII_PACKAGE_SIMPLE_FONTS
:
81 // The following fonts are invalid for a module that using Framework to UEFI thunk layer.
83 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT
:
84 case EFI_HII_PACKAGE_FONTS
:
85 case EFI_HII_PACKAGE_IMAGES
:
92 return (EFI_HII_PACKAGE_HEADER
*) NULL
;
96 This function scan EFI_IFR_VARSTORE_OP in the Form Package.
97 It create entries for these VARSTORE found and append the entry
100 If FormSetPackage is not EFI_HII_PACKAGE_FORM, then ASSERT.
101 If there is no linear buffer storage in this formset, then ASSERT.
103 @param FormSetPackage The Form Package header.
104 @param BufferStorageListHead The link list for the VARSTORE found in the form package.
106 @retval EFI_SUCCESS The function scan the form set and find one or more
108 @retval EFI_OUT_OF_RESOURCES There is not enough memory to complete the function.
112 IN CONST EFI_HII_PACKAGE_HEADER
*FormSetPackage
,
113 OUT LIST_ENTRY
*BufferStorageListHead
120 EFI_IFR_VARSTORE
*VarStoreOpCode
;
121 HII_TRHUNK_BUFFER_STORAGE_KEY
*BufferStorageKey
;
123 ASSERT (FormSetPackage
->Type
== EFI_HII_PACKAGE_FORM
);
125 OpCodeOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
126 while (OpCodeOffset
< FormSetPackage
->Length
) {
127 OpCodeData
= (UINT8
*) FormSetPackage
+ OpCodeOffset
;
129 OpCodeLength
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
130 OpCodeOffset
+= OpCodeLength
;
131 Operand
= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
;
133 if (Operand
== EFI_IFR_VARSTORE_OP
) {
134 VarStoreOpCode
= (EFI_IFR_VARSTORE
*)OpCodeData
;
135 BufferStorageKey
= AllocateZeroPool (sizeof (*BufferStorageKey
));
136 if (BufferStorageKey
== NULL
) {
137 return EFI_OUT_OF_RESOURCES
;
139 CopyMem (&BufferStorageKey
->Guid
, &VarStoreOpCode
->Guid
, sizeof (EFI_GUID
));
141 BufferStorageKey
->Name
= AllocateZeroPool (AsciiStrSize (VarStoreOpCode
->Name
) * 2);
142 AsciiStrToUnicodeStr (VarStoreOpCode
->Name
, BufferStorageKey
->Name
);
144 BufferStorageKey
->VarStoreId
= VarStoreOpCode
->VarStoreId
;
146 BufferStorageKey
->Size
= VarStoreOpCode
->Size
;
147 BufferStorageKey
->Signature
= HII_TRHUNK_BUFFER_STORAGE_KEY_SIGNATURE
;
149 InsertTailList (BufferStorageListHead
, &BufferStorageKey
->List
);
157 This function installs a EFI_CONFIG_ACCESS_PROTOCOL instance for a form package registered
158 by a module using Framework HII Protocol Interfaces.
160 UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
161 that Setup Utility can load the Buffer Storage using this protocol.
163 @param Packages The framework package list.
164 @param MapEntry The Thunk Layer Handle Mapping Database Entry.
166 @retval EFI_SUCCESS The Config Access Protocol is installed successfully.
167 @retval EFI_OUT_RESOURCE There is not enough memory.
171 InstallDefaultUefiConfigAccessProtocol (
172 IN CONST EFI_HII_PACKAGES
*Packages
,
173 IN OUT HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY
*MapEntry
176 EFI_HII_PACKAGE_HEADER
*FormSetPackage
;
178 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE
*ConfigAccessInstance
;
180 Status
= HiiLibCreateHiiDriverHandle (&MapEntry
->UefiHiiDriverHandle
);
181 ConfigAccessInstance
= AllocateCopyPool (
182 sizeof (HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE
),
183 &ConfigAccessProtocolInstanceTempate
185 ASSERT (ConfigAccessInstance
!= NULL
);
186 InitializeListHead (&ConfigAccessInstance
->ConfigAccessBufferStorageListHead
);
189 // We assume there is only one formset package in each Forms Package
191 FormSetPackage
= GetIfrFormSet (Packages
);
192 ASSERT (FormSetPackage
!= NULL
);
194 Status
= GetBufferStorage (FormSetPackage
, &ConfigAccessInstance
->ConfigAccessBufferStorageListHead
);
195 if (EFI_ERROR (Status
)) {
196 FreePool (ConfigAccessInstance
);
201 Status
= gBS
->InstallMultipleProtocolInterfaces (
202 &MapEntry
->UefiHiiDriverHandle
,
203 &gEfiHiiConfigAccessProtocolGuid
,
204 &ConfigAccessInstance
->ConfigAccessProtocol
,
207 ASSERT_EFI_ERROR (Status
);
208 if (EFI_ERROR (Status
)) {
209 FreePool (ConfigAccessInstance
);
218 Wrap EFI_HII_CONFIG_ACCESS_PROTOCOL.RouteConfig to a call to EFI_FORM_CALLBACK_PROTOCOL.NvWrite.
220 @param BufferStorageKey The key with all attributes needed to call EFI_FORM_CALLBACK_PROTOCOL.NvWrite.
221 @param FrameworkFormCallBack The EFI_FORM_CALLBACK_PROTOCOL registered by Framework HII module.
222 @param Data The data to be saved.
223 @param DataSize The size of data.
225 @retval EFI_STATUS The status returned by the EFI_FORM_CALLBACK_PROTOCOL.NvWrite.
228 RouteConfigToFrameworkFormCallBack (
229 IN HII_TRHUNK_BUFFER_STORAGE_KEY
*BufferStorageKey
,
230 IN EFI_FORM_CALLBACK_PROTOCOL
*FrameworkFormCallBack
,
236 BOOLEAN ResetRequired
;
238 Status
= FrameworkFormCallBack
->NvWrite (
239 FrameworkFormCallBack
,
240 BufferStorageKey
->Name
,
241 &BufferStorageKey
->Guid
,
242 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
251 Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to EFI_FORM_CALLBACK_PROTOCOL.NvRead.
253 @param BufferStorageKey The key with all attributes needed to call EFI_FORM_CALLBACK_PROTOCOL.NvRead.
254 @param FrameworkFormCallBack The EFI_FORM_CALLBACK_PROTOCOL registered by Framework HII module.
255 @param Data The data read.
256 @param DataSize The size of data.
258 @retval EFI_STATUS The status returned by the EFI_FORM_CALLBACK_PROTOCOL.NvWrite.
259 @retval EFI_INVALID_PARAMETER If the EFI_FORM_CALLBACK_PROTOCOL.NvRead return the size information of the data
260 does not match what has been recorded early in he HII_TRHUNK_BUFFER_STORAGE_KEY.
263 ExtractConfigFromFrameworkFormCallBack (
264 IN HII_TRHUNK_BUFFER_STORAGE_KEY
*BufferStorageKey
,
265 IN EFI_FORM_CALLBACK_PROTOCOL
*FrameworkFormCallBack
,
275 Status
= FrameworkFormCallBack
->NvRead (
276 FrameworkFormCallBack
,
277 BufferStorageKey
->Name
,
278 &BufferStorageKey
->Guid
,
283 if (Status
== EFI_BUFFER_TOO_SMALL
) {
284 if (BufferStorageKey
->Size
!= *DataSize
) {
286 return EFI_INVALID_PARAMETER
;
289 *Data
= AllocateZeroPool (*DataSize
);
291 return EFI_OUT_OF_RESOURCES
;
294 FrameworkFormCallBack
->NvRead (
295 FrameworkFormCallBack
,
296 BufferStorageKey
->Name
,
297 &BufferStorageKey
->Guid
,
308 Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to UEFI Variable Set Service.
310 @param BufferStorageKey The key with all attributes needed to call a UEFI Variable Get Service.
311 @param Data The data read.
312 @param DataSize The size of data.
314 @retval EFI_STATUS The status returned by the UEFI Variable Set Service.
318 RouteConfigToUefiVariable (
319 IN HII_TRHUNK_BUFFER_STORAGE_KEY
*BufferStorageKey
,
324 return gRT
->SetVariable (
325 BufferStorageKey
->Name
,
326 &BufferStorageKey
->Guid
,
327 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
335 Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to UEFI Variable Get Service.
337 @param BufferStorageKey The key with all attributes needed to call a UEFI Variable Get Service.
338 @param Data The data read.
339 @param DataSize The size of data.
341 If the UEFI Variable Get Service return the size information of the data
342 does not match what has been recorded early in he HII_TRHUNK_BUFFER_STORAGE_KEY.
345 @retval EFI_STATUS The status returned by the UEFI Variable Get Service.
346 @retval EFI_INVALID_PARAMETER If the UEFI Variable Get Service return the size information of the data
347 does not match what has been recorded early in he HII_TRHUNK_BUFFER_STORAGE_KEY.
351 ExtractConfigFromUefiVariable (
352 IN HII_TRHUNK_BUFFER_STORAGE_KEY
*BufferStorageKey
,
361 Status
= gRT
->GetVariable (
362 BufferStorageKey
->Name
,
363 &BufferStorageKey
->Guid
,
368 if (Status
== EFI_BUFFER_TOO_SMALL
) {
370 if (BufferStorageKey
->Size
!= *DataSize
) {
372 return EFI_INVALID_PARAMETER
;
375 *Data
= AllocateZeroPool (*DataSize
);
377 return EFI_OUT_OF_RESOURCES
;
380 Status
= gRT
->GetVariable (
381 BufferStorageKey
->Name
,
382 &BufferStorageKey
->Guid
,
394 This function implement the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig
395 so that data can be read from the data storage such as UEFI Variable or module's
396 customized storage exposed by EFI_FRAMEWORK_CALLBACK.
398 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL
399 @param Request A null-terminated Unicode string in <ConfigRequest> format. Note that this
400 includes the routing information as well as the configurable name / value pairs. It is
401 invalid for this string to be in <MultiConfigRequest> format.
403 @param Progress On return, points to a character in the Request string. Points to the string¡¯s null
404 terminator if request was successful. Points to the most recent ¡®&¡¯ before the first
405 failing name / value pair (or the beginning of the string if the failure is in the first
406 name / value pair) if the request was not successful
407 @param Results A null-terminated Unicode string in <ConfigAltResp> format which has all
408 values filled in for the names in the Request string. String to be allocated by the called
411 @retval EFI_INVALID_PARAMETER If there is no Buffer Storage for this Config Access instance.
412 @retval EFI_SUCCESS The setting is retrived successfully.
413 @retval !EFI_SUCCESS The error returned by UEFI Get Variable or Framework Form Callback Nvread.
418 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
419 IN CONST EFI_STRING Request
,
420 OUT EFI_STRING
*Progress
,
421 OUT EFI_STRING
*Results
425 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE
*ConfigaAccessInstance
;
426 LIST_ENTRY
*ListEntry
;
427 HII_TRHUNK_BUFFER_STORAGE_KEY
*BufferStorageKey
;
432 ConfigaAccessInstance
= HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This
);
435 // For now, only one var varstore is supported so that we don't need to parse the Configuration string.
437 ListEntry
= GetFirstNode (&ConfigaAccessInstance
->ConfigAccessBufferStorageListHead
);
438 if (ListEntry
== NULL
) {
440 return EFI_INVALID_PARAMETER
;
443 BufferStorageKey
= HII_TRHUNK_BUFFER_STORAGE_KEY_FROM_LIST_ENTRY (ListEntry
);
445 if (ConfigaAccessInstance
->FrameworkFormCallbackProtocol
== NULL
||
446 ConfigaAccessInstance
->FrameworkFormCallbackProtocol
->NvRead
== NULL
) {
447 Status
= ExtractConfigFromUefiVariable (
453 Status
= ExtractConfigFromFrameworkFormCallBack (
455 ConfigaAccessInstance
->FrameworkFormCallbackProtocol
,
461 if (!EFI_ERROR (Status
)) {
462 Status
= mHiiConfigRoutingProtocol
->BlockToConfig (
463 mHiiConfigRoutingProtocol
,
478 This function implement the EFI_HII_CONFIG_ACCESS_PROTOCOL.RouteConfig
479 so that data can be written to the data storage such as UEFI Variable or module's
480 customized storage exposed by EFI_FRAMEWORK_CALLBACK.
482 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL
483 @param Configuration A null-terminated Unicode string in <ConfigResp> format.
484 @param Progress A pointer to a string filled in with the offset of the most recent ¡®&¡¯ before the first
485 failing name / value pair (or the beginning of the string if the failure is in the first
486 name / value pair) or the terminating NULL if all was successful.
488 @retval EFI_INVALID_PARAMETER If there is no Buffer Storage for this Config Access instance.
489 @retval EFI_SUCCESS The setting is saved successfully.
490 @retval !EFI_SUCCESS The error returned by UEFI Set Variable or Framework Form Callback Nvwrite.
495 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
496 IN CONST EFI_STRING Configuration
,
497 OUT EFI_STRING
*Progress
501 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE
*ConfigaAccessInstance
;
502 LIST_ENTRY
*ListEntry
;
503 HII_TRHUNK_BUFFER_STORAGE_KEY
*BufferStorageKey
;
506 UINTN LastModifiedByteIndex
;
509 ConfigaAccessInstance
= HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This
);
512 // For now, only one var varstore is supported so that we don't need to parse the Configuration string.
514 ListEntry
= GetFirstNode (&ConfigaAccessInstance
->ConfigAccessBufferStorageListHead
);
515 if (ListEntry
== NULL
) {
517 return EFI_INVALID_PARAMETER
;
520 BufferStorageKey
= HII_TRHUNK_BUFFER_STORAGE_KEY_FROM_LIST_ENTRY (ListEntry
);
522 Data
= AllocateZeroPool (BufferStorageKey
->Size
);
524 return EFI_OUT_OF_RESOURCES
;
526 Status
= mHiiConfigRoutingProtocol
->ConfigToBlock (
527 mHiiConfigRoutingProtocol
,
530 &LastModifiedByteIndex
,
534 if (EFI_ERROR (Status
)) {
538 DataSize
= BufferStorageKey
->Size
;
539 if (ConfigaAccessInstance
->FrameworkFormCallbackProtocol
== NULL
||
540 ConfigaAccessInstance
->FrameworkFormCallbackProtocol
->NvRead
== NULL
) {
541 Status
= RouteConfigToUefiVariable (
547 Status
= RouteConfigToFrameworkFormCallBack (
549 ConfigaAccessInstance
->FrameworkFormCallbackProtocol
,
561 Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.CallBack to EFI_FORM_CALLBACK_PROTOCOL.Callback. Therefor,
562 the framework HII module willl do no porting (except some porting works needed for callback for EFI_ONE_OF_OPTION opcode)
563 and still work with a UEFI HII SetupBrowser.
565 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
566 @param Action Specifies the type of action taken by the browser. See EFI_BROWSER_ACTION_x.
567 @param QuestionId A unique value which is sent to the original exporting driver so that it can identify the
568 type of data to expect. The format of the data tends to vary based on the opcode that
569 generated the callback.
570 @param Type The type of value for the question. See EFI_IFR_TYPE_x in
571 EFI_IFR_ONE_OF_OPTION.
572 @param Value A pointer to the data being sent to the original exporting driver. The type is specified
573 by Type. Type EFI_IFR_TYPE_VALUE is defined in
574 EFI_IFR_ONE_OF_OPTION.
575 @param ActionRequest On return, points to the action requested by the callback function. Type
576 EFI_BROWSER_ACTION_REQUEST is specified in SendForm() in the Form
579 @retval EFI_UNSUPPORTED If the Framework HII module does not register Callback although it specify the opcode under
580 focuse to be INTERRACTIVE.
581 @retval EFI_SUCCESS The callback complete successfully.
582 @retval !EFI_SUCCESS The error code returned by EFI_FORM_CALLBACK_PROTOCOL.Callback.
588 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
589 IN EFI_BROWSER_ACTION Action
,
590 IN EFI_QUESTION_ID QuestionId
,
592 IN EFI_IFR_TYPE_VALUE
*Value
,
593 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
597 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE
*ConfigaAccessInstance
;
598 EFI_FORM_CALLBACK_PROTOCOL
*FrameworkFormCallbackProtocol
;
599 EFI_HII_CALLBACK_PACKET
*Packet
;
600 FRAMEWORK_EFI_IFR_DATA_ARRAY Data
;
601 FRAMEWORK_EFI_IFR_DATA_ENTRY
*DataEntry
;
602 EFI_FORM_CALLBACK Callback
;
604 ASSERT (This
!= NULL
);
605 ASSERT (Value
!= NULL
);
606 ASSERT (ActionRequest
!= NULL
);
608 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
610 ConfigaAccessInstance
= HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This
);
612 FrameworkFormCallbackProtocol
= ConfigaAccessInstance
->FrameworkFormCallbackProtocol
;
613 if (FrameworkFormCallbackProtocol
== NULL
) {
614 return EFI_UNSUPPORTED
;
616 Callback
= FrameworkFormCallbackProtocol
->Callback
;
619 FrameworkFormCallbackProtocol
,
626 // Callback require browser to perform action
628 if (Packet
!= NULL
) {
629 if (Packet
->DataArray
.EntryCount
== 1 && Packet
->DataArray
.NvRamMap
== NULL
) {
630 DataEntry
= (FRAMEWORK_EFI_IFR_DATA_ENTRY
*) ((UINT8
*) Packet
+ sizeof (FRAMEWORK_EFI_IFR_DATA_ARRAY
));
631 switch (DataEntry
->Flags
) {
633 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
636 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
639 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
642 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;