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
LocateHiiProtocols(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 *
PreparePackageList(IN UINTN NumberOfPackages,IN EFI_GUID * GuidId,...)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
CreateHiiDriverHandle(OUT EFI_HANDLE * DriverHandle)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
DestroyHiiDriverHandle(IN EFI_HANDLE DriverHandle)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
DevicePathToHiiHandle(IN EFI_HII_DATABASE_PROTOCOL * HiiDatabase,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
GetHiiHandles(IN OUT UINTN * HandleBufferLength,OUT EFI_HII_HANDLE ** HiiHandleBuffer)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
ExtractGuidFromHiiHandle(IN EFI_HII_HANDLE Handle,OUT EFI_GUID * Guid)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
ExtractClassFromHiiHandle(IN EFI_HII_HANDLE Handle,OUT UINT16 * Class,OUT EFI_STRING_ID * FormSetTitle,OUT EFI_STRING_ID * FormSetHelp)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
ExtractClassGuidFromHiiHandle(IN EFI_HII_HANDLE Handle,OUT UINT8 * NumberOfClassGuid,OUT EFI_GUID ** ClassGuid,OUT EFI_STRING_ID * FormSetTitle,OUT EFI_STRING_ID * FormSetHelp)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