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