]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/HiiLib/HiiLib.c
Add in more comments.
[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
1db1f6ad 81 IN VA_LIST Marker\r
7d582d6b 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
ccac388d 96\r
97 //\r
98 // Count the lenth of the final package list.\r
99 //\r
7d582d6b 100 for (Index = 0; Index < NumberOfPackages; Index++) {\r
101 CopyMem (&PackageLength, VA_ARG (Marker, VOID *), sizeof (UINT32));\r
29870c8d 102 //\r
103 // Do not count the BinaryLength field.\r
104 //\r
7d582d6b 105 PackageListLength += (PackageLength - sizeof (UINT32));\r
106 }\r
107\r
108 //\r
109 // Include the lenght of EFI_HII_PACKAGE_END\r
110 //\r
111 PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);\r
112 PackageListHeader = AllocateZeroPool (PackageListLength);\r
113 ASSERT (PackageListHeader != NULL);\r
29870c8d 114 \r
7d582d6b 115 CopyMem (&PackageListHeader->PackageListGuid, GuidId, sizeof (EFI_GUID));\r
116 PackageListHeader->PackageLength = PackageListLength;\r
117\r
118 PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
119\r
120 Marker = MarkerBackup;\r
ccac388d 121 //\r
122 // Prepare the final package list.\r
123 //\r
7d582d6b 124 for (Index = 0; Index < NumberOfPackages; Index++) {\r
125 PackageArray = (UINT8 *) VA_ARG (Marker, VOID *);\r
126 CopyMem (&PackageLength, PackageArray, sizeof (UINT32));\r
127 PackageLength -= sizeof (UINT32);\r
128 PackageArray += sizeof (UINT32);\r
129 CopyMem (PackageListData, PackageArray, PackageLength);\r
130 PackageListData += PackageLength;\r
131 }\r
132\r
133 //\r
134 // Append EFI_HII_PACKAGE_END\r
135 //\r
136 PackageHeader.Type = EFI_HII_PACKAGE_END;\r
137 PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);\r
138 CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);\r
139\r
140 return PackageListHeader;\r
141}\r
142\r
ad1b3619 143/**\r
144 Assemble EFI_HII_PACKAGE_LIST according to the passed in packages.\r
145\r
146 If GuidId is NULL, then ASSERT.\r
147 If not enough resource to complete the operation, then ASSERT.\r
148\r
149 @param NumberOfPackages Number of packages.\r
29870c8d 150 @param GuidId Package GUID.\r
151 @param ... Variable argument list for packages to be assembled.\r
ad1b3619 152\r
153 @return EFI_HII_PACKAGE_LIST_HEADER Pointer of EFI_HII_PACKAGE_LIST_HEADER. The function will ASSERT if system has\r
29870c8d 154 not enough resource to complete the operation.\r
ad1b3619 155\r
156**/\r
7d582d6b 157EFI_HII_PACKAGE_LIST_HEADER *\r
158EFIAPI\r
159HiiLibPreparePackageList (\r
160 IN UINTN NumberOfPackages,\r
161 IN CONST EFI_GUID *GuidId,\r
162 ...\r
163 )\r
7d582d6b 164{\r
165 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
166 VA_LIST Marker;\r
167\r
e52c5a9f 168 ASSERT (GuidId != NULL);\r
169\r
7d582d6b 170 VA_START (Marker, GuidId);\r
171 PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Marker);\r
172 VA_END (Marker);\r
173\r
174 return PackageListHeader;\r
175}\r
176\r
bad46384 177\r
ad1b3619 178/**\r
179 This function allocates pool for an EFI_HII_PACKAGE_LIST structure\r
180 with additional space that is big enough to host all packages described by the variable \r
181 argument list of package pointers. The allocated structure is initialized using NumberOfPackages, \r
182 GuidId, and the variable length argument list of package pointers.\r
183\r
184 Then, EFI_HII_PACKAGE_LIST will be register to the default System HII Database. The\r
185 Handle to the newly registered Package List is returned throught HiiHandle.\r
186\r
187 If HiiHandle is NULL, then ASSERT.\r
188\r
189 @param NumberOfPackages The number of HII packages to register.\r
190 @param GuidId Package List GUID ID.\r
191 @param DriverHandle Optional. If not NULL, the DriverHandle on which an instance of DEVICE_PATH_PROTOCOL is installed.\r
192 This DriverHandle uniquely defines the device that the added packages are associated with.\r
193 @param HiiHandle On output, the HiiHandle is update with the handle which can be used to retrieve the Package \r
194 List later. If the functions failed to add the package to the default HII database, this value will\r
195 be set to NULL.\r
196 @param ... The variable argument list describing all HII Package.\r
197\r
198 @return EFI_SUCCESS If the packages are successfully added to the default HII database.\r
199 @return EFI_OUT_OF_RESOURCE Not enough resource to complete the operation.\r
200\r
201**/\r
7d582d6b 202EFI_STATUS\r
203EFIAPI\r
e52c5a9f 204HiiLibAddPackages (\r
7d582d6b 205 IN UINTN NumberOfPackages,\r
206 IN CONST EFI_GUID *GuidId,\r
207 IN EFI_HANDLE DriverHandle, OPTIONAL\r
2a10d874 208 OUT EFI_HII_HANDLE *HiiHandle,\r
7d582d6b 209 ...\r
210 )\r
211{\r
212 VA_LIST Args;\r
213 EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
214 EFI_STATUS Status;\r
215\r
e52c5a9f 216 ASSERT (HiiHandle != NULL);\r
7d582d6b 217\r
54cf8780 218 LocateHiiProtocols ();\r
219\r
7d582d6b 220 VA_START (Args, HiiHandle);\r
221 PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Args);\r
222\r
223 Status = mHiiDatabaseProt->NewPackageList (mHiiDatabaseProt, PackageListHeader, DriverHandle, HiiHandle);\r
224 if (HiiHandle != NULL) {\r
225 if (EFI_ERROR (Status)) {\r
226 *HiiHandle = NULL;\r
227 }\r
228 }\r
229\r
230 FreePool (PackageListHeader);\r
231 VA_END (Args);\r
232 \r
233 return Status;\r
234}\r
235\r
ad1b3619 236/**\r
237 Removes a package list from the default HII database.\r
238\r
239 If HiiHandle is NULL, then ASSERT.\r
240 If HiiHandle is not a valid EFI_HII_HANDLE in the default HII database, then ASSERT.\r
241\r
242 @param HiiHandle The handle that was previously registered to the data base that is requested for removal.\r
243 List later.\r
244\r
ad1b3619 245**/\r
e52c5a9f 246VOID\r
7d582d6b 247EFIAPI\r
e52c5a9f 248HiiLibRemovePackages (\r
7d582d6b 249 IN EFI_HII_HANDLE HiiHandle\r
250 )\r
251{\r
e52c5a9f 252 EFI_STATUS Status;\r
29870c8d 253 ASSERT (IsHiiHandleRegistered (HiiHandle));\r
54cf8780 254\r
255 LocateHiiProtocols ();\r
256\r
e52c5a9f 257 Status = mHiiDatabaseProt->RemovePackageList (mHiiDatabaseProt, HiiHandle);\r
258 ASSERT_EFI_ERROR (Status);\r
7d582d6b 259}\r
260\r
e52c5a9f 261\r
ad1b3619 262/**\r
263 Determines the handles that are currently active in the database.\r
264 It's the caller's responsibility to free handle buffer.\r
265\r
266 If HandleBufferLength is NULL, then ASSERT.\r
267 If HiiHandleBuffer is NULL, then ASSERT.\r
268\r
269 @param HandleBufferLength On input, a pointer to the length of the handle\r
270 buffer. On output, the length of the handle buffer\r
271 that is required for the handles found.\r
272 @param HiiHandleBuffer Pointer to an array of Hii Handles returned.\r
273\r
274 @retval EFI_SUCCESS Get an array of Hii Handles successfully.\r
275\r
276**/\r
7d582d6b 277EFI_STATUS\r
278EFIAPI\r
e52c5a9f 279HiiLibGetHiiHandles (\r
280 IN OUT UINTN *HandleBufferLength,\r
281 OUT EFI_HII_HANDLE **HiiHandleBuffer\r
7d582d6b 282 )\r
283{\r
e52c5a9f 284 UINTN BufferLength;\r
7d582d6b 285 EFI_STATUS Status;\r
7d582d6b 286\r
e52c5a9f 287 ASSERT (HandleBufferLength != NULL);\r
288 ASSERT (HiiHandleBuffer != NULL);\r
7d582d6b 289\r
e52c5a9f 290 BufferLength = 0;\r
7d582d6b 291\r
54cf8780 292 LocateHiiProtocols ();\r
293\r
e52c5a9f 294 //\r
295 // Try to find the actual buffer size for HiiHandle Buffer.\r
296 //\r
297 Status = mHiiDatabaseProt->ListPackageLists (\r
298 mHiiDatabaseProt,\r
299 EFI_HII_PACKAGE_TYPE_ALL,\r
7d582d6b 300 NULL,\r
e52c5a9f 301 &BufferLength,\r
302 *HiiHandleBuffer\r
7d582d6b 303 );\r
7d582d6b 304\r
e52c5a9f 305 if (Status == EFI_BUFFER_TOO_SMALL) {\r
306 *HiiHandleBuffer = AllocateZeroPool (BufferLength);\r
307 Status = mHiiDatabaseProt->ListPackageLists (\r
308 mHiiDatabaseProt,\r
309 EFI_HII_PACKAGE_TYPE_ALL,\r
310 NULL,\r
311 &BufferLength,\r
312 *HiiHandleBuffer\r
313 );\r
314 //\r
315 // we should not fail here.\r
316 //\r
317 ASSERT_EFI_ERROR (Status);\r
7d582d6b 318 }\r
319\r
e52c5a9f 320 *HandleBufferLength = BufferLength;\r
7d582d6b 321\r
322 return Status;\r
323}\r
324\r
ad1b3619 325/**\r
326 Extract Hii package list GUID for given HII handle.\r
327\r
328 If HiiHandle could not be found in the default HII database, then ASSERT.\r
329 If Guid is NULL, then ASSERT.\r
330\r
331 @param Handle Hii handle\r
332 @param Guid Package list GUID\r
333\r
334 @retval EFI_SUCCESS Successfully extract GUID from Hii database.\r
335\r
336**/\r
7d582d6b 337EFI_STATUS\r
dd51a993 338EFIAPI\r
e52c5a9f 339HiiLibExtractGuidFromHiiHandle (\r
340 IN EFI_HII_HANDLE Handle,\r
341 OUT EFI_GUID *Guid\r
7d582d6b 342 )\r
343{\r
344 EFI_STATUS Status;\r
e52c5a9f 345 UINTN BufferSize;\r
346 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
7d582d6b 347\r
e52c5a9f 348 ASSERT (Guid != NULL);\r
29870c8d 349 ASSERT (IsHiiHandleRegistered (Handle));\r
7d582d6b 350\r
e52c5a9f 351 //\r
352 // Get HII PackageList\r
353 //\r
354 BufferSize = 0;\r
355 HiiPackageList = NULL;\r
54cf8780 356\r
357 LocateHiiProtocols ();\r
358\r
e52c5a9f 359 Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList);\r
360 ASSERT (Status != EFI_NOT_FOUND);\r
361 \r
362 if (Status == EFI_BUFFER_TOO_SMALL) {\r
363 HiiPackageList = AllocatePool (BufferSize);\r
364 ASSERT (HiiPackageList != NULL);\r
7d582d6b 365\r
e52c5a9f 366 Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList);\r
7d582d6b 367 }\r
7d582d6b 368 if (EFI_ERROR (Status)) {\r
369 return Status;\r
370 }\r
371\r
e52c5a9f 372 //\r
373 // Extract GUID\r
374 //\r
375 CopyMem (Guid, &HiiPackageList->PackageListGuid, sizeof (EFI_GUID));\r
7d582d6b 376\r
29870c8d 377 FreePool (HiiPackageList);\r
7d582d6b 378\r
379 return EFI_SUCCESS;\r
380}\r
381\r
ad1b3619 382/**\r
383 Find HII Handle in the default HII database associated with given Device Path.\r
384\r
385 If DevicePath is NULL, then ASSERT.\r
386\r
387 @param DevicePath Device Path associated with the HII package list\r
388 handle.\r
389\r
390 @retval Handle HII package list Handle associated with the Device\r
391 Path.\r
392 @retval NULL Hii Package list handle is not found.\r
393\r
394**/\r
e52c5a9f 395EFI_HII_HANDLE\r
396EFIAPI\r
397HiiLibDevicePathToHiiHandle (\r
398 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
7d582d6b 399 )\r
7d582d6b 400{\r
e52c5a9f 401 EFI_STATUS Status;\r
402 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
403 UINTN BufferSize;\r
404 UINTN HandleCount;\r
405 UINTN Index;\r
406 EFI_HANDLE *Handles;\r
407 EFI_HANDLE Handle;\r
408 UINTN Size;\r
409 EFI_HANDLE DriverHandle;\r
410 EFI_HII_HANDLE *HiiHandles;\r
411 EFI_HII_HANDLE HiiHandle;\r
7d582d6b 412\r
e52c5a9f 413 ASSERT (DevicePath != NULL);\r
7d582d6b 414\r
dd51a993 415 //\r
e52c5a9f 416 // Locate Device Path Protocol handle buffer\r
7d582d6b 417 //\r
e52c5a9f 418 Status = gBS->LocateHandleBuffer (\r
419 ByProtocol,\r
420 &gEfiDevicePathProtocolGuid,\r
7d582d6b 421 NULL,\r
e52c5a9f 422 &HandleCount,\r
423 &Handles\r
7d582d6b 424 );\r
425 if (EFI_ERROR (Status)) {\r
e52c5a9f 426 return NULL;\r
7d582d6b 427 }\r
428\r
429 //\r
e52c5a9f 430 // Search Driver Handle by Device Path\r
7d582d6b 431 //\r
e52c5a9f 432 DriverHandle = NULL;\r
433 BufferSize = GetDevicePathSize (DevicePath);\r
434 for(Index = 0; Index < HandleCount; Index++) {\r
435 Handle = Handles[Index];\r
436 gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **) &TmpDevicePath);\r
437\r
438 //\r
439 // Check whether DevicePath match\r
440 //\r
441 Size = GetDevicePathSize (TmpDevicePath);\r
442 if ((Size == BufferSize) && CompareMem (DevicePath, TmpDevicePath, Size) == 0) {\r
443 DriverHandle = Handle;\r
444 break;\r
445 }\r
7d582d6b 446 }\r
29870c8d 447 FreePool (Handles);\r
e52c5a9f 448\r
449 if (DriverHandle == NULL) {\r
450 return NULL;\r
7d582d6b 451 }\r
452\r
54cf8780 453 LocateHiiProtocols ();\r
454\r
bad46384 455 //\r
e52c5a9f 456 // Retrieve all Hii Handles from HII database\r
7d582d6b 457 //\r
e52c5a9f 458 BufferSize = 0x1000;\r
459 HiiHandles = AllocatePool (BufferSize);\r
460 ASSERT (HiiHandles != NULL);\r
461 Status = mHiiDatabaseProt->ListPackageLists (\r
462 mHiiDatabaseProt,\r
463 EFI_HII_PACKAGE_TYPE_ALL,\r
464 NULL,\r
465 &BufferSize,\r
466 HiiHandles\r
467 );\r
468 if (Status == EFI_BUFFER_TOO_SMALL) {\r
29870c8d 469 FreePool (HiiHandles);\r
e52c5a9f 470 HiiHandles = AllocatePool (BufferSize);\r
471 ASSERT (HiiHandles != NULL);\r
472\r
473 Status = mHiiDatabaseProt->ListPackageLists (\r
474 mHiiDatabaseProt,\r
475 EFI_HII_PACKAGE_TYPE_ALL,\r
476 NULL,\r
477 &BufferSize,\r
478 HiiHandles\r
479 );\r
480 }\r
7d582d6b 481\r
e52c5a9f 482 if (EFI_ERROR (Status)) {\r
29870c8d 483 FreePool (HiiHandles);\r
e52c5a9f 484 return NULL;\r
485 }\r
7d582d6b 486\r
e52c5a9f 487 //\r
488 // Search Hii Handle by Driver Handle\r
489 //\r
490 HiiHandle = NULL;\r
491 HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
492 for (Index = 0; Index < HandleCount; Index++) {\r
493 Status = mHiiDatabaseProt->GetPackageListHandle (\r
494 mHiiDatabaseProt,\r
495 HiiHandles[Index],\r
496 &Handle\r
497 );\r
498 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
499 HiiHandle = HiiHandles[Index];\r
500 break;\r
7d582d6b 501 }\r
7d582d6b 502 }\r
503\r
29870c8d 504 FreePool (HiiHandles);\r
e52c5a9f 505 return HiiHandle;\r
506}\r
7d582d6b 507\r
ad1b3619 508/**\r
509 This function check if the Hii Handle is a valid handle registered\r
510 in the HII database.\r
511\r
512 @param HiiHandle The HII Handle.\r
513\r
514 @retval TRUE If it is a valid HII handle.\r
515 @retval FALSE If it is a invalid HII handle.\r
516**/\r
e52c5a9f 517BOOLEAN\r
518IsHiiHandleRegistered (\r
519 EFI_HII_HANDLE HiiHandle\r
520 )\r
521{\r
522 EFI_STATUS Status;\r
523 UINTN BufferSize;\r
524 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
525\r
526 ASSERT (HiiHandle != NULL);\r
527\r
528 HiiPackageList = NULL;\r
529 BufferSize = 0;\r
54cf8780 530\r
531 LocateHiiProtocols ();\r
532\r
e52c5a9f 533 Status = mHiiDatabaseProt->ExportPackageLists (\r
534 mHiiDatabaseProt,\r
535 HiiHandle,\r
536 &BufferSize,\r
537 HiiPackageList\r
538 );\r
539\r
540 return (BOOLEAN) (Status == EFI_BUFFER_TOO_SMALL);\r
dd51a993 541}\r
7d582d6b 542\r