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"
18 Get the specified package from a package list based on an index.
19 The Buffer on output is updated to point to a package header in
20 the HiiPackageList. This is an internal function.
22 @param HiiPackageList The Package List Header.
23 @param PackageIndex The index of the package to get.
24 @param BufferLen The length of the package.
25 @param Buffer The starting address of package.
27 @retval EFI_SUCCESS This function completes successfully.
28 @retval EFI_NOT_FOUND The package is not found.
32 GetPackageDataFromPackageList (
33 IN EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
,
34 IN UINT32 PackageIndex
,
35 OUT UINT32
*BufferLen
,
36 OUT EFI_HII_PACKAGE_HEADER
**Buffer
40 EFI_HII_PACKAGE_HEADER
*Package
;
42 UINT32 PackageListLength
;
43 EFI_HII_PACKAGE_HEADER PackageHeader
;
45 PackageHeader
.Length
= 0;
46 PackageHeader
.Type
= 0;
48 ASSERT(HiiPackageList
!= NULL
);
50 if ((BufferLen
== NULL
) || (Buffer
== NULL
)) {
51 return EFI_INVALID_PARAMETER
;
56 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
57 CopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
58 while (Offset
< PackageListLength
) {
59 Package
= (EFI_HII_PACKAGE_HEADER
*) (((UINT8
*) HiiPackageList
) + Offset
);
60 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
61 if (Index
== PackageIndex
) {
64 Offset
+= PackageHeader
.Length
;
67 if (Offset
>= PackageListLength
) {
69 // no package found in this Package List
74 *BufferLen
= PackageHeader
.Length
;
80 This is the internal worker function to update the data in
81 a form specified by FormSetGuid,
83 @param FormSetGuid The optional Formset GUID.
84 @param FormId The form ID>
85 @param Package The package header.
86 @param PackageLength The package length.
87 @param Label The label for the update.
88 @param Insert True if inserting opcode to the form.
89 @param Data The data payload.
90 @param TempBuffer The resultant package.
91 @param TempBufferSize The length of the resultant package.
93 @retval EFI_OUT_OF_RESOURCES If there is not enough memory to complete the operation.
94 @retval EFI_INVALID_PARAMETER If TempBuffer or TempBufferSize is NULL.
95 @retval EFI_SUCCESS The function completes successfully.
100 UpdateFormPackageData (
101 IN EFI_GUID
*FormSetGuid
, OPTIONAL
102 IN EFI_FORM_ID FormId
,
103 IN EFI_HII_PACKAGE_HEADER
*Package
,
104 IN UINT32 PackageLength
,
107 IN EFI_HII_UPDATE_DATA
*Data
,
108 OUT UINT8
**TempBuffer
,
109 OUT UINT32
*TempBufferSize
114 EFI_HII_PACKAGE_HEADER PackageHeader
;
116 EFI_IFR_OP_HEADER
*IfrOpHdr
;
122 EFI_IFR_OP_HEADER
*AddOpCode
;
124 if ((TempBuffer
== NULL
) || (TempBufferSize
== NULL
)) {
125 return EFI_INVALID_PARAMETER
;
128 *TempBufferSize
= PackageLength
;
130 *TempBufferSize
+= Data
->Offset
;
132 *TempBuffer
= AllocateZeroPool (*TempBufferSize
);
133 if (*TempBuffer
== NULL
) {
134 return EFI_OUT_OF_RESOURCES
;
137 CopyMem (*TempBuffer
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
138 *TempBufferSize
= sizeof (EFI_HII_PACKAGE_HEADER
);
139 BufferPos
= *TempBuffer
+ sizeof (EFI_HII_PACKAGE_HEADER
);
141 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
142 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)((UINT8
*) Package
+ sizeof (EFI_HII_PACKAGE_HEADER
));
143 Offset
= sizeof (EFI_HII_PACKAGE_HEADER
);
144 GetFormSet
= (BOOLEAN
) ((FormSetGuid
== NULL
) ? TRUE
: FALSE
);
148 while (Offset
< PackageHeader
.Length
) {
149 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
150 BufferPos
+= IfrOpHdr
->Length
;
151 *TempBufferSize
+= IfrOpHdr
->Length
;
153 switch (IfrOpHdr
->OpCode
) {
154 case EFI_IFR_FORM_SET_OP
:
155 if (FormSetGuid
!= NULL
) {
156 if (CompareMem (&((EFI_IFR_FORM_SET
*) IfrOpHdr
)->Guid
, FormSetGuid
, sizeof (EFI_GUID
)) == 0) {
162 case EFI_IFR_FORM_OP
:
163 if (CompareMem (&((EFI_IFR_FORM
*) IfrOpHdr
)->FormId
, &FormId
, sizeof (EFI_FORM_ID
)) == 0) {
168 case EFI_IFR_GUID_OP
:
169 if (!GetFormSet
|| !GetForm
|| Updated
) {
171 // Go to the next Op-Code
173 Offset
+= IfrOpHdr
->Length
;
174 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
178 ExtendOpCode
= ((EFI_IFR_GUID_LABEL
*) IfrOpHdr
)->ExtendOpCode
;
179 CopyMem (&LabelNumber
, &((EFI_IFR_GUID_LABEL
*)IfrOpHdr
)->Number
, sizeof (UINT16
));
180 if ((ExtendOpCode
!= EFI_IFR_EXTEND_OP_LABEL
) || (LabelNumber
!= Label
)) {
182 // Go to the next Op-Code
184 Offset
+= IfrOpHdr
->Length
;
185 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
189 if (Insert
&& (Data
!= NULL
)) {
191 // insert the DataCount amount of opcodes to TempBuffer if Data is NULL remove
192 // DataCount amount of opcodes unless runing into a label.
194 AddOpCode
= (EFI_IFR_OP_HEADER
*)Data
->Data
;
196 while (AddSize
< Data
->Offset
) {
197 CopyMem (BufferPos
, AddOpCode
, AddOpCode
->Length
);
198 BufferPos
+= AddOpCode
->Length
;
199 *TempBufferSize
+= AddOpCode
->Length
;
201 AddSize
+= AddOpCode
->Length
;
202 AddOpCode
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (AddOpCode
) + AddOpCode
->Length
);
206 // Search the next Label.
209 Offset
+= IfrOpHdr
->Length
;
211 // Search the next label and Fail if not label found.
213 if (Offset
>= PackageHeader
.Length
) {
216 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
217 if (IfrOpHdr
->OpCode
== EFI_IFR_GUID_OP
) {
218 ExtendOpCode
= ((EFI_IFR_GUID_LABEL
*) IfrOpHdr
)->ExtendOpCode
;
219 if (ExtendOpCode
== EFI_IFR_EXTEND_OP_LABEL
) {
226 AddOpCode
= (EFI_IFR_OP_HEADER
*)Data
->Data
;
228 while (AddSize
< Data
->Offset
) {
229 CopyMem (BufferPos
, AddOpCode
, AddOpCode
->Length
);
230 BufferPos
+= AddOpCode
->Length
;
231 *TempBufferSize
+= AddOpCode
->Length
;
233 AddSize
+= AddOpCode
->Length
;
234 AddOpCode
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (AddOpCode
) + AddOpCode
->Length
);
239 // copy the next label
241 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
242 BufferPos
+= IfrOpHdr
->Length
;
243 *TempBufferSize
+= IfrOpHdr
->Length
;
253 // Go to the next Op-Code
255 Offset
+= IfrOpHdr
->Length
;
256 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
260 // Update the package length.
262 PackageHeader
.Length
= *TempBufferSize
;
263 CopyMem (*TempBuffer
, &PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
267 gBS
->FreePool (*TempBuffer
);
269 return EFI_NOT_FOUND
;
277 This function allows the caller to update a form that has
278 previously been registered with the EFI HII database.
280 @param Handle Hii Handle
281 @param FormSetGuid The formset should be updated.
282 @param FormId The form should be updated.
283 @param Label Update information starting immediately after this
285 @param Insert If TRUE and Data is not NULL, insert data after
286 Label. If FALSE, replace opcodes between two
288 @param Data The adding data; If NULL, remove opcodes between
291 @retval EFI_SUCCESS Update success.
292 @retval Other Update fail.
298 IN EFI_HII_HANDLE Handle
,
299 IN EFI_GUID
*FormSetGuid
, OPTIONAL
300 IN EFI_FORM_ID FormId
,
303 IN EFI_HII_UPDATE_DATA
*Data
307 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
308 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
310 EFI_HII_PACKAGE_LIST_HEADER
*UpdateBuffer
;
312 UINT8
*UpdateBufferPos
;
313 EFI_HII_PACKAGE_HEADER PackageHeader
;
314 EFI_HII_PACKAGE_HEADER
*Package
;
315 UINT32 PackageLength
;
316 EFI_HII_PACKAGE_HEADER
*TempBuffer
;
317 UINT32 TempBufferSize
;
321 return EFI_INVALID_PARAMETER
;
324 HiiDatabase
= gIfrLibHiiDatabase
;
327 // Get the orginal package list
330 HiiPackageList
= NULL
;
331 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
332 if (Status
== EFI_BUFFER_TOO_SMALL
) {
333 HiiPackageList
= AllocatePool (BufferSize
);
334 ASSERT (HiiPackageList
!= NULL
);
336 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
337 if (EFI_ERROR (Status
)) {
338 gBS
->FreePool (HiiPackageList
);
344 // Calculate and allocate space for retrieval of IFR data
346 BufferSize
+= Data
->Offset
;
347 UpdateBuffer
= AllocateZeroPool (BufferSize
);
348 if (UpdateBuffer
== NULL
) {
349 return EFI_OUT_OF_RESOURCES
;
352 UpdateBufferPos
= (UINT8
*) UpdateBuffer
;
355 // copy the package list header
357 CopyMem (UpdateBufferPos
, HiiPackageList
, sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
358 UpdateBufferPos
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
361 for (Index
= 0; ; Index
++) {
362 Status
= GetPackageDataFromPackageList (HiiPackageList
, Index
, &PackageLength
, &Package
);
363 if (Status
== EFI_SUCCESS
) {
364 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
365 if ((PackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) && !Updated
) {
366 Status
= UpdateFormPackageData (FormSetGuid
, FormId
, Package
, PackageLength
, Label
, Insert
, Data
, (UINT8
**)&TempBuffer
, &TempBufferSize
);
367 if (!EFI_ERROR(Status
)) {
368 if (FormSetGuid
== NULL
) {
371 CopyMem (UpdateBufferPos
, TempBuffer
, TempBufferSize
);
372 UpdateBufferPos
+= TempBufferSize
;
373 gBS
->FreePool (TempBuffer
);
378 CopyMem (UpdateBufferPos
, Package
, PackageLength
);
379 UpdateBufferPos
+= PackageLength
;
380 } else if (Status
== EFI_NOT_FOUND
) {
383 gBS
->FreePool (HiiPackageList
);
389 // Update package list length
391 BufferSize
= UpdateBufferPos
- (UINT8
*) UpdateBuffer
;
392 CopyMem (&UpdateBuffer
->PackageLength
, &BufferSize
, sizeof (UINT32
));
394 gBS
->FreePool (HiiPackageList
);
396 return HiiDatabase
->UpdatePackageList (HiiDatabase
, Handle
, UpdateBuffer
);
401 Configure the buffer accrording to ConfigBody strings.
403 @param Buffer The start address of buffer.
404 @param BufferSize The size of buffer.
405 @param Number The number of the strings.
406 @param ... Variable argument list for default value in <AltResp> format
407 generated by the tool.
409 @retval EFI_BUFFER_TOO_SMALL the BufferSize is too small to operate.
410 @retval EFI_INVALID_PARAMETER Buffer is NULL or BufferSize is 0.
411 @retval EFI_SUCCESS Operation successful.
416 IfrLibExtractDefault(
418 IN UINTN
*BufferSize
,
432 if ((Buffer
== NULL
) || (BufferSize
== NULL
)) {
433 return EFI_INVALID_PARAMETER
;
440 VA_START (Args
, Number
);
441 for (Index
= 0; Index
< Number
; Index
++) {
442 BufCfgArray
= (UINT8
*) VA_ARG (Args
, VOID
*);
443 CopyMem (&TotalLen
, BufCfgArray
, sizeof (UINT32
));
444 BufferPos
= BufCfgArray
+ sizeof (UINT32
);
446 while ((UINT32
)(BufferPos
- BufCfgArray
) < TotalLen
) {
447 CopyMem (&Offset
, BufferPos
, sizeof (UINT16
));
448 BufferPos
+= sizeof (UINT16
);
449 CopyMem (&Width
, BufferPos
, sizeof (UINT16
));
450 BufferPos
+= sizeof (UINT16
);
454 if ((UINTN
)(Offset
+ Width
) > *BufferSize
) {
455 return EFI_BUFFER_TOO_SMALL
;
458 CopyMem ((UINT8
*)Buffer
+ Offset
, Value
, Width
);
463 *BufferSize
= (UINTN
)Offset
;