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 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 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 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 * 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 * 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 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 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 successfully 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 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 Packages has added to HII database successfully. 648 @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL. 649 650 **/ 651 EFI_STATUS 652 EFIAPI 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 Packages has added to HII database successfully. 705 @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL. 706 707 **/ 708 EFI_STATUS 709 EFIAPI 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 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 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