]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/ExtendedIfrSupportLib/Form.c
sync comments, fix function header, rename variable name to follow coding style.
[mirror_edk2.git] / MdeModulePkg / Library / ExtendedIfrSupportLib / Form.c
1 /** @file
2 Common Library Routines to assist handle HII elements.
3
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
9
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.
12
13 **/
14
15 #include "LibraryInternal.h"
16
17 extern EFI_HII_DATABASE_PROTOCOL *gIfrLibHiiDatabase;
18
19 /**
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.
23
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.
28
29 @retval EFI_SUCCESS This function completes successfully.
30 @retval EFI_NOT_FOUND The package is not found.
31
32 **/
33 EFI_STATUS
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
39 )
40 {
41 UINT32 Index;
42 EFI_HII_PACKAGE_HEADER *Package;
43 UINT32 Offset;
44 UINT32 PackageListLength;
45 EFI_HII_PACKAGE_HEADER PackageHeader;
46
47 PackageHeader.Length = 0;
48 PackageHeader.Type = 0;
49
50 ASSERT(HiiPackageList != NULL);
51
52 if ((BufferLen == NULL) || (Buffer == NULL)) {
53 return EFI_INVALID_PARAMETER;
54 }
55
56 Package = NULL;
57 Index = 0;
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) {
64 break;
65 }
66 Offset += PackageHeader.Length;
67 Index++;
68 }
69 if (Offset >= PackageListLength) {
70 //
71 // no package found in this Package List
72 //
73 return EFI_NOT_FOUND;
74 }
75
76 *BufferLen = PackageHeader.Length;
77 *Buffer = Package;
78 return EFI_SUCCESS;
79 }
80
81 /**
82 This is the internal worker function to update the data in
83 a form specified by FormSetGuid, FormId and Label.
84
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.
94
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.
98
99 **/
100 EFI_STATUS
101 EFIAPI
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,
107 IN UINT16 Label,
108 IN BOOLEAN Insert,
109 IN EFI_HII_UPDATE_DATA *Data,
110 OUT UINT8 **TempBuffer,
111 OUT UINT32 *TempBufferSize
112 )
113 {
114 UINTN AddSize;
115 UINT8 *BufferPos;
116 EFI_HII_PACKAGE_HEADER PackageHeader;
117 UINTN Offset;
118 EFI_IFR_OP_HEADER *IfrOpHdr;
119 BOOLEAN GetFormSet;
120 BOOLEAN GetForm;
121 UINT8 ExtendOpCode;
122 UINT16 LabelNumber;
123 BOOLEAN Updated;
124 EFI_IFR_OP_HEADER *AddOpCode;
125
126 if ((TempBuffer == NULL) || (TempBufferSize == NULL)) {
127 return EFI_INVALID_PARAMETER;
128 }
129
130 *TempBufferSize = PackageLength;
131 if (Data != NULL) {
132 *TempBufferSize += Data->Offset;
133 }
134 *TempBuffer = AllocateZeroPool (*TempBufferSize);
135 if (*TempBuffer == NULL) {
136 return EFI_OUT_OF_RESOURCES;
137 }
138
139 CopyMem (*TempBuffer, Package, sizeof (EFI_HII_PACKAGE_HEADER));
140 *TempBufferSize = sizeof (EFI_HII_PACKAGE_HEADER);
141 BufferPos = *TempBuffer + sizeof (EFI_HII_PACKAGE_HEADER);
142
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);
147 GetForm = FALSE;
148 Updated = FALSE;
149
150 while (Offset < PackageHeader.Length) {
151 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
152 BufferPos += IfrOpHdr->Length;
153 *TempBufferSize += IfrOpHdr->Length;
154
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) {
159 GetFormSet = TRUE;
160 }
161 }
162 break;
163
164 case EFI_IFR_FORM_OP:
165 if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {
166 GetForm = TRUE;
167 }
168 break;
169
170 case EFI_IFR_GUID_OP :
171 if (!GetFormSet || !GetForm || Updated) {
172 //
173 // Go to the next Op-Code
174 //
175 Offset += IfrOpHdr->Length;
176 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
177 continue;
178 }
179
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_GUID *)(UINTN)(&((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Guid), &mIfrVendorGuid)) {
184 //
185 // Go to the next Op-Code
186 //
187 Offset += IfrOpHdr->Length;
188 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
189 continue;
190 }
191
192 if (Insert && (Data != NULL)) {
193 //
194 // insert the DataCount amount of opcodes to TempBuffer if Data is NULL remove
195 // DataCount amount of opcodes unless runing into a label.
196 //
197 AddOpCode = (EFI_IFR_OP_HEADER *)Data->Data;
198 AddSize = 0;
199 while (AddSize < Data->Offset) {
200 CopyMem (BufferPos, AddOpCode, AddOpCode->Length);
201 BufferPos += AddOpCode->Length;
202 *TempBufferSize += AddOpCode->Length;
203
204 AddSize += AddOpCode->Length;
205 AddOpCode = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (AddOpCode) + AddOpCode->Length);
206 }
207 } else {
208 //
209 // Search the next Label.
210 //
211 while (TRUE) {
212 Offset += IfrOpHdr->Length;
213 //
214 // Search the next label and Fail if not label found.
215 //
216 if (Offset >= PackageHeader.Length) {
217 goto Fail;
218 }
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)) {
223 break;
224 }
225 }
226 }
227
228 if (Data != NULL) {
229 AddOpCode = (EFI_IFR_OP_HEADER *)Data->Data;
230 AddSize = 0;
231 while (AddSize < Data->Offset) {
232 CopyMem (BufferPos, AddOpCode, AddOpCode->Length);
233 BufferPos += AddOpCode->Length;
234 *TempBufferSize += AddOpCode->Length;
235
236 AddSize += AddOpCode->Length;
237 AddOpCode = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (AddOpCode) + AddOpCode->Length);
238 }
239 }
240
241 //
242 // copy the next label
243 //
244 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
245 BufferPos += IfrOpHdr->Length;
246 *TempBufferSize += IfrOpHdr->Length;
247 }
248
249 Updated = TRUE;
250 break;
251 default :
252 break;
253 }
254
255 //
256 // Go to the next Op-Code
257 //
258 Offset += IfrOpHdr->Length;
259 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
260 }
261
262 //
263 // Update the package length.
264 //
265 PackageHeader.Length = *TempBufferSize;
266 CopyMem (*TempBuffer, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
267
268 Fail:
269 if (!Updated) {
270 FreePool (*TempBuffer);
271 *TempBufferSize = 0;
272 return EFI_NOT_FOUND;
273 }
274
275 return EFI_SUCCESS;
276 }
277
278 /**
279 This function initialize the data structure for dynamic opcode.
280
281 @param UpdateData The adding data;
282 @param BufferSize Length of the buffer to fill dynamic opcodes.
283
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.
287
288 **/
289 EFI_STATUS
290 IfrLibInitUpdateData (
291 IN OUT EFI_HII_UPDATE_DATA *UpdateData,
292 IN UINT32 BufferSize
293 )
294 {
295 ASSERT (UpdateData != NULL);
296
297 UpdateData->BufferSize = BufferSize;
298 UpdateData->Offset = 0;
299 UpdateData->Data = AllocatePool (BufferSize);
300
301 return (UpdateData->Data != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
302 }
303
304 /**
305
306 This function free the resource of update data.
307
308 @param UpdateData The adding data;
309
310 @retval EFI_SUCCESS Resource in UpdateData is released.
311 @retval EFI_INVALID_PARAMETER UpdateData is NULL.
312
313 **/
314 EFI_STATUS
315 IfrLibFreeUpdateData (
316 IN EFI_HII_UPDATE_DATA *UpdateData
317 )
318 {
319 EFI_STATUS Status;
320
321 if (UpdateData == NULL) {
322 return EFI_INVALID_PARAMETER;
323 }
324
325 Status = gBS->FreePool (UpdateData->Data);
326 UpdateData->Data = NULL;
327
328 return Status;
329 }
330
331 /**
332 This function allows the caller to update a form that has
333 previously been registered with the EFI HII database.
334
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
339 label in the IFR
340 @param Insert If TRUE and Data is not NULL, insert data after
341 Label. If FALSE, replace opcodes between two
342 labels with Data
343 @param Data The adding data; If NULL, remove opcodes between
344 two Label.
345
346 @retval EFI_SUCCESS Update success.
347 @retval Other Update fail.
348
349 **/
350 EFI_STATUS
351 EFIAPI
352 IfrLibUpdateForm (
353 IN EFI_HII_HANDLE Handle,
354 IN EFI_GUID *FormSetGuid, OPTIONAL
355 IN EFI_FORM_ID FormId,
356 IN UINT16 Label,
357 IN BOOLEAN Insert,
358 IN EFI_HII_UPDATE_DATA *Data
359 )
360 {
361 EFI_STATUS Status;
362 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
363 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
364 UINT32 Index;
365 EFI_HII_PACKAGE_LIST_HEADER *UpdateBuffer;
366 UINTN BufferSize;
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;
373 BOOLEAN Updated;
374
375 if (Data == NULL) {
376 return EFI_INVALID_PARAMETER;
377 }
378
379 HiiDatabase = gIfrLibHiiDatabase;
380
381 //
382 // Get the orginal package list
383 //
384 BufferSize = 0;
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);
390
391 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
392 if (EFI_ERROR (Status)) {
393 FreePool (HiiPackageList);
394 return Status;
395 }
396 }
397
398 //
399 // Calculate and allocate space for retrieval of IFR data
400 //
401 BufferSize += Data->Offset;
402 UpdateBuffer = AllocateZeroPool (BufferSize);
403 if (UpdateBuffer == NULL) {
404 return EFI_OUT_OF_RESOURCES;
405 }
406
407 UpdateBufferPos = (UINT8 *) UpdateBuffer;
408
409 //
410 // copy the package list header
411 //
412 CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));
413 UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);
414
415 Updated = FALSE;
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) {
424 Updated = TRUE;
425 }
426 CopyMem (UpdateBufferPos, TempBuffer, TempBufferSize);
427 UpdateBufferPos += TempBufferSize;
428 FreePool (TempBuffer);
429 continue;
430 }
431 }
432
433 CopyMem (UpdateBufferPos, Package, PackageLength);
434 UpdateBufferPos += PackageLength;
435 } else if (Status == EFI_NOT_FOUND) {
436 break;
437 } else {
438 FreePool (HiiPackageList);
439 return Status;
440 }
441 }
442
443 //
444 // Update package list length
445 //
446 BufferSize = UpdateBufferPos - (UINT8 *) UpdateBuffer;
447 CopyMem (&UpdateBuffer->PackageLength, &BufferSize, sizeof (UINT32));
448
449 FreePool (HiiPackageList);
450
451 return HiiDatabase->UpdatePackageList (HiiDatabase, Handle, UpdateBuffer);
452 }
453
454
455 /**
456 Configure the buffer accrording to ConfigBody strings.
457
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.
463
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.
467
468 **/
469 EFI_STATUS
470 EFIAPI
471 IfrLibExtractDefault(
472 IN VOID *Buffer,
473 IN UINTN *BufferSize,
474 UINTN Number,
475 ...
476 )
477 {
478 VA_LIST Args;
479 UINTN Index;
480 UINT32 TotalLen;
481 UINT8 *BufCfgArray;
482 UINT8 *BufferPos;
483 UINT16 Offset;
484 UINT16 Width;
485 UINT8 *Value;
486
487 if ((Buffer == NULL) || (BufferSize == NULL)) {
488 return EFI_INVALID_PARAMETER;
489 }
490
491 Offset = 0;
492 Width = 0;
493 Value = NULL;
494
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);
500
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);
506 Value = BufferPos;
507 BufferPos += Width;
508
509 if ((UINTN)(Offset + Width) > *BufferSize) {
510 return EFI_BUFFER_TOO_SMALL;
511 }
512
513 CopyMem ((UINT8 *)Buffer + Offset, Value, Width);
514 }
515 }
516 VA_END (Args);
517
518 *BufferSize = (UINTN)Offset;
519
520 return EFI_SUCCESS;
521 }
522
523