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