2 This file contains the form processing code to the HII database.
4 Copyright (c) 2006 - 2008 Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HiiDatabase.h"
17 #include "UefiIfrDefault.h"
22 IN EFI_HII_PROTOCOL
*This
,
23 IN FRAMEWORK_EFI_HII_HANDLE Handle
,
24 IN OUT UINTN
*BufferSize
,
31 This function allows a program to extract a form or form package that has
32 previously been registered with the EFI HII database.
41 return EFI_UNSUPPORTED
;
47 IN EFI_HII_PROTOCOL
*This
,
48 IN FRAMEWORK_EFI_HII_HANDLE Handle
,
49 IN EFI_FORM_ID FormId
,
50 IN OUT UINTN
*BufferLengthTemp
,
57 This function allows a program to extract a form or form package that has
58 previously been registered with the EFI HII database.
61 This - A pointer to the EFI_HII_PROTOCOL instance.
63 Handle - Handle on which the form resides. Type FRAMEWORK_EFI_HII_HANDLE is defined in
64 EFI_HII_PROTOCOL.NewPack() in the Packages section.
66 FormId - The ID of the form to return. If the ID is zero, the entire form package is returned.
67 Type EFI_FORM_ID is defined in "Related Definitions" below.
69 BufferLength - On input, the length of the Buffer. On output, the length of the returned buffer, if
70 the length was sufficient and, if it was not, the length that is required to fit the
73 Buffer - The buffer designed to receive the form(s).
77 EFI_SUCCESS - Buffer filled with the requested forms. BufferLength
80 EFI_INVALID_PARAMETER - The handle is unknown.
82 EFI_NOT_FOUND - A form on the requested handle cannot be found with the
85 EFI_BUFFER_TOO_SMALL - The buffer provided was not large enough to allow the form to be stored.
90 return EFI_UNSUPPORTED
;
97 IN EFI_HII_PROTOCOL
*This
,
98 IN FRAMEWORK_EFI_HII_HANDLE Handle
,
100 OUT EFI_HII_VARIABLE_PACK_LIST
**VariablePackList
106 This function allows a program to extract the NV Image
107 that represents the default storage image
110 This - A pointer to the EFI_HII_PROTOCOL instance.
111 Handle - The HII handle from which will have default data retrieved.
112 UINTN - Mask used to retrieve the default image.
113 VariablePackList - Callee allocated, tightly-packed, link list data
114 structure that contain all default varaible packs
115 from the Hii Database.
118 EFI_NOT_FOUND - If Hii database does not contain any default images.
119 EFI_INVALID_PARAMETER - Invalid input parameter.
120 EFI_SUCCESS - Operation successful.
124 LIST_ENTRY
*UefiDefaults
;
125 EFI_HII_HANDLE UefiHiiHandle
;
127 EFI_HII_THUNK_PRIVATE_DATA
*Private
;
129 Private
= EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This
);
131 UefiHiiHandle
= FrameworkHiiHandleToUefiHiiHandle (Private
, Handle
);
132 if (UefiHiiHandle
== NULL
) {
134 return EFI_INVALID_PARAMETER
;
138 Status
= UefiIfrGetBufferTypeDefaults (UefiHiiHandle
, &UefiDefaults
);
139 if (EFI_ERROR (Status
)) {
143 Status
= UefiDefaultsToFrameworkDefaults (UefiDefaults
, DefaultMask
, VariablePackList
);
146 FreeDefaultList (UefiDefaults
);
152 ThunkUpdateFormCallBack (
153 IN EFI_HANDLE CallbackHandle
,
154 IN CONST HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY
*HandleMapEntry
158 EFI_FORM_CALLBACK_PROTOCOL
*FrameworkFormCallbackProtocol
;
159 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccessProtocol
;
160 EFI_HANDLE UefiDriverHandle
;
161 HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE
*ConfigAccessProtocolInstance
;
163 Status
= gBS
->HandleProtocol (
165 &gEfiFormCallbackProtocolGuid
,
166 (VOID
**) &FrameworkFormCallbackProtocol
168 if (EFI_ERROR (Status
)) {
169 return EFI_INVALID_PARAMETER
;
172 Status
= mHiiDatabase
->GetPackageListHandle (
174 HandleMapEntry
->UefiHiiHandle
,
177 ASSERT_EFI_ERROR (Status
);
178 Status
= gBS
->HandleProtocol (
180 &gEfiHiiConfigAccessProtocolGuid
,
181 (VOID
**) &ConfigAccessProtocol
183 ASSERT_EFI_ERROR (Status
);
185 ConfigAccessProtocolInstance
= HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (ConfigAccessProtocol
);
187 ConfigAccessProtocolInstance
->FrameworkFormCallbackProtocol
= FrameworkFormCallbackProtocol
;
192 #define LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL 0x1000
195 AppendToUpdateBuffer (
196 IN CONST UINT8
*OpCodeBuf
,
198 OUT EFI_HII_UPDATE_DATA
*UefiData
203 if (UefiData
->Offset
+ BufSize
> UefiData
->BufferSize
) {
204 NewBuff
= AllocateCopyPool (UefiData
->BufferSize
+ LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL
, UefiData
->Data
);
205 if (NewBuff
== NULL
) {
206 return EFI_OUT_OF_RESOURCES
;
208 UefiData
->BufferSize
+= LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL
;
209 FreePool (UefiData
->Data
);
210 UefiData
->Data
= NewBuff
;
213 CopyMem (UefiData
->Data
+ UefiData
->Offset
, OpCodeBuf
, BufSize
);
214 UefiData
->Offset
+= (UINT32
) BufSize
;
220 F2UCreateSubtitleOpCode (
221 IN CONST FRAMEWORK_EFI_IFR_SUBTITLE
*FwSubTitle
,
222 OUT EFI_HII_UPDATE_DATA
*UefiData
225 EFI_IFR_SUBTITLE USubTitle
;
227 ZeroMem (&USubTitle
, sizeof(USubTitle
));
229 USubTitle
.Header
.OpCode
= EFI_IFR_SUBTITLE_OP
;
230 USubTitle
.Header
.Length
= sizeof (EFI_IFR_SUBTITLE
);
232 USubTitle
.Statement
.Prompt
= FwSubTitle
->SubTitle
;
234 return AppendToUpdateBuffer ((UINT8
*)&USubTitle
, sizeof(EFI_IFR_SUBTITLE
), UefiData
);
238 F2UCreateTextOpCode (
239 IN CONST FRAMEWORK_EFI_IFR_TEXT
*FwText
,
240 OUT EFI_HII_UPDATE_DATA
*UefiData
245 ZeroMem (&UText
, sizeof(UText
));
247 UText
.Header
.OpCode
= EFI_IFR_TEXT_OP
;
248 UText
.Header
.Length
= sizeof (EFI_IFR_TEXT
);
250 UText
.Statement
.Help
= FwText
->Help
;
252 UText
.Statement
.Prompt
= FwText
->Text
;
253 UText
.TextTwo
= FwText
->TextTwo
;
255 return AppendToUpdateBuffer ((UINT8
*) &UText
, sizeof(EFI_IFR_TEXT
), UefiData
);
260 ThunkFrameworkUpdateDataToUefiUpdateData (
261 IN CONST FRAMEWORK_EFI_HII_UPDATE_DATA
*Data
,
263 OUT EFI_HII_UPDATE_DATA
**UefiData
266 FRAMEWORK_EFI_IFR_OP_HEADER
*FrameworkOpcodeBuffer
;
267 EFI_HII_UPDATE_DATA
*UefiUpdateDataBuffer
;
271 UefiUpdateDataBuffer
= AllocateZeroPool (sizeof (EFI_HII_UPDATE_DATA
));
272 if (UefiUpdateDataBuffer
== NULL
) {
273 return EFI_OUT_OF_RESOURCES
;
276 UefiUpdateDataBuffer
->Data
= AllocateZeroPool (LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL
);
277 if (UefiUpdateDataBuffer
->Data
== NULL
) {
278 return EFI_OUT_OF_RESOURCES
;
281 UefiUpdateDataBuffer
->BufferSize
= LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL
;
282 UefiUpdateDataBuffer
->Offset
= 0;
284 FrameworkOpcodeBuffer
= (FRAMEWORK_EFI_IFR_OP_HEADER
*) &Data
->Data
;
286 for (Index
= 0; Index
< Data
->DataCount
; Index
++) {
287 switch (FrameworkOpcodeBuffer
->OpCode
) {
288 case FRAMEWORK_EFI_IFR_SUBTITLE_OP
:
289 Status
= F2UCreateSubtitleOpCode ((FRAMEWORK_EFI_IFR_SUBTITLE
*) FrameworkOpcodeBuffer
, UefiUpdateDataBuffer
);
292 case FRAMEWORK_EFI_IFR_TEXT_OP
:
293 Status
= F2UCreateTextOpCode ((FRAMEWORK_EFI_IFR_TEXT
*) FrameworkOpcodeBuffer
, UefiUpdateDataBuffer
);
298 return EFI_UNSUPPORTED
;
301 if (EFI_ERROR (Status
)) {
302 FreePool (UefiUpdateDataBuffer
->Data
);
303 FreePool (UefiUpdateDataBuffer
);
307 FrameworkOpcodeBuffer
= (FRAMEWORK_EFI_IFR_OP_HEADER
*)((UINT8
*) FrameworkOpcodeBuffer
+ FrameworkOpcodeBuffer
->Length
);
310 *UefiData
= UefiUpdateDataBuffer
;
317 GetPackageDataFromPackageList (
318 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
319 IN UINT32 PackageIndex
,
320 OUT UINT32
*BufferLen
,
321 OUT EFI_HII_PACKAGE_HEADER
**Buffer
325 EFI_HII_PACKAGE_HEADER
*Package
;
327 UINT32 PackageListLength
;
328 EFI_HII_PACKAGE_HEADER PackageHeader
= {0, 0};
330 ASSERT(HiiPackageList
!= NULL
);
332 if ((BufferLen
== NULL
) || (Buffer
== NULL
)) {
333 return EFI_INVALID_PARAMETER
;
338 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
339 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
340 while (Offset
< PackageListLength
) {
341 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
342 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
343 if (Index
== PackageIndex
) {
346 Offset
+= PackageHeader
.Length
;
349 if (Offset
>= PackageListLength
) {
351 // no package found in this Package List
353 return EFI_NOT_FOUND
;
356 *BufferLen
= PackageHeader
.Length
;
362 Check if Label exist in the IFR form package.
369 IN CONST EFI_HII_PACKAGE_HEADER
*Package
,
370 IN EFI_FORM_LABEL Label
,
371 OUT EFI_GUID
*FormsetGuid
,
372 OUT EFI_FORM_ID
*FormId
376 EFI_IFR_OP_HEADER
*IfrOpHdr
;
379 EFI_GUID InternalFormSetGuid
;
380 EFI_FORM_ID InternalFormId
;
384 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ sizeof (EFI_HII_PACKAGE_HEADER
));
385 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
388 ZeroMem (&InternalFormSetGuid
, sizeof (EFI_GUID
));
392 while (Offset
< Package
->Length
) {
393 switch (IfrOpHdr
->OpCode
) {
394 case EFI_IFR_FORM_SET_OP
:
395 CopyMem (&InternalFormSetGuid
, &((EFI_IFR_FORM_SET
*) IfrOpHdr
)->Guid
, sizeof (EFI_GUID
));
399 case EFI_IFR_FORM_OP
:
400 CopyMem (&InternalFormId
, &((EFI_IFR_FORM
*) IfrOpHdr
)->FormId
, sizeof (EFI_FORM_ID
));
404 case EFI_IFR_GUID_OP
:
405 ExtendOpCode
= ((EFI_IFR_GUID_LABEL
*) IfrOpHdr
)->ExtendOpCode
;
407 if (ExtendOpCode
!= EFI_IFR_EXTEND_OP_LABEL
) {
409 // Go to the next Op-Code
411 Offset
+= IfrOpHdr
->Length
;
412 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
416 CopyMem (&LabelNumber
, &((EFI_IFR_GUID_LABEL
*)IfrOpHdr
)->Number
, sizeof (UINT16
));
417 if (LabelNumber
== Label
) {
418 ASSERT (GetForm
&& GetFormSet
);
419 CopyGuid (FormsetGuid
, &InternalFormSetGuid
);
420 *FormId
= InternalFormId
;
431 // Go to the next Op-Code
433 Offset
+= IfrOpHdr
->Length
;
434 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
437 return EFI_NOT_FOUND
;
441 Find the first EFI_FORM_LABEL in FormSets for a given EFI_HII_HANLDE defined.
443 EFI_FORM_LABEL is a specific to Tiano implementation. The current implementation
444 does not restrict labels with same label value to be duplicated in either FormSet
445 scope or Form scope. This function will only locate the FIRST EFI_FORM_LABEL
446 with value as the same as the input Label in the Formset registered with UefiHiiHandle. The FormSet GUID
447 and Form ID is returned if such Label is found.
450 @retval EFI_INVALID_PARAMETER If UefiHiiHandle is not a valid handle.
451 @retval EFI_NOT_FOUND The package list identified by UefiHiiHandle deos not contain FormSet or
452 There is no Form ID with value Label found in all Form Sets in the pacakge
455 @retval EFI_SUCCESS The first found Form ID is returned in FormId.
459 IN EFI_HII_HANDLE Handle
,
460 IN EFI_FORM_LABEL Label
,
461 OUT EFI_GUID
*FormsetGuid
,
462 OUT EFI_FORM_ID
*FormId
466 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
469 EFI_HII_PACKAGE_HEADER PackageHeader
;
470 EFI_HII_PACKAGE_HEADER
*Package
;
471 UINT32 PackageLength
;
474 HiiPackageList
= NULL
;
475 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
476 if (Status
== EFI_BUFFER_TOO_SMALL
) {
477 HiiPackageList
= AllocatePool (BufferSize
);
478 ASSERT (HiiPackageList
!= NULL
);
480 Status
= mHiiDatabase
->ExportPackageLists (mHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
481 if (EFI_ERROR (Status
)) {
486 for (Index
= 0; ; Index
++) {
487 Status
= GetPackageDataFromPackageList (HiiPackageList
, Index
, &PackageLength
, &Package
);
488 if (!EFI_ERROR (Status
)) {
489 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
490 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
491 Status
= LocateLabel (Package
, Label
, FormsetGuid
, FormId
);
492 if (!EFI_ERROR(Status
)) {
503 FreePool (HiiPackageList
);
510 IN EFI_HII_PROTOCOL
*This
,
511 IN FRAMEWORK_EFI_HII_HANDLE Handle
,
512 IN EFI_FORM_LABEL Label
,
514 IN FRAMEWORK_EFI_HII_UPDATE_DATA
*Data
519 This function allows the caller to update a form that has
520 previously been registered with the EFI HII database.
523 Handle - Hii Handle associated with the Formset to modify
524 Label - Update information starting immediately after this label in the IFR
525 AddData - If TRUE, add data. If FALSE, remove data
526 Data - If adding data, this is the pointer to the data to add
529 EFI_SUCCESS - Update success.
535 EFI_HII_THUNK_PRIVATE_DATA
*Private
;
536 HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY
*HandleMapEntry
;
537 EFI_HII_UPDATE_DATA
*UefiHiiUpdateData
;
538 EFI_HII_HANDLE UefiHiiHandle
;
539 EFI_GUID FormsetGuid
;
542 Status
= EFI_SUCCESS
;
544 Private
= EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This
);
546 HandleMapEntry
= FrameworkHiiHandleToMapDatabaseEntry (Private
, Handle
);
548 if (HandleMapEntry
== NULL
) {
549 return EFI_NOT_FOUND
;
552 if (Data
->FormSetUpdate
) {
553 Status
= ThunkUpdateFormCallBack ((EFI_HANDLE
) (UINTN
) Data
->FormCallbackHandle
, HandleMapEntry
);
554 if (EFI_ERROR (Status
)) {
559 if (Data
->DataCount
!= 0) {
560 if (HandleMapEntry
->IsPackageListWithOnlyStringPackages
) {
561 UefiHiiHandle
= TagGuidToUefiIfrHiiHandle (Private
, &HandleMapEntry
->TagGuid
);
563 if (UefiHiiHandle
== NULL
) {
564 return EFI_INVALID_PARAMETER
;
567 UefiHiiHandle
= HandleMapEntry
->UefiHiiHandle
;
570 UefiHiiUpdateData
= NULL
;
572 ThunkFrameworkUpdateDataToUefiUpdateData (Data
, AddData
, &UefiHiiUpdateData
);
574 Status
= ThunkLocateFormId (UefiHiiHandle
, Label
, &FormsetGuid
, &FormId
);
575 ASSERT_EFI_ERROR (Status
);
577 Status
= IfrLibUpdateForm (UefiHiiHandle
, &FormsetGuid
, FormId
, Label
, AddData
, UefiHiiUpdateData
);
578 ASSERT_EFI_ERROR (Status
);
580 if (UefiHiiUpdateData
!= NULL
) {
581 SafeFreePool (UefiHiiUpdateData
->Data
);
582 SafeFreePool (UefiHiiUpdateData
);