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 *OpCodeData; 526 UINT32 Offset; 527 UINT32 Offset2; 528 UINT32 PackageListLength; 529 EFI_HII_PACKAGE_HEADER PackageHeader; 530 BOOLEAN ClassFound; 531 532 *Class = EFI_NON_DEVICE_CLASS; 533 *FormSetTitle = 0; 534 *FormSetHelp = 0; 535 ClassFound = FALSE; 536 537 // 538 // Locate HII Database protocol 539 // 540 Status = gBS->LocateProtocol ( 541 &gEfiHiiDatabaseProtocolGuid, 542 NULL, 543 (VOID **) &HiiDatabase 544 ); 545 if (EFI_ERROR (Status)) { 546 return Status; 547 } 548 549 // 550 // Get HII PackageList 551 // 552 BufferSize = 0; 553 HiiPackageList = NULL; 554 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); 555 if (Status == EFI_BUFFER_TOO_SMALL) { 556 HiiPackageList = EfiLibAllocatePool (BufferSize); 557 ASSERT (HiiPackageList != NULL); 558 559 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); 560 } 561 if (HiiPackageList == NULL) { 562 return EFI_OUT_OF_RESOURCES; 563 } 564 if (EFI_ERROR (Status)) { 565 gBS->FreePool (HiiPackageList); 566 return Status; 567 } 568 569 // 570 // Get Form package from this HII package List 571 // 572 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); 573 Offset2 = 0; 574 EfiCopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); 575 576 while (Offset < PackageListLength) { 577 Package = ((UINT8 *) HiiPackageList) + Offset; 578 EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); 579 580 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { 581 // 582 // Search Class Opcode in this Form Package 583 // 584 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); 585 while (Offset2 < PackageHeader.Length) { 586 OpCodeData = Package + Offset2; 587 588 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { 589 // 590 // Find FormSet OpCode 591 // 592 EfiCopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); 593 EfiCopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); 594 } 595 596 if ((((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP) && 597 (EfiCompareGuid (&mIfrVendorGuid, &((EFI_IFR_GUID *) OpCodeData)->Guid)) && 598 (((EFI_IFR_GUID_CLASS *) OpCodeData)->ExtendOpCode == EFI_IFR_EXTEND_OP_CLASS) 599 ) { 600 // 601 // Find GUIDed Class OpCode 602 // 603 EfiCopyMem (Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16)); 604 605 // 606 // Till now, we ought to have found the formset Opcode 607 // 608 ClassFound = TRUE; 609 break; 610 } 611 612 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; 613 } 614 615 if (Offset2 < PackageHeader.Length) { 616 // 617 // Target formset found 618 // 619 break; 620 } 621 } 622 623 Offset += PackageHeader.Length; 624 } 625 626 gBS->FreePool (HiiPackageList); 627 628 return ClassFound ? EFI_SUCCESS : EFI_NOT_FOUND; 629 } 630 631 EFI_STATUS 632 ExtractClassGuidFromHiiHandle ( 633 IN EFI_HII_HANDLE Handle, 634 OUT UINT8 *NumberOfClassGuid, 635 OUT EFI_GUID **ClassGuid, 636 OUT EFI_STRING_ID *FormSetTitle, 637 OUT EFI_STRING_ID *FormSetHelp 638 ) 639 /*++ 640 641 Routine Description: 642 Extract formset ClassGuid for given HII handle. 643 644 Arguments: 645 HiiHandle - Hii handle 646 NumberOfClassGuid - Number of ClassGuid 647 ClassGuid - Pointer to callee allocated buffer, an array of ClassGuid 648 FormSetTitle - Formset title string 649 FormSetHelp - Formset help string 650 651 Returns: 652 EFI_SUCCESS - Successfully extract Class for specified Hii handle. 653 654 --*/ 655 { 656 EFI_STATUS Status; 657 UINTN BufferSize; 658 EFI_HII_DATABASE_PROTOCOL *HiiDatabase; 659 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; 660 UINT8 *Package; 661 UINT8 *OpCodeData; 662 UINT32 Offset; 663 UINT32 Offset2; 664 UINT32 PackageListLength; 665 EFI_HII_PACKAGE_HEADER PackageHeader; 666 667 if (NumberOfClassGuid == NULL || ClassGuid == NULL || FormSetTitle == NULL || FormSetHelp == NULL) { 668 return EFI_INVALID_PARAMETER; 669 } 670 671 *NumberOfClassGuid = 0; 672 *ClassGuid = NULL; 673 *FormSetTitle = 0; 674 *FormSetHelp = 0; 675 676 // 677 // Locate HII Database protocol 678 // 679 Status = gBS->LocateProtocol ( 680 &gEfiHiiDatabaseProtocolGuid, 681 NULL, 682 (VOID **) &HiiDatabase 683 ); 684 if (EFI_ERROR (Status)) { 685 return Status; 686 } 687 688 // 689 // Get HII PackageList 690 // 691 BufferSize = 0; 692 HiiPackageList = NULL; 693 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); 694 if (Status == EFI_BUFFER_TOO_SMALL) { 695 HiiPackageList = EfiLibAllocatePool (BufferSize); 696 ASSERT (HiiPackageList != NULL); 697 698 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); 699 } 700 if (EFI_ERROR (Status) || (HiiPackageList == NULL)) { 701 return Status; 702 } 703 704 // 705 // Get Form package from this HII package List 706 // 707 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); 708 Offset2 = 0; 709 EfiCopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); 710 711 while (Offset < PackageListLength) { 712 Package = ((UINT8 *) HiiPackageList) + Offset; 713 EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); 714 715 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { 716 // 717 // Search Class Opcode in this Form Package 718 // 719 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); 720 while (Offset2 < PackageHeader.Length) { 721 OpCodeData = Package + Offset2; 722 723 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { 724 // 725 // Find FormSet OpCode 726 // 727 EfiCopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); 728 EfiCopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); 729 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > ((UINTN) &((EFI_IFR_FORM_SET *) 0)->Flags)) { 730 // 731 // New version of formset OpCode 732 // 733 *NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3); 734 *ClassGuid = EfiLibAllocateCopyPool ( 735 *NumberOfClassGuid * sizeof (EFI_GUID), 736 ((EFI_IFR_FORM_SET *) OpCodeData)->ClassGuid 737 ); 738 } 739 break; 740 } 741 742 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; 743 } 744 745 if (Offset2 < PackageHeader.Length) { 746 // 747 // Target formset found 748 // 749 break; 750 } 751 } 752 753 Offset += PackageHeader.Length; 754 } 755 756 gBS->FreePool (HiiPackageList); 757 758 return EFI_SUCCESS; 759 } 760