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
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.
18 Common Library Routines to assist handle HII elements.
22 #include "UefiIfrLibrary.h"
25 // Hii vendor device path template
27 HII_VENDOR_DEVICE_PATH mHiiVendorDevicePathTemplate
= {
34 (UINT8
) (sizeof (HII_VENDOR_DEVICE_PATH_NODE
)),
35 (UINT8
) ((sizeof (HII_VENDOR_DEVICE_PATH_NODE
)) >> 8)
45 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
47 END_DEVICE_PATH_LENGTH
53 // Hii relative protocols
55 BOOLEAN mHiiProtocolsInitialized
= FALSE
;
57 EFI_HII_DATABASE_PROTOCOL
*gIfrLibHiiDatabase
;
58 EFI_HII_STRING_PROTOCOL
*gIfrLibHiiString
;
67 This function locate Hii relative protocols for later usage.
79 if (mHiiProtocolsInitialized
) {
83 Status
= gBS
->LocateProtocol (&gEfiHiiDatabaseProtocolGuid
, NULL
, (VOID
**) &gIfrLibHiiDatabase
);
84 ASSERT_EFI_ERROR (Status
);
86 Status
= gBS
->LocateProtocol (&gEfiHiiStringProtocolGuid
, NULL
, (VOID
**) &gIfrLibHiiString
);
87 ASSERT_EFI_ERROR (Status
);
89 mHiiProtocolsInitialized
= TRUE
;
92 EFI_HII_PACKAGE_LIST_HEADER
*
94 IN UINTN NumberOfPackages
,
101 Assemble EFI_HII_PACKAGE_LIST according to the passed in packages.
104 NumberOfPackages - Number of packages.
105 GuidId - Package GUID.
108 Pointer of EFI_HII_PACKAGE_LIST_HEADER.
113 EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
;
114 UINT8
*PackageListData
;
115 UINT32 PackageListLength
;
116 UINT32 PackageLength
;
117 EFI_HII_PACKAGE_HEADER PackageHeader
;
121 PackageListLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
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
));
131 // Include the lenght of EFI_HII_PACKAGE_END
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
;
139 PackageListData
= ((UINT8
*) PackageListHeader
) + sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
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
;
153 // Append EFI_HII_PACKAGE_END
155 PackageHeader
.Type
= EFI_HII_PACKAGE_END
;
156 PackageHeader
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
157 EfiCopyMem (PackageListData
, &PackageHeader
, PackageHeader
.Length
);
159 return PackageListHeader
;
163 CreateHiiDriverHandle (
164 OUT EFI_HANDLE
*DriverHandle
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().
175 DriverHandle - Handle to be returned
178 EFI_SUCCESS - Handle destroy success.
179 EFI_OUT_OF_RESOURCES - Not enough memory.
184 HII_VENDOR_DEVICE_PATH_NODE
*VendorDevicePath
;
186 VendorDevicePath
= EfiLibAllocateCopyPool (sizeof (HII_VENDOR_DEVICE_PATH
), &mHiiVendorDevicePathTemplate
);
187 if (VendorDevicePath
== NULL
) {
188 return EFI_OUT_OF_RESOURCES
;
192 // Use memory address as unique ID to distinguish from different device paths
194 VendorDevicePath
->UniqueId
= (UINT64
) ((UINTN
) VendorDevicePath
);
196 *DriverHandle
= NULL
;
197 Status
= gBS
->InstallMultipleProtocolInterfaces (
199 &gEfiDevicePathProtocolGuid
,
203 if (EFI_ERROR (Status
)) {
211 DestroyHiiDriverHandle (
212 IN EFI_HANDLE DriverHandle
217 Destroy the Driver Handle created by CreateHiiDriverHandle().
220 DriverHandle - Handle returned by CreateHiiDriverHandle()
223 EFI_SUCCESS - Handle destroy success.
224 other - Handle destroy fail.
229 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
231 Status
= gBS
->HandleProtocol (
233 &gEfiDevicePathProtocolGuid
,
234 (VOID
**) &DevicePath
236 if (EFI_ERROR (Status
)) {
240 Status
= gBS
->UninstallProtocolInterface (
242 &gEfiDevicePathProtocolGuid
,
245 gBS
->FreePool (DevicePath
);
250 DevicePathToHiiHandle (
251 IN EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
,
252 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
257 Find HII Handle associated with given Device Path.
260 HiiDatabase - Point to EFI_HII_DATABASE_PROTOCOL instance.
261 DevicePath - Device Path associated with the HII package list handle.
264 Handle - HII package list Handle associated with the Device Path.
265 NULL - Hii Package list handle is not found.
270 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
277 EFI_HANDLE DriverHandle
;
278 EFI_HII_HANDLE
*HiiHandles
;
279 EFI_HII_HANDLE HiiHandle
;
282 // Locate Device Path Protocol handle buffer
284 Status
= gBS
->LocateHandleBuffer (
286 &gEfiDevicePathProtocolGuid
,
291 if (EFI_ERROR (Status
)) {
296 // Search Driver Handle by Device Path
299 BufferSize
= EfiDevicePathSize (DevicePath
);
300 for(Index
= 0; Index
< HandleCount
; Index
++) {
301 Handle
= Handles
[Index
];
302 gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**) &TmpDevicePath
);
305 // Check whether DevicePath match
307 Size
= EfiDevicePathSize (TmpDevicePath
);
308 if ((Size
== BufferSize
) && EfiCompareMem (DevicePath
, TmpDevicePath
, Size
) == 0) {
309 DriverHandle
= Handle
;
313 gBS
->FreePool (Handles
);
315 if (DriverHandle
== NULL
) {
320 // Retrieve all Hii Handles from HII database
323 HiiHandles
= EfiLibAllocatePool (BufferSize
);
324 ASSERT (HiiHandles
!= NULL
);
325 Status
= HiiDatabase
->ListPackageLists (
327 EFI_HII_PACKAGE_TYPE_ALL
,
332 if (Status
== EFI_BUFFER_TOO_SMALL
) {
333 gBS
->FreePool (HiiHandles
);
334 HiiHandles
= EfiLibAllocatePool (BufferSize
);
335 ASSERT (HiiHandles
!= NULL
);
337 Status
= HiiDatabase
->ListPackageLists (
339 EFI_HII_PACKAGE_TYPE_ALL
,
346 if (EFI_ERROR (Status
)) {
347 gBS
->FreePool (HiiHandles
);
352 // Search Hii Handle by Driver Handle
355 HandleCount
= BufferSize
/ sizeof (EFI_HII_HANDLE
);
356 for (Index
= 0; Index
< HandleCount
; Index
++) {
357 Status
= HiiDatabase
->GetPackageListHandle (
362 if (!EFI_ERROR (Status
) && (Handle
== DriverHandle
)) {
363 HiiHandle
= HiiHandles
[Index
];
368 gBS
->FreePool (HiiHandles
);
374 IN OUT UINTN
*HandleBufferLength
,
375 OUT EFI_HII_HANDLE
**HiiHandleBuffer
380 Determines the handles that are currently active in the database.
381 It's the caller's responsibility to free handle buffer.
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.
390 EFI_SUCCESS - Get an array of Hii Handles successfully.
391 EFI_INVALID_PARAMETER - Hii is NULL.
392 EFI_NOT_FOUND - Database not found.
401 LocateHiiProtocols ();
404 // Try to find the actual buffer size for HiiHandle Buffer.
406 Status
= gIfrLibHiiDatabase
->ListPackageLists (
408 EFI_HII_PACKAGE_TYPE_ALL
,
414 if (Status
== EFI_BUFFER_TOO_SMALL
) {
415 *HiiHandleBuffer
= EfiLibAllocateZeroPool (BufferLength
);
416 Status
= gIfrLibHiiDatabase
->ListPackageLists (
418 EFI_HII_PACKAGE_TYPE_ALL
,
424 // we should not fail here.
426 ASSERT_EFI_ERROR (Status
);
429 *HandleBufferLength
= BufferLength
;
435 ExtractGuidFromHiiHandle (
436 IN EFI_HII_HANDLE Handle
,
442 Extract Hii package list GUID for given HII handle.
445 HiiHandle - Hii handle
446 Guid - Package list GUID
449 EFI_SUCCESS - Successfully extract GUID from Hii database.
455 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
456 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
459 // Locate HII Database protocol
461 Status
= gBS
->LocateProtocol (
462 &gEfiHiiDatabaseProtocolGuid
,
464 (VOID
**) &HiiDatabase
466 if (EFI_ERROR (Status
)) {
471 // Get HII PackageList
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
);
480 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
482 if (EFI_ERROR (Status
)) {
489 EfiCopyMem (Guid
, &HiiPackageList
->PackageListGuid
, sizeof (EFI_GUID
));
491 gBS
->FreePool (HiiPackageList
);
497 ExtractClassFromHiiHandle (
498 IN EFI_HII_HANDLE Handle
,
500 OUT EFI_STRING_ID
*FormSetTitle
,
501 OUT EFI_STRING_ID
*FormSetHelp
506 Extract formset class for given HII handle.
509 HiiHandle - Hii handle
510 Class - Class of the formset
511 FormSetTitle - Formset title string
512 FormSetHelp - Formset help string
515 EFI_SUCCESS - Successfully extract Class for specified Hii handle.
516 EFI_NOT_FOUND - Class not found.
522 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
523 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
529 UINT32 PackageListLength
;
530 EFI_HII_PACKAGE_HEADER PackageHeader
;
533 *Class
= EFI_NON_DEVICE_CLASS
;
539 // Locate HII Database protocol
541 Status
= gBS
->LocateProtocol (
542 &gEfiHiiDatabaseProtocolGuid
,
544 (VOID
**) &HiiDatabase
546 if (EFI_ERROR (Status
)) {
551 // Get HII PackageList
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
);
560 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
562 if (HiiPackageList
== NULL
) {
563 return EFI_OUT_OF_RESOURCES
;
565 if (EFI_ERROR (Status
)) {
566 gBS
->FreePool (HiiPackageList
);
571 // Get Form package from this HII package List
573 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
576 EfiCopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
578 while (Offset
< PackageListLength
) {
579 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
580 EfiCopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
582 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
584 // Search Class Opcode in this Form Package
586 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
587 while (Offset2
< PackageHeader
.Length
) {
588 OpCodeData
= Package
+ Offset2
;
590 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
592 // Find FormSet OpCode
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
));
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
)
603 // Find GUIDed Class OpCode
605 EfiCopyMem (Class
, &((EFI_IFR_GUID_CLASS
*) OpCodeData
)->Class
, sizeof (UINT16
));
608 // Till now, we ought to have found the formset Opcode
614 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
617 if (Offset2
< PackageHeader
.Length
) {
619 // Target formset found
625 Offset
+= PackageHeader
.Length
;
628 gBS
->FreePool (HiiPackageList
);
630 return ClassFound
? EFI_SUCCESS
: EFI_NOT_FOUND
;
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
644 Extract formset ClassGuid for given HII handle.
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
654 EFI_SUCCESS - Successfully extract Class for specified Hii handle.
660 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
661 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
667 UINT32 PackageListLength
;
668 EFI_HII_PACKAGE_HEADER PackageHeader
;
670 if (NumberOfClassGuid
== NULL
|| ClassGuid
== NULL
|| FormSetTitle
== NULL
|| FormSetHelp
== NULL
) {
671 return EFI_INVALID_PARAMETER
;
674 *NumberOfClassGuid
= 0;
680 // Locate HII Database protocol
682 Status
= gBS
->LocateProtocol (
683 &gEfiHiiDatabaseProtocolGuid
,
685 (VOID
**) &HiiDatabase
687 if (EFI_ERROR (Status
)) {
692 // Get HII PackageList
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
);
701 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
703 if (EFI_ERROR (Status
)) {
708 // Get Form package from this HII package List
710 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
713 EfiCopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
715 while (Offset
< PackageListLength
) {
716 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
717 EfiCopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
719 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
721 // Search Class Opcode in this Form Package
723 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
724 while (Offset2
< PackageHeader
.Length
) {
725 OpCodeData
= Package
+ Offset2
;
727 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
729 // Find FormSet OpCode
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
)) {
735 // New version of formset OpCode
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
746 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
749 if (Offset2
< PackageHeader
.Length
) {
751 // Target formset found
757 Offset
+= PackageHeader
.Length
;
760 gBS
->FreePool (HiiPackageList
);