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