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