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
)) {
184 // Go to the next Op-Code
186 Offset
+= IfrOpHdr
->Length
;
187 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
191 if (Insert
&& (Data
!= NULL
)) {
193 // insert the DataCount amount of opcodes to TempBuffer if Data is NULL remove
194 // DataCount amount of opcodes unless runing into a label.
196 AddOpCode
= (EFI_IFR_OP_HEADER
*)Data
->Data
;
198 while (AddSize
< Data
->Offset
) {
199 CopyMem (BufferPos
, AddOpCode
, AddOpCode
->Length
);
200 BufferPos
+= AddOpCode
->Length
;
201 *TempBufferSize
+= AddOpCode
->Length
;
203 AddSize
+= AddOpCode
->Length
;
204 AddOpCode
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (AddOpCode
) + AddOpCode
->Length
);
208 // Search the next Label.
211 Offset
+= IfrOpHdr
->Length
;
213 // Search the next label and Fail if not label found.
215 if (Offset
>= PackageHeader
.Length
) {
218 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
219 if (IfrOpHdr
->OpCode
== EFI_IFR_GUID_OP
) {
220 ExtendOpCode
= ((EFI_IFR_GUID_LABEL
*) IfrOpHdr
)->ExtendOpCode
;
221 if (ExtendOpCode
== EFI_IFR_EXTEND_OP_LABEL
) {
228 AddOpCode
= (EFI_IFR_OP_HEADER
*)Data
->Data
;
230 while (AddSize
< Data
->Offset
) {
231 CopyMem (BufferPos
, AddOpCode
, AddOpCode
->Length
);
232 BufferPos
+= AddOpCode
->Length
;
233 *TempBufferSize
+= AddOpCode
->Length
;
235 AddSize
+= AddOpCode
->Length
;
236 AddOpCode
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (AddOpCode
) + AddOpCode
->Length
);
241 // copy the next label
243 CopyMem (BufferPos
, IfrOpHdr
, IfrOpHdr
->Length
);
244 BufferPos
+= IfrOpHdr
->Length
;
245 *TempBufferSize
+= IfrOpHdr
->Length
;
255 // Go to the next Op-Code
257 Offset
+= IfrOpHdr
->Length
;
258 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) ((CHAR8
*) (IfrOpHdr
) + IfrOpHdr
->Length
);
262 // Update the package length.
264 PackageHeader
.Length
= *TempBufferSize
;
265 CopyMem (*TempBuffer
, &PackageHeader
, sizeof (EFI_HII_PACKAGE_HEADER
));
269 FreePool (*TempBuffer
);
271 return EFI_NOT_FOUND
;
279 This function allows the caller to update a form that has
280 previously been registered with the EFI HII database.
282 @param Handle Hii Handle
283 @param FormSetGuid The formset should be updated.
284 @param FormId The form should be updated.
285 @param Label Update information starting immediately after this
287 @param Insert If TRUE and Data is not NULL, insert data after
288 Label. If FALSE, replace opcodes between two
290 @param Data The adding data; If NULL, remove opcodes between
293 @retval EFI_SUCCESS Update success.
294 @retval Other Update fail.
300 IN EFI_HII_HANDLE Handle
,
301 IN EFI_GUID
*FormSetGuid
, OPTIONAL
302 IN EFI_FORM_ID FormId
,
305 IN EFI_HII_UPDATE_DATA
*Data
309 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
310 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
312 EFI_HII_PACKAGE_LIST_HEADER
*UpdateBuffer
;
314 UINT8
*UpdateBufferPos
;
315 EFI_HII_PACKAGE_HEADER PackageHeader
;
316 EFI_HII_PACKAGE_HEADER
*Package
;
317 UINT32 PackageLength
;
318 EFI_HII_PACKAGE_HEADER
*TempBuffer
;
319 UINT32 TempBufferSize
;
323 return EFI_INVALID_PARAMETER
;
326 HiiDatabase
= gIfrLibHiiDatabase
;
329 // Get the orginal package list
332 HiiPackageList
= NULL
;
333 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
334 if (Status
== EFI_BUFFER_TOO_SMALL
) {
335 HiiPackageList
= AllocatePool (BufferSize
);
336 ASSERT (HiiPackageList
!= NULL
);
338 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
339 if (EFI_ERROR (Status
)) {
340 FreePool (HiiPackageList
);
346 // Calculate and allocate space for retrieval of IFR data
348 BufferSize
+= Data
->Offset
;
349 UpdateBuffer
= AllocateZeroPool (BufferSize
);
350 if (UpdateBuffer
== NULL
) {
351 return EFI_OUT_OF_RESOURCES
;
354 UpdateBufferPos
= (UINT8
*) UpdateBuffer
;
357 // copy the package list header
359 CopyMem (UpdateBufferPos
, HiiPackageList
, sizeof (EFI_HII_PACKAGE_LIST_HEADER
));
360 UpdateBufferPos
+= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
363 for (Index
= 0; ; Index
++) {
364 Status
= GetPackageDataFromPackageList (HiiPackageList
, Index
, &PackageLength
, &Package
);
365 if (Status
== EFI_SUCCESS
) {
366 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
367 if ((PackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) && !Updated
) {
368 Status
= UpdateFormPackageData (FormSetGuid
, FormId
, Package
, PackageLength
, Label
, Insert
, Data
, (UINT8
**)&TempBuffer
, &TempBufferSize
);
369 if (!EFI_ERROR(Status
)) {
370 if (FormSetGuid
== NULL
) {
373 CopyMem (UpdateBufferPos
, TempBuffer
, TempBufferSize
);
374 UpdateBufferPos
+= TempBufferSize
;
375 FreePool (TempBuffer
);
380 CopyMem (UpdateBufferPos
, Package
, PackageLength
);
381 UpdateBufferPos
+= PackageLength
;
382 } else if (Status
== EFI_NOT_FOUND
) {
385 FreePool (HiiPackageList
);
391 // Update package list length
393 BufferSize
= UpdateBufferPos
- (UINT8
*) UpdateBuffer
;
394 CopyMem (&UpdateBuffer
->PackageLength
, &BufferSize
, sizeof (UINT32
));
396 FreePool (HiiPackageList
);
398 return HiiDatabase
->UpdatePackageList (HiiDatabase
, Handle
, UpdateBuffer
);
403 Configure the buffer accrording to ConfigBody strings.
405 @param Buffer The start address of buffer.
406 @param BufferSize The size of buffer.
407 @param Number The number of the strings.
408 @param ... Variable argument list for default value in <AltResp> format
409 generated by the tool.
411 @retval EFI_BUFFER_TOO_SMALL the BufferSize is too small to operate.
412 @retval EFI_INVALID_PARAMETER Buffer is NULL or BufferSize is 0.
413 @retval EFI_SUCCESS Operation successful.
418 IfrLibExtractDefault(
420 IN UINTN
*BufferSize
,
434 if ((Buffer
== NULL
) || (BufferSize
== NULL
)) {
435 return EFI_INVALID_PARAMETER
;
442 VA_START (Args
, Number
);
443 for (Index
= 0; Index
< Number
; Index
++) {
444 BufCfgArray
= (UINT8
*) VA_ARG (Args
, VOID
*);
445 CopyMem (&TotalLen
, BufCfgArray
, sizeof (UINT32
));
446 BufferPos
= BufCfgArray
+ sizeof (UINT32
);
448 while ((UINT32
)(BufferPos
- BufCfgArray
) < TotalLen
) {
449 CopyMem (&Offset
, BufferPos
, sizeof (UINT16
));
450 BufferPos
+= sizeof (UINT16
);
451 CopyMem (&Width
, BufferPos
, sizeof (UINT16
));
452 BufferPos
+= sizeof (UINT16
);
456 if ((UINTN
)(Offset
+ Width
) > *BufferSize
) {
457 return EFI_BUFFER_TOO_SMALL
;
460 CopyMem ((UINT8
*)Buffer
+ Offset
, Value
, Width
);
465 *BufferSize
= (UINTN
)Offset
;