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