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