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