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