]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Package.c
1) Add in SharingStringPack to make UpdateString only create/update string token...
[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 #include "HiiHandle.h"
18
19
20 BOOLEAN mInFrameworkHiiNewPack = FALSE;
21 BOOLEAN mInFrameworkHiiRemovePack = FALSE;
22 BOOLEAN mInFrameworkUpdatePakcage = FALSE;
23 UINT64 mGuidCount = 0;
24
25
26 /**
27 Get the number of package IFR and STRING packages in the package list passed in.
28
29 @param Packages Package List.
30 @param IfrPackageCount Number of IFR Packages.
31 @param StringPackageCount Number of String Packages.
32
33 @retval EFI_INVALID_PARAMETER If the Package List has package with type of
34 EFI_HII_PACKAGE_KEYBOARD_LAYOUT, EFI_HII_PACKAGE_FONTS, EFI_HII_PACKAGE_IMAGES.
35 @reval EFI_SUCCESS Successfully get the number of IFR and STRING package.
36
37
38 **/
39 EFI_STATUS
40 GetPackageCount (
41 IN CONST EFI_HII_PACKAGES *Packages,
42 OUT UINTN *IfrPackageCount,
43 OUT UINTN *StringPackageCount,
44 OUT UINTN *FontPackageCount
45 )
46 {
47 UINTN Index;
48 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
49
50 ASSERT (Packages != NULL);
51 ASSERT (IfrPackageCount != NULL);
52 ASSERT (StringPackageCount != NULL);
53 ASSERT (FontPackageCount != NULL);
54
55 *IfrPackageCount = 0;
56 *StringPackageCount = 0;
57 *FontPackageCount = 0;
58
59 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));
60
61 for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
62 //
63 // The current UEFI HII build tool generate a binary in the format defined by
64 // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
65 // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
66 // may not be the exact number of valid package number in the binary generated
67 // by HII Build tool.
68 //
69 switch (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type) {
70 case EFI_HII_IFR:
71 *IfrPackageCount += 1;
72 break;
73 case EFI_HII_STRING:
74 *StringPackageCount += 1;
75 break;
76
77 case EFI_HII_FONT:
78 *FontPackageCount += 1;
79 break;
80
81 //
82 // The following fonts are invalid for a module that using Framework to UEFI thunk layer.
83 //
84 default:
85 ASSERT (FALSE);
86 return EFI_INVALID_PARAMETER;
87 break;
88 }
89 }
90
91 return EFI_SUCCESS;
92 }
93
94 /**
95 Insert the String Package into the Package Lists which has the TAG GUID matching
96 the PackageListGuid of the String Package.
97
98 The Package List must have only IFR Package and no String Package.
99 Otherwise, ASSERT.
100
101 @param Private The HII THUNK driver context data.
102 @param StringPackageThunkContext The HII THUNK context data.
103 @param StringPackageListHeader The String Package List Header.
104
105 **/
106 VOID
107 UpdatePackListWithOnlyIfrPack (
108 IN HII_THUNK_PRIVATE_DATA *Private,
109 IN HII_THUNK_CONTEXT *StringPackageThunkContext,
110 IN CONST EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader
111 )
112 {
113 EFI_STATUS Status;
114 LIST_ENTRY *Link;
115 HII_THUNK_CONTEXT *ThunkContext;
116
117 Link = GetFirstNode (&Private->ThunkContextListHead);
118 while (!IsNull (&Private->ThunkContextListHead, Link)) {
119
120 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
121
122 if (StringPackageThunkContext != ThunkContext) {
123 //
124 // Skip the String Package Thunk Entry itself.
125 //
126
127 if (CompareGuid (&StringPackageListHeader->PackageListGuid, &ThunkContext->TagGuid)) {
128
129 ASSERT (ThunkContext->StringPackageCount == 0 && ThunkContext->IfrPackageCount == 1);
130
131 ThunkContext->StringPackageCount = GetPackageCountByType (StringPackageListHeader, EFI_HII_PACKAGE_STRINGS);
132
133 Status = mHiiDatabase->UpdatePackageList (
134 mHiiDatabase,
135 ThunkContext->UefiHiiHandle,
136 StringPackageListHeader
137 );
138 ASSERT_EFI_ERROR (Status);
139
140 ThunkContext->SharingStringPack = TRUE;
141 StringPackageThunkContext->SharingStringPack = TRUE;
142
143 }
144 }
145
146 Link = GetNextNode (&Private->ThunkContextListHead, Link);
147 }
148
149 }
150
151 /**
152 Caculate the size of UEFI Simple Font Package that is needed to
153 convert all the font a Framework Font Paackage.
154
155 ONLY Narrow Font is supported. Wide Font is discarded.
156
157 If the Package Header is not of EFI_HII_FONT type, then ASSERT.
158
159 @param The Package header of the Framework Font Package.
160
161 @return The size of the UEFI Simple Font Package.
162
163 **/
164 UINTN
165 GetUefiSimpleFontPackSize (
166 IN CONST EFI_HII_PACK_HEADER * PackHeader
167 )
168 {
169 UINTN Size;
170 EFI_HII_FONT_PACK *FwFontPack;
171
172 FwFontPack = (EFI_HII_FONT_PACK *) PackHeader;
173
174 ASSERT (FwFontPack->Header.Type == EFI_HII_FONT);
175
176 Size = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR)
177 + (FwFontPack->NumberOfNarrowGlyphs * sizeof (EFI_NARROW_GLYPH));
178
179 return Size;
180 }
181
182
183 /**
184 Convert Font Package in Framework format to a newly allocated UEFI
185 Simple Font Package.
186
187 ONLY Narrow Font is supported. Wide Font is discarded.
188
189 If memory allocation fails, then ASSERT.
190
191 @param FwFontPack Framework Font Package.
192
193 @reture UEFI Simple Font Package.
194 **/
195 EFI_HII_SIMPLE_FONT_PACKAGE_HDR *
196 FrameworkFontPackToUefiSimpliedFont (
197 IN CONST EFI_HII_PACK_HEADER * PackHeader
198 )
199 {
200 EFI_HII_SIMPLE_FONT_PACKAGE_HDR *FontPack;
201 UINTN Size;
202 EFI_NARROW_GLYPH *FwNarrowGlyph;
203 EFI_NARROW_GLYPH *NarrowGlyph;
204 UINTN Idx;
205 EFI_HII_FONT_PACK *FwFontPack;
206
207 Size = GetUefiSimpleFontPackSize (PackHeader);
208
209 FwFontPack = (EFI_HII_FONT_PACK *) PackHeader;
210
211 FontPack = AllocateZeroPool (Size);
212 ASSERT (FontPack != NULL);
213
214 //
215 // Prepare the Header information.
216 //
217 FontPack->Header.Length = (UINT32) Size;
218 FontPack->Header.Type = EFI_HII_PACKAGE_SIMPLE_FONTS;
219
220 FontPack->NumberOfNarrowGlyphs = FwFontPack->NumberOfNarrowGlyphs;
221
222 //
223 // ONLY Narrow Font is supported. Wide Font is discarded.
224 //
225 FontPack->NumberOfWideGlyphs = 0;
226
227 //
228 // Copy Narrow Glyph
229 //
230 NarrowGlyph = (EFI_NARROW_GLYPH *) (FontPack + 1);
231 FwNarrowGlyph = (EFI_NARROW_GLYPH *) (FwFontPack + 1);
232 CopyMem (NarrowGlyph, FwNarrowGlyph, sizeof (EFI_NARROW_GLYPH) * FwFontPack->NumberOfNarrowGlyphs);
233 for (Idx = 0; Idx < FwFontPack->NumberOfNarrowGlyphs; Idx++) {
234 //
235 // Clear the GLYPH_NON_BREAKING (EFI_GLYPH_WIDE is used here as they are all 0x02)
236 // attribute which is not defined in UEFI EFI_NARROW_GLYPH
237 //
238 NarrowGlyph[Idx].Attributes = (UINT8) (NarrowGlyph[Idx].Attributes & ~(EFI_GLYPH_WIDE));
239 }
240
241 return FontPack;
242 }
243
244 /**
245 Prepare a UEFI Package List from a Framework HII package list registered
246 from a Framework HII NewPack () function.
247
248 If either Packages or PackageListGuid is NULL, then ASSERT.
249
250 @param Packages The Framework HII Package List.
251 @param PackageListGuid The Package List GUID.
252
253
254 @return The UEFI Package List.
255 **/
256 EFI_HII_PACKAGE_LIST_HEADER *
257 PrepareUefiPackageListFromFrameworkHiiPackages (
258 IN CONST EFI_HII_PACKAGES *Packages,
259 IN CONST EFI_GUID *PackageListGuid
260 )
261 {
262 UINTN NumberOfPackages;
263 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
264 UINT8 *PackageListData;
265 UINT32 PackageListLength;
266 UINT32 PackageLength;
267 EFI_HII_PACKAGE_HEADER PackageHeader;
268 UINTN Index;
269 TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
270 EFI_HII_SIMPLE_FONT_PACKAGE_HDR *FontPack;
271
272
273 ASSERT (Packages != NULL);
274 ASSERT (PackageListGuid != NULL);
275
276 TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) ((UINT8 *) &Packages->GuidId + sizeof (Packages->GuidId));
277 NumberOfPackages = Packages->NumberOfPackages;
278
279 PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
280
281 for (Index = 0; Index < NumberOfPackages; Index++) {
282 if (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type == EFI_HII_FONT) {
283 //
284 // There is no tool to generate Font package in Framework HII's implementation.
285 // Therefore, Font Package be a C structure defined in Framework HII code.
286 // Therefore, Font Package will be in Framework HII format defined by EFI_HII_FONT_PACK.
287 // We need to create a UEFI Simple Font Package and copy over all data. Hence, EFI_HII_FONT
288 // is handled differently than EFI_HII_IFR and EFI_HII_STRING.
289 //
290 PackageListLength = (UINT32) (PackageListLength + GetUefiSimpleFontPackSize (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader));
291
292 } else {
293 //
294 // For EFI_HII_IFR and EFI_HII_STRING, EDK II's VFR Compiler and Build.exe will generate a binary in a format
295 // defined by TIANO_AUTOGEN_PACKAGES_HEADER. A Framework HII's EFI_HII_PACK_HEADER is inserted before
296 // the UEFI package data.
297 //
298 CopyMem (&PackageLength, &TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Length, sizeof (UINT32));
299 //
300 // EFI_HII_PACK_HEADER.FrameworkPackageHeader.Length include the sizeof FrameworkPackageHeader itself.
301 //
302 PackageListLength += (PackageLength - sizeof(EFI_HII_PACK_HEADER));
303
304 }
305 }
306
307 //
308 // Include the lenght of EFI_HII_PACKAGE_END
309 //
310 PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);
311 PackageListHeader = AllocateZeroPool (PackageListLength);
312 ASSERT (PackageListHeader != NULL);
313
314 CopyMem (&PackageListHeader->PackageListGuid, PackageListGuid, sizeof (EFI_GUID));
315 PackageListHeader->PackageLength = PackageListLength;
316
317 PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);
318
319 //
320 // Build the UEFI Package List.
321 //
322 for (Index = 0; Index < NumberOfPackages; Index++) {
323 if (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type == EFI_HII_FONT) {
324 PackageLength = (UINT32) GetUefiSimpleFontPackSize (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader);
325 FontPack = FrameworkFontPackToUefiSimpliedFont (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader);
326 CopyMem (PackageListData, FontPack, PackageLength);
327 FreePool (FontPack);
328
329 } else {
330 CopyMem (&PackageLength, &(TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Length), sizeof (UINT32));
331 PackageLength -= sizeof (EFI_HII_PACK_HEADER);
332 CopyMem (PackageListData, &(TianoAutogenPackageHdrArray[Index]->PackageHeader), PackageLength);
333
334 }
335 PackageListData += PackageLength;
336 }
337
338 //
339 // Append EFI_HII_PACKAGE_END
340 //
341 PackageHeader.Type = EFI_HII_PACKAGE_END;
342 PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);
343 CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);
344
345 return PackageListHeader;
346 }
347
348
349 /**
350 Generate a Random GUID.
351
352 @param Guid On output, a Random GUID will be filled.
353
354 **/
355 VOID
356 GenerateRandomGuid (
357 OUT EFI_GUID * Guid
358 )
359 {
360 EFI_GUID GuidBase = { 0x14f95e01, 0xd562, 0x432e, { 0x84, 0x4a, 0x95, 0xa4, 0x39, 0x5, 0x10, 0x7e }};
361
362 CopyGuid (Guid, &GuidBase);
363
364 mGuidCount++;
365 *((UINT64 *) Guid) = *((UINT64 *) Guid) + mGuidCount;
366 }
367
368 /**
369 Given a Package List with only a IFR package, find the Package List that only has a String Package based on
370 the TAG GUID. Then export the String Package from the Package List and insert it
371 to the given IFR package.
372
373 This is to handle the case of Framework HII interface which allow String Package
374 and IFR package to be registered using two different NewPack () calls.
375
376 @param Private The HII THUNK driver context data.
377 @param IfrThunkContext Package List with only a IFR package.
378
379 @retval EFI_SUCCESS If the String Package is found and inserted to the
380 Package List with only a IFR package.
381 @retval EFI_NOT_FOUND No String Package matching the TAG GUID is found.
382 **/
383 EFI_STATUS
384 FindStringPackAndUpdatePackListWithOnlyIfrPack (
385 IN HII_THUNK_PRIVATE_DATA *Private,
386 IN HII_THUNK_CONTEXT *IfrThunkContext
387 )
388 {
389 EFI_STATUS Status;
390 LIST_ENTRY *Link;
391 EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader;
392 UINTN Size;
393 HII_THUNK_CONTEXT *ThunkContext;
394
395 Link = GetFirstNode (&Private->ThunkContextListHead);
396
397 while (!IsNull (&Private->ThunkContextListHead, Link)) {
398
399 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
400
401 if (ThunkContext != IfrThunkContext) {
402 if (CompareGuid (&IfrThunkContext->TagGuid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount == 0)) {
403 Status = HiiLibExportPackageLists (ThunkContext->UefiHiiHandle, &StringPackageListHeader, &Size);
404 ASSERT_EFI_ERROR (Status);
405
406 IfrThunkContext->StringPackageCount = GetPackageCountByType (StringPackageListHeader, EFI_HII_PACKAGE_STRINGS);
407 //
408 // Add Function to only get only String Packages from the Package List
409 //
410 Status = mHiiDatabase->UpdatePackageList (
411 mHiiDatabase,
412 IfrThunkContext->UefiHiiHandle,
413 StringPackageListHeader
414 );
415 ASSERT_EFI_ERROR (Status);
416
417 FreePool (StringPackageListHeader);
418
419 IfrThunkContext->SharingStringPack = TRUE;
420 ThunkContext->SharingStringPack = TRUE;
421
422 return EFI_SUCCESS;
423
424 }
425 }
426
427 Link = GetNextNode (&Private->ThunkContextListHead, Link);
428 }
429
430 //
431 // A Form Package must have a String Package to function.
432 // If ASSERT here, check the sequence of call to Hii->NewPack.
433 // String Pack must be registered before Ifr Package is registered.
434 //
435 ASSERT (FALSE);
436 return EFI_NOT_FOUND;
437
438 }
439
440
441 /**
442 Register the Package List passed from the Framework HII NewPack () interface.
443 The FRAMEWORK_EFI_HII_HANDLE will be returned.
444
445 @param This The EFI_HII_PROTOCOL context data. Only used
446 to call HiiRemovePack.
447 @param Private The HII THUNK driver context data.
448 @param Package Package List.
449 @param Handle On output, a FRAMEWORK_EFI_HII_HANDLE number is
450 returned.
451
452 @retval EFI_SUCCESS The Package List is registered successfull in
453 the database.
454 @retval EFI_UNSUPPORTED The number of IFR package in the package list
455 is greater than 1.
456 @retval EFI_OUT_OF_RESOURCE Not enough resouce.
457
458 **/
459 EFI_STATUS
460 UefiRegisterPackageList (
461 IN EFI_HII_PROTOCOL *This,
462 IN HII_THUNK_PRIVATE_DATA *Private,
463 IN EFI_HII_PACKAGES *Packages,
464 OUT FRAMEWORK_EFI_HII_HANDLE *Handle
465 )
466 {
467 EFI_STATUS Status;
468 UINTN StringPackageCount;
469 UINTN IfrPackageCount;
470 UINTN FontPackageCount;
471 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
472 HII_THUNK_CONTEXT *ThunkContext;
473 HII_THUNK_CONTEXT *ThunkContextToRemove;
474 EFI_GUID GuidId;
475 EFI_HII_PACKAGE_HEADER *IfrPackage;
476
477 PackageListHeader = NULL;
478
479 Status = GetPackageCount (Packages, &IfrPackageCount, &StringPackageCount, &FontPackageCount);
480 ASSERT_EFI_ERROR (Status);
481
482 if (IfrPackageCount > 1) {
483 //
484 // HII Thunk only handle package with 0 or 1 IFR package.
485 //
486 ASSERT (FALSE);
487 return EFI_UNSUPPORTED;
488 }
489
490 ThunkContext = CreateThunkContext (Private, StringPackageCount, IfrPackageCount);
491 if (ThunkContext == NULL) {
492 return EFI_OUT_OF_RESOURCES;
493 }
494 ThunkContext->ByFrameworkHiiNewPack = TRUE;
495
496 if (Packages->GuidId == NULL) {
497 //
498 // UEFI HII Database require Package List GUID must be unique.
499 //
500 // If Packages->GuidId is NULL, the caller of FramworkHii->NewPack is registering
501 // packages with at least 1 StringPack and 1 IfrPack. Therefore, Packages->GuidId is
502 // not used as the name of the package list. Formset GUID is used as the Package List
503 // GUID instead.
504 //
505 ASSERT ((StringPackageCount >=1 && IfrPackageCount == 1) || (FontPackageCount > 0));
506 if (IfrPackageCount > 0) {
507 IfrPackage = GetIfrPackage (Packages);
508 GetFormSetGuid (IfrPackage, &ThunkContext->TagGuid);
509 } else {
510 ASSERT (FontPackageCount > 0);
511 GenerateRandomGuid (&ThunkContext->TagGuid);
512 }
513
514 } else {
515 ThunkContextToRemove = TagGuidToIfrPackThunkContext (Private, Packages->GuidId);
516
517 if (IfrPackageCount > 0 &&
518 StringPackageCount > 0 &&
519 (ThunkContextToRemove != NULL)) {
520 DEBUG((EFI_D_WARN, "Framework code registers HII package list with the same GUID more than once.\n"));
521 DEBUG((EFI_D_WARN, "Remove the previously registered package list and register the new one.\n"));
522 HiiRemovePack (This, ThunkContextToRemove->FwHiiHandle);
523 }
524 CopyGuid (&ThunkContext->TagGuid, Packages->GuidId);
525
526 }
527
528 //
529 // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
530 // that Setup Utility can load the Buffer Storage using this protocol. An UEFI VFR can only
531 // produce IFR package generated with Buffer Storage type and EFI Variable Storage.
532 // The default EFI_HII_CONFIG_ACCESS_PROTOCOL is used to Get/Set the Buffer Storage.
533 //
534 if (IfrPackageCount != 0) {
535 InstallDefaultConfigAccessProtocol (Packages, ThunkContext);
536 }
537
538 PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &ThunkContext->TagGuid);
539 Status = mHiiDatabase->NewPackageList (
540 mHiiDatabase,
541 PackageListHeader,
542 ThunkContext->UefiHiiDriverHandle,
543 &ThunkContext->UefiHiiHandle
544 );
545 if (Status == EFI_INVALID_PARAMETER) {
546 FreePool (PackageListHeader);
547
548 //
549 // UEFI HII database does not allow two package list with the same GUID.
550 // In Framework HII implementation, Packages->GuidId is used as an identifier to associate
551 // a PackageList with only IFR to a Package list the with String package.
552 //
553 GenerateRandomGuid (&GuidId);
554
555 PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &GuidId);
556 Status = mHiiDatabase->NewPackageList (
557 mHiiDatabase,
558 PackageListHeader,
559 ThunkContext->UefiHiiDriverHandle,
560 &ThunkContext->UefiHiiHandle
561 );
562 }
563
564 //
565 // BUGBUG: Remove when development is done
566 //
567 ASSERT_EFI_ERROR (Status);
568 if (EFI_ERROR (Status)) {
569 goto Done;
570 }
571
572 if (IfrPackageCount == 0) {
573 if (StringPackageCount != 0) {
574 //
575 // Look for a Package List with only IFR Package with the same TAG GUID name.
576 // If found one, add the String Packages to the found Package List.
577 // This is needed because Framework HII Module may not register the String Package
578 // and IFR Package in one NewPack () call.
579 //
580 UpdatePackListWithOnlyIfrPack (
581 Private,
582 ThunkContext,
583 PackageListHeader
584 );
585 }
586 } else {
587 if (StringPackageCount == 0) {
588 //
589 // Look for the String Package with the same TAG GUID name and add
590 // the found String Package to this Package List.
591 // This is needed because Framework HII Module may not register the String Package
592 // and IFR Package in one NewPack () call.
593 //
594 Status = FindStringPackAndUpdatePackListWithOnlyIfrPack (
595 Private,
596 ThunkContext
597 );
598
599 if (EFI_ERROR (Status)) {
600 goto Done;
601 }
602 }
603
604 //
605 // Parse the Formset. Must be called after FindStringPackAndUpdatePackListWithOnlyIfrPack is called so
606 // that String Package is ready.
607 //
608 ThunkContext->FormSet = ParseFormSet (ThunkContext->UefiHiiHandle);
609 ASSERT (ThunkContext->FormSet != NULL);
610
611 }
612
613 Done:
614 if (EFI_ERROR (Status)) {
615 DestroyThunkContext (ThunkContext);
616 } else {
617 InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
618 *Handle = ThunkContext->FwHiiHandle;
619 }
620
621 if (PackageListHeader != NULL) {
622 FreePool (PackageListHeader);
623 }
624
625 return Status;
626 }
627
628
629 /**
630
631 Registers the various packages that are passed in a Package List.
632
633 @param This Pointer of Frameowk HII protocol instance.
634 @param Packages Pointer of HII packages.
635 @param Handle Handle value to be returned.
636
637 @retval EFI_SUCCESS Pacakges has added to HII database successfully.
638 @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL.
639
640 **/
641 EFI_STATUS
642 EFIAPI
643 HiiNewPack (
644 IN EFI_HII_PROTOCOL *This,
645 IN EFI_HII_PACKAGES *Packages,
646 OUT FRAMEWORK_EFI_HII_HANDLE *Handle
647 )
648 {
649 EFI_STATUS Status;
650 HII_THUNK_PRIVATE_DATA *Private;
651 EFI_TPL OldTpl;
652
653 if (Handle == NULL) {
654 return EFI_INVALID_PARAMETER;
655 }
656
657 if (Packages == NULL) {
658 return EFI_INVALID_PARAMETER;
659 }
660
661 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
662
663 //
664 // We use a simple Global variable to inform NewOrAddPackNotify()
665 // that the package list registered here is already registered
666 // in the HII Thunk Layer. So NewOrAddPackNotify () does not need to
667 // call registered the Package List again.
668 //
669 mInFrameworkHiiNewPack = TRUE;
670
671 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
672
673 Status = UefiRegisterPackageList (
674 This,
675 Private,
676 Packages,
677 Handle
678 );
679
680 mInFrameworkHiiNewPack = FALSE;
681
682 gBS->RestoreTPL (OldTpl);
683
684 return Status;
685 }
686
687 /**
688
689 Remove a package from the HII database.
690
691 @param This Pointer of Frameowk HII protocol instance.
692 @param Handle Handle value to be removed.
693
694 @retval EFI_SUCCESS Pacakges has added to HII database successfully.
695 @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL.
696
697 **/
698 EFI_STATUS
699 EFIAPI
700 HiiRemovePack (
701 IN EFI_HII_PROTOCOL *This,
702 IN FRAMEWORK_EFI_HII_HANDLE Handle
703 )
704 {
705 EFI_STATUS Status;
706 HII_THUNK_PRIVATE_DATA *Private;
707 HII_THUNK_CONTEXT *ThunkContext;
708 EFI_TPL OldTpl;
709
710 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
711
712 mInFrameworkHiiRemovePack = TRUE;
713
714 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
715
716 ThunkContext = FwHiiHandleToThunkContext (Private, Handle);
717
718 if (ThunkContext != NULL) {
719 Status = mHiiDatabase->RemovePackageList (
720 mHiiDatabase,
721 ThunkContext->UefiHiiHandle
722 );
723 ASSERT_EFI_ERROR (Status);
724
725 if (ThunkContext->IfrPackageCount != 0) {
726 UninstallDefaultConfigAccessProtocol (ThunkContext);
727 }
728
729 DestroyThunkContext (ThunkContext);
730 }else {
731 Status = EFI_NOT_FOUND;
732 }
733
734 mInFrameworkHiiRemovePack = FALSE;
735 gBS->RestoreTPL (OldTpl);
736
737 return Status;
738 }
739
740 /**
741 This notification function will be called when a Package List is registered
742 using UEFI HII interface. The Package List registered need to be recorded in
743 Framework Thunk module as Thunk Module may need to look for String Package in
744 the package registered.
745
746 If the Package List registered is not either Sting Package or IFR package,
747 then ASSERT. If the NotifyType is not ADD_PACK or NEW_PACK, then ASSERT.
748 Both cases means UEFI HII Database itself is buggy.
749
750 @param PackageType The Package Type.
751 @param PackageGuid The Package GUID.
752 @param Package The Package Header.
753 @param Handle The HII Handle of this Package List.
754 @param NotifyType The reason of the notification.
755
756 @retval EFI_SUCCESS The notification function is successful.
757
758 **/
759 EFI_STATUS
760 EFIAPI
761 NewOrAddPackNotify (
762 IN UINT8 PackageType,
763 IN CONST EFI_GUID *PackageGuid,
764 IN CONST EFI_HII_PACKAGE_HEADER *Package,
765 IN EFI_HII_HANDLE Handle,
766 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
767 )
768 {
769 EFI_STATUS Status;
770 HII_THUNK_PRIVATE_DATA *Private;
771 HII_THUNK_CONTEXT *ThunkContext;
772
773 ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS || PackageType == EFI_HII_PACKAGE_FORMS);
774 ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK || NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK);
775
776 Status = EFI_SUCCESS;
777 Private = mHiiThunkPrivateData;
778
779 if (mInFrameworkHiiNewPack || mInFrameworkUpdatePakcage) {
780 return EFI_SUCCESS;
781 }
782
783 //
784 // We will create a ThunkContext to log the package list only if the
785 // package is not registered with by Framework HII Thunk module yet.
786 //
787 ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);
788 if (ThunkContext == NULL) {
789 ThunkContext = CreateThunkContextForUefiHiiHandle (Handle);
790 ASSERT (ThunkContext != NULL);
791
792 InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
793 }
794
795 if (PackageType == EFI_HII_PACKAGE_FORMS) {
796 if (ThunkContext->FormSet != NULL) {
797 DestroyFormSet (ThunkContext->FormSet);
798 }
799
800 //
801 // Reparse the FormSet.
802 //
803 ThunkContext->FormSet = ParseFormSet (ThunkContext->UefiHiiHandle);
804 ASSERT (ThunkContext->FormSet != NULL);
805 }
806
807 return Status;
808 }
809
810 /**
811 This notification function will be called when a Package List is removed
812 using UEFI HII interface. The Package List removed need to be removed from
813 Framework Thunk module too.
814
815 If the Package List registered is not Sting Package,
816 then ASSERT. If the NotifyType is not REMOVE_PACK, then ASSERT.
817 Both cases means UEFI HII Database itself is buggy.
818
819 @param PackageType The Package Type.
820 @param PackageGuid The Package GUID.
821 @param Package The Package Header.
822 @param Handle The HII Handle of this Package List.
823 @param NotifyType The reason of the notification.
824
825 @retval EFI_SUCCESS The notification function is successful.
826
827 **/
828 EFI_STATUS
829 EFIAPI
830 RemovePackNotify (
831 IN UINT8 PackageType,
832 IN CONST EFI_GUID *PackageGuid,
833 IN CONST EFI_HII_PACKAGE_HEADER *Package,
834 IN EFI_HII_HANDLE Handle,
835 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
836 )
837 {
838 EFI_STATUS Status;
839 HII_THUNK_PRIVATE_DATA *Private;
840 HII_THUNK_CONTEXT *ThunkContext;
841 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
842 UINTN BufferSize;
843
844 Status = EFI_SUCCESS;
845
846 ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS);
847 ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK);
848
849 if (mInFrameworkHiiRemovePack || mInFrameworkUpdatePakcage) {
850 return EFI_SUCCESS;
851 }
852
853 Private = mHiiThunkPrivateData;
854
855 ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);
856
857 //
858 // BugBug: Change to ASSERT if HII Database fix the bug and to also invoke
859 // NEW_PACK_NOTIFY for package (String Package) created internally.
860 //
861 if (ThunkContext != NULL) {
862 if (!ThunkContext->ByFrameworkHiiNewPack) {
863 Status = HiiLibExportPackageLists (Handle, &HiiPackageList, &BufferSize);
864 ASSERT_EFI_ERROR (Status);
865
866 if (GetPackageCountByType (HiiPackageList, EFI_HII_PACKAGE_STRINGS) == 1) {
867 //
868 // If the string package will be removed is the last string package
869 // in the package list, we will remove the HII Thunk entry from the
870 // database.
871 //
872 DestroyThunkContextForUefiHiiHandle (Private, Handle);
873 }
874
875 FreePool (HiiPackageList);
876 }
877 }
878
879
880 return Status;
881 }
882
883
884