]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/ExtendedIfrSupportLib/Form.c
1, Add <Library/DevicePathLib.h> for all source that use device path utility macros
[mirror_edk2.git] / MdeModulePkg / Library / ExtendedIfrSupportLib / Form.c
CommitLineData
8dbae30d 1/** @file\r
2 Common Library Routines to assist handle HII elements.\r
3\r
4Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "LibraryInternal.h"\r
16\r
13492369 17extern EFI_HII_DATABASE_PROTOCOL *gIfrLibHiiDatabase;\r
18\r
6ca46b63 19/**\r
20 Get the specified package from a package list based on an index.\r
21 The Buffer on output is updated to point to a package header in\r
22 the HiiPackageList. This is an internal function.\r
23\r
24 @param HiiPackageList The Package List Header.\r
25 @param PackageIndex The index of the package to get.\r
26 @param BufferLen The length of the package.\r
27 @param Buffer The starting address of package.\r
28\r
29 @retval EFI_SUCCESS This function completes successfully.\r
30 @retval EFI_NOT_FOUND The package is not found.\r
31\r
32**/\r
8dbae30d 33EFI_STATUS\r
34GetPackageDataFromPackageList (\r
35 IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,\r
36 IN UINT32 PackageIndex,\r
37 OUT UINT32 *BufferLen,\r
38 OUT EFI_HII_PACKAGE_HEADER **Buffer\r
39 )\r
40{\r
41 UINT32 Index;\r
42 EFI_HII_PACKAGE_HEADER *Package;\r
43 UINT32 Offset;\r
44 UINT32 PackageListLength;\r
6ca46b63 45 EFI_HII_PACKAGE_HEADER PackageHeader;\r
46\r
47 PackageHeader.Length = 0;\r
48 PackageHeader.Type = 0;\r
8dbae30d 49\r
50 ASSERT(HiiPackageList != NULL);\r
51\r
52 if ((BufferLen == NULL) || (Buffer == NULL)) {\r
53 return EFI_INVALID_PARAMETER;\r
54 }\r
55\r
56 Package = NULL;\r
57 Index = 0;\r
58 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
59 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
60 while (Offset < PackageListLength) {\r
61 Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);\r
62 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
63 if (Index == PackageIndex) {\r
64 break;\r
65 }\r
66 Offset += PackageHeader.Length;\r
67 Index++;\r
68 }\r
69 if (Offset >= PackageListLength) {\r
70 //\r
71 // no package found in this Package List\r
72 //\r
73 return EFI_NOT_FOUND;\r
74 }\r
75\r
76 *BufferLen = PackageHeader.Length;\r
77 *Buffer = Package;\r
78 return EFI_SUCCESS;\r
79}\r
80\r
6ca46b63 81/**\r
82 This is the internal worker function to update the data in\r
5df74ff8 83 a form specified by FormSetGuid, FormId and Label.\r
6ca46b63 84\r
85 @param FormSetGuid The optional Formset GUID.\r
86 @param FormId The form ID>\r
87 @param Package The package header.\r
88 @param PackageLength The package length.\r
89 @param Label The label for the update.\r
90 @param Insert True if inserting opcode to the form.\r
91 @param Data The data payload.\r
92 @param TempBuffer The resultant package.\r
93 @param TempBufferSize The length of the resultant package.\r
94\r
95 @retval EFI_OUT_OF_RESOURCES If there is not enough memory to complete the operation.\r
96 @retval EFI_INVALID_PARAMETER If TempBuffer or TempBufferSize is NULL.\r
97 @retval EFI_SUCCESS The function completes successfully.\r
98\r
99**/\r
8dbae30d 100EFI_STATUS\r
101EFIAPI\r
102UpdateFormPackageData (\r
6ca46b63 103 IN EFI_GUID *FormSetGuid, OPTIONAL\r
8dbae30d 104 IN EFI_FORM_ID FormId,\r
105 IN EFI_HII_PACKAGE_HEADER *Package,\r
106 IN UINT32 PackageLength,\r
107 IN UINT16 Label,\r
108 IN BOOLEAN Insert,\r
109 IN EFI_HII_UPDATE_DATA *Data,\r
110 OUT UINT8 **TempBuffer,\r
111 OUT UINT32 *TempBufferSize\r
112 )\r
113{\r
114 UINTN AddSize;\r
115 UINT8 *BufferPos;\r
116 EFI_HII_PACKAGE_HEADER PackageHeader;\r
117 UINTN Offset;\r
118 EFI_IFR_OP_HEADER *IfrOpHdr;\r
119 BOOLEAN GetFormSet;\r
120 BOOLEAN GetForm;\r
121 UINT8 ExtendOpCode;\r
122 UINT16 LabelNumber;\r
123 BOOLEAN Updated;\r
124 EFI_IFR_OP_HEADER *AddOpCode;\r
125\r
126 if ((TempBuffer == NULL) || (TempBufferSize == NULL)) {\r
127 return EFI_INVALID_PARAMETER;\r
128 }\r
129\r
130 *TempBufferSize = PackageLength;\r
131 if (Data != NULL) {\r
132 *TempBufferSize += Data->Offset;\r
133 }\r
134 *TempBuffer = AllocateZeroPool (*TempBufferSize);\r
135 if (*TempBuffer == NULL) {\r
136 return EFI_OUT_OF_RESOURCES;\r
137 }\r
138\r
139 CopyMem (*TempBuffer, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
140 *TempBufferSize = sizeof (EFI_HII_PACKAGE_HEADER);\r
141 BufferPos = *TempBuffer + sizeof (EFI_HII_PACKAGE_HEADER);\r
142\r
143 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
144 IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));\r
145 Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
146 GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);\r
147 GetForm = FALSE;\r
148 Updated = FALSE;\r
149\r
150 while (Offset < PackageHeader.Length) {\r
151 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
152 BufferPos += IfrOpHdr->Length;\r
153 *TempBufferSize += IfrOpHdr->Length;\r
154\r
155 switch (IfrOpHdr->OpCode) {\r
156 case EFI_IFR_FORM_SET_OP :\r
157 if (FormSetGuid != NULL) {\r
158 if (CompareMem (&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid, sizeof (EFI_GUID)) == 0) {\r
159 GetFormSet = TRUE;\r
160 }\r
161 }\r
162 break;\r
163\r
164 case EFI_IFR_FORM_OP:\r
165 if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {\r
166 GetForm = TRUE;\r
167 }\r
168 break;\r
169\r
170 case EFI_IFR_GUID_OP :\r
171 if (!GetFormSet || !GetForm || Updated) {\r
172 //\r
173 // Go to the next Op-Code\r
174 //\r
175 Offset += IfrOpHdr->Length;\r
176 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
177 continue;\r
178 }\r
179\r
180 ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;\r
181 CopyMem (&LabelNumber, &((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number, sizeof (UINT16));\r
3597bcbe 182 if ((ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) || (LabelNumber != Label) \r
5cd6c13b 183 || !CompareGuid ((EFI_GUID *)(UINTN)(&((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Guid), &mIfrVendorGuid)) {\r
8dbae30d 184 //\r
185 // Go to the next Op-Code\r
186 //\r
187 Offset += IfrOpHdr->Length;\r
188 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
189 continue;\r
190 }\r
191\r
192 if (Insert && (Data != NULL)) {\r
193 //\r
194 // insert the DataCount amount of opcodes to TempBuffer if Data is NULL remove\r
195 // DataCount amount of opcodes unless runing into a label.\r
196 //\r
197 AddOpCode = (EFI_IFR_OP_HEADER *)Data->Data;\r
198 AddSize = 0;\r
199 while (AddSize < Data->Offset) {\r
200 CopyMem (BufferPos, AddOpCode, AddOpCode->Length);\r
201 BufferPos += AddOpCode->Length;\r
202 *TempBufferSize += AddOpCode->Length;\r
203\r
204 AddSize += AddOpCode->Length;\r
205 AddOpCode = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (AddOpCode) + AddOpCode->Length);\r
206 }\r
207 } else {\r
208 //\r
209 // Search the next Label.\r
210 //\r
211 while (TRUE) {\r
212 Offset += IfrOpHdr->Length;\r
213 //\r
214 // Search the next label and Fail if not label found.\r
215 //\r
216 if (Offset >= PackageHeader.Length) {\r
217 goto Fail;\r
218 }\r
219 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
220 if (IfrOpHdr->OpCode == EFI_IFR_GUID_OP) {\r
221 ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;\r
5cd6c13b 222 if ((ExtendOpCode == EFI_IFR_EXTEND_OP_LABEL) && CompareGuid ((EFI_GUID *)(UINTN)(&((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Guid), &mIfrVendorGuid)) {\r
8dbae30d 223 break;\r
224 }\r
225 }\r
226 }\r
227\r
228 if (Data != NULL) {\r
229 AddOpCode = (EFI_IFR_OP_HEADER *)Data->Data;\r
230 AddSize = 0;\r
231 while (AddSize < Data->Offset) {\r
232 CopyMem (BufferPos, AddOpCode, AddOpCode->Length);\r
233 BufferPos += AddOpCode->Length;\r
234 *TempBufferSize += AddOpCode->Length;\r
235\r
236 AddSize += AddOpCode->Length;\r
237 AddOpCode = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (AddOpCode) + AddOpCode->Length);\r
238 }\r
239 }\r
240\r
241 //\r
242 // copy the next label\r
243 //\r
244 CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
245 BufferPos += IfrOpHdr->Length;\r
246 *TempBufferSize += IfrOpHdr->Length;\r
247 }\r
248\r
249 Updated = TRUE;\r
250 break;\r
251 default :\r
252 break;\r
253 }\r
254\r
255 //\r
256 // Go to the next Op-Code\r
257 //\r
258 Offset += IfrOpHdr->Length;\r
259 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
260 }\r
261\r
262 //\r
263 // Update the package length.\r
264 //\r
265 PackageHeader.Length = *TempBufferSize;\r
266 CopyMem (*TempBuffer, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
267\r
268Fail:\r
269 if (!Updated) {\r
cfb9b643 270 FreePool (*TempBuffer);\r
8dbae30d 271 *TempBufferSize = 0;\r
272 return EFI_NOT_FOUND;\r
273 }\r
274\r
275 return EFI_SUCCESS;\r
276}\r
277\r
8d00a0f1 278/**\r
279 This function initialize the data structure for dynamic opcode.\r
280\r
281 @param UpdateData The adding data;\r
282 @param BufferSize Length of the buffer to fill dynamic opcodes.\r
283\r
284 @retval EFI_SUCCESS Update data is initialized.\r
285 @retval EFI_INVALID_PARAMETER UpdateData is NULL.\r
286 @retval EFI_OUT_OF_RESOURCES No enough memory to allocate.\r
287\r
288**/\r
289EFI_STATUS\r
290IfrLibInitUpdateData (\r
291 IN OUT EFI_HII_UPDATE_DATA *UpdateData,\r
292 IN UINT32 BufferSize\r
293 )\r
294{\r
295 ASSERT (UpdateData != NULL);\r
296\r
297 UpdateData->BufferSize = BufferSize;\r
298 UpdateData->Offset = 0;\r
299 UpdateData->Data = AllocatePool (BufferSize);\r
300\r
301 return (UpdateData->Data != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;\r
302}\r
303\r
304/**\r
305\r
306 This function free the resource of update data.\r
307\r
308 @param UpdateData The adding data;\r
309\r
310 @retval EFI_SUCCESS Resource in UpdateData is released.\r
311 @retval EFI_INVALID_PARAMETER UpdateData is NULL.\r
312\r
313**/\r
314EFI_STATUS\r
315IfrLibFreeUpdateData (\r
316 IN EFI_HII_UPDATE_DATA *UpdateData\r
317 )\r
318{\r
319 EFI_STATUS Status;\r
320\r
321 if (UpdateData == NULL) {\r
322 return EFI_INVALID_PARAMETER;\r
323 }\r
324\r
325 Status = gBS->FreePool (UpdateData->Data);\r
326 UpdateData->Data = NULL;\r
327\r
328 return Status;\r
329}\r
8dbae30d 330\r
331/**\r
332 This function allows the caller to update a form that has\r
333 previously been registered with the EFI HII database.\r
334\r
335 @param Handle Hii Handle\r
336 @param FormSetGuid The formset should be updated.\r
337 @param FormId The form should be updated.\r
338 @param Label Update information starting immediately after this\r
339 label in the IFR\r
340 @param Insert If TRUE and Data is not NULL, insert data after\r
341 Label. If FALSE, replace opcodes between two\r
342 labels with Data\r
343 @param Data The adding data; If NULL, remove opcodes between\r
344 two Label.\r
345\r
346 @retval EFI_SUCCESS Update success.\r
347 @retval Other Update fail.\r
348\r
349**/\r
350EFI_STATUS\r
351EFIAPI\r
352IfrLibUpdateForm (\r
353 IN EFI_HII_HANDLE Handle,\r
354 IN EFI_GUID *FormSetGuid, OPTIONAL\r
355 IN EFI_FORM_ID FormId,\r
356 IN UINT16 Label,\r
357 IN BOOLEAN Insert,\r
358 IN EFI_HII_UPDATE_DATA *Data\r
359 )\r
360{\r
361 EFI_STATUS Status;\r
362 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
363 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
364 UINT32 Index;\r
365 EFI_HII_PACKAGE_LIST_HEADER *UpdateBuffer;\r
366 UINTN BufferSize;\r
367 UINT8 *UpdateBufferPos;\r
368 EFI_HII_PACKAGE_HEADER PackageHeader;\r
369 EFI_HII_PACKAGE_HEADER *Package;\r
370 UINT32 PackageLength;\r
371 EFI_HII_PACKAGE_HEADER *TempBuffer;\r
372 UINT32 TempBufferSize;\r
373 BOOLEAN Updated;\r
374\r
375 if (Data == NULL) {\r
376 return EFI_INVALID_PARAMETER;\r
377 }\r
378\r
379 HiiDatabase = gIfrLibHiiDatabase;\r
380\r
381 //\r
382 // Get the orginal package list\r
383 //\r
384 BufferSize = 0;\r
385 HiiPackageList = NULL;\r
386 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
387 if (Status == EFI_BUFFER_TOO_SMALL) {\r
388 HiiPackageList = AllocatePool (BufferSize);\r
389 ASSERT (HiiPackageList != NULL);\r
390\r
391 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
392 if (EFI_ERROR (Status)) {\r
cfb9b643 393 FreePool (HiiPackageList);\r
8dbae30d 394 return Status;\r
395 }\r
396 }\r
397\r
398 //\r
399 // Calculate and allocate space for retrieval of IFR data\r
400 //\r
401 BufferSize += Data->Offset;\r
402 UpdateBuffer = AllocateZeroPool (BufferSize);\r
403 if (UpdateBuffer == NULL) {\r
404 return EFI_OUT_OF_RESOURCES;\r
405 }\r
406\r
407 UpdateBufferPos = (UINT8 *) UpdateBuffer;\r
408\r
409 //\r
410 // copy the package list header\r
411 //\r
412 CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
413 UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
414\r
415 Updated = FALSE;\r
416 for (Index = 0; ; Index++) {\r
417 Status = GetPackageDataFromPackageList (HiiPackageList, Index, &PackageLength, &Package);\r
418 if (Status == EFI_SUCCESS) {\r
419 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
8d00a0f1 420 if ((PackageHeader.Type == EFI_HII_PACKAGE_FORMS) && !Updated) {\r
8dbae30d 421 Status = UpdateFormPackageData (FormSetGuid, FormId, Package, PackageLength, Label, Insert, Data, (UINT8 **)&TempBuffer, &TempBufferSize);\r
422 if (!EFI_ERROR(Status)) {\r
423 if (FormSetGuid == NULL) {\r
424 Updated = TRUE;\r
425 }\r
426 CopyMem (UpdateBufferPos, TempBuffer, TempBufferSize);\r
427 UpdateBufferPos += TempBufferSize;\r
cfb9b643 428 FreePool (TempBuffer);\r
8dbae30d 429 continue;\r
430 }\r
431 }\r
432\r
433 CopyMem (UpdateBufferPos, Package, PackageLength);\r
434 UpdateBufferPos += PackageLength;\r
435 } else if (Status == EFI_NOT_FOUND) {\r
436 break;\r
437 } else {\r
cfb9b643 438 FreePool (HiiPackageList);\r
8dbae30d 439 return Status;\r
440 }\r
441 }\r
442\r
443 //\r
444 // Update package list length\r
445 //\r
446 BufferSize = UpdateBufferPos - (UINT8 *) UpdateBuffer;\r
447 CopyMem (&UpdateBuffer->PackageLength, &BufferSize, sizeof (UINT32));\r
448\r
cfb9b643 449 FreePool (HiiPackageList);\r
8dbae30d 450\r
451 return HiiDatabase->UpdatePackageList (HiiDatabase, Handle, UpdateBuffer);\r
452}\r
453\r
454\r
455/**\r
456 Configure the buffer accrording to ConfigBody strings.\r
457\r
6ca46b63 458 @param Buffer The start address of buffer.\r
459 @param BufferSize The size of buffer.\r
460 @param Number The number of the strings.\r
461 @param ... Variable argument list for default value in <AltResp> format \r
462 generated by the tool.\r
8dbae30d 463\r
464 @retval EFI_BUFFER_TOO_SMALL the BufferSize is too small to operate.\r
465 @retval EFI_INVALID_PARAMETER Buffer is NULL or BufferSize is 0.\r
466 @retval EFI_SUCCESS Operation successful.\r
467\r
468**/\r
469EFI_STATUS\r
470EFIAPI\r
471IfrLibExtractDefault(\r
472 IN VOID *Buffer,\r
473 IN UINTN *BufferSize,\r
474 UINTN Number,\r
475 ...\r
476 )\r
477{\r
478 VA_LIST Args;\r
479 UINTN Index;\r
480 UINT32 TotalLen;\r
481 UINT8 *BufCfgArray;\r
482 UINT8 *BufferPos;\r
483 UINT16 Offset;\r
484 UINT16 Width;\r
485 UINT8 *Value;\r
486\r
487 if ((Buffer == NULL) || (BufferSize == NULL)) {\r
488 return EFI_INVALID_PARAMETER;\r
489 }\r
490\r
491 Offset = 0;\r
492 Width = 0;\r
493 Value = NULL;\r
494\r
495 VA_START (Args, Number);\r
496 for (Index = 0; Index < Number; Index++) {\r
497 BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);\r
498 CopyMem (&TotalLen, BufCfgArray, sizeof (UINT32));\r
499 BufferPos = BufCfgArray + sizeof (UINT32);\r
500\r
501 while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {\r
502 CopyMem (&Offset, BufferPos, sizeof (UINT16));\r
503 BufferPos += sizeof (UINT16);\r
504 CopyMem (&Width, BufferPos, sizeof (UINT16));\r
505 BufferPos += sizeof (UINT16);\r
506 Value = BufferPos;\r
507 BufferPos += Width;\r
508\r
509 if ((UINTN)(Offset + Width) > *BufferSize) {\r
510 return EFI_BUFFER_TOO_SMALL;\r
511 }\r
512\r
513 CopyMem ((UINT8 *)Buffer + Offset, Value, Width);\r
514 }\r
515 }\r
516 VA_END (Args);\r
517\r
518 *BufferSize = (UINTN)Offset;\r
519\r
520 return EFI_SUCCESS;\r
521}\r
522\r
523\r