]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrCommon.c
90afafe83721df7d5243e31d9264e77d458ffb21
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Dxe / UefiEfiIfrSupportLib / UefiIfrCommon.c
1 /*++
2
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
8
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.
11
12 Module Name:
13
14 UefiIfrCommon.c
15
16 Abstract:
17
18 Common Library Routines to assist handle HII elements.
19
20 --*/
21
22 #include "UefiIfrLibrary.h"
23
24 //
25 // Hii vendor device path template
26 //
27 HII_VENDOR_DEVICE_PATH mHiiVendorDevicePathTemplate = {
28 {
29 {
30 {
31 HARDWARE_DEVICE_PATH,
32 HW_VENDOR_DP,
33 {
34 (UINT8) (sizeof (HII_VENDOR_DEVICE_PATH_NODE)),
35 (UINT8) ((sizeof (HII_VENDOR_DEVICE_PATH_NODE)) >> 8)
36 }
37 },
38 EFI_IFR_TIANO_GUID,
39 },
40 0
41 },
42 {
43 END_DEVICE_PATH_TYPE,
44 END_ENTIRE_DEVICE_PATH_SUBTYPE,
45 {
46 END_DEVICE_PATH_LENGTH
47 }
48 }
49 };
50
51 //
52 // Hii relative protocols
53 //
54 BOOLEAN mHiiProtocolsInitialized = FALSE;
55
56 EFI_HII_DATABASE_PROTOCOL *gIfrLibHiiDatabase;
57 EFI_HII_STRING_PROTOCOL *gIfrLibHiiString;
58
59 VOID
60 LocateHiiProtocols (
61 VOID
62 )
63 /*++
64
65 Routine Description:
66 This function locate Hii relative protocols for later usage.
67
68 Arguments:
69 None.
70
71 Returns:
72 None.
73
74 --*/
75 {
76 EFI_STATUS Status;
77
78 if (mHiiProtocolsInitialized) {
79 return;
80 }
81
82 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gIfrLibHiiDatabase);
83 ASSERT_EFI_ERROR (Status);
84
85 Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &gIfrLibHiiString);
86 ASSERT_EFI_ERROR (Status);
87
88 mHiiProtocolsInitialized = TRUE;
89 }
90
91 EFI_HII_PACKAGE_LIST_HEADER *
92 PreparePackageList (
93 IN UINTN NumberOfPackages,
94 IN EFI_GUID *GuidId,
95 ...
96 )
97 /*++
98
99 Routine Description:
100 Assemble EFI_HII_PACKAGE_LIST according to the passed in packages.
101
102 Arguments:
103 NumberOfPackages - Number of packages.
104 GuidId - Package GUID.
105
106 Returns:
107 Pointer of EFI_HII_PACKAGE_LIST_HEADER.
108
109 --*/
110 {
111 VA_LIST Marker;
112 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
113 UINT8 *PackageListData;
114 UINT32 PackageListLength;
115 UINT32 PackageLength;
116 EFI_HII_PACKAGE_HEADER PackageHeader;
117 UINT8 *PackageArray;
118 UINTN Index;
119
120 PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
121
122 VA_START (Marker, GuidId);
123 for (Index = 0; Index < NumberOfPackages; Index++) {
124 EfiCopyMem (&PackageLength, VA_ARG (Marker, VOID *), sizeof (UINT32));
125 PackageListLength += (PackageLength - sizeof (UINT32));
126 }
127 VA_END (Marker);
128
129 //
130 // Include the lenght of EFI_HII_PACKAGE_END
131 //
132 PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);
133 PackageListHeader = EfiLibAllocateZeroPool (PackageListLength);
134 ASSERT (PackageListHeader != NULL);
135 EfiCopyMem (&PackageListHeader->PackageListGuid, GuidId, sizeof (EFI_GUID));
136 PackageListHeader->PackageLength = PackageListLength;
137
138 PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);
139
140 VA_START (Marker, GuidId);
141 for (Index = 0; Index < NumberOfPackages; Index++) {
142 PackageArray = (UINT8 *) VA_ARG (Marker, VOID *);
143 EfiCopyMem (&PackageLength, PackageArray, sizeof (UINT32));
144 PackageLength -= sizeof (UINT32);
145 PackageArray += sizeof (UINT32);
146 EfiCopyMem (PackageListData, PackageArray, PackageLength);
147 PackageListData += PackageLength;
148 }
149 VA_END (Marker);
150
151 //
152 // Append EFI_HII_PACKAGE_END
153 //
154 PackageHeader.Type = EFI_HII_PACKAGE_END;
155 PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);
156 EfiCopyMem (PackageListData, &PackageHeader, PackageHeader.Length);
157
158 return PackageListHeader;
159 }
160
161 EFI_STATUS
162 CreateHiiDriverHandle (
163 OUT EFI_HANDLE *DriverHandle
164 )
165 /*++
166
167 Routine Description:
168 The HII driver handle passed in for HiiDatabase.NewPackageList() requires
169 that there should be DevicePath Protocol installed on it.
170 This routine create a virtual Driver Handle by installing a vendor device
171 path on it, so as to use it to invoke HiiDatabase.NewPackageList().
172
173 Arguments:
174 DriverHandle - Handle to be returned
175
176 Returns:
177 EFI_SUCCESS - Handle destroy success.
178 EFI_OUT_OF_RESOURCES - Not enough memory.
179
180 --*/
181 {
182 EFI_STATUS Status;
183 HII_VENDOR_DEVICE_PATH_NODE *VendorDevicePath;
184 UINT64 MonotonicCount;
185
186 VendorDevicePath = EfiLibAllocateCopyPool (sizeof (HII_VENDOR_DEVICE_PATH), &mHiiVendorDevicePathTemplate);
187 if (VendorDevicePath == NULL) {
188 return EFI_OUT_OF_RESOURCES;
189 }
190
191 gBS->GetNextMonotonicCount (&MonotonicCount);
192 VendorDevicePath->MonotonicCount = (UINT32) MonotonicCount;
193
194 *DriverHandle = NULL;
195 Status = gBS->InstallProtocolInterface (
196 DriverHandle,
197 &gEfiDevicePathProtocolGuid,
198 EFI_NATIVE_INTERFACE,
199 VendorDevicePath
200 );
201 if (EFI_ERROR (Status)) {
202 return Status;
203 }
204
205 return EFI_SUCCESS;
206 }
207
208 EFI_STATUS
209 DestroyHiiDriverHandle (
210 IN EFI_HANDLE DriverHandle
211 )
212 /*++
213
214 Routine Description:
215 Destroy the Driver Handle created by CreateHiiDriverHandle().
216
217 Arguments:
218 DriverHandle - Handle returned by CreateHiiDriverHandle()
219
220 Returns:
221 EFI_SUCCESS - Handle destroy success.
222 other - Handle destroy fail.
223
224 --*/
225 {
226 EFI_STATUS Status;
227 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
228
229 Status = gBS->HandleProtocol (
230 DriverHandle,
231 &gEfiDevicePathProtocolGuid,
232 (VOID **) &DevicePath
233 );
234 if (EFI_ERROR (Status)) {
235 return Status;
236 }
237
238 Status = gBS->UninstallProtocolInterface (
239 DriverHandle,
240 &gEfiDevicePathProtocolGuid,
241 DevicePath
242 );
243
244 return Status;
245 }
246
247 EFI_HII_HANDLE
248 DevicePathToHiiHandle (
249 IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase,
250 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
251 )
252 /*++
253
254 Routine Description:
255 Find HII Handle associated with given Device Path.
256
257 Arguments:
258 HiiDatabase - Point to EFI_HII_DATABASE_PROTOCOL instance.
259 DevicePath - Device Path associated with the HII package list handle.
260
261 Returns:
262 Handle - HII package list Handle associated with the Device Path.
263 NULL - Hii Package list handle is not found.
264
265 --*/
266 {
267 EFI_STATUS Status;
268 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
269 UINTN BufferSize;
270 UINTN HandleCount;
271 UINTN Index;
272 EFI_HANDLE *Handles;
273 EFI_HANDLE Handle;
274 UINTN Size;
275 EFI_HANDLE DriverHandle;
276 EFI_HII_HANDLE *HiiHandles;
277 EFI_HII_HANDLE HiiHandle;
278
279 //
280 // Locate Device Path Protocol handle buffer
281 //
282 Status = gBS->LocateHandleBuffer (
283 ByProtocol,
284 &gEfiDevicePathProtocolGuid,
285 NULL,
286 &HandleCount,
287 &Handles
288 );
289 if (EFI_ERROR (Status)) {
290 return NULL;
291 }
292
293 //
294 // Search Driver Handle by Device Path
295 //
296 DriverHandle = NULL;
297 BufferSize = EfiDevicePathSize (DevicePath);
298 for(Index = 0; Index < HandleCount; Index++) {
299 Handle = Handles[Index];
300 gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **) &TmpDevicePath);
301
302 //
303 // Check whether DevicePath match
304 //
305 Size = EfiDevicePathSize (TmpDevicePath);
306 if ((Size == BufferSize) && EfiCompareMem (DevicePath, TmpDevicePath, Size) == 0) {
307 DriverHandle = Handle;
308 break;
309 }
310 }
311 gBS->FreePool (Handles);
312
313 if (DriverHandle == NULL) {
314 return NULL;
315 }
316
317 //
318 // Retrieve all Hii Handles from HII database
319 //
320 BufferSize = 0x1000;
321 HiiHandles = EfiLibAllocatePool (BufferSize);
322 ASSERT (HiiHandles != NULL);
323 Status = HiiDatabase->ListPackageLists (
324 HiiDatabase,
325 EFI_HII_PACKAGE_TYPE_ALL,
326 NULL,
327 &BufferSize,
328 HiiHandles
329 );
330 if (Status == EFI_BUFFER_TOO_SMALL) {
331 gBS->FreePool (HiiHandles);
332 HiiHandles = EfiLibAllocatePool (BufferSize);
333 ASSERT (HiiHandles != NULL);
334
335 Status = HiiDatabase->ListPackageLists (
336 HiiDatabase,
337 EFI_HII_PACKAGE_TYPE_ALL,
338 NULL,
339 &BufferSize,
340 HiiHandles
341 );
342 }
343
344 if (EFI_ERROR (Status)) {
345 gBS->FreePool (HiiHandles);
346 return NULL;
347 }
348
349 //
350 // Search Hii Handle by Driver Handle
351 //
352 HiiHandle = NULL;
353 HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);
354 for (Index = 0; Index < HandleCount; Index++) {
355 Status = HiiDatabase->GetPackageListHandle (
356 HiiDatabase,
357 HiiHandles[Index],
358 &Handle
359 );
360 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {
361 HiiHandle = HiiHandles[Index];
362 break;
363 }
364 }
365
366 gBS->FreePool (HiiHandles);
367 return HiiHandle;
368 }
369
370 EFI_STATUS
371 GetHiiHandles (
372 IN OUT UINTN *HandleBufferLength,
373 OUT EFI_HII_HANDLE **HiiHandleBuffer
374 )
375 /*++
376
377 Routine Description:
378 Determines the handles that are currently active in the database.
379 It's the caller's responsibility to free handle buffer.
380
381 Arguments:
382 HiiDatabase - A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
383 HandleBufferLength - On input, a pointer to the length of the handle buffer. On output,
384 the length of the handle buffer that is required for the handles found.
385 HiiHandleBuffer - Pointer to an array of Hii Handles returned.
386
387 Returns:
388 EFI_SUCCESS - Get an array of Hii Handles successfully.
389 EFI_INVALID_PARAMETER - Hii is NULL.
390 EFI_NOT_FOUND - Database not found.
391
392 --*/
393 {
394 UINTN BufferLength;
395 EFI_STATUS Status;
396
397 BufferLength = 0;
398
399 LocateHiiProtocols ();
400
401 //
402 // Try to find the actual buffer size for HiiHandle Buffer.
403 //
404 Status = gIfrLibHiiDatabase->ListPackageLists (
405 gIfrLibHiiDatabase,
406 EFI_HII_PACKAGE_TYPE_ALL,
407 NULL,
408 &BufferLength,
409 *HiiHandleBuffer
410 );
411
412 if (Status == EFI_BUFFER_TOO_SMALL) {
413 *HiiHandleBuffer = EfiLibAllocateZeroPool (BufferLength);
414 Status = gIfrLibHiiDatabase->ListPackageLists (
415 gIfrLibHiiDatabase,
416 EFI_HII_PACKAGE_TYPE_ALL,
417 NULL,
418 &BufferLength,
419 *HiiHandleBuffer
420 );
421 //
422 // we should not fail here.
423 //
424 ASSERT_EFI_ERROR (Status);
425 }
426
427 *HandleBufferLength = BufferLength;
428
429 return Status;
430 }
431
432 EFI_STATUS
433 ExtractGuidFromHiiHandle (
434 IN EFI_HII_HANDLE Handle,
435 OUT EFI_GUID *Guid
436 )
437 /*++
438
439 Routine Description:
440 Extract Hii package list GUID for given HII handle.
441
442 Arguments:
443 HiiHandle - Hii handle
444 Guid - Package list GUID
445
446 Returns:
447 EFI_SUCCESS - Successfully extract GUID from Hii database.
448
449 --*/
450 {
451 EFI_STATUS Status;
452 UINTN BufferSize;
453 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
454 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
455
456 //
457 // Locate HII Database protocol
458 //
459 Status = gBS->LocateProtocol (
460 &gEfiHiiDatabaseProtocolGuid,
461 NULL,
462 (VOID **) &HiiDatabase
463 );
464 if (EFI_ERROR (Status)) {
465 return Status;
466 }
467
468 //
469 // Get HII PackageList
470 //
471 BufferSize = 0;
472 HiiPackageList = NULL;
473 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
474 if (Status == EFI_BUFFER_TOO_SMALL) {
475 HiiPackageList = EfiLibAllocatePool (BufferSize);
476 ASSERT (HiiPackageList != NULL);
477
478 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
479 }
480 if (EFI_ERROR (Status)) {
481 return Status;
482 }
483
484 //
485 // Extract GUID
486 //
487 EfiCopyMem (Guid, &HiiPackageList->PackageListGuid, sizeof (EFI_GUID));
488
489 gBS->FreePool (HiiPackageList);
490
491 return EFI_SUCCESS;
492 }
493
494 EFI_STATUS
495 ExtractClassFromHiiHandle (
496 IN EFI_HII_HANDLE Handle,
497 OUT UINT16 *Class,
498 OUT EFI_STRING_ID *FormSetTitle,
499 OUT EFI_STRING_ID *FormSetHelp
500 )
501 /*++
502
503 Routine Description:
504 Extract formset class for given HII handle.
505
506 Arguments:
507 HiiHandle - Hii handle
508 Class - Class of the formset
509 FormSetTitle - Formset title string
510 FormSetHelp - Formset help string
511
512 Returns:
513 EFI_SUCCESS - Successfully extract Class for specified Hii handle.
514
515 --*/
516 {
517 EFI_STATUS Status;
518 UINTN BufferSize;
519 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
520 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
521 UINT8 *Package;
522 UINT8 *FormSet;
523 UINT8 *OpCodeData;
524 UINT32 Offset;
525 UINT32 Offset2;
526 UINT32 PackageListLength;
527 EFI_HII_PACKAGE_HEADER PackageHeader;
528
529 *Class = EFI_NON_DEVICE_CLASS;
530 *FormSetTitle = 0;
531 *FormSetHelp = 0;
532
533 //
534 // Locate HII Database protocol
535 //
536 Status = gBS->LocateProtocol (
537 &gEfiHiiDatabaseProtocolGuid,
538 NULL,
539 (VOID **) &HiiDatabase
540 );
541 if (EFI_ERROR (Status)) {
542 return Status;
543 }
544
545 //
546 // Get HII PackageList
547 //
548 BufferSize = 0;
549 HiiPackageList = NULL;
550 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
551 if (Status == EFI_BUFFER_TOO_SMALL) {
552 HiiPackageList = EfiLibAllocatePool (BufferSize);
553 ASSERT (HiiPackageList != NULL);
554
555 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
556 }
557 if (HiiPackageList == NULL) {
558 return EFI_OUT_OF_RESOURCES;
559 }
560 if (EFI_ERROR (Status)) {
561 gBS->FreePool (HiiPackageList);
562 return Status;
563 }
564
565 //
566 // Get Form package from this HII package List
567 //
568 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
569 Offset2 = 0;
570 FormSet = NULL;
571 EfiCopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
572
573 while (Offset < PackageListLength) {
574 Package = ((UINT8 *) HiiPackageList) + Offset;
575 EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
576
577 if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
578 //
579 // Search Class Opcode in this Form Package
580 //
581 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
582 while (Offset2 < PackageHeader.Length) {
583 OpCodeData = Package + Offset2;
584
585 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
586 //
587 // Find FormSet OpCode
588 //
589 EfiCopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
590 EfiCopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
591 }
592
593 if ((((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP) &&
594 (EfiCompareGuid (&mIfrVendorGuid, &((EFI_IFR_GUID *) OpCodeData)->Guid)) &&
595 (((EFI_IFR_GUID_CLASS *) OpCodeData)->ExtendOpCode == EFI_IFR_EXTEND_OP_CLASS)
596 ) {
597 //
598 // Find GUIDed Class OpCode
599 //
600 EfiCopyMem (Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));
601
602 //
603 // Till now, we ought to have found the formset Opcode
604 //
605 break;
606 }
607
608 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
609 }
610
611 if (Offset2 < PackageHeader.Length) {
612 //
613 // Target formset found
614 //
615 break;
616 }
617 }
618
619 Offset += PackageHeader.Length;
620 }
621
622 gBS->FreePool (HiiPackageList);
623
624 return EFI_SUCCESS;
625 }