2 Common Library Routines to assist handle HII elements.
4 Copyright (c) 2007 - 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.
15 #include "LibraryInternal.h"
17 extern EFI_HII_DATABASE_PROTOCOL
*gIfrLibHiiDatabase
;
20 Get the specified package from a package list based on an index.
21 The Buffer on output is updated to point to a package header in
22 the HiiPackageList. This is an internal function.
24 @param HiiPackageList The Package List Header.
25 @param PackageIndex The index of the package to get.
26 @param BufferLen The length of the package.
27 @param Buffer The starting address of package.
29 @retval EFI_SUCCESS This function completes successfully.
30 @retval EFI_NOT_FOUND The package is not found.
34 GetPackageDataFromPackageList (
35 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
36 IN UINT32 PackageIndex
,
37 OUT UINT32
*BufferLen
,
38 OUT EFI_HII_PACKAGE_HEADER
**Buffer
42 EFI_HII_PACKAGE_HEADER
*Package
;
44 UINT32 PackageListLength
;
45 EFI_HII_PACKAGE_HEADER PackageHeader
;
47 PackageHeader
.Length
= 0;
48 PackageHeader
.Type
= 0;
50 ASSERT (HiiPackageList
!= NULL
);
52 if ((BufferLen
== NULL
) || (Buffer
== NULL
)) {
53 return EFI_INVALID_PARAMETER
;
58 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
59 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
60 while (Offset
< PackageListLength
) {
61 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
62 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
63 if (Index
== PackageIndex
) {
66 Offset
+= PackageHeader
.Length
;
69 if (Offset
>= PackageListLength
) {
71 // no package found in this Package List
76 *BufferLen
= PackageHeader
.Length
;
82 This is the internal worker function to update the data in
83 a form specified by FormSetGuid, FormId and Label.
85 @param FormSetGuid The optional Formset GUID.
86 @param FormId The Form ID.
87 @param Package The package header.
88 @param PackageLength The package length.
89 @param Label The label for the update.
90 @param Insert True if inserting opcode to the form.
91 @param Data The data payload.
92 @param TempBuffer The resultant package.
93 @param TempBufferSize The length of the resultant package.
95 @retval EFI_OUT_OF_RESOURCES If there is not enough memory to complete the operation.
96 @retval EFI_INVALID_PARAMETER If TempBuffer or TempBufferSize is NULL.
97 @retval EFI_SUCCESS The function completes successfully.
102 UpdateFormPackageData (
103 IN EFI_GUID
*FormSetGuid
, OPTIONAL
104 IN EFI_FORM_ID FormId
,
105 IN EFI_HII_PACKAGE_HEADER
*Package
,
106 IN UINT32 PackageLength
,
109 IN EFI_HII_UPDATE_DATA
*Data
,
110 OUT UINT8
**TempBuffer
,
111 OUT UINT32
*TempBufferSize
116 EFI_HII_PACKAGE_HEADER PackageHeader
;
118 EFI_IFR_OP_HEADER
*IfrOpHdr
;
124 EFI_IFR_OP_HEADER
*AddOpCode
;
126 if ((TempBuffer
== NULL
) || (TempBufferSize
== NULL
)) {
127 return EFI_INVALID_PARAMETER
;
130 *TempBufferSize
= PackageLength
;
132 *TempBufferSize
+= Data
->Offset
;
134 *TempBuffer
= AllocateZeroPool (*TempBufferSize
);
135 if (*TempBuffer
== NULL
) {
136 return EFI_OUT_OF_RESOURCES
;
139 CopyMem (*TempBuffer
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
140 *TempBufferSize
= sizeof (EFI_HII_PACKAGE_HEADER
);
141 BufferPos
= *TempBuffer
+ sizeof (EFI_HII_PACKAGE_HEADER
);
143 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
144 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ sizeof (EFI_HII_PACKAGE_HEADER
));
145 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
146 GetFormSet
= (BOOLEAN
) ((FormSetGuid
== NULL
) ? TRUE
: FALSE
);
150 while (Offset
< PackageHeader
.Length
) {
151 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
152 BufferPos
+= IfrOpHdr
->Length
;
153 *TempBufferSize
+= IfrOpHdr
->Length
;
155 switch (IfrOpHdr
->OpCode
) {
156 case EFI_IFR_FORM_SET_OP
:
157 if (FormSetGuid
!= NULL
) {
158 if (CompareMem (&((EFI_IFR_FORM_SET
*) IfrOpHdr
)->Guid
, FormSetGuid
, sizeof (EFI_GUID
)) == 0) {
164 case EFI_IFR_FORM_OP
:
165 if (CompareMem (&((EFI_IFR_FORM
*) IfrOpHdr
)->FormId
, &FormId
, sizeof (EFI_FORM_ID
)) == 0) {
170 case EFI_IFR_GUID_OP
:
171 if (!GetFormSet
|| !GetForm
|| Updated
) {
173 // Go to the next Op-Code
175 Offset
+= IfrOpHdr
->Length
;
176 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
180 ExtendOpCode
= ((EFI_IFR_GUID_LABEL
*) IfrOpHdr
)->ExtendOpCode
;
181 LabelNumber
= ReadUnaligned16 ((UINT16
*)(VOID
*)&((EFI_IFR_GUID_LABEL
*)IfrOpHdr
)->Number
);
182 if ((ExtendOpCode
!= EFI_IFR_EXTEND_OP_LABEL
) || (LabelNumber
!= Label
)
183 || !CompareGuid ((EFI_GUID
*)(UINTN
)(&((EFI_IFR_GUID_LABEL
*)IfrOpHdr
)->Guid
), &mIfrVendorGuid
)) {
185 // Go to the next Op-Code
187 Offset
+= IfrOpHdr
->Length
;
188 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
192 if (Insert
&& (Data
!= NULL
)) {
194 // insert the DataCount amount of opcodes to TempBuffer if Data is NULL remove
195 // DataCount amount of opcodes unless runing into a label.
197 AddOpCode
= (EFI_IFR_OP_HEADER
*)Data
->Data
;
199 while (AddSize
< Data
->Offset
) {
200 CopyMem (BufferPos
, AddOpCode
, AddOpCode
->Length
);
201 BufferPos
+= AddOpCode
->Length
;
202 *TempBufferSize
+= AddOpCode
->Length
;
204 AddSize
+= AddOpCode
->Length
;
205 AddOpCode
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (AddOpCode
) + AddOpCode
->Length
);
209 // Search the next Label.
212 Offset
+= IfrOpHdr
->Length
;
214 // Search the next label and Fail if not label found.
216 if (Offset
>= PackageHeader
.Length
) {
219 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
220 if (IfrOpHdr
->OpCode
== EFI_IFR_GUID_OP
) {
221 ExtendOpCode
= ((EFI_IFR_GUID_LABEL
*) IfrOpHdr
)->ExtendOpCode
;
222 if ((ExtendOpCode
== EFI_IFR_EXTEND_OP_LABEL
) && CompareGuid ((EFI_GUID
*)(UINTN
)(&((EFI_IFR_GUID_LABEL
*)IfrOpHdr
)->Guid
), &mIfrVendorGuid
)) {
229 AddOpCode
= (EFI_IFR_OP_HEADER
*)Data
->Data
;
231 while (AddSize
< Data
->Offset
) {
232 CopyMem (BufferPos
, AddOpCode
, AddOpCode
->Length
);
233 BufferPos
+= AddOpCode
->Length
;
234 *TempBufferSize
+= AddOpCode
->Length
;
236 AddSize
+= AddOpCode
->Length
;
237 AddOpCode
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (AddOpCode
) + AddOpCode
->Length
);
242 // copy the next label
244 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
245 BufferPos
+= IfrOpHdr
->Length
;
246 *TempBufferSize
+= IfrOpHdr
->Length
;
256 // Go to the next Op-Code
258 Offset
+= IfrOpHdr
->Length
;
259 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
263 // Update the package length.
265 PackageHeader
.Length
= *TempBufferSize
;
266 CopyMem (*TempBuffer
, &PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
270 FreePool (*TempBuffer
);
272 return EFI_NOT_FOUND
;
279 This function initialize the data structure for dynamic opcode.
281 @param UpdateData The adding data;
282 @param BufferSize Length of the buffer to fill dynamic opcodes.
284 @retval EFI_SUCCESS Update data is initialized.
285 @retval EFI_INVALID_PARAMETER UpdateData is NULL.
286 @retval EFI_OUT_OF_RESOURCES No enough memory to allocate.
290 IfrLibInitUpdateData (
291 IN OUT EFI_HII_UPDATE_DATA
*UpdateData
,
295 ASSERT (UpdateData
!= NULL
);
297 UpdateData
->BufferSize
= BufferSize
;
298 UpdateData
->Offset
= 0;
299 UpdateData
->Data
= AllocatePool (BufferSize
);
301 return (UpdateData
->Data
!= NULL
) ? EFI_SUCCESS
: EFI_OUT_OF_RESOURCES
;
306 This function free the resource of update data.
308 @param UpdateData The adding data;
312 IfrLibFreeUpdateData (
313 IN EFI_HII_UPDATE_DATA
*UpdateData
316 ASSERT (UpdateData
!= NULL
);
318 FreePool (UpdateData
->Data
);
319 UpdateData
->Data
= NULL
;
324 This function allows the caller to update a form that has
325 previously been registered with the EFI HII database.
327 @param Handle Hii Handle
328 @param FormSetGuid The formset should be updated.
329 @param FormId The form should be updated.
330 @param Label Update information starting immediately after this
332 @param Insert If TRUE and Data is not NULL, insert data after
333 Label. If FALSE, replace opcodes between two
335 @param Data The adding data; If NULL, remove opcodes between
338 @retval EFI_SUCCESS Update success.
339 @retval Other Update fail.
345 IN EFI_HII_HANDLE Handle
,
346 IN EFI_GUID
*FormSetGuid
, OPTIONAL
347 IN EFI_FORM_ID FormId
,
350 IN EFI_HII_UPDATE_DATA
*Data
354 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
355 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
357 EFI_HII_PACKAGE_LIST_HEADER
*UpdateBuffer
;
359 UINT8
*UpdateBufferPos
;
360 EFI_HII_PACKAGE_HEADER PackageHeader
;
361 EFI_HII_PACKAGE_HEADER
*Package
;
362 UINT32 PackageLength
;
363 EFI_HII_PACKAGE_HEADER
*TempBuffer
;
364 UINT32 TempBufferSize
;
368 return EFI_INVALID_PARAMETER
;
371 HiiDatabase
= gIfrLibHiiDatabase
;
374 // Get the orginal package list
377 HiiPackageList
= NULL
;
378 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
379 if (Status
== EFI_BUFFER_TOO_SMALL
) {
380 HiiPackageList
= AllocatePool (BufferSize
);
381 ASSERT (HiiPackageList
!= NULL
);
383 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
384 if (EFI_ERROR (Status
)) {
385 FreePool (HiiPackageList
);
391 // Calculate and allocate space for retrieval of IFR data
393 BufferSize
+= Data
->Offset
;
394 UpdateBuffer
= AllocateZeroPool (BufferSize
);
395 if (UpdateBuffer
== NULL
) {
396 return EFI_OUT_OF_RESOURCES
;
399 UpdateBufferPos
= (UINT8
*) UpdateBuffer
;
402 // copy the package list header
404 CopyMem (UpdateBufferPos
, HiiPackageList
, sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
405 UpdateBufferPos
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
408 for (Index
= 0; ; Index
++) {
409 Status
= GetPackageDataFromPackageList (HiiPackageList
, Index
, &PackageLength
, &Package
);
410 if (Status
== EFI_SUCCESS
) {
411 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
412 if ((PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) && !Updated
) {
413 Status
= UpdateFormPackageData (FormSetGuid
, FormId
, Package
, PackageLength
, Label
, Insert
, Data
, (UINT8
**)&TempBuffer
, &TempBufferSize
);
414 if (!EFI_ERROR(Status
)) {
415 if (FormSetGuid
== NULL
) {
418 CopyMem (UpdateBufferPos
, TempBuffer
, TempBufferSize
);
419 UpdateBufferPos
+= TempBufferSize
;
420 FreePool (TempBuffer
);
425 CopyMem (UpdateBufferPos
, Package
, PackageLength
);
426 UpdateBufferPos
+= PackageLength
;
427 } else if (Status
== EFI_NOT_FOUND
) {
430 FreePool (HiiPackageList
);
436 // Update package list length
438 BufferSize
= UpdateBufferPos
- (UINT8
*) UpdateBuffer
;
439 WriteUnaligned32 (&UpdateBuffer
->PackageLength
, (UINT32
)BufferSize
);
441 FreePool (HiiPackageList
);
443 return HiiDatabase
->UpdatePackageList (HiiDatabase
, Handle
, UpdateBuffer
);
448 Configure the buffer accrording to ConfigBody strings in the format of
449 <Length:4 bytes>, <Offset: 2 bytes>, <Width:2 bytes>, <Data:n bytes>.
450 This ConfigBody strings is generated by UEFI VfrCompiler for the default
451 values in a Form Set. The name of the ConfigBody strings is VfrMyIfrNVDataDefault0000
452 constructed following this rule:
453 "Vfr" + varstore.name + "Default" + defaultstore.attributes.
454 Check the generated C file in Output for details.
456 @param Buffer The start address of buffer.
457 @param BufferSize The size of buffer.
458 @param Number The number of the strings.
459 @param ... Variable argument list for default value in <AltResp> format
460 generated by the tool.
462 @retval EFI_BUFFER_TOO_SMALL the BufferSize is too small to operate.
463 @retval EFI_INVALID_PARAMETER Buffer is NULL or BufferSize is 0.
464 @retval EFI_SUCCESS Operation successful.
469 IfrLibExtractDefault(
471 IN UINTN
*BufferSize
,
485 if ((Buffer
== NULL
) || (BufferSize
== NULL
)) {
486 return EFI_INVALID_PARAMETER
;
493 VA_START (Args
, Number
);
494 for (Index
= 0; Index
< Number
; Index
++) {
495 BufCfgArray
= (UINT8
*) VA_ARG (Args
, VOID
*);
496 TotalLen
= ReadUnaligned32 ((UINT32
*)BufCfgArray
);
497 BufferPos
= BufCfgArray
+ sizeof (UINT32
);
499 while ((UINT32
)(BufferPos
- BufCfgArray
) < TotalLen
) {
500 Offset
= ReadUnaligned16 ((UINT16
*)BufferPos
);
501 BufferPos
+= sizeof (UINT16
);
502 Width
= ReadUnaligned16 ((UINT16
*)BufferPos
);
503 BufferPos
+= sizeof (UINT16
);
507 if ((UINTN
)(Offset
+ Width
) > *BufferSize
) {
508 return EFI_BUFFER_TOO_SMALL
;
511 CopyMem ((UINT8
*)Buffer
+ Offset
, Value
, Width
);
516 *BufferSize
= (UINTN
)Offset
;