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 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
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 CopyMem (&LabelNumber
, &((EFI_IFR_GUID_LABEL
*)IfrOpHdr
)->Number
, sizeof (UINT16
));
182 if ((ExtendOpCode
!= EFI_IFR_EXTEND_OP_LABEL
) || (LabelNumber
!= Label
)
183 || !CompareGuid (&((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_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;
310 @retval EFI_SUCCESS Resource in UpdateData is released.
311 @retval EFI_INVALID_PARAMETER UpdateData is NULL.
315 IfrLibFreeUpdateData (
316 IN EFI_HII_UPDATE_DATA
*UpdateData
321 if (UpdateData
== NULL
) {
322 return EFI_INVALID_PARAMETER
;
325 Status
= gBS
->FreePool (UpdateData
->Data
);
326 UpdateData
->Data
= NULL
;
332 This function allows the caller to update a form that has
333 previously been registered with the EFI HII database.
335 @param Handle Hii Handle
336 @param FormSetGuid The formset should be updated.
337 @param FormId The form should be updated.
338 @param Label Update information starting immediately after this
340 @param Insert If TRUE and Data is not NULL, insert data after
341 Label. If FALSE, replace opcodes between two
343 @param Data The adding data; If NULL, remove opcodes between
346 @retval EFI_SUCCESS Update success.
347 @retval Other Update fail.
353 IN EFI_HII_HANDLE Handle
,
354 IN EFI_GUID
*FormSetGuid
, OPTIONAL
355 IN EFI_FORM_ID FormId
,
358 IN EFI_HII_UPDATE_DATA
*Data
362 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
363 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
365 EFI_HII_PACKAGE_LIST_HEADER
*UpdateBuffer
;
367 UINT8
*UpdateBufferPos
;
368 EFI_HII_PACKAGE_HEADER PackageHeader
;
369 EFI_HII_PACKAGE_HEADER
*Package
;
370 UINT32 PackageLength
;
371 EFI_HII_PACKAGE_HEADER
*TempBuffer
;
372 UINT32 TempBufferSize
;
376 return EFI_INVALID_PARAMETER
;
379 HiiDatabase
= gIfrLibHiiDatabase
;
382 // Get the orginal package list
385 HiiPackageList
= NULL
;
386 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
387 if (Status
== EFI_BUFFER_TOO_SMALL
) {
388 HiiPackageList
= AllocatePool (BufferSize
);
389 ASSERT (HiiPackageList
!= NULL
);
391 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
392 if (EFI_ERROR (Status
)) {
393 FreePool (HiiPackageList
);
399 // Calculate and allocate space for retrieval of IFR data
401 BufferSize
+= Data
->Offset
;
402 UpdateBuffer
= AllocateZeroPool (BufferSize
);
403 if (UpdateBuffer
== NULL
) {
404 return EFI_OUT_OF_RESOURCES
;
407 UpdateBufferPos
= (UINT8
*) UpdateBuffer
;
410 // copy the package list header
412 CopyMem (UpdateBufferPos
, HiiPackageList
, sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
413 UpdateBufferPos
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
416 for (Index
= 0; ; Index
++) {
417 Status
= GetPackageDataFromPackageList (HiiPackageList
, Index
, &PackageLength
, &Package
);
418 if (Status
== EFI_SUCCESS
) {
419 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
420 if ((PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) && !Updated
) {
421 Status
= UpdateFormPackageData (FormSetGuid
, FormId
, Package
, PackageLength
, Label
, Insert
, Data
, (UINT8
**)&TempBuffer
, &TempBufferSize
);
422 if (!EFI_ERROR(Status
)) {
423 if (FormSetGuid
== NULL
) {
426 CopyMem (UpdateBufferPos
, TempBuffer
, TempBufferSize
);
427 UpdateBufferPos
+= TempBufferSize
;
428 FreePool (TempBuffer
);
433 CopyMem (UpdateBufferPos
, Package
, PackageLength
);
434 UpdateBufferPos
+= PackageLength
;
435 } else if (Status
== EFI_NOT_FOUND
) {
438 FreePool (HiiPackageList
);
444 // Update package list length
446 BufferSize
= UpdateBufferPos
- (UINT8
*) UpdateBuffer
;
447 CopyMem (&UpdateBuffer
->PackageLength
, &BufferSize
, sizeof (UINT32
));
449 FreePool (HiiPackageList
);
451 return HiiDatabase
->UpdatePackageList (HiiDatabase
, Handle
, UpdateBuffer
);
456 Configure the buffer accrording to ConfigBody strings.
458 @param Buffer The start address of buffer.
459 @param BufferSize The size of buffer.
460 @param Number The number of the strings.
461 @param ... Variable argument list for default value in <AltResp> format
462 generated by the tool.
464 @retval EFI_BUFFER_TOO_SMALL the BufferSize is too small to operate.
465 @retval EFI_INVALID_PARAMETER Buffer is NULL or BufferSize is 0.
466 @retval EFI_SUCCESS Operation successful.
471 IfrLibExtractDefault(
473 IN UINTN
*BufferSize
,
487 if ((Buffer
== NULL
) || (BufferSize
== NULL
)) {
488 return EFI_INVALID_PARAMETER
;
495 VA_START (Args
, Number
);
496 for (Index
= 0; Index
< Number
; Index
++) {
497 BufCfgArray
= (UINT8
*) VA_ARG (Args
, VOID
*);
498 CopyMem (&TotalLen
, BufCfgArray
, sizeof (UINT32
));
499 BufferPos
= BufCfgArray
+ sizeof (UINT32
);
501 while ((UINT32
)(BufferPos
- BufCfgArray
) < TotalLen
) {
502 CopyMem (&Offset
, BufferPos
, sizeof (UINT16
));
503 BufferPos
+= sizeof (UINT16
);
504 CopyMem (&Width
, BufferPos
, sizeof (UINT16
));
505 BufferPos
+= sizeof (UINT16
);
509 if ((UINTN
)(Offset
+ Width
) > *BufferSize
) {
510 return EFI_BUFFER_TOO_SMALL
;
513 CopyMem ((UINT8
*)Buffer
+ Offset
, Value
, Width
);
518 *BufferSize
= (UINTN
)Offset
;