]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Package.c
Bug fixes for FrameworkHiiToUefiHiiThunk;
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiToUefiHiiThunk / Package.c
CommitLineData
4259256b 1/**@file\r
0368663f 2 Implement protocol interface related to package registrations.\r
4259256b 3\r
4Copyright (c) 2006 - 2008, Intel Corporation\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\r
16#include "HiiDatabase.h"\r
17\r
18\r
0368663f 19STATIC BOOLEAN mInFrameworkHiiNewPack = FALSE;\r
20STATIC BOOLEAN mInFrameworkHiiRemovePack = FALSE;\r
21BOOLEAN mInFrameworkUpdatePakcage = FALSE;\r
63dd6a96 22\r
23\r
4259256b 24EFI_STATUS\r
0368663f 25GetPackageCount (\r
4259256b 26 IN CONST EFI_HII_PACKAGES *Packages,\r
0368663f 27 UINTN *IfrPackageCount,\r
28 UINTN *StringPackageCount\r
4259256b 29 )\r
30{\r
31 UINTN Index;\r
32 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;\r
33\r
34 ASSERT (Packages != NULL);\r
0368663f 35 ASSERT (IfrPackageCount != NULL);\r
36 ASSERT (StringPackageCount != NULL);\r
4259256b 37\r
0368663f 38 *IfrPackageCount = 0;\r
39 *StringPackageCount = 0;\r
4259256b 40\r
41 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));\r
0368663f 42 \r
4259256b 43 for (Index = 0; Index < Packages->NumberOfPackages; Index++) {\r
44 //\r
45 // BugBug: The current UEFI HII build tool generate a binary in the format defined in: \r
46 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in\r
0368663f 47 // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount\r
4259256b 48 // may not be the exact number of valid package number in the binary generated \r
49 // by HII Build tool.\r
50 //\r
51 switch (TianoAutogenPackageHdrArray[Index]->PackageHeader.Type) {\r
52 case EFI_HII_PACKAGE_FORM:\r
0368663f 53 *IfrPackageCount += 1;\r
4259256b 54 break;\r
55 case EFI_HII_PACKAGE_STRINGS:\r
0368663f 56 *StringPackageCount += 1;\r
4259256b 57 break;\r
58\r
59 case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
60 break;\r
61\r
62 //\r
63 // The following fonts are invalid for a module that using Framework to UEFI thunk layer.\r
64 //\r
65 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
66 case EFI_HII_PACKAGE_FONTS:\r
67 case EFI_HII_PACKAGE_IMAGES:\r
68 default:\r
69 ASSERT (FALSE);\r
70 return EFI_INVALID_PARAMETER;\r
71 break;\r
72 }\r
73 }\r
74\r
75 return EFI_SUCCESS;\r
76}\r
77\r
4259256b 78/**\r
79 Removes a node from a doubly linked list, and returns the node that follows\r
80 the removed node.\r
81\r
82 Removes the node Entry from a doubly linked list. It is up to the caller of\r
83 this function to release the memory used by this node if that is required. On\r
84 exit, the node following Entry in the doubly linked list is returned. If\r
85 Entry is the only node in the linked list, then the head node of the linked\r
86 list is returned.\r
87\r
88 If Entry is NULL, then ASSERT().\r
89 If Entry is the head node of an empty list, then ASSERT().\r
90 If PcdMaximumLinkedListLength is not zero, and the number of nodes in the\r
91 linked list containing Entry, including the Entry node, is greater than\r
92 or equal to PcdMaximumLinkedListLength, then ASSERT().\r
93\r
94 @param Entry A pointer to a node in a linked list\r
95\r
96 @return Entry\r
97\r
98**/\r
99EFI_STATUS\r
0368663f 100FindPackListWithOnlyIfrPackAndAddStringPack (\r
101 IN HII_THUNK_PRIVATE_DATA *Private,\r
102 IN HII_THUNK_CONTEXT *StringPackageThunkContext,\r
4259256b 103 IN CONST EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader\r
104 )\r
105{\r
106 EFI_STATUS Status;\r
0368663f 107 LIST_ENTRY *Link;\r
108 HII_THUNK_CONTEXT *ThunkContext;\r
109\r
110 Link = GetFirstNode (&Private->ThunkContextListHead);\r
111 while (!IsNull (&Private->ThunkContextListHead, Link)) {\r
112\r
113 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);\r
114\r
115 if (StringPackageThunkContext != ThunkContext) {\r
116 //\r
117 // Skip the String Package Thunk Entry itself.\r
118 //\r
119 \r
120 if (CompareGuid (&StringPackageListHeader->PackageListGuid, &ThunkContext->TagGuid)) {\r
121\r
122 ASSERT (ThunkContext->StringPackageCount == 0 && ThunkContext->IfrPackageCount == 1);\r
123\r
124 ThunkContext->StringPackageCount = GetPackageCountByType (StringPackageListHeader, EFI_HII_PACKAGE_STRINGS);\r
125 \r
126 Status = mHiiDatabase->UpdatePackageList (\r
127 mHiiDatabase,\r
128 ThunkContext->UefiHiiHandle,\r
129 StringPackageListHeader\r
130 );\r
131 ASSERT (Status != EFI_NOT_FOUND);\r
132 \r
133 if (EFI_ERROR (Status)) {\r
134 return Status;\r
135 }\r
136 }\r
4259256b 137 }\r
0368663f 138 \r
139 Link = GetNextNode (&Private->ThunkContextListHead, Link);\r
4259256b 140 }\r
141 \r
0368663f 142\r
4259256b 143 return EFI_NOT_FOUND;\r
144}\r
0368663f 145\r
146\r
4259256b 147EFI_HII_PACKAGE_LIST_HEADER *\r
148PrepareUefiPackageListFromFrameworkHiiPackages (\r
149 IN CONST EFI_HII_PACKAGES *Packages,\r
63dd6a96 150 IN CONST EFI_GUID *PackageListGuid\r
4259256b 151 )\r
152{\r
153 UINTN NumberOfPackages;\r
154 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
155 UINT8 *PackageListData;\r
156 UINT32 PackageListLength;\r
157 UINT32 PackageLength;\r
158 EFI_HII_PACKAGE_HEADER PackageHeader;\r
159 UINTN Index;\r
160 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;\r
161\r
63dd6a96 162 ASSERT (Packages != NULL);\r
163 ASSERT (PackageListGuid != NULL);\r
164\r
4259256b 165 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) ((UINT8 *) &Packages->GuidId + sizeof (Packages->GuidId));\r
166 NumberOfPackages = Packages->NumberOfPackages;\r
167\r
168 PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
169\r
170 for (Index = 0; Index < NumberOfPackages; Index++) {\r
171 CopyMem (&PackageLength, &TianoAutogenPackageHdrArray[Index]->BinaryLength, sizeof (UINT32));\r
99a83b4c 172 //\r
173 //TIANO_AUTOGEN_PACKAGES_HEADER.BinaryLength include the BinaryLength itself.\r
174 //\r
175 PackageListLength += (PackageLength - sizeof(UINT32)); \r
4259256b 176 }\r
177\r
178 //\r
179 // Include the lenght of EFI_HII_PACKAGE_END\r
180 //\r
181 PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);\r
182 PackageListHeader = AllocateZeroPool (PackageListLength);\r
183 ASSERT (PackageListHeader != NULL);\r
63dd6a96 184\r
185 CopyMem (&PackageListHeader->PackageListGuid, PackageListGuid, sizeof (EFI_GUID));\r
4259256b 186 PackageListHeader->PackageLength = PackageListLength;\r
187\r
188 PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
189\r
190 for (Index = 0; Index < NumberOfPackages; Index++) {\r
191 CopyMem (&PackageLength, &(TianoAutogenPackageHdrArray[Index]->BinaryLength), sizeof (UINT32));\r
192 PackageLength -= sizeof (UINT32);\r
193 CopyMem (PackageListData, &(TianoAutogenPackageHdrArray[Index]->PackageHeader), PackageLength);\r
194 PackageListData += PackageLength;\r
195 }\r
196\r
197 //\r
198 // Append EFI_HII_PACKAGE_END\r
199 //\r
200 PackageHeader.Type = EFI_HII_PACKAGE_END;\r
201 PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);\r
202 CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);\r
203\r
204 return PackageListHeader; \r
205}\r
206\r
59336178 207VOID\r
208GenerateGuidId (\r
209 IN CONST EFI_GUID * InGuid,\r
210 OUT EFI_GUID * OutGuid\r
4259256b 211 )\r
212{\r
4259256b 213 UINT64 MonotonicCount;\r
214\r
59336178 215 CopyMem (OutGuid, InGuid, sizeof (EFI_GUID));\r
4259256b 216 \r
217 gBS->GetNextMonotonicCount (&MonotonicCount);\r
218 //\r
219 // Use Monotonic Count as a psedo random number generator.\r
220 //\r
59336178 221 *((UINT64 *) OutGuid) = *((UINT64 *) OutGuid) + MonotonicCount;\r
4259256b 222}\r
223\r
224EFI_STATUS\r
0368663f 225FindStringPackAndAddToPackListWithOnlyIfrPack(\r
226 IN HII_THUNK_PRIVATE_DATA *Private,\r
227 IN HII_THUNK_CONTEXT *IfrThunkContext\r
4259256b 228 )\r
229{\r
0368663f 230 EFI_STATUS Status;\r
231 LIST_ENTRY *Link;\r
232 EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader;\r
233 UINTN Size;\r
234 HII_THUNK_CONTEXT *ThunkContext;\r
4259256b 235\r
0368663f 236 \r
237 Link = GetFirstNode (&Private->ThunkContextListHead);\r
238\r
239 while (!IsNull (&Private->ThunkContextListHead, Link)) {\r
240\r
241 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);\r
242\r
243 if (ThunkContext != IfrThunkContext) {\r
244 if (CompareGuid (&IfrThunkContext->TagGuid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount == 0)) {\r
245 Status = HiiLibExportPackageLists (ThunkContext->UefiHiiHandle, &StringPackageListHeader, &Size);\r
246 ASSERT_EFI_ERROR (Status);\r
247\r
248 IfrThunkContext->StringPackageCount = GetPackageCountByType (StringPackageListHeader, EFI_HII_PACKAGE_STRINGS);\r
249 //\r
250 // Add Function to only get only String Packages from the Package List\r
251 //\r
252 Status = mHiiDatabase->UpdatePackageList (\r
253 mHiiDatabase,\r
254 IfrThunkContext->UefiHiiHandle,\r
255 StringPackageListHeader\r
256 );\r
257 ASSERT_EFI_ERROR (Status);\r
258 \r
259 FreePool (StringPackageListHeader);\r
260 return EFI_SUCCESS;\r
261 }\r
262 }\r
4259256b 263\r
0368663f 264 Link = GetNextNode (&Private->ThunkContextListHead, Link);\r
265 }\r
266\r
267 return EFI_NOT_FOUND;\r
268\r
269}\r
270\r
271HII_THUNK_CONTEXT *\r
272CreateThunkContext (\r
273 IN HII_THUNK_PRIVATE_DATA *Private,\r
274 IN UINTN StringPackageCount,\r
275 IN UINTN IfrPackageCount\r
276 )\r
277{\r
278 EFI_STATUS Status;\r
279 HII_THUNK_CONTEXT *ThunkContext;\r
280\r
281 ThunkContext = AllocateZeroPool (sizeof (HII_THUNK_CONTEXT));\r
282 ASSERT (ThunkContext != NULL);\r
283 \r
284 ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;\r
285 ThunkContext->IfrPackageCount = IfrPackageCount;\r
286 ThunkContext->StringPackageCount = StringPackageCount;\r
287 Status = AssignFrameworkHiiHandle (Private, TRUE, &ThunkContext->FwHiiHandle);\r
288 if (EFI_ERROR (Status)) {\r
289 return NULL;\r
290 }\r
291\r
292 InitializeListHead (&ThunkContext->QuestionIdMapListHead);\r
293 InitializeListHead (&ThunkContext->OneOfOptionMapListHead);\r
294\r
295\r
296 return ThunkContext;\r
297 \r
298}\r
299\r
300VOID\r
301FreeFrameworkHiiHandle (\r
302 IN HII_THUNK_PRIVATE_DATA *Private,\r
303 IN FRAMEWORK_EFI_HII_HANDLE FwHandle\r
304 )\r
305{\r
306 //\r
307 // TODO: \r
308 //\r
309 \r
310 return;\r
311}\r
312\r
313VOID\r
314DestoryOneOfOptionMap (\r
315 IN LIST_ENTRY *OneOfOptionMapListHead\r
316 )\r
317{\r
318 ONE_OF_OPTION_MAP *Map;\r
319 ONE_OF_OPTION_MAP_ENTRY *MapEntry;\r
320 LIST_ENTRY *Link;\r
321 LIST_ENTRY *Link2;\r
322\r
323 while (!IsListEmpty (OneOfOptionMapListHead)) {\r
324 Link = GetFirstNode (OneOfOptionMapListHead);\r
325 \r
326 Map = ONE_OF_OPTION_MAP_FROM_LINK (Link);\r
327\r
328 while (!IsListEmpty (&Map->OneOfOptionMapEntryListHead)) {\r
329 Link2 = GetFirstNode (&Map->OneOfOptionMapEntryListHead);\r
4259256b 330 \r
0368663f 331 MapEntry = ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link);\r
332\r
333 RemoveEntryList (Link2);\r
334\r
335 FreePool (MapEntry);\r
4259256b 336 }\r
0368663f 337\r
338 RemoveEntryList (Link);\r
339 FreePool (Map);\r
4259256b 340 }\r
0368663f 341}\r
4259256b 342\r
0368663f 343VOID\r
344DestroyQuestionIdMap (\r
345 IN LIST_ENTRY *QuestionIdMapListHead\r
346 )\r
347{\r
348 QUESTION_ID_MAP *IdMap;\r
349 QUESTION_ID_MAP_ENTRY *IdMapEntry;\r
350 LIST_ENTRY *Link;\r
351 LIST_ENTRY *Link2;\r
4259256b 352\r
0368663f 353 while (!IsListEmpty (QuestionIdMapListHead)) {\r
354 Link = GetFirstNode (QuestionIdMapListHead);\r
355 \r
356 IdMap = QUESTION_ID_MAP_FROM_LINK (Link);\r
357\r
358 while (!IsListEmpty (&IdMap->MapEntryListHead)) {\r
359 Link2 = GetFirstNode (&IdMap->MapEntryListHead);\r
360 \r
361 IdMapEntry = QUESTION_ID_MAP_ENTRY_FROM_LINK (Link);\r
362\r
363 RemoveEntryList (Link2);\r
364\r
365 FreePool (IdMapEntry);\r
366 }\r
367\r
368 RemoveEntryList (Link);\r
369 FreePool (IdMap);\r
370 }\r
371}\r
372\r
373VOID\r
374DestroyThunkContext (\r
375 IN HII_THUNK_PRIVATE_DATA *Private,\r
376 IN HII_THUNK_CONTEXT *ThunkContext\r
377 )\r
378{\r
379 ASSERT (ThunkContext != NULL);\r
380\r
381 FreeFrameworkHiiHandle (Private, ThunkContext->FwHiiHandle);\r
382\r
383 DestroyQuestionIdMap (&ThunkContext->QuestionIdMapListHead);\r
384\r
385 DestoryOneOfOptionMap (&ThunkContext->OneOfOptionMapListHead);\r
386\r
387 FreePool (ThunkContext);\r
4259256b 388}\r
389\r
59336178 390CONST EFI_GUID mAGuid = \r
391 { 0x14f95e01, 0xd562, 0x432e, { 0x84, 0x4a, 0x95, 0xa4, 0x39, 0x5, 0x10, 0x7e } };\r
392\r
4259256b 393EFI_STATUS\r
394UefiRegisterPackageList(\r
0368663f 395 IN HII_THUNK_PRIVATE_DATA *Private,\r
396 IN EFI_HII_PACKAGES *Packages,\r
397 OUT FRAMEWORK_EFI_HII_HANDLE *Handle\r
4259256b 398 )\r
399{\r
400 EFI_STATUS Status;\r
0368663f 401 UINTN StringPackageCount;\r
402 UINTN IfrPackageCount;\r
403 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
404 HII_THUNK_CONTEXT *ThunkContext;\r
59336178 405 EFI_GUID GuidId;\r
4259256b 406\r
0368663f 407 PackageListHeader = NULL;\r
4259256b 408\r
0368663f 409 Status = GetPackageCount (Packages, &IfrPackageCount, &StringPackageCount);\r
4259256b 410 ASSERT_EFI_ERROR (Status);\r
0368663f 411 \r
412 if (IfrPackageCount > 1) {\r
413 //\r
414 // HII Thunk only handle package with 0 or 1 IFR package. \r
415 //\r
59336178 416 return EFI_UNSUPPORTED;\r
417 }\r
4259256b 418\r
0368663f 419 ThunkContext = CreateThunkContext (Private, StringPackageCount, IfrPackageCount);\r
420 if (ThunkContext == NULL) {\r
421 return EFI_OUT_OF_RESOURCES;\r
ea58467b 422 }\r
59336178 423\r
59336178 424 if (Packages->GuidId == NULL) {\r
0368663f 425 //\r
426 // UEFI HII Database require Package List GUID must be unique.\r
427 //\r
428 // If Packages->GuidId is NULL, the caller of FramworkHii->NewPack is registering\r
429 // packages with at least 1 StringPack and 1 IfrPack. Therefore, Packages->GuidId is\r
430 // not used as the name of the package list. A GUID is generated as a Package List\r
431 // GUID.\r
432 //\r
433 ASSERT (StringPackageCount >=1 && IfrPackageCount == 1);\r
59336178 434 Packages->GuidId = &GuidId;\r
435 GenerateGuidId (&mAGuid, Packages->GuidId);\r
63dd6a96 436 } else {\r
0368663f 437 //BugBug We need fix this.\r
438 //ASSERT (StringPackageCount == 0 || IfrPackageCount == 0);\r
63dd6a96 439 CopyGuid (&GuidId, Packages->GuidId);\r
59336178 440 }\r
4259256b 441\r
0368663f 442 //\r
443 // Record the Package List GUID, it is used as a name for the package list by Framework HII.\r
444 //\r
445 CopyGuid (&ThunkContext->TagGuid, Packages->GuidId);\r
446\r
447 if ((StringPackageCount == 0) && (IfrPackageCount != 0)) {\r
4259256b 448 //\r
449 // UEFI HII database does not allow two package list with the same GUID.\r
450 // In Framework HII implementation, Packages->GuidId is used as an identifier to associate \r
451 // a PackageList with only IFR to a Package list the with String package.\r
452 //\r
59336178 453 GenerateGuidId (Packages->GuidId, &GuidId);\r
4259256b 454 }\r
455\r
456 //\r
457 // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so\r
5391c4f1 458 // that Setup Utility can load the Buffer Storage using this protocol.\r
4259256b 459 //\r
0368663f 460 if (IfrPackageCount != 0) {\r
461 InstallDefaultConfigAccessProtocol (Packages, ThunkContext);\r
4259256b 462 }\r
0368663f 463 PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &GuidId);\r
59336178 464 Status = mHiiDatabase->NewPackageList (\r
465 mHiiDatabase,\r
0368663f 466 PackageListHeader, \r
467 ThunkContext->UefiHiiDriverHandle,\r
468 &ThunkContext->UefiHiiHandle\r
4259256b 469 );\r
0368663f 470\r
471 //\r
472 // BUGBUG: Remove when development is done\r
473 //\r
4259256b 474 ASSERT_EFI_ERROR (Status);\r
475 if (EFI_ERROR (Status)) {\r
476 goto Done;\r
477 }\r
478 \r
0368663f 479 if (IfrPackageCount == 0) {\r
480 if (StringPackageCount != 0) {\r
4259256b 481 //\r
0368663f 482 // Find if there is Package List with only IFR Package in the databasee with the same\r
483 // tag. If found, add the String Package to this Package List.\r
4259256b 484 //\r
0368663f 485 Status = FindPackListWithOnlyIfrPackAndAddStringPack (\r
4259256b 486 Private,\r
0368663f 487 ThunkContext,\r
488 PackageListHeader\r
4259256b 489 );\r
490\r
0368663f 491 if (Status == EFI_NOT_FOUND) {\r
492 Status = EFI_SUCCESS;\r
4259256b 493 }\r
494 }\r
495 } else {\r
0368663f 496 CreateQuestionIdMap (ThunkContext);\r
497 \r
498 if (StringPackageCount == 0) {\r
4259256b 499 //\r
500 // Register the Package List to UEFI HII first.\r
501 //\r
0368663f 502 Status = FindStringPackAndAddToPackListWithOnlyIfrPack (\r
4259256b 503 Private,\r
0368663f 504 ThunkContext\r
4259256b 505 );\r
506 ASSERT_EFI_ERROR (Status);\r
4259256b 507 }\r
508 }\r
509\r
4259256b 510Done:\r
511 if (EFI_ERROR (Status)) {\r
0368663f 512 DestroyThunkContext (Private, ThunkContext);\r
4259256b 513 } else {\r
0368663f 514 InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);\r
515 *Handle = ThunkContext->FwHiiHandle;\r
4259256b 516 }\r
517\r
0368663f 518 SafeFreePool (PackageListHeader);\r
4259256b 519 \r
520 return Status;\r
521}\r
522\r
ea58467b 523\r
4259256b 524EFI_STATUS\r
525EFIAPI\r
526HiiNewPack (\r
527 IN EFI_HII_PROTOCOL *This,\r
528 IN EFI_HII_PACKAGES *Packages,\r
529 OUT FRAMEWORK_EFI_HII_HANDLE *Handle\r
530 )\r
531/*++\r
532\r
533Routine Description:\r
534\r
535 Extracts the various packs from a package list.\r
536\r
537Arguments:\r
538\r
539 This - Pointer of HII protocol.\r
540 Packages - Pointer of HII packages.\r
541 Handle - Handle value to be returned.\r
542\r
543Returns:\r
544\r
545 EFI_SUCCESS - Pacakges has added to HII database successfully.\r
546 EFI_INVALID_PARAMETER - Invalid parameter.\r
547\r
548--*/\r
549{\r
550 EFI_STATUS Status;\r
0368663f 551 HII_THUNK_PRIVATE_DATA *Private;\r
63dd6a96 552 EFI_TPL OldTpl;\r
4259256b 553\r
554 if (Handle == NULL) {\r
555 return EFI_INVALID_PARAMETER;\r
556 }\r
557\r
558 if (Packages == NULL) {\r
559 return EFI_INVALID_PARAMETER;\r
560 }\r
561\r
63dd6a96 562 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
563 \r
ea58467b 564 //\r
565 // We use a simple Global variable to inform NewPackNotify\r
566 // that the package list registered here is already registered\r
567 // in the HII Thunk Layer. So NewPackNotify does not need to\r
568 // call RegisterUefiHiiHandle () to registered it.\r
569 //\r
570 mInFrameworkHiiNewPack = TRUE;\r
571\r
0368663f 572 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);\r
4259256b 573\r
574 Status = UefiRegisterPackageList (\r
575 Private,\r
576 Packages,\r
577 Handle\r
578 );\r
579\r
ea58467b 580 mInFrameworkHiiNewPack = FALSE;\r
581\r
63dd6a96 582 gBS->RestoreTPL (OldTpl);\r
583\r
4259256b 584 return Status;\r
585}\r
586\r
587EFI_STATUS\r
588EFIAPI\r
589HiiRemovePack (\r
590 IN EFI_HII_PROTOCOL *This,\r
591 IN FRAMEWORK_EFI_HII_HANDLE Handle\r
592 )\r
593/*++\r
594\r
595Routine Description:\r
596 Removes the various packs from a Handle\r
597\r
598Arguments:\r
599\r
600Returns:\r
601\r
602--*/\r
603{\r
604 EFI_STATUS Status;\r
0368663f 605 HII_THUNK_PRIVATE_DATA *Private;\r
606 HII_THUNK_CONTEXT *ThunkContext;\r
63dd6a96 607 EFI_TPL OldTpl;\r
63dd6a96 608\r
609 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
610\r
611 mInFrameworkHiiRemovePack = TRUE;\r
4259256b 612\r
0368663f 613 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);\r
4259256b 614\r
0368663f 615 ThunkContext = FwHiiHandleToThunkContext (Private, Handle);\r
4259256b 616\r
0368663f 617 if (ThunkContext != NULL) {\r
59336178 618 Status = mHiiDatabase->RemovePackageList (\r
619 mHiiDatabase,\r
0368663f 620 ThunkContext->UefiHiiHandle\r
99a83b4c 621 );\r
622 ASSERT_EFI_ERROR (Status);\r
623\r
0368663f 624 if (ThunkContext->IfrPackageCount != 0) {\r
625 UninstallDefaultConfigAccessProtocol (ThunkContext);\r
4259256b 626 }\r
99a83b4c 627\r
0368663f 628 RemoveEntryList (&ThunkContext->Link);\r
63dd6a96 629\r
0368663f 630 DestroyThunkContext (Private, ThunkContext);\r
63dd6a96 631 }else {\r
632 Status = EFI_NOT_FOUND;\r
4259256b 633 }\r
634\r
63dd6a96 635 mInFrameworkHiiRemovePack = FALSE;\r
636 \r
637 gBS->RestoreTPL (OldTpl);\r
638\r
639 return Status;\r
4259256b 640}\r
0368663f 641\r
642EFI_STATUS\r
643EFIAPI\r
644NewOrAddPackNotify (\r
645 IN UINT8 PackageType,\r
646 IN CONST EFI_GUID *PackageGuid,\r
647 IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
648 IN EFI_HII_HANDLE Handle,\r
649 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
650 )\r
651{\r
652 EFI_STATUS Status;\r
653 HII_THUNK_PRIVATE_DATA *Private;\r
654 HII_THUNK_CONTEXT *ThunkContext;\r
655\r
656 ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS || PackageType == EFI_HII_PACKAGE_FORM);\r
657 ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK || NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK);\r
658\r
659 Status = EFI_SUCCESS;\r
660 Private = mHiiThunkPrivateData;\r
661\r
662 if (mInFrameworkHiiNewPack || mInFrameworkUpdatePakcage) {\r
663 return EFI_SUCCESS;\r
664 }\r
665\r
666 //\r
667 // We only create a ThunkContext if the Uefi Hii Handle is only already registered\r
668 // by the HII Thunk Layer.\r
669 //\r
670 ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);\r
671 if (ThunkContext == NULL) {\r
672 ThunkContext = CreateThunkContextForUefiHiiHandle (Private, Handle);\r
673 ASSERT (ThunkContext != NULL);\r
674 } \r
675\r
676\r
677 if (PackageType == EFI_HII_PACKAGE_FORM) {\r
678 Status = CreateQuestionIdMap (ThunkContext);\r
679 }\r
680\r
681 return Status; \r
682}\r
683\r
684\r
685BOOLEAN\r
686IsRemovingLastStringPack (\r
687 IN EFI_HII_HANDLE Handle\r
688 )\r
689{\r
690 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
691 UINTN BufferSize;\r
692 EFI_STATUS Status;\r
693 EFI_HII_PACKAGE_HEADER *PackageHeader;\r
694 UINTN StringPackageCount;\r
695\r
696 HiiPackageList = NULL;\r
697 BufferSize = 0;\r
698 StringPackageCount = 0;\r
699\r
700 Status = HiiLibExportPackageLists (Handle, &HiiPackageList, &BufferSize);\r
701 ASSERT_EFI_ERROR (Status);\r
702 \r
703 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) HiiPackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
704\r
705 while (PackageHeader->Type != EFI_HII_PACKAGE_END) {\r
706 switch (PackageHeader->Type) {\r
707 case EFI_HII_PACKAGE_STRINGS:\r
708 StringPackageCount++;\r
709\r
710 if (StringPackageCount > 1) {\r
711 //\r
712 // More than one String Pack in the package list\r
713 //\r
714 FreePool (HiiPackageList);\r
715 return FALSE;\r
716 }\r
717 break; \r
718\r
719 default:\r
720 break;\r
721 }\r
722 //\r
723 // goto header of next package\r
724 //\r
725 PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHeader + PackageHeader->Length);\r
726 }\r
727\r
728\r
729 //\r
730 // We will always be notified for the removal of String Pack from a package list.\r
731 // So StringPackageCount must be one at this point.\r
732 //\r
733 ASSERT (StringPackageCount == 1);\r
734 \r
735 FreePool (HiiPackageList);\r
736 return TRUE;\r
737}\r
738\r
739\r
740\r
741// Framework HII module may cache a GUID as the name of the package list.\r
742// Then search for the Framework HII handle database for the handle matching\r
743// this GUID\r
744\r
745EFI_STATUS\r
746EFIAPI\r
747RemovePackNotify (\r
748 IN UINT8 PackageType,\r
749 IN CONST EFI_GUID *PackageGuid,\r
750 IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
751 IN EFI_HII_HANDLE Handle,\r
752 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
753 )\r
754{\r
755 EFI_STATUS Status;\r
756 HII_THUNK_PRIVATE_DATA *Private;\r
757 HII_THUNK_CONTEXT * ThunkContext;\r
758\r
759 Status = EFI_SUCCESS;\r
760\r
761 ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS);\r
762 ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK);\r
763\r
764 if (mInFrameworkHiiRemovePack || mInFrameworkUpdatePakcage) {\r
765 return EFI_SUCCESS;\r
766 }\r
767\r
768 Private = mHiiThunkPrivateData;\r
769\r
770 ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);\r
771\r
772 if (ThunkContext->FwHiiHandle > Private->StaticHiiHandle) {\r
773 if (IsRemovingLastStringPack (Handle)) {\r
774 //\r
775 // If the string package will be removed is the last string package\r
776 // in the package list, we will remove the HII Thunk entry from the\r
777 // database.\r
778 //\r
779 Status = DestroyThunkContextForUefiHiiHandle (Private, Handle);\r
780 }\r
781 }\r
782\r
783 return Status;\r
784}\r
785\r
786\r
787\r