]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Utility.c
Merge branch 'master' of https://github.com/tianocore/edk2
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiOnUefiHiiThunk / Utility.c
CommitLineData
26a76fbc 1/** @file\r
4259256b 2\r
3 This file contains the keyboard processing code to the HII database.\r
4\r
de03a274 5Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
584d5652 6This program and the accompanying materials\r
4259256b 7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16\r
17#include "HiiDatabase.h"\r
d4775f2a 18#include "HiiHandle.h"\r
a9d85320 19#include <Library/DebugLib.h>\r
de03a274 20#include <Guid/ZeroGuid.h>\r
4259256b 21\r
dee207ee 22CONST CHAR16 FrameworkReservedVarstoreName[] = FRAMEWORK_RESERVED_VARSTORE_NAME;\r
23\r
cb7d01c0 24/**\r
25 \r
26 This function returns a list of the package handles of the \r
27 specified type that are currently active in the HII database. The \r
28 pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package \r
29 handles to be listed.\r
30\r
31 If HandleBufferLength is NULL, then ASSERT.\r
32 If HandleBuffer is NULL, the ASSERT.\r
33 If PackageType is EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is\r
34 NULL, then ASSERT.\r
35 If PackageType is not EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is not\r
36 NULL, then ASSERT.\r
37 \r
38 \r
39 @param PackageType Specifies the package type of the packages\r
40 to list or EFI_HII_PACKAGE_TYPE_ALL for\r
41 all packages to be listed.\r
42 \r
43 @param PackageGuid If PackageType is\r
44 EFI_HII_PACKAGE_TYPE_GUID, then this is\r
45 the pointer to the GUID which must match\r
46 the Guid field of\r
47 EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it\r
48 must be NULL.\r
49 \r
50 @param HandleBufferLength On output, the length of the handle buffer\r
51 that is required for the handles found.\r
52\r
53 @param HandleBuffer On output, an array of EFI_HII_HANDLE instances returned.\r
54 The caller is responcible to free this pointer allocated.\r
55\r
56 @retval EFI_SUCCESS The matching handles are outputed successfully.\r
57 HandleBufferLength is updated with the actual length.\r
58 @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operation.\r
59 @retval EFI_NOT_FOUND No matching handle could not be found in database.\r
60**/\r
61EFI_STATUS\r
62EFIAPI\r
63ListPackageLists (\r
64 IN UINT8 PackageType,\r
65 IN CONST EFI_GUID *PackageGuid,\r
66 IN OUT UINTN *HandleBufferLength,\r
67 OUT EFI_HII_HANDLE **HandleBuffer\r
68 )\r
69{\r
70 EFI_STATUS Status;\r
71 \r
72 ASSERT (HandleBufferLength != NULL);\r
73 ASSERT (HandleBuffer != NULL);\r
74 \r
75 *HandleBufferLength = 0;\r
76 *HandleBuffer = NULL;\r
77\r
78 if (PackageType == EFI_HII_PACKAGE_TYPE_GUID) {\r
79 ASSERT (PackageGuid != NULL);\r
80 } else {\r
81 ASSERT (PackageGuid == NULL);\r
82 }\r
83\r
84 Status = mHiiDatabase->ListPackageLists (\r
85 mHiiDatabase,\r
86 PackageType,\r
87 PackageGuid,\r
88 HandleBufferLength,\r
89 *HandleBuffer\r
90 );\r
91 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
92 //\r
93 // No packages is registered to UEFI HII Database, just return.\r
94 // \r
95 //\r
96 return Status;\r
97 }\r
98\r
99 *HandleBuffer = AllocateZeroPool (*HandleBufferLength);\r
100 \r
101 if (*HandleBuffer == NULL) {\r
102 return EFI_OUT_OF_RESOURCES;\r
103 }\r
104 \r
105 return mHiiDatabase->ListPackageLists (\r
106 mHiiDatabase,\r
107 PackageType,\r
108 PackageGuid,\r
109 HandleBufferLength,\r
110 *HandleBuffer\r
111 );\r
112 \r
113}\r
114\r
115/**\r
116 Exports the contents of one or all package lists in the HII database into a buffer.\r
117\r
118 If Handle is not NULL and not a valid EFI_HII_HANDLE registered in the database, \r
119 then ASSERT.\r
120 If PackageListHeader is NULL, then ASSERT.\r
121 If PackageListSize is NULL, then ASSERT.\r
122\r
123 @param Handle The HII Handle.\r
124 @param PackageListHeader A pointer to a buffer that will contain the results of \r
125 the export function.\r
126 @param PackageListSize On output, the length of the buffer that is required for the exported data.\r
127\r
128 @retval EFI_SUCCESS Package exported.\r
129\r
130 @retval EFI_OUT_OF_RESOURCES Not enought memory to complete the operations.\r
131\r
132**/\r
133EFI_STATUS \r
134EFIAPI\r
135ExportPackageLists (\r
136 IN EFI_HII_HANDLE Handle,\r
137 OUT EFI_HII_PACKAGE_LIST_HEADER **PackageListHeader,\r
138 OUT UINTN *PackageListSize\r
139 )\r
140{\r
141 EFI_STATUS Status;\r
142 UINTN Size;\r
143 EFI_HII_PACKAGE_LIST_HEADER *PackageListHdr;\r
144\r
145 ASSERT (PackageListSize != NULL);\r
146 ASSERT (PackageListHeader != NULL);\r
147\r
148 Size = 0;\r
149 PackageListHdr = NULL;\r
150 Status = mHiiDatabase->ExportPackageLists (\r
151 mHiiDatabase,\r
152 Handle,\r
153 &Size,\r
154 PackageListHdr\r
155 );\r
02066979 156 ASSERT (Status != EFI_BUFFER_TOO_SMALL);\r
cb7d01c0 157 \r
158 if (Status == EFI_BUFFER_TOO_SMALL) {\r
159 PackageListHdr = AllocateZeroPool (Size);\r
160 \r
161 if (PackageListHeader == NULL) {\r
162 return EFI_OUT_OF_RESOURCES;\r
163 } else {\r
164 Status = mHiiDatabase->ExportPackageLists (\r
165 mHiiDatabase,\r
166 Handle,\r
167 &Size,\r
168 PackageListHdr\r
169 );\r
170 }\r
171 }\r
172\r
173 if (!EFI_ERROR (Status)) {\r
174 *PackageListHeader = PackageListHdr;\r
175 *PackageListSize = Size;\r
176 } else {\r
177 FreePool (PackageListHdr);\r
178 }\r
179\r
180 return Status;\r
181}\r
182\r
183/**\r
184 Extract Hii package list GUID for given HII handle.\r
185\r
186 If HiiHandle could not be found in the HII database, then ASSERT.\r
187 If Guid is NULL, then ASSERT.\r
188\r
189 @param Handle Hii handle\r
190 @param Guid Package list GUID\r
191\r
192 @retval EFI_SUCCESS Successfully extract GUID from Hii database.\r
193\r
194**/\r
195EFI_STATUS\r
196EFIAPI\r
197ExtractGuidFromHiiHandle (\r
198 IN EFI_HII_HANDLE Handle,\r
199 OUT EFI_GUID *Guid\r
200 )\r
201{\r
202 EFI_STATUS Status;\r
203 UINTN BufferSize;\r
204 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
205\r
206 ASSERT (Guid != NULL);\r
207 ASSERT (Handle != NULL);\r
208\r
209 //\r
210 // Get HII PackageList\r
211 //\r
212 BufferSize = 0;\r
213 HiiPackageList = NULL;\r
214\r
215 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
216 ASSERT (Status != EFI_NOT_FOUND);\r
217 \r
218 if (Status == EFI_BUFFER_TOO_SMALL) {\r
219 HiiPackageList = AllocatePool (BufferSize);\r
220 ASSERT (HiiPackageList != NULL);\r
221\r
222 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
223 }\r
224 if (EFI_ERROR (Status)) {\r
225 FreePool (HiiPackageList);\r
226 return Status;\r
227 }\r
228\r
229 //\r
230 // Extract GUID\r
231 //\r
232 CopyGuid (Guid, &HiiPackageList->PackageListGuid);\r
233\r
234 FreePool (HiiPackageList);\r
235\r
236 return EFI_SUCCESS;\r
237}\r
0368663f 238\r
a9d85320 239/**\r
240 Find the corressponding UEFI HII Handle from a Framework HII Handle given.\r
241\r
242 @param Private The HII Thunk Module Private context.\r
243 @param FwHiiHandle The Framemwork HII Handle.\r
0368663f 244\r
a9d85320 245 @return NULL If Framework HII Handle is invalid.\r
246 @return The corresponding UEFI HII Handle.\r
247**/\r
ee3428bb 248EFI_HII_HANDLE\r
0368663f 249FwHiiHandleToUefiHiiHandle (\r
250 IN CONST HII_THUNK_PRIVATE_DATA *Private,\r
251 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle\r
ee3428bb 252 )\r
253{\r
0368663f 254 HII_THUNK_CONTEXT *ThunkContext;\r
ee3428bb 255\r
0368663f 256 ASSERT (FwHiiHandle != (FRAMEWORK_EFI_HII_HANDLE) 0);\r
ee3428bb 257 ASSERT (Private != NULL);\r
258\r
0368663f 259 ThunkContext = FwHiiHandleToThunkContext (Private, FwHiiHandle);\r
ee3428bb 260\r
0368663f 261 if (ThunkContext != NULL) {\r
262 return ThunkContext->UefiHiiHandle;\r
ee3428bb 263 }\r
264 \r
265 return (EFI_HII_HANDLE) NULL;\r
266}\r
267\r
ebbd2793 268\r
a9d85320 269/**\r
270 Find the corressponding HII Thunk Context from a Framework HII Handle given.\r
271\r
272 @param Private The HII Thunk Module Private context.\r
273 @param FwHiiHandle The Framemwork HII Handle.\r
274\r
275 @return NULL If Framework HII Handle is invalid.\r
276 @return The corresponding HII Thunk Context.\r
277**/\r
0368663f 278HII_THUNK_CONTEXT *\r
279FwHiiHandleToThunkContext (\r
280 IN CONST HII_THUNK_PRIVATE_DATA *Private,\r
281 IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle\r
ebbd2793 282 )\r
283{\r
0368663f 284 LIST_ENTRY *Link;\r
285 HII_THUNK_CONTEXT *ThunkContext;\r
286\r
ebbd2793 287\r
0368663f 288 Link = GetFirstNode (&Private->ThunkContextListHead);\r
ebbd2793 289\r
0368663f 290 while (!IsNull (&Private->ThunkContextListHead, Link)) {\r
291 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);\r
292\r
293 if (FwHiiHandle == ThunkContext->FwHiiHandle) {\r
294 return ThunkContext;\r
ebbd2793 295 }\r
0368663f 296\r
297 Link = GetNextNode (&Private->ThunkContextListHead, Link);\r
ebbd2793 298 }\r
299\r
0368663f 300 return NULL;\r
ebbd2793 301}\r
302\r
a9d85320 303/**\r
304 Find the corressponding HII Thunk Context from a UEFI HII Handle given.\r
305\r
26a76fbc
LG
306 @param Private The HII Thunk Module Private context.\r
307 @param UefiHiiHandle The UEFI HII Handle.\r
a9d85320 308\r
309 @return NULL If UEFI HII Handle is invalid.\r
310 @return The corresponding HII Thunk Context.\r
311**/\r
0368663f 312HII_THUNK_CONTEXT *\r
313UefiHiiHandleToThunkContext (\r
314 IN CONST HII_THUNK_PRIVATE_DATA *Private,\r
ea58467b 315 IN EFI_HII_HANDLE UefiHiiHandle\r
316 )\r
317{\r
0368663f 318 LIST_ENTRY *Link;\r
319 HII_THUNK_CONTEXT *ThunkContext;\r
ea58467b 320\r
0368663f 321 Link = GetFirstNode (&Private->ThunkContextListHead);\r
ea58467b 322\r
0368663f 323 while (!IsNull (&Private->ThunkContextListHead, Link)) {\r
324 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);\r
325\r
326 if (UefiHiiHandle == ThunkContext->UefiHiiHandle) {\r
327 return ThunkContext;\r
ea58467b 328 }\r
0368663f 329 Link = GetNextNode (&Private->ThunkContextListHead, Link);\r
ea58467b 330 }\r
331\r
0368663f 332 return NULL;\r
ea58467b 333}\r
99a83b4c 334\r
a9d85320 335/**\r
336 Find the corressponding HII Thunk Context from a Tag GUID.\r
337\r
338 @param Private The HII Thunk Module Private context.\r
339 @param Guid The Tag GUID.\r
340\r
341 @return NULL No HII Thunk Context matched the Tag GUID.\r
342 @return The corresponding HII Thunk Context.\r
343**/\r
8ea58c07 344HII_THUNK_CONTEXT *\r
345TagGuidToIfrPackThunkContext (\r
0368663f 346 IN CONST HII_THUNK_PRIVATE_DATA *Private,\r
99a83b4c 347 IN CONST EFI_GUID *Guid\r
348 )\r
349{\r
0368663f 350 LIST_ENTRY *Link;\r
351 HII_THUNK_CONTEXT *ThunkContext;\r
352\r
353 Link = GetFirstNode (&Private->ThunkContextListHead);\r
99a83b4c 354\r
0368663f 355 while (!IsNull (&Private->ThunkContextListHead, Link)) {\r
356 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);\r
99a83b4c 357\r
8ea58c07 358 if (CompareGuid (Guid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount != 0)) {\r
359 return ThunkContext;\r
99a83b4c 360 }\r
0368663f 361\r
362 Link = GetNextNode (&Private->ThunkContextListHead, Link);\r
99a83b4c 363 }\r
364\r
0368663f 365 return NULL;\r
99a83b4c 366 \r
367}\r
368\r
a9d85320 369/**\r
370 Clean up the HII Thunk Context for a UEFI HII Handle.\r
371\r
26a76fbc
LG
372 @param Private The HII Thunk Module Private context.\r
373 @param UefiHiiHandle The UEFI HII Handle.\r
0368663f 374\r
a9d85320 375**/\r
d4775f2a 376VOID\r
0368663f 377DestroyThunkContextForUefiHiiHandle (\r
378 IN HII_THUNK_PRIVATE_DATA *Private,\r
379 IN EFI_HII_HANDLE UefiHiiHandle\r
26a76fbc 380 )\r
0368663f 381{\r
382 HII_THUNK_CONTEXT *ThunkContext;\r
383\r
384 ThunkContext = UefiHiiHandleToThunkContext (Private, UefiHiiHandle);\r
385 ASSERT (ThunkContext != NULL);\r
386\r
d4775f2a 387 DestroyThunkContext (ThunkContext);\r
0368663f 388}\r
389\r
390\r
391/**\r
26a76fbc
LG
392 This function create a HII_THUNK_CONTEXT for the input UEFI HiiHandle\r
393 that is created when a package list registered by a module calling \r
394 EFI_HII_DATABASE_PROTOCOL.NewPackageList. \r
395 This function records the PackageListGuid of EFI_HII_PACKAGE_LIST_HEADER \r
396 into the TagGuid of the created HII_THUNK_CONTEXT.\r
397\r
398 @param UefiHiiHandle The UEFI HII Handle.\r
399 \r
400 @return the new created Hii thunk context.\r
0368663f 401\r
402**/\r
403HII_THUNK_CONTEXT *\r
404CreateThunkContextForUefiHiiHandle (\r
0368663f 405 IN EFI_HII_HANDLE UefiHiiHandle\r
26a76fbc 406 )\r
0368663f 407{\r
408 EFI_STATUS Status;\r
409 EFI_GUID PackageGuid;\r
410 HII_THUNK_CONTEXT *ThunkContext;\r
411\r
412 ThunkContext = AllocateZeroPool (sizeof (*ThunkContext));\r
413 ASSERT (ThunkContext != NULL);\r
414 \r
415 ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;\r
416\r
d4775f2a 417 Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);\r
0368663f 418 if (EFI_ERROR (Status)) {\r
419 return NULL;\r
420 }\r
421 \r
422 ThunkContext->UefiHiiHandle = UefiHiiHandle;\r
423 \r
cb7d01c0 424 Status = ExtractGuidFromHiiHandle (UefiHiiHandle, &PackageGuid);\r
0368663f 425 ASSERT_EFI_ERROR (Status);\r
426 \r
427 CopyGuid(&ThunkContext->TagGuid, &PackageGuid);\r
428\r
0368663f 429 return ThunkContext;\r
430}\r
431\r
432\r
a9d85320 433/**\r
434 Get the number of HII Package for a Package type.\r
435\r
436 @param PackageListHeader The Package List.\r
437 @param PackageType The Package Type.\r
438\r
439 @return The number of Package for given type.\r
440**/\r
0368663f 441UINTN\r
442GetPackageCountByType (\r
443 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader,\r
444 IN UINT8 PackageType\r
ea58467b 445 )\r
446{\r
0368663f 447 UINTN Count;\r
448 EFI_HII_PACKAGE_HEADER *PackageHeader;\r
449\r
450 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageListHeader + sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
451 Count = 0;\r
452 \r
453 while (PackageHeader->Type != EFI_HII_PACKAGE_END) {\r
454 if (PackageHeader->Type == PackageType ) {\r
455 Count++;\r
456 }\r
457 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHeader + PackageHeader->Length);\r
458 }\r
459 \r
460 \r
461 return Count;\r
462}\r
463\r
a9d85320 464/**\r
465 Get the Form Package from a Framework Package List.\r
0368663f 466\r
a9d85320 467 @param Packages Framework Package List.\r
99a83b4c 468\r
a9d85320 469 @return The Form Package Header found.\r
470**/\r
bc226416 471EFI_HII_PACKAGE_HEADER *\r
472GetIfrPackage (\r
473 IN CONST EFI_HII_PACKAGES *Packages\r
474 )\r
475{\r
476 UINTN Index;\r
477 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;\r
478\r
479 ASSERT (Packages != NULL);\r
480\r
481 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));\r
482 \r
483 for (Index = 0; Index < Packages->NumberOfPackages; Index++) {\r
484 //\r
485 // The current UEFI HII build tool generate a binary in the format defined by \r
486 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in\r
487 // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount\r
488 // may not be the exact number of valid package number in the binary generated \r
489 // by HII Build tool.\r
490 //\r
70d72ba9 491 switch (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type) {\r
492 case EFI_HII_IFR:\r
bc226416 493 return &TianoAutogenPackageHdrArray[Index]->PackageHeader;\r
494 break;\r
70d72ba9 495 case EFI_HII_STRING:\r
496 case EFI_HII_FONT:\r
bc226416 497 break;\r
498\r
bc226416 499 default:\r
500 ASSERT (FALSE);\r
501 return NULL;\r
502 break;\r
503 }\r
504 }\r
505\r
506 return NULL;\r
507}\r
508\r
a9d85320 509/**\r
510 Get FormSet GUID.\r
511\r
512 ASSERT if no FormSet Opcode is found.\r
513\r
514 @param Packages Form Framework Package.\r
515 @param FormSetGuid Return the FormSet Guid.\r
516\r
517**/\r
bc226416 518VOID\r
519GetFormSetGuid (\r
520 IN EFI_HII_PACKAGE_HEADER *Package,\r
521 OUT EFI_GUID *FormSetGuid\r
522 )\r
523{\r
524 UINTN Offset;\r
525 EFI_IFR_OP_HEADER *OpCode;\r
526 EFI_IFR_FORM_SET *FormSet;\r
527\r
528 Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
529 while (Offset < Package->Length) {\r
530 OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset);\r
531\r
532 switch (OpCode->OpCode) {\r
533 case EFI_IFR_FORM_SET_OP:\r
534 FormSet = (EFI_IFR_FORM_SET *) OpCode;\r
66df2531 535 CopyGuid (FormSetGuid, (EFI_GUID *)(VOID *)&FormSet->Guid);\r
bc226416 536 return;\r
537 \r
538 default:\r
539 break;\r
540 \r
541 }\r
542 Offset += OpCode->Length;\r
543 }\r
544\r
545 //\r
546 // A proper IFR must have a formset opcode.\r
547 //\r
548 ASSERT (FALSE);\r
549\r
550}\r
551\r
a9d85320 552/**\r
553 Creat a Thunk Context.\r
554\r
555 ASSERT if no FormSet Opcode is found.\r
556\r
557 @param Private The HII Thunk Private Context.\r
558 @param StringPackageCount The String package count.\r
26a76fbc 559 @param IfrPackageCount The IFR Package count.\r
a9d85320 560\r
561 @return A newly created Thunk Context.\r
562 @retval NULL No resource to create a new Thunk Context.\r
563**/\r
564HII_THUNK_CONTEXT *\r
565CreateThunkContext (\r
566 IN HII_THUNK_PRIVATE_DATA *Private,\r
567 IN UINTN StringPackageCount,\r
568 IN UINTN IfrPackageCount\r
569 )\r
570{\r
571 EFI_STATUS Status;\r
572 HII_THUNK_CONTEXT *ThunkContext;\r
573\r
574 ThunkContext = AllocateZeroPool (sizeof (HII_THUNK_CONTEXT));\r
575 ASSERT (ThunkContext != NULL);\r
576 \r
577 ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;\r
578 ThunkContext->IfrPackageCount = IfrPackageCount;\r
579 ThunkContext->StringPackageCount = StringPackageCount;\r
580 Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);\r
581 if (EFI_ERROR (Status)) {\r
582 return NULL;\r
583 }\r
584\r
585 return ThunkContext;\r
586 \r
587}\r
588\r
589/**\r
590 Destroy the Thunk Context and free up all resource.\r
bc226416 591\r
a9d85320 592 @param ThunkContext The HII Thunk Private Context to be freed.\r
593\r
594**/\r
59930165 595VOID\r
a9d85320 596DestroyThunkContext (\r
597 IN HII_THUNK_CONTEXT *ThunkContext\r
59930165 598 )\r
599{\r
a9d85320 600 ASSERT (ThunkContext != NULL);\r
59930165 601\r
a9d85320 602 FreeHiiHandle (ThunkContext->FwHiiHandle);\r
59930165 603\r
a9d85320 604 RemoveEntryList (&ThunkContext->Link);\r
605\r
606 if (ThunkContext->FormSet != NULL) {\r
607 DestroyFormSet (ThunkContext->FormSet);\r
608 }\r
609\r
610 FreePool (ThunkContext);\r
611}\r
612\r
613/**\r
614 Get the FormSet's Default Varstore ID based on the rule (Descending Priority):\r
615\r
03254710 616 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used.\r
617 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used \r
618 as the default Var Store ID.\r
a9d85320 619\r
03254710 620 @param FormSet The Form Set. The Default Varstore ID is updated if found.\r
a9d85320 621 \r
622**/\r
623VOID\r
624GetFormsetDefaultVarstoreId (\r
625 IN OUT FORM_BROWSER_FORMSET * FormSet\r
626 )\r
627{\r
628 LIST_ENTRY *StorageList;\r
629 FORMSET_STORAGE *Storage;\r
59930165 630\r
631 //\r
a9d85320 632 // VarStoreId 0 is invalid in UEFI IFR.\r
59930165 633 //\r
a9d85320 634 FormSet->DefaultVarStoreId = 0;\r
635 StorageList = GetFirstNode (&FormSet->StorageListHead);\r
59930165 636\r
a9d85320 637 while (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
638 Storage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
59930165 639\r
73d1dcbb 640 DEBUG ((EFI_D_INFO, "FormSet %g: Found Varstore ID %x Name %s Size 0x%x\n", &FormSet->Guid, Storage->VarStoreId, Storage->Name, Storage->Size));\r
59930165 641\r
a9d85320 642 if (Storage->VarStoreId == FRAMEWORK_RESERVED_VARSTORE_ID) {\r
73d1dcbb 643 //\r
644 // 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used.\r
645 //\r
a9d85320 646 FormSet->DefaultVarStoreId = FRAMEWORK_RESERVED_VARSTORE_ID;\r
59930165 647 break;\r
648 }\r
649\r
a9d85320 650 StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);\r
651 }\r
652\r
653 if (FormSet->DefaultVarStoreId != FRAMEWORK_RESERVED_VARSTORE_ID) {\r
73d1dcbb 654 //\r
655 // \r
656 // 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used \r
657 // as the default Var Store ID.\r
658 //\r
a9d85320 659 StorageList = GetFirstNode (&FormSet->StorageListHead);\r
660 if (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
661 Storage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
98b16b9d 662 FormSet->DefaultVarStoreId = Storage->VarStoreId;\r
a9d85320 663 }\r
664 \r
59930165 665 }\r
666\r
a9d85320 667 if (FormSet->DefaultVarStoreId == 0) {\r
668 DEBUG ((EFI_D_INFO, "FormSet %g: No Varstore Found\n", &FormSet->Guid));\r
e0e51f62 669 } \r
a9d85320 670 \r
671 return;\r
59930165 672}\r
673\r
a9d85320 674/**\r
675 Fetch the Ifr binary data of a FormSet.\r
676\r
677 @param Handle PackageList Handle\r
678 @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
679 GUID), take the first FormSet found in package\r
680 list.\r
681 @param BinaryLength The length of the FormSet IFR binary.\r
682 @param BinaryData The buffer designed to receive the FormSet.\r
99a83b4c 683\r
a9d85320 684 @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
685 BufferLength was updated.\r
686 @retval EFI_INVALID_PARAMETER The handle is unknown.\r
687 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
688 be found with the requested FormId.\r
689\r
690**/\r
0368663f 691EFI_STATUS\r
a9d85320 692GetIfrBinaryData (\r
693 IN EFI_HII_HANDLE Handle,\r
694 IN OUT EFI_GUID *FormSetGuid,\r
695 OUT UINTN *BinaryLength,\r
696 OUT UINT8 **BinaryData\r
0368663f 697 )\r
698{\r
a9d85320 699 EFI_STATUS Status;\r
700 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
701 UINTN BufferSize;\r
702 UINT8 *Package;\r
703 UINT8 *OpCodeData;\r
704 UINT32 Offset;\r
705 UINT32 Offset2;\r
706 BOOLEAN ReturnDefault;\r
707 UINT32 PackageListLength;\r
708 EFI_HII_PACKAGE_HEADER PackageHeader;\r
709\r
710 OpCodeData = NULL;\r
711 Package = NULL;\r
712 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;\r
59e87364 713\r
714 //\r
a9d85320 715 // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list\r
59e87364 716 //\r
a9d85320 717 if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
718 ReturnDefault = TRUE;\r
719 } else {\r
720 ReturnDefault = FALSE;\r
ea58467b 721 }\r
99a83b4c 722\r
0368663f 723 //\r
a9d85320 724 // Get HII PackageList\r
0368663f 725 //\r
a9d85320 726 BufferSize = 0;\r
727 HiiPackageList = NULL;\r
728 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
729 if (Status == EFI_BUFFER_TOO_SMALL) {\r
730 HiiPackageList = AllocatePool (BufferSize);\r
731 ASSERT (HiiPackageList != NULL);\r
732\r
733 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
734 }\r
234980f6
LG
735 if (EFI_ERROR (Status) || HiiPackageList == NULL) {\r
736 return EFI_NOT_FOUND;\r
a9d85320 737 }\r
0368663f 738\r
739 //\r
a9d85320 740 // Get Form package from this HII package List\r
0368663f 741 //\r
a9d85320 742 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
743 Offset2 = 0;\r
744 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
0368663f 745\r
a9d85320 746 while (Offset < PackageListLength) {\r
747 Package = ((UINT8 *) HiiPackageList) + Offset;\r
748 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
0368663f 749\r
a9d85320 750 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
0368663f 751 //\r
a9d85320 752 // Search FormSet in this Form Package\r
0368663f 753 //\r
a9d85320 754 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
755 while (Offset2 < PackageHeader.Length) {\r
756 OpCodeData = Package + Offset2;\r
757\r
758 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
0368663f 759 //\r
a9d85320 760 // Check whether return default FormSet\r
0368663f 761 //\r
a9d85320 762 if (ReturnDefault) {\r
763 break;\r
59e87364 764 }\r
765\r
a9d85320 766 //\r
767 // FormSet GUID is specified, check it\r
768 //\r
769 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
770 break;\r
0368663f 771 }\r
0368663f 772 }\r
773\r
a9d85320 774 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
775 }\r
776\r
777 if (Offset2 < PackageHeader.Length) {\r
778 //\r
779 // Target formset found\r
780 //\r
781 break;\r
0368663f 782 }\r
0368663f 783 }\r
784\r
a9d85320 785 Offset += PackageHeader.Length;\r
0368663f 786 }\r
787\r
a9d85320 788 if (Offset >= PackageListLength) {\r
789 //\r
790 // Form package not found in this Package List\r
791 //\r
792 gBS->FreePool (HiiPackageList);\r
793 return EFI_NOT_FOUND;\r
794 }\r
0368663f 795\r
a9d85320 796 if (ReturnDefault && FormSetGuid != NULL) {\r
797 //\r
798 // Return the default FormSet GUID\r
799 //\r
800 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
0368663f 801 }\r
0368663f 802\r
a9d85320 803 //\r
804 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
805 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
806 // of the Form Package.\r
807 //\r
808 *BinaryLength = PackageHeader.Length - Offset2;\r
809 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
0368663f 810\r
a9d85320 811 gBS->FreePool (HiiPackageList);\r
d4775f2a 812\r
a9d85320 813 if (*BinaryData == NULL) {\r
814 return EFI_OUT_OF_RESOURCES;\r
d4775f2a 815 }\r
816\r
a9d85320 817 return EFI_SUCCESS;\r
d4775f2a 818}\r
819\r
a9d85320 820/**\r
821 Initialize the internal data structure of a FormSet.\r
d4775f2a 822\r
a9d85320 823 @param Handle PackageList Handle\r
824 @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
825 GUID), take the first FormSet found in package\r
826 list.\r
827 @param FormSet FormSet data structure.\r
d4775f2a 828\r
a9d85320 829 @retval EFI_SUCCESS The function completed successfully.\r
830 @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
d4775f2a 831\r
a9d85320 832**/\r
833EFI_STATUS\r
834InitializeFormSet (\r
835 IN EFI_HII_HANDLE Handle,\r
836 IN OUT EFI_GUID *FormSetGuid,\r
837 OUT FORM_BROWSER_FORMSET *FormSet\r
d4775f2a 838 )\r
839{\r
a9d85320 840 EFI_STATUS Status;\r
d4775f2a 841\r
a9d85320 842 Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
843 if (EFI_ERROR (Status)) {\r
844 return Status;\r
845 }\r
d4775f2a 846\r
a9d85320 847 FormSet->HiiHandle = Handle;\r
848 CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
d4775f2a 849\r
a9d85320 850 //\r
851 // Parse the IFR binary OpCodes\r
852 //\r
853 Status = ParseOpCodes (FormSet);\r
854 if (EFI_ERROR (Status)) {\r
855 return Status;\r
d4775f2a 856 }\r
a9d85320 857\r
858 GetFormsetDefaultVarstoreId (FormSet);\r
859 return Status;\r
d4775f2a 860}\r
861\r
a9d85320 862/**\r
863 Parse the Form Package and build a FORM_BROWSER_FORMSET structure.\r
d4775f2a 864\r
a9d85320 865 @param UefiHiiHandle PackageList Handle\r
d4775f2a 866\r
a9d85320 867 @return A pointer to FORM_BROWSER_FORMSET.\r
d4775f2a 868\r
a9d85320 869**/\r
870FORM_BROWSER_FORMSET *\r
871ParseFormSet (\r
872 IN EFI_HII_HANDLE UefiHiiHandle\r
873 )\r
874{\r
875 FORM_BROWSER_FORMSET *FormSet;\r
876 EFI_GUID FormSetGuid;\r
877 EFI_STATUS Status;\r
878 \r
879 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET)); \r
880 ASSERT (FormSet != NULL);\r
d4775f2a 881\r
a9d85320 882 CopyGuid (&FormSetGuid, &gZeroGuid);\r
883 Status = InitializeFormSet (UefiHiiHandle, &FormSetGuid, FormSet);\r
904ac28c 884 if (EFI_ERROR (Status)) {\r
885 FreePool (FormSet);\r
886 return NULL;\r
887 }\r
d4775f2a 888\r
a9d85320 889 return FormSet;\r
d4775f2a 890}\r
891\r