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