]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/HiiLib/HiiLib.c
Clean up HiiLib.
[mirror_edk2.git] / MdePkg / Library / HiiLib / HiiLib.c
CommitLineData
dd51a993 1/** @file\r
2 HII Library implementation that uses DXE protocols and services.\r
3\r
4 Copyright (c) 2006, Intel Corporation<BR>\r
bad46384 5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
dd51a993 9\r
bad46384 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
dd51a993 12\r
dd51a993 13**/\r
14\r
7d582d6b 15#include "InternalHiiLib.h"\r
16\r
c344685c 17CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabaseProt;\r
18CONST EFI_HII_STRING_PROTOCOL *mHiiStringProt;\r
54cf8780 19BOOLEAN mHiiProtocolsInitialized = FALSE;\r
20\r
7d582d6b 21\r
e52c5a9f 22/**\r
7d582d6b 23\r
54cf8780 24 This function locate Hii relative protocols for later usage.\r
25\r
e52c5a9f 26**/\r
54cf8780 27VOID\r
28LocateHiiProtocols (\r
29 VOID\r
7d582d6b 30 )\r
31{\r
54cf8780 32 EFI_STATUS Status;\r
33\r
34 if (mHiiProtocolsInitialized) {\r
29870c8d 35 //\r
36 // Only need to initialize the protocol instance once.\r
37 //\r
54cf8780 38 return;\r
39 }\r
40\r
41 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &mHiiDatabaseProt);\r
7d582d6b 42 ASSERT_EFI_ERROR (Status);\r
7d582d6b 43\r
54cf8780 44 Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &mHiiStringProt);\r
7d582d6b 45 ASSERT_EFI_ERROR (Status);\r
7d582d6b 46\r
54cf8780 47 mHiiProtocolsInitialized = TRUE;\r
7d582d6b 48}\r
49\r
7d582d6b 50\r
51\r
ad1b3619 52/**\r
53 This funciton build the package list based on the package number,\r
54 the GUID of the package list and the list of pointer which point to\r
55 package header that defined by UEFI VFR compiler and StringGather\r
56 tool.\r
57\r
29870c8d 58 #pragma pack (push, 1)\r
59 typedef struct {\r
60 UINT32 BinaryLength;\r
61 EFI_HII_PACKAGE_HEADER PackageHeader;\r
62 } TIANO_AUTOGEN_PACKAGES_HEADER;\r
63 #pragma pack (pop)\r
64\r
ad1b3619 65 If there is not enough resource for the new package list,\r
66 the function will ASSERT.\r
67\r
68 @param NumberOfPackages The number of packages be \r
69 @param GuidId The GUID for the package list to be generated.\r
70 @param Marker The variable argument list. Each entry represent a specific package header that is\r
71 generated by VFR compiler and StrGather tool. The first 4 bytes is a UINT32 value\r
72 that indicate the overall length of the package.\r
73\r
74 @return The pointer to the package list header.\r
75\r
76**/\r
7d582d6b 77EFI_HII_PACKAGE_LIST_HEADER *\r
78InternalHiiLibPreparePackages (\r
79 IN UINTN NumberOfPackages,\r
ad1b3619 80 IN CONST EFI_GUID *GuidId,\r
7d582d6b 81 VA_LIST Marker\r
82 )\r
83{\r
84 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
85 UINT8 *PackageListData;\r
86 UINT32 PackageListLength;\r
87 UINT32 PackageLength;\r
88 EFI_HII_PACKAGE_HEADER PackageHeader;\r
89 UINT8 *PackageArray;\r
90 UINTN Index;\r
91 VA_LIST MarkerBackup;\r
92\r
93 PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
94\r
95 MarkerBackup = Marker;\r
96 \r
97 for (Index = 0; Index < NumberOfPackages; Index++) {\r
98 CopyMem (&PackageLength, VA_ARG (Marker, VOID *), sizeof (UINT32));\r
29870c8d 99 //\r
100 // Do not count the BinaryLength field.\r
101 //\r
7d582d6b 102 PackageListLength += (PackageLength - sizeof (UINT32));\r
103 }\r
104\r
105 //\r
106 // Include the lenght of EFI_HII_PACKAGE_END\r
107 //\r
108 PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);\r
109 PackageListHeader = AllocateZeroPool (PackageListLength);\r
110 ASSERT (PackageListHeader != NULL);\r
29870c8d 111 \r
7d582d6b 112 CopyMem (&PackageListHeader->PackageListGuid, GuidId, sizeof (EFI_GUID));\r
113 PackageListHeader->PackageLength = PackageListLength;\r
114\r
115 PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
116\r
117 Marker = MarkerBackup;\r
118 for (Index = 0; Index < NumberOfPackages; Index++) {\r
119 PackageArray = (UINT8 *) VA_ARG (Marker, VOID *);\r
120 CopyMem (&PackageLength, PackageArray, sizeof (UINT32));\r
121 PackageLength -= sizeof (UINT32);\r
122 PackageArray += sizeof (UINT32);\r
123 CopyMem (PackageListData, PackageArray, PackageLength);\r
124 PackageListData += PackageLength;\r
125 }\r
126\r
127 //\r
128 // Append EFI_HII_PACKAGE_END\r
129 //\r
130 PackageHeader.Type = EFI_HII_PACKAGE_END;\r
131 PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);\r
132 CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);\r
133\r
134 return PackageListHeader;\r
135}\r
136\r
ad1b3619 137/**\r
138 Assemble EFI_HII_PACKAGE_LIST according to the passed in packages.\r
139\r
140 If GuidId is NULL, then ASSERT.\r
141 If not enough resource to complete the operation, then ASSERT.\r
142\r
143 @param NumberOfPackages Number of packages.\r
29870c8d 144 @param GuidId Package GUID.\r
145 @param ... Variable argument list for packages to be assembled.\r
ad1b3619 146\r
147 @return EFI_HII_PACKAGE_LIST_HEADER Pointer of EFI_HII_PACKAGE_LIST_HEADER. The function will ASSERT if system has\r
29870c8d 148 not enough resource to complete the operation.\r
ad1b3619 149\r
150**/\r
7d582d6b 151EFI_HII_PACKAGE_LIST_HEADER *\r
152EFIAPI\r
153HiiLibPreparePackageList (\r
154 IN UINTN NumberOfPackages,\r
155 IN CONST EFI_GUID *GuidId,\r
156 ...\r
157 )\r
7d582d6b 158{\r
159 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
160 VA_LIST Marker;\r
161\r
e52c5a9f 162 ASSERT (GuidId != NULL);\r
163\r
7d582d6b 164 VA_START (Marker, GuidId);\r
165 PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Marker);\r
166 VA_END (Marker);\r
167\r
168 return PackageListHeader;\r
169}\r
170\r
bad46384 171\r
ad1b3619 172/**\r
173 This function allocates pool for an EFI_HII_PACKAGE_LIST structure\r
174 with additional space that is big enough to host all packages described by the variable \r
175 argument list of package pointers. The allocated structure is initialized using NumberOfPackages, \r
176 GuidId, and the variable length argument list of package pointers.\r
177\r
178 Then, EFI_HII_PACKAGE_LIST will be register to the default System HII Database. The\r
179 Handle to the newly registered Package List is returned throught HiiHandle.\r
180\r
181 If HiiHandle is NULL, then ASSERT.\r
182\r
183 @param NumberOfPackages The number of HII packages to register.\r
184 @param GuidId Package List GUID ID.\r
185 @param DriverHandle Optional. If not NULL, the DriverHandle on which an instance of DEVICE_PATH_PROTOCOL is installed.\r
186 This DriverHandle uniquely defines the device that the added packages are associated with.\r
187 @param HiiHandle On output, the HiiHandle is update with the handle which can be used to retrieve the Package \r
188 List later. If the functions failed to add the package to the default HII database, this value will\r
189 be set to NULL.\r
190 @param ... The variable argument list describing all HII Package.\r
191\r
192 @return EFI_SUCCESS If the packages are successfully added to the default HII database.\r
193 @return EFI_OUT_OF_RESOURCE Not enough resource to complete the operation.\r
194\r
195**/\r
7d582d6b 196EFI_STATUS\r
197EFIAPI\r
e52c5a9f 198HiiLibAddPackages (\r
7d582d6b 199 IN UINTN NumberOfPackages,\r
200 IN CONST EFI_GUID *GuidId,\r
201 IN EFI_HANDLE DriverHandle, OPTIONAL\r
2a10d874 202 OUT EFI_HII_HANDLE *HiiHandle,\r
7d582d6b 203 ...\r
204 )\r
205{\r
206 VA_LIST Args;\r
207 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
208 EFI_STATUS Status;\r
209\r
e52c5a9f 210 ASSERT (HiiHandle != NULL);\r
7d582d6b 211\r
54cf8780 212 LocateHiiProtocols ();\r
213\r
7d582d6b 214 VA_START (Args, HiiHandle);\r
215 PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Args);\r
216\r
217 Status = mHiiDatabaseProt->NewPackageList (mHiiDatabaseProt, PackageListHeader, DriverHandle, HiiHandle);\r
218 if (HiiHandle != NULL) {\r
219 if (EFI_ERROR (Status)) {\r
220 *HiiHandle = NULL;\r
221 }\r
222 }\r
223\r
224 FreePool (PackageListHeader);\r
225 VA_END (Args);\r
226 \r
227 return Status;\r
228}\r
229\r
ad1b3619 230/**\r
231 Removes a package list from the default HII database.\r
232\r
233 If HiiHandle is NULL, then ASSERT.\r
234 If HiiHandle is not a valid EFI_HII_HANDLE in the default HII database, then ASSERT.\r
235\r
236 @param HiiHandle The handle that was previously registered to the data base that is requested for removal.\r
237 List later.\r
238\r
ad1b3619 239**/\r
e52c5a9f 240VOID\r
7d582d6b 241EFIAPI\r
e52c5a9f 242HiiLibRemovePackages (\r
7d582d6b 243 IN EFI_HII_HANDLE HiiHandle\r
244 )\r
245{\r
e52c5a9f 246 EFI_STATUS Status;\r
29870c8d 247 ASSERT (IsHiiHandleRegistered (HiiHandle));\r
54cf8780 248\r
249 LocateHiiProtocols ();\r
250\r
e52c5a9f 251 Status = mHiiDatabaseProt->RemovePackageList (mHiiDatabaseProt, HiiHandle);\r
252 ASSERT_EFI_ERROR (Status);\r
7d582d6b 253}\r
254\r
e52c5a9f 255\r
ad1b3619 256/**\r
257 Determines the handles that are currently active in the database.\r
258 It's the caller's responsibility to free handle buffer.\r
259\r
260 If HandleBufferLength is NULL, then ASSERT.\r
261 If HiiHandleBuffer is NULL, then ASSERT.\r
262\r
263 @param HandleBufferLength On input, a pointer to the length of the handle\r
264 buffer. On output, the length of the handle buffer\r
265 that is required for the handles found.\r
266 @param HiiHandleBuffer Pointer to an array of Hii Handles returned.\r
267\r
268 @retval EFI_SUCCESS Get an array of Hii Handles successfully.\r
269\r
270**/\r
7d582d6b 271EFI_STATUS\r
272EFIAPI\r
e52c5a9f 273HiiLibGetHiiHandles (\r
274 IN OUT UINTN *HandleBufferLength,\r
275 OUT EFI_HII_HANDLE **HiiHandleBuffer\r
7d582d6b 276 )\r
277{\r
e52c5a9f 278 UINTN BufferLength;\r
7d582d6b 279 EFI_STATUS Status;\r
7d582d6b 280\r
e52c5a9f 281 ASSERT (HandleBufferLength != NULL);\r
282 ASSERT (HiiHandleBuffer != NULL);\r
7d582d6b 283\r
e52c5a9f 284 BufferLength = 0;\r
7d582d6b 285\r
54cf8780 286 LocateHiiProtocols ();\r
287\r
e52c5a9f 288 //\r
289 // Try to find the actual buffer size for HiiHandle Buffer.\r
290 //\r
291 Status = mHiiDatabaseProt->ListPackageLists (\r
292 mHiiDatabaseProt,\r
293 EFI_HII_PACKAGE_TYPE_ALL,\r
7d582d6b 294 NULL,\r
e52c5a9f 295 &BufferLength,\r
296 *HiiHandleBuffer\r
7d582d6b 297 );\r
7d582d6b 298\r
e52c5a9f 299 if (Status == EFI_BUFFER_TOO_SMALL) {\r
300 *HiiHandleBuffer = AllocateZeroPool (BufferLength);\r
301 Status = mHiiDatabaseProt->ListPackageLists (\r
302 mHiiDatabaseProt,\r
303 EFI_HII_PACKAGE_TYPE_ALL,\r
304 NULL,\r
305 &BufferLength,\r
306 *HiiHandleBuffer\r
307 );\r
308 //\r
309 // we should not fail here.\r
310 //\r
311 ASSERT_EFI_ERROR (Status);\r
7d582d6b 312 }\r
313\r
e52c5a9f 314 *HandleBufferLength = BufferLength;\r
7d582d6b 315\r
316 return Status;\r
317}\r
318\r
ad1b3619 319/**\r
320 Extract Hii package list GUID for given HII handle.\r
321\r
322 If HiiHandle could not be found in the default HII database, then ASSERT.\r
323 If Guid is NULL, then ASSERT.\r
324\r
325 @param Handle Hii handle\r
326 @param Guid Package list GUID\r
327\r
328 @retval EFI_SUCCESS Successfully extract GUID from Hii database.\r
329\r
330**/\r
7d582d6b 331EFI_STATUS\r
dd51a993 332EFIAPI\r
e52c5a9f 333HiiLibExtractGuidFromHiiHandle (\r
334 IN EFI_HII_HANDLE Handle,\r
335 OUT EFI_GUID *Guid\r
7d582d6b 336 )\r
337{\r
338 EFI_STATUS Status;\r
e52c5a9f 339 UINTN BufferSize;\r
340 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
7d582d6b 341\r
e52c5a9f 342 ASSERT (Guid != NULL);\r
29870c8d 343 ASSERT (IsHiiHandleRegistered (Handle));\r
7d582d6b 344\r
e52c5a9f 345 //\r
346 // Get HII PackageList\r
347 //\r
348 BufferSize = 0;\r
349 HiiPackageList = NULL;\r
54cf8780 350\r
351 LocateHiiProtocols ();\r
352\r
e52c5a9f 353 Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList);\r
354 ASSERT (Status != EFI_NOT_FOUND);\r
355 \r
356 if (Status == EFI_BUFFER_TOO_SMALL) {\r
357 HiiPackageList = AllocatePool (BufferSize);\r
358 ASSERT (HiiPackageList != NULL);\r
7d582d6b 359\r
e52c5a9f 360 Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList);\r
7d582d6b 361 }\r
7d582d6b 362 if (EFI_ERROR (Status)) {\r
363 return Status;\r
364 }\r
365\r
e52c5a9f 366 //\r
367 // Extract GUID\r
368 //\r
369 CopyMem (Guid, &HiiPackageList->PackageListGuid, sizeof (EFI_GUID));\r
7d582d6b 370\r
29870c8d 371 FreePool (HiiPackageList);\r
7d582d6b 372\r
373 return EFI_SUCCESS;\r
374}\r
375\r
ad1b3619 376/**\r
377 Find HII Handle in the default HII database associated with given Device Path.\r
378\r
379 If DevicePath is NULL, then ASSERT.\r
380\r
381 @param DevicePath Device Path associated with the HII package list\r
382 handle.\r
383\r
384 @retval Handle HII package list Handle associated with the Device\r
385 Path.\r
386 @retval NULL Hii Package list handle is not found.\r
387\r
388**/\r
e52c5a9f 389EFI_HII_HANDLE\r
390EFIAPI\r
391HiiLibDevicePathToHiiHandle (\r
392 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
7d582d6b 393 )\r
7d582d6b 394{\r
e52c5a9f 395 EFI_STATUS Status;\r
396 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
397 UINTN BufferSize;\r
398 UINTN HandleCount;\r
399 UINTN Index;\r
400 EFI_HANDLE *Handles;\r
401 EFI_HANDLE Handle;\r
402 UINTN Size;\r
403 EFI_HANDLE DriverHandle;\r
404 EFI_HII_HANDLE *HiiHandles;\r
405 EFI_HII_HANDLE HiiHandle;\r
7d582d6b 406\r
e52c5a9f 407 ASSERT (DevicePath != NULL);\r
7d582d6b 408\r
dd51a993 409 //\r
e52c5a9f 410 // Locate Device Path Protocol handle buffer\r
7d582d6b 411 //\r
e52c5a9f 412 Status = gBS->LocateHandleBuffer (\r
413 ByProtocol,\r
414 &gEfiDevicePathProtocolGuid,\r
7d582d6b 415 NULL,\r
e52c5a9f 416 &HandleCount,\r
417 &Handles\r
7d582d6b 418 );\r
419 if (EFI_ERROR (Status)) {\r
e52c5a9f 420 return NULL;\r
7d582d6b 421 }\r
422\r
423 //\r
e52c5a9f 424 // Search Driver Handle by Device Path\r
7d582d6b 425 //\r
e52c5a9f 426 DriverHandle = NULL;\r
427 BufferSize = GetDevicePathSize (DevicePath);\r
428 for(Index = 0; Index < HandleCount; Index++) {\r
429 Handle = Handles[Index];\r
430 gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **) &TmpDevicePath);\r
431\r
432 //\r
433 // Check whether DevicePath match\r
434 //\r
435 Size = GetDevicePathSize (TmpDevicePath);\r
436 if ((Size == BufferSize) && CompareMem (DevicePath, TmpDevicePath, Size) == 0) {\r
437 DriverHandle = Handle;\r
438 break;\r
439 }\r
7d582d6b 440 }\r
29870c8d 441 FreePool (Handles);\r
e52c5a9f 442\r
443 if (DriverHandle == NULL) {\r
444 return NULL;\r
7d582d6b 445 }\r
446\r
54cf8780 447 LocateHiiProtocols ();\r
448\r
bad46384 449 //\r
e52c5a9f 450 // Retrieve all Hii Handles from HII database\r
7d582d6b 451 //\r
e52c5a9f 452 BufferSize = 0x1000;\r
453 HiiHandles = AllocatePool (BufferSize);\r
454 ASSERT (HiiHandles != NULL);\r
455 Status = mHiiDatabaseProt->ListPackageLists (\r
456 mHiiDatabaseProt,\r
457 EFI_HII_PACKAGE_TYPE_ALL,\r
458 NULL,\r
459 &BufferSize,\r
460 HiiHandles\r
461 );\r
462 if (Status == EFI_BUFFER_TOO_SMALL) {\r
29870c8d 463 FreePool (HiiHandles);\r
e52c5a9f 464 HiiHandles = AllocatePool (BufferSize);\r
465 ASSERT (HiiHandles != NULL);\r
466\r
467 Status = mHiiDatabaseProt->ListPackageLists (\r
468 mHiiDatabaseProt,\r
469 EFI_HII_PACKAGE_TYPE_ALL,\r
470 NULL,\r
471 &BufferSize,\r
472 HiiHandles\r
473 );\r
474 }\r
7d582d6b 475\r
e52c5a9f 476 if (EFI_ERROR (Status)) {\r
29870c8d 477 FreePool (HiiHandles);\r
e52c5a9f 478 return NULL;\r
479 }\r
7d582d6b 480\r
e52c5a9f 481 //\r
482 // Search Hii Handle by Driver Handle\r
483 //\r
484 HiiHandle = NULL;\r
485 HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
486 for (Index = 0; Index < HandleCount; Index++) {\r
487 Status = mHiiDatabaseProt->GetPackageListHandle (\r
488 mHiiDatabaseProt,\r
489 HiiHandles[Index],\r
490 &Handle\r
491 );\r
492 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
493 HiiHandle = HiiHandles[Index];\r
494 break;\r
7d582d6b 495 }\r
7d582d6b 496 }\r
497\r
29870c8d 498 FreePool (HiiHandles);\r
e52c5a9f 499 return HiiHandle;\r
500}\r
7d582d6b 501\r
ad1b3619 502/**\r
503 This function check if the Hii Handle is a valid handle registered\r
504 in the HII database.\r
505\r
506 @param HiiHandle The HII Handle.\r
507\r
508 @retval TRUE If it is a valid HII handle.\r
509 @retval FALSE If it is a invalid HII handle.\r
510**/\r
e52c5a9f 511BOOLEAN\r
512IsHiiHandleRegistered (\r
513 EFI_HII_HANDLE HiiHandle\r
514 )\r
515{\r
516 EFI_STATUS Status;\r
517 UINTN BufferSize;\r
518 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
519\r
520 ASSERT (HiiHandle != NULL);\r
521\r
522 HiiPackageList = NULL;\r
523 BufferSize = 0;\r
54cf8780 524\r
525 LocateHiiProtocols ();\r
526\r
e52c5a9f 527 Status = mHiiDatabaseProt->ExportPackageLists (\r
528 mHiiDatabaseProt,\r
529 HiiHandle,\r
530 &BufferSize,\r
531 HiiPackageList\r
532 );\r
533\r
534 return (BOOLEAN) (Status == EFI_BUFFER_TOO_SMALL);\r
dd51a993 535}\r
7d582d6b 536\r