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