3 Copyright (c) 2007, Intel Corporation
4 All rights reserved. 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
= {
33 (UINT8
) (sizeof (HII_VENDOR_DEVICE_PATH_NODE
)),
34 (UINT8
) ((sizeof (HII_VENDOR_DEVICE_PATH_NODE
)) >> 8)
42 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
43 END_DEVICE_PATH_LENGTH
,
49 // Hii relative protocols
51 BOOLEAN mHiiProtocolsInitialized
= FALSE
;
53 EFI_HII_DATABASE_PROTOCOL
*gIfrLibHiiDatabase
;
54 EFI_HII_STRING_PROTOCOL
*gIfrLibHiiString
;
63 This function locate Hii relative protocols for later usage.
75 if (mHiiProtocolsInitialized
) {
79 Status
= gBS
->LocateProtocol (&gEfiHiiDatabaseProtocolGuid
, NULL
, &gIfrLibHiiDatabase
);
80 ASSERT_EFI_ERROR (Status
);
82 Status
= gBS
->LocateProtocol (&gEfiHiiStringProtocolGuid
, NULL
, &gIfrLibHiiString
);
83 ASSERT_EFI_ERROR (Status
);
85 mHiiProtocolsInitialized
= TRUE
;
88 EFI_HII_PACKAGE_LIST_HEADER
*
90 IN UINTN NumberOfPackages
,
97 Assemble EFI_HII_PACKAGE_LIST according to the passed in packages.
100 NumberOfPackages - Number of packages.
101 GuidId - Package GUID.
104 Pointer of EFI_HII_PACKAGE_LIST_HEADER.
109 EFI_HII_PACKAGE_LIST_HEADER
*PackageListHeader
;
110 UINT8
*PackageListData
;
111 UINT32 PackageListLength
;
112 UINT32 PackageLength
;
113 EFI_HII_PACKAGE_HEADER PackageHeader
;
117 PackageListLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
119 VA_START (Marker
, GuidId
);
120 for (Index
= 0; Index
< NumberOfPackages
; Index
++) {
121 EfiCopyMem (&PackageLength
, VA_ARG (Marker
, VOID
*), sizeof (UINT32
));
122 PackageListLength
+= (PackageLength
- sizeof (UINT32
));
127 // Include the lenght of EFI_HII_PACKAGE_END
129 PackageListLength
+= sizeof (EFI_HII_PACKAGE_HEADER
);
130 PackageListHeader
= EfiLibAllocateZeroPool (PackageListLength
);
131 ASSERT (PackageListHeader
!= NULL
);
132 EfiCopyMem (&PackageListHeader
->PackageListGuid
, GuidId
, sizeof (EFI_GUID
));
133 PackageListHeader
->PackageLength
= PackageListLength
;
135 PackageListData
= ((UINT8
*) PackageListHeader
) + sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
137 VA_START (Marker
, GuidId
);
138 for (Index
= 0; Index
< NumberOfPackages
; Index
++) {
139 PackageArray
= (UINT8
*) VA_ARG (Marker
, VOID
*);
140 EfiCopyMem (&PackageLength
, PackageArray
, sizeof (UINT32
));
141 PackageLength
-= sizeof (UINT32
);
142 PackageArray
+= sizeof (UINT32
);
143 EfiCopyMem (PackageListData
, PackageArray
, PackageLength
);
144 PackageListData
+= PackageLength
;
149 // Append EFI_HII_PACKAGE_END
151 PackageHeader
.Type
= EFI_HII_PACKAGE_END
;
152 PackageHeader
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
153 EfiCopyMem (PackageListData
, &PackageHeader
, PackageHeader
.Length
);
155 return PackageListHeader
;
159 CreateHiiDriverHandle (
160 OUT EFI_HANDLE
*DriverHandle
165 The HII driver handle passed in for HiiDatabase.NewPackageList() requires
166 that there should be DevicePath Protocol installed on it.
167 This routine create a virtual Driver Handle by installing a vendor device
168 path on it, so as to use it to invoke HiiDatabase.NewPackageList().
171 DriverHandle - Handle to be returned
174 EFI_SUCCESS - Handle destroy success.
175 EFI_OUT_OF_RESOURCES - Not enough memory.
180 HII_VENDOR_DEVICE_PATH_NODE
*VendorDevicePath
;
181 UINT64 MonotonicCount
;
183 VendorDevicePath
= EfiLibAllocateCopyPool (sizeof (HII_VENDOR_DEVICE_PATH
), &mHiiVendorDevicePathTemplate
);
184 if (VendorDevicePath
== NULL
) {
185 return EFI_OUT_OF_RESOURCES
;
188 gBS
->GetNextMonotonicCount (&MonotonicCount
);
189 VendorDevicePath
->MonotonicCount
= (UINT32
) MonotonicCount
;
191 *DriverHandle
= NULL
;
192 Status
= gBS
->InstallProtocolInterface (
194 &gEfiDevicePathProtocolGuid
,
195 EFI_NATIVE_INTERFACE
,
198 if (EFI_ERROR (Status
)) {
206 DestroyHiiDriverHandle (
207 IN EFI_HANDLE DriverHandle
212 Destroy the Driver Handle created by CreateHiiDriverHandle().
215 DriverHandle - Handle returned by CreateHiiDriverHandle()
218 EFI_SUCCESS - Handle destroy success.
219 other - Handle destroy fail.
224 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
226 Status
= gBS
->HandleProtocol (
228 &gEfiDevicePathProtocolGuid
,
231 if (EFI_ERROR (Status
)) {
235 Status
= gBS
->UninstallProtocolInterface (
237 &gEfiDevicePathProtocolGuid
,
245 DevicePathToHiiHandle (
246 IN EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
,
247 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
252 Find HII Handle associated with given Device Path.
255 HiiDatabase - Point to EFI_HII_DATABASE_PROTOCOL instance.
256 DevicePath - Device Path associated with the HII package list handle.
259 Handle - HII package list Handle associated with the Device Path.
260 NULL - Hii Package list handle is not found.
265 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
272 EFI_HANDLE DriverHandle
;
273 EFI_HII_HANDLE
*HiiHandles
;
274 EFI_HII_HANDLE HiiHandle
;
277 // Locate Device Path Protocol handle buffer
279 Status
= gBS
->LocateHandleBuffer (
281 &gEfiDevicePathProtocolGuid
,
286 if (EFI_ERROR (Status
)) {
291 // Search Driver Handle by Device Path
294 BufferSize
= EfiDevicePathSize (DevicePath
);
295 for(Index
= 0; Index
< HandleCount
; Index
++) {
296 Handle
= Handles
[Index
];
297 gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, &TmpDevicePath
);
300 // Check whether DevicePath match
302 Size
= EfiDevicePathSize (TmpDevicePath
);
303 if ((Size
== BufferSize
) && EfiCompareMem (DevicePath
, TmpDevicePath
, Size
) == 0) {
304 DriverHandle
= Handle
;
308 gBS
->FreePool (Handles
);
310 if (DriverHandle
== NULL
) {
315 // Retrieve all Hii Handles from HII database
318 HiiHandles
= EfiLibAllocatePool (BufferSize
);
319 ASSERT (HiiHandles
!= NULL
);
320 Status
= HiiDatabase
->ListPackageLists (
322 EFI_HII_PACKAGE_TYPE_ALL
,
327 if (Status
== EFI_BUFFER_TOO_SMALL
) {
328 gBS
->FreePool (HiiHandles
);
329 HiiHandles
= EfiLibAllocatePool (BufferSize
);
330 ASSERT (HiiHandles
!= NULL
);
332 Status
= HiiDatabase
->ListPackageLists (
334 EFI_HII_PACKAGE_TYPE_ALL
,
341 if (EFI_ERROR (Status
)) {
342 gBS
->FreePool (HiiHandles
);
347 // Search Hii Handle by Driver Handle
350 HandleCount
= BufferSize
/ sizeof (EFI_HII_HANDLE
);
351 for (Index
= 0; Index
< HandleCount
; Index
++) {
352 Status
= HiiDatabase
->GetPackageListHandle (
357 if (!EFI_ERROR (Status
) && (Handle
== DriverHandle
)) {
358 HiiHandle
= HiiHandles
[Index
];
363 gBS
->FreePool (HiiHandles
);
369 IN OUT UINTN
*HandleBufferLength
,
370 OUT EFI_HII_HANDLE
**HiiHandleBuffer
375 Determines the handles that are currently active in the database.
376 It's the caller's responsibility to free handle buffer.
379 HiiDatabase - A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
380 HandleBufferLength - On input, a pointer to the length of the handle buffer. On output,
381 the length of the handle buffer that is required for the handles found.
382 HiiHandleBuffer - Pointer to an array of Hii Handles returned.
385 EFI_SUCCESS - Get an array of Hii Handles successfully.
386 EFI_INVALID_PARAMETER - Hii is NULL.
387 EFI_NOT_FOUND - Database not found.
396 LocateHiiProtocols ();
399 // Try to find the actual buffer size for HiiHandle Buffer.
401 Status
= gIfrLibHiiDatabase
->ListPackageLists (
403 EFI_HII_PACKAGE_TYPE_ALL
,
409 if (Status
== EFI_BUFFER_TOO_SMALL
) {
410 *HiiHandleBuffer
= EfiLibAllocateZeroPool (BufferLength
);
411 Status
= gIfrLibHiiDatabase
->ListPackageLists (
413 EFI_HII_PACKAGE_TYPE_ALL
,
419 // we should not fail here.
421 ASSERT_EFI_ERROR (Status
);
424 *HandleBufferLength
= BufferLength
;
430 ExtractGuidFromHiiHandle (
431 IN EFI_HII_HANDLE Handle
,
437 Extract Hii package list GUID for given HII handle.
440 HiiHandle - Hii handle
441 Guid - Package list GUID
444 EFI_SUCCESS - Successfully extract GUID from Hii database.
450 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
451 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
454 // Locate HII Database protocol
456 Status
= gBS
->LocateProtocol (
457 &gEfiHiiDatabaseProtocolGuid
,
461 if (EFI_ERROR (Status
)) {
466 // Get HII PackageList
469 HiiPackageList
= NULL
;
470 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
471 if (Status
== EFI_BUFFER_TOO_SMALL
) {
472 HiiPackageList
= EfiLibAllocatePool (BufferSize
);
473 ASSERT (HiiPackageList
!= NULL
);
475 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
477 if (EFI_ERROR (Status
)) {
484 EfiCopyMem (Guid
, &HiiPackageList
->PackageListGuid
, sizeof (EFI_GUID
));
486 gBS
->FreePool (HiiPackageList
);
492 ExtractClassFromHiiHandle (
493 IN EFI_HII_HANDLE Handle
,
495 OUT EFI_STRING_ID
*FormSetTitle
,
496 OUT EFI_STRING_ID
*FormSetHelp
501 Extract formset class for given HII handle.
504 HiiHandle - Hii handle
505 Class - Class of the formset
506 FormSetTitle - Formset title string
507 FormSetHelp - Formset help string
510 EFI_SUCCESS - Successfully extract Class for specified Hii handle.
516 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
517 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
523 UINT32 PackageListLength
;
524 EFI_HII_PACKAGE_HEADER PackageHeader
;
526 *Class
= EFI_NON_DEVICE_CLASS
;
531 // Locate HII Database protocol
533 Status
= gBS
->LocateProtocol (
534 &gEfiHiiDatabaseProtocolGuid
,
538 if (EFI_ERROR (Status
)) {
543 // Get HII PackageList
546 HiiPackageList
= NULL
;
547 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
548 if (Status
== EFI_BUFFER_TOO_SMALL
) {
549 HiiPackageList
= EfiLibAllocatePool (BufferSize
);
550 ASSERT (HiiPackageList
!= NULL
);
552 Status
= HiiDatabase
->ExportPackageLists (HiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
554 if (EFI_ERROR (Status
)) {
559 // Get Form package from this HII package List
561 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
564 EfiCopyMem (&PackageListLength
, &HiiPackageList
->PackageLength
, sizeof (UINT32
));
566 while (Offset
< PackageListLength
) {
567 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
568 EfiCopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
570 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
572 // Search Class Opcode in this Form Package
574 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
575 while (Offset2
< PackageHeader
.Length
) {
576 OpCodeData
= Package
+ Offset2
;
578 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
580 // Find FormSet OpCode
582 EfiCopyMem (FormSetTitle
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->FormSetTitle
, sizeof (EFI_STRING_ID
));
583 EfiCopyMem (FormSetHelp
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Help
, sizeof (EFI_STRING_ID
));
586 if ((((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_GUID_OP
) &&
587 (EfiCompareGuid (&mIfrVendorGuid
, &((EFI_IFR_GUID
*) OpCodeData
)->Guid
)) &&
588 (((EFI_IFR_GUID_CLASS
*) OpCodeData
)->ExtendOpCode
== EFI_IFR_EXTEND_OP_CLASS
)
591 // Find GUIDed Class OpCode
593 EfiCopyMem (Class
, &((EFI_IFR_GUID_CLASS
*) OpCodeData
)->Class
, sizeof (UINT16
));
596 // Till now, we ought to have found the formset Opcode
601 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
604 if (Offset2
< PackageHeader
.Length
) {
606 // Target formset found
612 Offset
+= PackageHeader
.Length
;
615 gBS
->FreePool (HiiPackageList
);