1 /*++ 2 3 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 Module Name: 13 14 UefiIfrCommon.c 15 16 Abstract: 17 18 Common Library Routines to assist handle HII elements. 19 20 --*/ 21 22 #include "UefiIfrLibrary.h" 23 24 // 25 // Hii vendor device path template 26 // 27 HII_VENDOR_DEVICE_PATH mHiiVendorDevicePathTemplate = { 28 { 29 { 30 { 31 HARDWARE_DEVICE_PATH, 32 HW_VENDOR_DP, 33 { 34 (UINT8) (sizeof (HII_VENDOR_DEVICE_PATH_NODE)), 35 (UINT8) ((sizeof (HII_VENDOR_DEVICE_PATH_NODE)) >> 8) 36 } 37 }, 38 EFI_IFR_TIANO_GUID, 39 }, 40 0, 41 0 42 }, 43 { 44 END_DEVICE_PATH_TYPE, 45 END_ENTIRE_DEVICE_PATH_SUBTYPE, 46 { 47 END_DEVICE_PATH_LENGTH 48 } 49 } 50 }; 51 52 // 53 // Hii relative protocols 54 // 55 BOOLEAN mHiiProtocolsInitialized = FALSE; 56 57 EFI_HII_DATABASE_PROTOCOL *gIfrLibHiiDatabase; 58 EFI_HII_STRING_PROTOCOL *gIfrLibHiiString; 59 60 VOID 61 LocateHiiProtocols ( 62 VOID 63 ) 64 /*++ 65 66 Routine Description: 67 This function locate Hii relative protocols for later usage. 68 69 Arguments: 70 None. 71 72 Returns: 73 None. 74 75 --*/ 76 { 77 EFI_STATUS Status; 78 79 if (mHiiProtocolsInitialized) { 80 return; 81 } 82 83 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gIfrLibHiiDatabase); 84 ASSERT_EFI_ERROR (Status); 85 86 Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &gIfrLibHiiString); 87 ASSERT_EFI_ERROR (Status); 88 89 mHiiProtocolsInitialized = TRUE; 90 } 91 92 EFI_HII_PACKAGE_LIST_HEADER * 93 PreparePackageList ( 94 IN UINTN NumberOfPackages, 95 IN EFI_GUID *GuidId, 96 ... 97 ) 98 /*++ 99 100 Routine Description: 101 Assemble EFI_HII_PACKAGE_LIST according to the passed in packages. 102 103 Arguments: 104 NumberOfPackages - Number of packages. 105 GuidId - Package GUID. 106 107 Returns: 108 Pointer of EFI_HII_PACKAGE_LIST_HEADER. 109 110 --*/ 111 { 112 VA_LIST Marker; 113 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; 114 UINT8 *PackageListData; 115 UINT32 PackageListLength; 116 UINT32 PackageLength; 117 EFI_HII_PACKAGE_HEADER PackageHeader; 118 UINT8 *PackageArray; 119 UINTN Index; 120 121 PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER); 122 123 VA_START (Marker, GuidId); 124 for (Index = 0; Index < NumberOfPackages; Index++) { 125 EfiCopyMem (&PackageLength, VA_ARG (Marker, VOID *), sizeof (UINT32)); 126 PackageListLength += (PackageLength - sizeof (UINT32)); 127 } 128 VA_END (Marker); 129 130 // 131 // Include the lenght of EFI_HII_PACKAGE_END 132 // 133 PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER); 134 PackageListHeader = EfiLibAllocateZeroPool (PackageListLength); 135 ASSERT (PackageListHeader != NULL); 136 EfiCopyMem (&PackageListHeader->PackageListGuid, GuidId, sizeof (EFI_GUID)); 137 PackageListHeader->PackageLength = PackageListLength; 138 139 PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER); 140 141 VA_START (Marker, GuidId); 142 for (Index = 0; Index < NumberOfPackages; Index++) { 143 PackageArray = (UINT8 *) VA_ARG (Marker, VOID *); 144 EfiCopyMem (&PackageLength, PackageArray, sizeof (UINT32)); 145 PackageLength -= sizeof (UINT32); 146 PackageArray += sizeof (UINT32); 147 EfiCopyMem (PackageListData, PackageArray, PackageLength); 148 PackageListData += PackageLength; 149 } 150 VA_END (Marker); 151 152 // 153 // Append EFI_HII_PACKAGE_END 154 // 155 PackageHeader.Type = EFI_HII_PACKAGE_END; 156 PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER); 157 EfiCopyMem (PackageListData, &PackageHeader, PackageHeader.Length); 158 159 return PackageListHeader; 160 } 161 162 EFI_STATUS 163 CreateHiiDriverHandle ( 164 OUT EFI_HANDLE *DriverHandle 165 ) 166 /*++ 167 168 Routine Description: 169 The HII driver handle passed in for HiiDatabase.NewPackageList() requires 170 that there should be DevicePath Protocol installed on it. 171 This routine create a virtual Driver Handle by installing a vendor device 172 path on it, so as to use it to invoke HiiDatabase.NewPackageList(). 173 174 Arguments: 175 DriverHandle - Handle to be returned 176 177 Returns: 178 EFI_SUCCESS - Handle destroy success. 179 EFI_OUT_OF_RESOURCES - Not enough memory. 180 181 --*/ 182 { 183 EFI_STATUS Status; 184 HII_VENDOR_DEVICE_PATH_NODE *VendorDevicePath; 185 186 VendorDevicePath = EfiLibAllocateCopyPool (sizeof (HII_VENDOR_DEVICE_PATH), &mHiiVendorDevicePathTemplate); 187 if (VendorDevicePath == NULL) { 188 return EFI_OUT_OF_RESOURCES; 189 } 190 191 // 192 // Use memory address as unique ID to distinguish from different device paths 193 // 194 VendorDevicePath->UniqueId = (UINT64) ((UINTN) VendorDevicePath); 195 196 *DriverHandle = NULL; 197 Status = gBS->InstallMultipleProtocolInterfaces ( 198 DriverHandle, 199 &gEfiDevicePathProtocolGuid, 200 VendorDevicePath, 201 NULL 202 ); 203 if (EFI_ERROR (Status)) { 204 return Status; 205 } 206 207 return EFI_SUCCESS; 208 } 209 210 EFI_STATUS 211 DestroyHiiDriverHandle ( 212 IN EFI_HANDLE DriverHandle 213 ) 214 /*++ 215 216 Routine Description: 217 Destroy the Driver Handle created by CreateHiiDriverHandle(). 218 219 Arguments: 220 DriverHandle - Handle returned by CreateHiiDriverHandle() 221 222 Returns: 223 EFI_SUCCESS - Handle destroy success. 224 other - Handle destroy fail. 225 226 --*/ 227 { 228 EFI_STATUS Status; 229 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 230 231 Status = gBS->HandleProtocol ( 232 DriverHandle, 233 &gEfiDevicePathProtocolGuid, 234 (VOID **) &DevicePath 235 ); 236 if (EFI_ERROR (Status)) { 237 return Status; 238 } 239 240 Status = gBS->UninstallProtocolInterface ( 241 DriverHandle, 242 &gEfiDevicePathProtocolGuid, 243 DevicePath 244 ); 245 gBS->FreePool (DevicePath); 246 return Status; 247 } 248 249 EFI_HII_HANDLE 250 DevicePathToHiiHandle ( 251 IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase, 252 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath 253 ) 254 /*++ 255 256 Routine Description: 257 Find HII Handle associated with given Device Path. 258 259 Arguments: 260 HiiDatabase - Point to EFI_HII_DATABASE_PROTOCOL instance. 261 DevicePath - Device Path associated with the HII package list handle. 262 263 Returns: 264 Handle - HII package list Handle associated with the Device Path. 265 NULL - Hii Package list handle is not found. 266 267 --*/ 268 { 269 EFI_STATUS Status; 270 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; 271 UINTN BufferSize; 272 UINTN HandleCount; 273 UINTN Index; 274 EFI_HANDLE *Handles; 275 EFI_HANDLE Handle; 276 UINTN Size; 277 EFI_HANDLE DriverHandle; 278 EFI_HII_HANDLE *HiiHandles; 279 EFI_HII_HANDLE HiiHandle; 280 281 // 282 // Locate Device Path Protocol handle buffer 283 // 284 Status = gBS->LocateHandleBuffer ( 285 ByProtocol, 286 &gEfiDevicePathProtocolGuid, 287 NULL, 288 &HandleCount, 289 &Handles 290 ); 291 if (EFI_ERROR (Status)) { 292 return NULL; 293 } 294 295 // 296 // Search Driver Handle by Device Path 297 // 298 DriverHandle = NULL; 299 BufferSize = EfiDevicePathSize (DevicePath); 300 for(Index = 0; Index < HandleCount; Index++) { 301 Handle = Handles[Index]; 302 gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **) &TmpDevicePath); 303 304 // 305 // Check whether DevicePath match 306 // 307 Size = EfiDevicePathSize (TmpDevicePath); 308 if ((Size == BufferSize) && EfiCompareMem (DevicePath, TmpDevicePath, Size) == 0) { 309 DriverHandle = Handle; 310 break; 311 } 312 } 313 gBS->FreePool (Handles); 314 315 if (DriverHandle == NULL) { 316 return NULL; 317 } 318 319 // 320 // Retrieve all Hii Handles from HII database 321 // 322 BufferSize = 0x1000; 323 HiiHandles = EfiLibAllocatePool (BufferSize); 324 ASSERT (HiiHandles != NULL); 325 Status = HiiDatabase->ListPackageLists ( 326 HiiDatabase, 327 EFI_HII_PACKAGE_TYPE_ALL, 328 NULL, 329 &BufferSize, 330 HiiHandles 331 ); 332 if (Status == EFI_BUFFER_TOO_SMALL) { 333 gBS->FreePool (HiiHandles); 334 HiiHandles = EfiLibAllocatePool (BufferSize); 335 ASSERT (HiiHandles != NULL); 336 337 Status = HiiDatabase->ListPackageLists ( 338 HiiDatabase, 339 EFI_HII_PACKAGE_TYPE_ALL, 340 NULL, 341 &BufferSize, 342 HiiHandles 343 ); 344 } 345 346 if (EFI_ERROR (Status)) { 347 gBS->FreePool (HiiHandles); 348 return NULL; 349 } 350 351 // 352 // Search Hii Handle by Driver Handle 353 // 354 HiiHandle = NULL; 355 HandleCount = BufferSize / sizeof (EFI_HII_HANDLE); 356 for (Index = 0; Index < HandleCount; Index++) { 357 Status = HiiDatabase->GetPackageListHandle ( 358 HiiDatabase, 359 HiiHandles[Index], 360 &Handle 361 ); 362 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) { 363 HiiHandle = HiiHandles[Index]; 364 break; 365 } 366 } 367 368 gBS->FreePool (HiiHandles); 369 return HiiHandle; 370 } 371 372 EFI_STATUS 373 GetHiiHandles ( 374 IN OUT UINTN *HandleBufferLength, 375 OUT EFI_HII_HANDLE **HiiHandleBuffer 376 ) 377 /*++ 378 379 Routine Description: 380 Determines the handles that are currently active in the database. 381 It's the caller's responsibility to free handle buffer. 382 383 Arguments: 384 HiiDatabase - A pointer to the EFI_HII_DATABASE_PROTOCOL instance. 385 HandleBufferLength - On input, a pointer to the length of the handle buffer. On output, 386 the length of the handle buffer that is required for the handles found. 387 HiiHandleBuffer - Pointer to an array of Hii Handles returned. 388 389 Returns: 390 EFI_SUCCESS - Get an array of Hii Handles successfully. 391 EFI_INVALID_PARAMETER - Hii is NULL. 392 EFI_NOT_FOUND - Database not found. 393 394 --*/ 395 { 396 UINTN BufferLength; 397 EFI_STATUS Status; 398 399 BufferLength = 0; 400 401 LocateHiiProtocols (); 402 403 // 404 // Try to find the actual buffer size for HiiHandle Buffer. 405 // 406 Status = gIfrLibHiiDatabase->ListPackageLists ( 407 gIfrLibHiiDatabase, 408 EFI_HII_PACKAGE_TYPE_ALL, 409 NULL, 410 &BufferLength, 411 *HiiHandleBuffer 412 ); 413 414 if (Status == EFI_BUFFER_TOO_SMALL) { 415 *HiiHandleBuffer = EfiLibAllocateZeroPool (BufferLength); 416 Status = gIfrLibHiiDatabase->ListPackageLists ( 417 gIfrLibHiiDatabase, 418 EFI_HII_PACKAGE_TYPE_ALL, 419 NULL, 420 &BufferLength, 421 *HiiHandleBuffer 422 ); 423 // 424 // we should not fail here. 425 // 426 ASSERT_EFI_ERROR (Status); 427 } 428 429 *HandleBufferLength = BufferLength; 430 431 return Status; 432 } 433 434 EFI_STATUS 435 ExtractGuidFromHiiHandle ( 436 IN EFI_HII_HANDLE Handle, 437 OUT EFI_GUID *Guid 438 ) 439 /*++ 440 441 Routine Description: 442 Extract Hii package list GUID for given HII handle. 443 444 Arguments: 445 HiiHandle - Hii handle 446 Guid - Package list GUID 447 448 Returns: 449 EFI_SUCCESS - Successfully extract GUID from Hii database. 450 451 --*/ 452 { 453 EFI_STATUS Status; 454 UINTN BufferSize; 455 EFI_HII_DATABASE_PROTOCOL *HiiDatabase; 456 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; 457 458 // 459 // Locate HII Database protocol 460 // 461 Status = gBS->LocateProtocol ( 462 &gEfiHiiDatabaseProtocolGuid, 463 NULL, 464 (VOID **) &HiiDatabase 465 ); 466 if (EFI_ERROR (Status)) { 467 return Status; 468 } 469 470 // 471 // Get HII PackageList 472 // 473 BufferSize = 0; 474 HiiPackageList = NULL; 475 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); 476 if (Status == EFI_BUFFER_TOO_SMALL) { 477 HiiPackageList = EfiLibAllocatePool (BufferSize); 478 ASSERT (HiiPackageList != NULL); 479 480 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); 481 } 482 if (EFI_ERROR (Status)) { 483 return Status; 484 } 485 486 // 487 // Extract GUID 488 // 489 EfiCopyMem (Guid, &HiiPackageList->PackageListGuid, sizeof (EFI_GUID)); 490 491 gBS->FreePool (HiiPackageList); 492 493 return EFI_SUCCESS; 494 } 495 496 EFI_STATUS 497 ExtractClassFromHiiHandle ( 498 IN EFI_HII_HANDLE Handle, 499 OUT UINT16 *Class, 500 OUT EFI_STRING_ID *FormSetTitle, 501 OUT EFI_STRING_ID *FormSetHelp 502 ) 503 /*++ 504 505 Routine Description: 506 Extract formset class for given HII handle. 507 508 Arguments: 509 HiiHandle - Hii handle 510 Class - Class of the formset 511 FormSetTitle - Formset title string 512 FormSetHelp - Formset help string 513 514 Returns: 515 EFI_SUCCESS - Successfully extract Class for specified Hii handle. 516 EFI_NOT_FOUND - Class not found. 517 518 --*/ 519 { 520 EFI_STATUS Status; 521 UINTN BufferSize; 522 EFI_HII_DATABASE_PROTOCOL *HiiDatabase; 523 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; 524 UINT8 *Package; 525 UINT8 *FormSet; 526 UINT8 *OpCodeData; 527 UINT32 Offset; 528 UINT32 Offset2; 529 UINT32 PackageListLength; 530 EFI_HII_PACKAGE_HEADER PackageHeader; 531 BOOLEAN ClassFound; 532 533 *Class = EFI_NON_DEVICE_CLASS; 534 *FormSetTitle = 0; 535 *FormSetHelp = 0; 536 ClassFound = FALSE; 537 538 // 539 // Locate HII Database protocol 540 // 541 Status = gBS->LocateProtocol ( 542 &gEfiHiiDatabaseProtocolGuid, 543 NULL, 544 (VOID **) &HiiDatabase 545 ); 546 if (EFI_ERROR (Status)) { 547 return Status; 548 } 549 550 // 551 // Get HII PackageList 552 // 553 BufferSize = 0; 554 HiiPackageList = NULL; 555 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); 556 if (Status == EFI_BUFFER_TOO_SMALL) { 557 HiiPackageList = EfiLibAllocatePool (BufferSize); 558 ASSERT (HiiPackageList != NULL); 559 560 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); 561 } 562 if (HiiPackageList == NULL) { 563 return EFI_OUT_OF_RESOURCES; 564 } 565 if (EFI_ERROR (Status)) { 566 gBS->FreePool (HiiPackageList); 567 return Status; 568 } 569 570 // 571 // Get Form package from this HII package List 572 // 573 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); 574 Offset2 = 0; 575 FormSet = NULL; 576 EfiCopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); 577 578 while (Offset < PackageListLength) { 579 Package = ((UINT8 *) HiiPackageList) + Offset; 580 EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); 581 582 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { 583 // 584 // Search Class Opcode in this Form Package 585 // 586 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); 587 while (Offset2 < PackageHeader.Length) { 588 OpCodeData = Package + Offset2; 589 590 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { 591 // 592 // Find FormSet OpCode 593 // 594 EfiCopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); 595 EfiCopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); 596 } 597 598 if ((((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP) && 599 (EfiCompareGuid (&mIfrVendorGuid, &((EFI_IFR_GUID *) OpCodeData)->Guid)) && 600 (((EFI_IFR_GUID_CLASS *) OpCodeData)->ExtendOpCode == EFI_IFR_EXTEND_OP_CLASS) 601 ) { 602 // 603 // Find GUIDed Class OpCode 604 // 605 EfiCopyMem (Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16)); 606 607 // 608 // Till now, we ought to have found the formset Opcode 609 // 610 ClassFound = TRUE; 611 break; 612 } 613 614 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; 615 } 616 617 if (Offset2 < PackageHeader.Length) { 618 // 619 // Target formset found 620 // 621 break; 622 } 623 } 624 625 Offset += PackageHeader.Length; 626 } 627 628 gBS->FreePool (HiiPackageList); 629 630 return ClassFound ? EFI_SUCCESS : EFI_NOT_FOUND; 631 } 632 633 EFI_STATUS 634 ExtractClassGuidFromHiiHandle ( 635 IN EFI_HII_HANDLE Handle, 636 OUT UINT8 *NumberOfClassGuid, 637 OUT EFI_GUID **ClassGuid, 638 OUT EFI_STRING_ID *FormSetTitle, 639 OUT EFI_STRING_ID *FormSetHelp 640 ) 641 /*++ 642 643 Routine Description: 644 Extract formset ClassGuid for given HII handle. 645 646 Arguments: 647 HiiHandle - Hii handle 648 NumberOfClassGuid - Number of ClassGuid 649 ClassGuid - Pointer to callee allocated buffer, an array of ClassGuid 650 FormSetTitle - Formset title string 651 FormSetHelp - Formset help string 652 653 Returns: 654 EFI_SUCCESS - Successfully extract Class for specified Hii handle. 655 656 --*/ 657 { 658 EFI_STATUS Status; 659 UINTN BufferSize; 660 EFI_HII_DATABASE_PROTOCOL *HiiDatabase; 661 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; 662 UINT8 *Package; 663 UINT8 *FormSet; 664 UINT8 *OpCodeData; 665 UINT32 Offset; 666 UINT32 Offset2; 667 UINT32 PackageListLength; 668 EFI_HII_PACKAGE_HEADER PackageHeader; 669 670 if (NumberOfClassGuid == NULL || ClassGuid == NULL || FormSetTitle == NULL || FormSetHelp == NULL) { 671 return EFI_INVALID_PARAMETER; 672 } 673 674 *NumberOfClassGuid = 0; 675 *ClassGuid = NULL; 676 *FormSetTitle = 0; 677 *FormSetHelp = 0; 678 679 // 680 // Locate HII Database protocol 681 // 682 Status = gBS->LocateProtocol ( 683 &gEfiHiiDatabaseProtocolGuid, 684 NULL, 685 (VOID **) &HiiDatabase 686 ); 687 if (EFI_ERROR (Status)) { 688 return Status; 689 } 690 691 // 692 // Get HII PackageList 693 // 694 BufferSize = 0; 695 HiiPackageList = NULL; 696 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); 697 if (Status == EFI_BUFFER_TOO_SMALL) { 698 HiiPackageList = EfiLibAllocatePool (BufferSize); 699 ASSERT (HiiPackageList != NULL); 700 701 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); 702 } 703 if (EFI_ERROR (Status) || (HiiPackageList == NULL)) { 704 return Status; 705 } 706 707 // 708 // Get Form package from this HII package List 709 // 710 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); 711 Offset2 = 0; 712 FormSet = NULL; 713 EfiCopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); 714 715 while (Offset < PackageListLength) { 716 Package = ((UINT8 *) HiiPackageList) + Offset; 717 EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); 718 719 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { 720 // 721 // Search Class Opcode in this Form Package 722 // 723 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); 724 while (Offset2 < PackageHeader.Length) { 725 OpCodeData = Package + Offset2; 726 727 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { 728 // 729 // Find FormSet OpCode 730 // 731 EfiCopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); 732 EfiCopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); 733 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > ((UINTN) &((EFI_IFR_FORM_SET *) 0)->Flags)) { 734 // 735 // New version of formset OpCode 736 // 737 *NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3); 738 *ClassGuid = EfiLibAllocateCopyPool ( 739 *NumberOfClassGuid * sizeof (EFI_GUID), 740 ((EFI_IFR_FORM_SET *) OpCodeData)->ClassGuid 741 ); 742 } 743 break; 744 } 745 746 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; 747 } 748 749 if (Offset2 < PackageHeader.Length) { 750 // 751 // Target formset found 752 // 753 break; 754 } 755 } 756 757 Offset += PackageHeader.Length; 758 } 759 760 gBS->FreePool (HiiPackageList); 761 762 return EFI_SUCCESS; 763 } 764