]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
K8:
[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 length 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 length 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 through 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 EFI_STATUS Status;
285
286 ASSERT (HandleBufferLength != NULL);
287 ASSERT (HiiHandleBuffer != NULL);
288
289 *HandleBufferLength = 0;
290 *HiiHandleBuffer = NULL;
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 HandleBufferLength,
300 *HiiHandleBuffer
301 );
302
303 if (Status == EFI_BUFFER_TOO_SMALL) {
304 *HiiHandleBuffer = AllocateZeroPool (*HandleBufferLength);
305 ASSERT (*HiiHandleBuffer != NULL);
306 Status = mHiiDatabaseProt->ListPackageLists (
307 mHiiDatabaseProt,
308 EFI_HII_PACKAGE_TYPE_ALL,
309 NULL,
310 HandleBufferLength,
311 *HiiHandleBuffer
312 );
313
314 if (EFI_ERROR (Status)) {
315 FreePool (*HiiHandleBuffer);
316 *HiiHandleBuffer = NULL;
317 }
318 }
319
320 return Status;
321 }
322
323 /**
324 Extract Hii package list GUID for given HII handle.
325
326 If HiiHandle could not be found in the default HII database, then ASSERT.
327 If Guid is NULL, then ASSERT.
328
329 @param Handle Hii handle
330 @param Guid Package list GUID
331
332 @retval EFI_SUCCESS Successfully extract GUID from Hii database.
333
334 **/
335 EFI_STATUS
336 EFIAPI
337 HiiLibExtractGuidFromHiiHandle (
338 IN EFI_HII_HANDLE Handle,
339 OUT EFI_GUID *Guid
340 )
341 {
342 EFI_STATUS Status;
343 UINTN BufferSize;
344 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
345
346 ASSERT (Guid != NULL);
347 ASSERT (IsHiiHandleRegistered (Handle));
348
349 //
350 // Get HII PackageList
351 //
352 BufferSize = 0;
353 HiiPackageList = NULL;
354
355 Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList);
356 ASSERT (Status != EFI_NOT_FOUND);
357
358 if (Status == EFI_BUFFER_TOO_SMALL) {
359 HiiPackageList = AllocatePool (BufferSize);
360 ASSERT (HiiPackageList != NULL);
361
362 Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList);
363 }
364 if (EFI_ERROR (Status)) {
365 FreePool (HiiPackageList);
366 return Status;
367 }
368
369 //
370 // Extract GUID
371 //
372 CopyGuid (Guid, &HiiPackageList->PackageListGuid);
373
374 FreePool (HiiPackageList);
375
376 return EFI_SUCCESS;
377 }
378
379 /**
380 Find HII Handle in the default HII database associated with given Device Path.
381
382 If DevicePath is NULL, then ASSERT.
383
384 @param DevicePath Device Path associated with the HII package list
385 handle.
386
387 @retval Handle HII package list Handle associated with the Device
388 Path.
389 @retval NULL Hii Package list handle is not found.
390
391 **/
392 EFI_HII_HANDLE
393 EFIAPI
394 HiiLibDevicePathToHiiHandle (
395 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
396 )
397 {
398 EFI_STATUS Status;
399 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
400 UINTN BufferSize;
401 UINTN HandleCount;
402 UINTN Index;
403 EFI_HANDLE *Handles;
404 EFI_HANDLE Handle;
405 UINTN Size;
406 EFI_HANDLE DriverHandle;
407 EFI_HII_HANDLE *HiiHandles;
408 EFI_HII_HANDLE HiiHandle;
409
410 ASSERT (DevicePath != NULL);
411
412 //
413 // Locate Device Path Protocol handle buffer
414 //
415 Status = gBS->LocateHandleBuffer (
416 ByProtocol,
417 &gEfiDevicePathProtocolGuid,
418 NULL,
419 &HandleCount,
420 &Handles
421 );
422 if (EFI_ERROR (Status)) {
423 return NULL;
424 }
425
426 //
427 // Search Driver Handle by Device Path
428 //
429 DriverHandle = NULL;
430 BufferSize = GetDevicePathSize (DevicePath);
431 for(Index = 0; Index < HandleCount; Index++) {
432 Handle = Handles[Index];
433 gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **) &TmpDevicePath);
434
435 //
436 // Check whether DevicePath match
437 //
438 Size = GetDevicePathSize (TmpDevicePath);
439 if ((Size == BufferSize) && CompareMem (DevicePath, TmpDevicePath, Size) == 0) {
440 DriverHandle = Handle;
441 break;
442 }
443 }
444 FreePool (Handles);
445
446 if (DriverHandle == NULL) {
447 return NULL;
448 }
449
450 //
451 // Retrieve all Hii Handles from HII database
452 //
453 BufferSize = 0x1000;
454 HiiHandles = AllocatePool (BufferSize);
455 ASSERT (HiiHandles != NULL);
456 Status = mHiiDatabaseProt->ListPackageLists (
457 mHiiDatabaseProt,
458 EFI_HII_PACKAGE_TYPE_ALL,
459 NULL,
460 &BufferSize,
461 HiiHandles
462 );
463 if (Status == EFI_BUFFER_TOO_SMALL) {
464 FreePool (HiiHandles);
465 HiiHandles = AllocatePool (BufferSize);
466 ASSERT (HiiHandles != NULL);
467
468 Status = mHiiDatabaseProt->ListPackageLists (
469 mHiiDatabaseProt,
470 EFI_HII_PACKAGE_TYPE_ALL,
471 NULL,
472 &BufferSize,
473 HiiHandles
474 );
475 }
476
477 if (EFI_ERROR (Status)) {
478 FreePool (HiiHandles);
479 return NULL;
480 }
481
482 //
483 // Search Hii Handle by Driver Handle
484 //
485 HiiHandle = NULL;
486 HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);
487 for (Index = 0; Index < HandleCount; Index++) {
488 Status = mHiiDatabaseProt->GetPackageListHandle (
489 mHiiDatabaseProt,
490 HiiHandles[Index],
491 &Handle
492 );
493 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {
494 HiiHandle = HiiHandles[Index];
495 break;
496 }
497 }
498
499 FreePool (HiiHandles);
500 return HiiHandle;
501 }
502
503 /**
504 Exports the contents of one or all package lists in the HII database into a buffer.
505
506 If Handle is not NULL and not a valid EFI_HII_HANDLE registered in the database,
507 then ASSERT.
508 If PackageListHeader is NULL, then ASSERT.
509 If PackageListSize is NULL, then ASSERT.
510
511 @param Handle The HII Handle.
512 @param PackageListHeader A pointer to a buffer that will contain the results of
513 the export function.
514 @param PackageListSize On output, the length of the buffer that is required for the exported data.
515
516 @retval EFI_SUCCESS Package exported.
517
518 @retval EFI_OUT_OF_RESOURCES Not enought memory to complete the operations.
519
520 **/
521 EFI_STATUS
522 EFIAPI
523 HiiLibExportPackageLists (
524 IN EFI_HII_HANDLE Handle,
525 OUT EFI_HII_PACKAGE_LIST_HEADER **PackageListHeader,
526 OUT UINTN *PackageListSize
527 )
528 {
529 EFI_STATUS Status;
530 UINTN Size;
531 EFI_HII_PACKAGE_LIST_HEADER *PackageListHdr;
532
533 ASSERT (PackageListSize != NULL);
534 ASSERT (PackageListHeader != NULL);
535
536 if (Handle != NULL) {
537 ASSERT (IsHiiHandleRegistered (Handle));
538 }
539
540 Size = 0;
541 PackageListHdr = NULL;
542 Status = mHiiDatabaseProt->ExportPackageLists (
543 mHiiDatabaseProt,
544 Handle,
545 &Size,
546 PackageListHdr
547 );
548 ASSERT_EFI_ERROR (Status != EFI_BUFFER_TOO_SMALL);
549
550 if (Status == EFI_BUFFER_TOO_SMALL) {
551 PackageListHdr = AllocateZeroPool (Size);
552
553 if (PackageListHeader == NULL) {
554 return EFI_OUT_OF_RESOURCES;
555 } else {
556 Status = mHiiDatabaseProt->ExportPackageLists (
557 mHiiDatabaseProt,
558 Handle,
559 &Size,
560 PackageListHdr
561 );
562 }
563 }
564
565 if (!EFI_ERROR (Status)) {
566 *PackageListHeader = PackageListHdr;
567 *PackageListSize = Size;
568 } else {
569 FreePool (PackageListHdr);
570 }
571
572 return Status;
573 }
574
575 /**
576
577 This function returns a list of the package handles of the
578 specified type that are currently active in the HII database. The
579 pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package
580 handles to be listed.
581
582 If HandleBufferLength is NULL, then ASSERT.
583 If HandleBuffer is NULL, the ASSERT.
584 If PackageType is EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is
585 NULL, then ASSERT.
586 If PackageType is not EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is not
587 NULL, then ASSERT.
588
589
590 @param PackageType Specifies the package type of the packages
591 to list or EFI_HII_PACKAGE_TYPE_ALL for
592 all packages to be listed.
593
594 @param PackageGuid If PackageType is
595 EFI_HII_PACKAGE_TYPE_GUID, then this is
596 the pointer to the GUID which must match
597 the Guid field of
598 EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it
599 must be NULL.
600
601 @param HandleBufferLength On output, the length of the handle buffer
602 that is required for the handles found.
603
604 @param HandleBuffer On output, an array of EFI_HII_HANDLE instances returned.
605 The caller is responcible to free this pointer allocated.
606
607 @retval EFI_SUCCESS The matching handles are outputed successfully.
608 HandleBufferLength is updated with the actual length.
609 @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operation.
610 @retval EFI_NOT_FOUND No matching handle could not be found in database.
611 **/
612 EFI_STATUS
613 EFIAPI
614 HiiLibListPackageLists (
615 IN UINT8 PackageType,
616 IN CONST EFI_GUID *PackageGuid,
617 IN OUT UINTN *HandleBufferLength,
618 OUT EFI_HII_HANDLE **HandleBuffer
619 )
620 {
621 EFI_STATUS Status;
622
623 ASSERT (HandleBufferLength != NULL);
624 ASSERT (HandleBuffer != NULL);
625
626 *HandleBufferLength = 0;
627 *HandleBuffer = NULL;
628
629 if (PackageType == EFI_HII_PACKAGE_TYPE_GUID) {
630 ASSERT (PackageGuid != NULL);
631 } else {
632 ASSERT (PackageGuid == NULL);
633 }
634
635 Status = mHiiDatabaseProt->ListPackageLists (
636 mHiiDatabaseProt,
637 PackageType,
638 PackageGuid,
639 HandleBufferLength,
640 *HandleBuffer
641 );
642 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
643 //
644 // No packages is registered to UEFI HII Database, just return.
645 //
646 //
647 return Status;
648 }
649
650 *HandleBuffer = AllocateZeroPool (*HandleBufferLength);
651
652 if (*HandleBuffer == NULL) {
653 return EFI_OUT_OF_RESOURCES;
654 }
655
656 return mHiiDatabaseProt->ListPackageLists (
657 mHiiDatabaseProt,
658 PackageType,
659 PackageGuid,
660 HandleBufferLength,
661 *HandleBuffer
662 );
663
664 }
665 /**
666 This function check if the Hii Handle is a valid handle registered
667 in the HII database.
668
669 @param HiiHandle The HII Handle.
670
671 @retval TRUE If it is a valid HII handle.
672 @retval FALSE If it is a invalid HII handle.
673 **/
674 BOOLEAN
675 IsHiiHandleRegistered (
676 EFI_HII_HANDLE HiiHandle
677 )
678 {
679 EFI_STATUS Status;
680 UINTN BufferSize;
681 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
682
683 ASSERT (HiiHandle != NULL);
684
685 HiiPackageList = NULL;
686 BufferSize = 0;
687
688 Status = mHiiDatabaseProt->ExportPackageLists (
689 mHiiDatabaseProt,
690 HiiHandle,
691 &BufferSize,
692 HiiPackageList
693 );
694
695 return (BOOLEAN) (Status == EFI_BUFFER_TOO_SMALL);
696 }
697