]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/ExtendedIfrSupportLib/Form.c
Move MdeModuleHii.h into Include\Guid directory
[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
53dff899 50 ASSERT (HiiPackageList != NULL);\r
8dbae30d 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
3a306c10 59 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);\r
8dbae30d 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
53dff899 86 @param FormId The Form ID.\r
6ca46b63 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
54656366 158 if (CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid)) {\r
8dbae30d 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
54656366 181 LabelNumber = ReadUnaligned16 ((UINT16 *)(VOID *)&((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number);\r
3597bcbe 182 if ((ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) || (LabelNumber != Label) \r
5c526736 183 || !CompareGuid ((EFI_GUID *)(UINTN)(&((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Guid), &gEfiIfrTianoGuid)) {\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
5c526736 222 if ((ExtendOpCode == EFI_IFR_EXTEND_OP_LABEL) && CompareGuid ((EFI_GUID *)(UINTN)(&((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Guid), &gEfiIfrTianoGuid)) {\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
8d00a0f1 310**/\r
f875a4f1 311VOID\r
8d00a0f1 312IfrLibFreeUpdateData (\r
313 IN EFI_HII_UPDATE_DATA *UpdateData\r
314 )\r
315{\r
f875a4f1 316 ASSERT (UpdateData != NULL);\r
317 \r
318 FreePool (UpdateData->Data);\r
8d00a0f1 319 UpdateData->Data = NULL;\r
320\r
8d00a0f1 321}\r
8dbae30d 322\r
323/**\r
324 This function allows the caller to update a form that has\r
325 previously been registered with the EFI HII database.\r
326\r
327 @param Handle Hii Handle\r
328 @param FormSetGuid The formset should be updated.\r
329 @param FormId The form should be updated.\r
330 @param Label Update information starting immediately after this\r
331 label in the IFR\r
332 @param Insert If TRUE and Data is not NULL, insert data after\r
333 Label. If FALSE, replace opcodes between two\r
334 labels with Data\r
335 @param Data The adding data; If NULL, remove opcodes between\r
336 two Label.\r
337\r
338 @retval EFI_SUCCESS Update success.\r
339 @retval Other Update fail.\r
340\r
341**/\r
342EFI_STATUS\r
343EFIAPI\r
344IfrLibUpdateForm (\r
345 IN EFI_HII_HANDLE Handle,\r
346 IN EFI_GUID *FormSetGuid, OPTIONAL\r
347 IN EFI_FORM_ID FormId,\r
348 IN UINT16 Label,\r
349 IN BOOLEAN Insert,\r
350 IN EFI_HII_UPDATE_DATA *Data\r
351 )\r
352{\r
353 EFI_STATUS Status;\r
354 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
355 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
356 UINT32 Index;\r
357 EFI_HII_PACKAGE_LIST_HEADER *UpdateBuffer;\r
358 UINTN BufferSize;\r
359 UINT8 *UpdateBufferPos;\r
360 EFI_HII_PACKAGE_HEADER PackageHeader;\r
361 EFI_HII_PACKAGE_HEADER *Package;\r
362 UINT32 PackageLength;\r
363 EFI_HII_PACKAGE_HEADER *TempBuffer;\r
364 UINT32 TempBufferSize;\r
365 BOOLEAN Updated;\r
366\r
367 if (Data == NULL) {\r
368 return EFI_INVALID_PARAMETER;\r
369 }\r
370\r
371 HiiDatabase = gIfrLibHiiDatabase;\r
372\r
373 //\r
374 // Get the orginal package list\r
375 //\r
376 BufferSize = 0;\r
377 HiiPackageList = NULL;\r
378 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
fa7b3168 379 //\r
380 // Handle is a invalid handle. Check if Handle is corrupted.\r
381 //\r
382 ASSERT (Status != EFI_NOT_FOUND);\r
383 //\r
384 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.\r
385 //\r
386 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
387 HiiPackageList = AllocatePool (BufferSize);\r
388 ASSERT (HiiPackageList != NULL);\r
389\r
390 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);\r
391 if (EFI_ERROR (Status)) {\r
392 FreePool (HiiPackageList);\r
393 return Status;\r
8dbae30d 394 }\r
395\r
396 //\r
397 // Calculate and allocate space for retrieval of IFR data\r
398 //\r
399 BufferSize += Data->Offset;\r
400 UpdateBuffer = AllocateZeroPool (BufferSize);\r
401 if (UpdateBuffer == NULL) {\r
402 return EFI_OUT_OF_RESOURCES;\r
403 }\r
404\r
405 UpdateBufferPos = (UINT8 *) UpdateBuffer;\r
406\r
407 //\r
408 // copy the package list header\r
409 //\r
410 CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
411 UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
412\r
413 Updated = FALSE;\r
414 for (Index = 0; ; Index++) {\r
415 Status = GetPackageDataFromPackageList (HiiPackageList, Index, &PackageLength, &Package);\r
416 if (Status == EFI_SUCCESS) {\r
417 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
8d00a0f1 418 if ((PackageHeader.Type == EFI_HII_PACKAGE_FORMS) && !Updated) {\r
8dbae30d 419 Status = UpdateFormPackageData (FormSetGuid, FormId, Package, PackageLength, Label, Insert, Data, (UINT8 **)&TempBuffer, &TempBufferSize);\r
420 if (!EFI_ERROR(Status)) {\r
421 if (FormSetGuid == NULL) {\r
422 Updated = TRUE;\r
423 }\r
424 CopyMem (UpdateBufferPos, TempBuffer, TempBufferSize);\r
425 UpdateBufferPos += TempBufferSize;\r
cfb9b643 426 FreePool (TempBuffer);\r
8dbae30d 427 continue;\r
428 }\r
429 }\r
430\r
431 CopyMem (UpdateBufferPos, Package, PackageLength);\r
432 UpdateBufferPos += PackageLength;\r
433 } else if (Status == EFI_NOT_FOUND) {\r
434 break;\r
435 } else {\r
cfb9b643 436 FreePool (HiiPackageList);\r
8dbae30d 437 return Status;\r
438 }\r
439 }\r
440\r
441 //\r
442 // Update package list length\r
443 //\r
444 BufferSize = UpdateBufferPos - (UINT8 *) UpdateBuffer;\r
3a306c10 445 WriteUnaligned32 (&UpdateBuffer->PackageLength, (UINT32)BufferSize);\r
8dbae30d 446\r
cfb9b643 447 FreePool (HiiPackageList);\r
8dbae30d 448\r
449 return HiiDatabase->UpdatePackageList (HiiDatabase, Handle, UpdateBuffer);\r
450}\r
451\r
452\r
453/**\r
53dff899 454 Configure the buffer accrording to ConfigBody strings in the format of\r
455 <Length:4 bytes>, <Offset: 2 bytes>, <Width:2 bytes>, <Data:n bytes>.\r
456 This ConfigBody strings is generated by UEFI VfrCompiler for the default\r
457 values in a Form Set. The name of the ConfigBody strings is VfrMyIfrNVDataDefault0000\r
458 constructed following this rule: \r
459 "Vfr" + varstore.name + "Default" + defaultstore.attributes.\r
460 Check the generated C file in Output for details.\r
8dbae30d 461\r
6ca46b63 462 @param Buffer The start address of buffer.\r
463 @param BufferSize The size of buffer.\r
464 @param Number The number of the strings.\r
465 @param ... Variable argument list for default value in <AltResp> format \r
466 generated by the tool.\r
8dbae30d 467\r
468 @retval EFI_BUFFER_TOO_SMALL the BufferSize is too small to operate.\r
469 @retval EFI_INVALID_PARAMETER Buffer is NULL or BufferSize is 0.\r
470 @retval EFI_SUCCESS Operation successful.\r
471\r
472**/\r
473EFI_STATUS\r
474EFIAPI\r
475IfrLibExtractDefault(\r
476 IN VOID *Buffer,\r
477 IN UINTN *BufferSize,\r
478 UINTN Number,\r
479 ...\r
480 )\r
481{\r
482 VA_LIST Args;\r
483 UINTN Index;\r
484 UINT32 TotalLen;\r
485 UINT8 *BufCfgArray;\r
486 UINT8 *BufferPos;\r
487 UINT16 Offset;\r
488 UINT16 Width;\r
489 UINT8 *Value;\r
490\r
491 if ((Buffer == NULL) || (BufferSize == NULL)) {\r
492 return EFI_INVALID_PARAMETER;\r
493 }\r
494\r
495 Offset = 0;\r
496 Width = 0;\r
497 Value = NULL;\r
498\r
499 VA_START (Args, Number);\r
500 for (Index = 0; Index < Number; Index++) {\r
501 BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);\r
3a306c10 502 TotalLen = ReadUnaligned32 ((UINT32 *)BufCfgArray);\r
8dbae30d 503 BufferPos = BufCfgArray + sizeof (UINT32);\r
504\r
505 while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {\r
3a306c10 506 Offset = ReadUnaligned16 ((UINT16 *)BufferPos);\r
8dbae30d 507 BufferPos += sizeof (UINT16);\r
3a306c10 508 Width = ReadUnaligned16 ((UINT16 *)BufferPos);\r
8dbae30d 509 BufferPos += sizeof (UINT16);\r
510 Value = BufferPos;\r
511 BufferPos += Width;\r
512\r
513 if ((UINTN)(Offset + Width) > *BufferSize) {\r
514 return EFI_BUFFER_TOO_SMALL;\r
515 }\r
516\r
517 CopyMem ((UINT8 *)Buffer + Offset, Value, Width);\r
518 }\r
519 }\r
520 VA_END (Args);\r
521\r
522 *BufferSize = (UINTN)Offset;\r
523\r
524 return EFI_SUCCESS;\r
525}\r
526\r
527\r