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