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
;
528 UINT32 PackageListLength
;
529 EFI_HII_PACKAGE_HEADER PackageHeader
;
532 *Class
= EFI_NON_DEVICE_CLASS
;
538 // Locate HII Database protocol
540 Status
= gBS
->LocateProtocol (
541 &gEfiHiiDatabaseProtocolGuid
,
543 (VOID
**) &HiiDatabase
545 if (EFI_ERROR (Status
)) {
550 // Get HII PackageList
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
);
559 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
561 if (HiiPackageList
== NULL
) {
562 return EFI_OUT_OF_RESOURCES
;
564 if (EFI_ERROR (Status
)) {
565 gBS
->FreePool (HiiPackageList
);
570 // Get Form package from this HII package List
572 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
574 EfiCopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
576 while (Offset
< PackageListLength
) {
577 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
578 EfiCopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
580 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
582 // Search Class Opcode in this Form Package
584 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
585 while (Offset2
< PackageHeader
.Length
) {
586 OpCodeData
= Package
+ Offset2
;
588 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
590 // Find FormSet OpCode
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
));
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
)
601 // Find GUIDed Class OpCode
603 EfiCopyMem (Class
, &((EFI_IFR_GUID_CLASS
*) OpCodeData
)->Class
, sizeof (UINT16
));
606 // Till now, we ought to have found the formset Opcode
612 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
615 if (Offset2
< PackageHeader
.Length
) {
617 // Target formset found
623 Offset
+= PackageHeader
.Length
;
626 gBS
->FreePool (HiiPackageList
);
628 return ClassFound
? EFI_SUCCESS
: EFI_NOT_FOUND
;
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
642 Extract formset ClassGuid for given HII handle.
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
652 EFI_SUCCESS - Successfully extract Class for specified Hii handle.
658 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
659 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
664 UINT32 PackageListLength
;
665 EFI_HII_PACKAGE_HEADER PackageHeader
;
667 if (NumberOfClassGuid
== NULL
|| ClassGuid
== NULL
|| FormSetTitle
== NULL
|| FormSetHelp
== NULL
) {
668 return EFI_INVALID_PARAMETER
;
671 *NumberOfClassGuid
= 0;
677 // Locate HII Database protocol
679 Status
= gBS
->LocateProtocol (
680 &gEfiHiiDatabaseProtocolGuid
,
682 (VOID
**) &HiiDatabase
684 if (EFI_ERROR (Status
)) {
689 // Get HII PackageList
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
);
698 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
700 if (EFI_ERROR (Status
) || (HiiPackageList
== NULL
)) {
705 // Get Form package from this HII package List
707 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
709 EfiCopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
711 while (Offset
< PackageListLength
) {
712 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
713 EfiCopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
715 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
717 // Search Class Opcode in this Form Package
719 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
720 while (Offset2
< PackageHeader
.Length
) {
721 OpCodeData
= Package
+ Offset2
;
723 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
725 // Find FormSet OpCode
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
)) {
731 // New version of formset OpCode
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
742 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
745 if (Offset2
< PackageHeader
.Length
) {
747 // Target formset found
753 Offset
+= PackageHeader
.Length
;
756 gBS
->FreePool (HiiPackageList
);