]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
b59a9b2965af10c527510a25089602473862de18
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / Database.c
1 /** @file
2 Implementation for EFI_HII_DATABASE_PROTOCOL.
3
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 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
16 #include "HiiDatabase.h"
17
18 #define BASE_NUMBER 10
19
20 EFI_HII_PACKAGE_LIST_HEADER *gRTDatabaseInfoBuffer = NULL;
21 EFI_STRING gRTConfigRespBuffer = NULL;
22 UINTN gDatabaseInfoSize = 0;
23 UINTN gConfigRespSize = 0;
24 BOOLEAN gExportConfigResp = FALSE;
25 UINTN gNvDefaultStoreSize = 0;
26 SKU_ID gSkuId = 0xFFFFFFFFFFFFFFFF;
27 LIST_ENTRY gVarStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gVarStorageList);
28
29 //
30 // HII database lock.
31 //
32 EFI_LOCK mHiiDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_NOTIFY);
33
34 /**
35 This function generates a HII_DATABASE_RECORD node and adds into hii database.
36 This is a internal function.
37
38 @param Private hii database private structure
39 @param DatabaseNode HII_DATABASE_RECORD node which is used to store a
40 package list
41
42 @retval EFI_SUCCESS A database record is generated successfully.
43 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
44 database contents.
45 @retval EFI_INVALID_PARAMETER Private is NULL or DatabaseRecord is NULL.
46
47 **/
48 EFI_STATUS
49 GenerateHiiDatabaseRecord (
50 IN HII_DATABASE_PRIVATE_DATA *Private,
51 OUT HII_DATABASE_RECORD **DatabaseNode
52 )
53 {
54 HII_DATABASE_RECORD *DatabaseRecord;
55 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
56 HII_HANDLE *HiiHandle;
57
58 if (Private == NULL || DatabaseNode == NULL) {
59 return EFI_INVALID_PARAMETER;
60 }
61
62 DatabaseRecord = (HII_DATABASE_RECORD *) AllocateZeroPool (sizeof (HII_DATABASE_RECORD));
63 if (DatabaseRecord == NULL) {
64 return EFI_OUT_OF_RESOURCES;
65 }
66 DatabaseRecord->Signature = HII_DATABASE_RECORD_SIGNATURE;
67
68 DatabaseRecord->PackageList = AllocateZeroPool (sizeof (HII_DATABASE_PACKAGE_LIST_INSTANCE));
69 if (DatabaseRecord->PackageList == NULL) {
70 FreePool (DatabaseRecord);
71 return EFI_OUT_OF_RESOURCES;
72 }
73
74 PackageList = DatabaseRecord->PackageList;
75
76 InitializeListHead (&PackageList->GuidPkgHdr);
77 InitializeListHead (&PackageList->FormPkgHdr);
78 InitializeListHead (&PackageList->KeyboardLayoutHdr);
79 InitializeListHead (&PackageList->StringPkgHdr);
80 InitializeListHead (&PackageList->FontPkgHdr);
81 InitializeListHead (&PackageList->SimpleFontPkgHdr);
82 PackageList->ImagePkg = NULL;
83 PackageList->DevicePathPkg = NULL;
84
85 //
86 // Create a new hii handle
87 //
88 HiiHandle = (HII_HANDLE *) AllocateZeroPool (sizeof (HII_HANDLE));
89 if (HiiHandle == NULL) {
90 FreePool (DatabaseRecord->PackageList);
91 FreePool (DatabaseRecord);
92 return EFI_OUT_OF_RESOURCES;
93 }
94 HiiHandle->Signature = HII_HANDLE_SIGNATURE;
95 //
96 // Backup the number of Hii handles
97 //
98 Private->HiiHandleCount++;
99 HiiHandle->Key = (UINTN) Private->HiiHandleCount;
100 //
101 // Insert the handle to hii handle list of the whole database.
102 //
103 InsertTailList (&Private->HiiHandleList, &HiiHandle->Handle);
104
105 DatabaseRecord->Handle = (EFI_HII_HANDLE) HiiHandle;
106
107 //
108 // Insert the Package List node to Package List link of the whole database.
109 //
110 InsertTailList (&Private->DatabaseList, &DatabaseRecord->DatabaseEntry);
111
112 *DatabaseNode = DatabaseRecord;
113
114 return EFI_SUCCESS;
115
116 }
117
118
119 /**
120 This function checks whether a handle is a valid EFI_HII_HANDLE
121 This is a internal function.
122
123 @param Handle Pointer to a EFI_HII_HANDLE
124
125 @retval TRUE Valid
126 @retval FALSE Invalid
127
128 **/
129 BOOLEAN
130 IsHiiHandleValid (
131 EFI_HII_HANDLE Handle
132 )
133 {
134 HII_HANDLE *HiiHandle;
135
136 HiiHandle = (HII_HANDLE *) Handle;
137
138 if (HiiHandle == NULL) {
139 return FALSE;
140 }
141
142 if (HiiHandle->Signature != HII_HANDLE_SIGNATURE) {
143 return FALSE;
144 }
145
146 return TRUE;
147 }
148
149
150 /**
151 This function invokes the matching registered function.
152 This is a internal function.
153
154 @param Private HII Database driver private structure.
155 @param NotifyType The type of change concerning the database.
156 @param PackageInstance Points to the package referred to by the
157 notification.
158 @param PackageType Package type
159 @param Handle The handle of the package list which contains the
160 specified package.
161
162 @retval EFI_SUCCESS Already checked all registered function and
163 invoked if matched.
164 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
165
166 **/
167 EFI_STATUS
168 InvokeRegisteredFunction (
169 IN HII_DATABASE_PRIVATE_DATA *Private,
170 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
171 IN VOID *PackageInstance,
172 IN UINT8 PackageType,
173 IN EFI_HII_HANDLE Handle
174 )
175 {
176 HII_DATABASE_NOTIFY *Notify;
177 LIST_ENTRY *Link;
178 EFI_HII_PACKAGE_HEADER *Package;
179 UINT8 *Buffer;
180 UINT32 BufferSize;
181 UINT32 HeaderSize;
182 UINT32 ImageBlockSize;
183 UINT32 PaletteInfoSize;
184
185 if (Private == NULL || (NotifyType & 0xF) == 0 || PackageInstance == NULL) {
186 return EFI_INVALID_PARAMETER;
187 }
188 if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
189 return EFI_INVALID_PARAMETER;
190 }
191 if (!IsHiiHandleValid (Handle)) {
192 return EFI_INVALID_PARAMETER;
193 }
194
195 Buffer = NULL;
196 Package = NULL;
197
198 //
199 // Convert the incoming package from hii database storage format to UEFI
200 // storage format. e.g. HII_GUID_PACKAGE_INSTANCE to EFI_HII_GUID_PACKAGE_HDR.
201 //
202 switch (PackageType) {
203 case EFI_HII_PACKAGE_TYPE_GUID:
204 Package = (EFI_HII_PACKAGE_HEADER *) (((HII_GUID_PACKAGE_INSTANCE *) PackageInstance)->GuidPkg);
205 break;
206
207 case EFI_HII_PACKAGE_FORMS:
208 BufferSize = ((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->FormPkgHdr.Length;
209 Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
210 ASSERT (Buffer != NULL);
211 CopyMem (
212 Buffer,
213 &((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->FormPkgHdr,
214 sizeof (EFI_HII_PACKAGE_HEADER)
215 );
216 CopyMem (
217 Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
218 ((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->IfrData,
219 BufferSize - sizeof (EFI_HII_PACKAGE_HEADER)
220 );
221 Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
222 break;
223
224 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
225 Package = (EFI_HII_PACKAGE_HEADER *) (((HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *) PackageInstance)->KeyboardPkg);
226 break;
227
228 case EFI_HII_PACKAGE_STRINGS:
229 BufferSize = ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr->Header.Length;
230 HeaderSize = ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr->HdrSize;
231 Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
232 ASSERT (Buffer != NULL);
233 CopyMem (
234 Buffer,
235 ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr,
236 HeaderSize
237 );
238 CopyMem (
239 Buffer + HeaderSize,
240 ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringBlock,
241 BufferSize - HeaderSize
242 );
243 Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
244 break;
245
246 case EFI_HII_PACKAGE_FONTS:
247 BufferSize = ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr->Header.Length;
248 HeaderSize = ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr->HdrSize;
249 Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
250 ASSERT (Buffer != NULL);
251 CopyMem (
252 Buffer,
253 ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr,
254 HeaderSize
255 );
256 CopyMem (
257 Buffer + HeaderSize,
258 ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->GlyphBlock,
259 BufferSize - HeaderSize
260 );
261 Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
262 break;
263
264 case EFI_HII_PACKAGE_IMAGES:
265 BufferSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImagePkgHdr.Header.Length;
266 HeaderSize = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
267 Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
268 ASSERT (Buffer != NULL);
269
270 CopyMem (
271 Buffer,
272 &((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImagePkgHdr,
273 HeaderSize
274 );
275 CopyMem (
276 Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
277 &HeaderSize,
278 sizeof (UINT32)
279 );
280
281 ImageBlockSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImageBlockSize;
282 if (ImageBlockSize != 0) {
283 CopyMem (
284 Buffer + HeaderSize,
285 ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImageBlock,
286 ImageBlockSize
287 );
288 }
289
290 PaletteInfoSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->PaletteInfoSize;
291 if (PaletteInfoSize != 0) {
292 CopyMem (
293 Buffer + HeaderSize + ImageBlockSize,
294 ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->PaletteBlock,
295 PaletteInfoSize
296 );
297 HeaderSize += ImageBlockSize;
298 CopyMem (
299 Buffer + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT32),
300 &HeaderSize,
301 sizeof (UINT32)
302 );
303 }
304 Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
305 break;
306
307 case EFI_HII_PACKAGE_SIMPLE_FONTS:
308 BufferSize = ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *) PackageInstance)->SimpleFontPkgHdr->Header.Length;
309 Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
310 ASSERT (Buffer != NULL);
311 CopyMem (
312 Buffer,
313 ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *) PackageInstance)->SimpleFontPkgHdr,
314 BufferSize
315 );
316 Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
317 break;
318
319 case EFI_HII_PACKAGE_DEVICE_PATH:
320 Package = (EFI_HII_PACKAGE_HEADER *) PackageInstance;
321 break;
322
323 default:
324 return EFI_INVALID_PARAMETER;
325 }
326
327 for (Link = Private->DatabaseNotifyList.ForwardLink;
328 Link != &Private->DatabaseNotifyList;
329 Link = Link->ForwardLink
330 ) {
331 Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);
332 if (Notify->NotifyType == NotifyType && Notify->PackageType == PackageType) {
333 //
334 // Check in case PackageGuid is not NULL when Package is GUID package
335 //
336 if (PackageType != EFI_HII_PACKAGE_TYPE_GUID) {
337 Notify->PackageGuid = NULL;
338 }
339 //
340 // Status of Registered Function is unknown so did not check it
341 //
342 Notify->PackageNotifyFn (
343 Notify->PackageType,
344 Notify->PackageGuid,
345 Package,
346 Handle,
347 NotifyType
348 );
349 }
350 }
351
352 if (Buffer != NULL) {
353 FreePool (Buffer);
354 }
355
356 return EFI_SUCCESS;
357 }
358
359
360 /**
361 This function insert a GUID package to a package list node.
362 This is a internal function.
363
364 @param PackageHdr Pointer to a buffer stored with GUID package
365 information.
366 @param NotifyType The type of change concerning the database.
367 @param PackageList Pointer to a package list which will be inserted
368 to.
369 @param Package Created GUID package
370
371 @retval EFI_SUCCESS Guid Package is inserted successfully.
372 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
373 Guid package.
374 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
375
376 **/
377 EFI_STATUS
378 InsertGuidPackage (
379 IN VOID *PackageHdr,
380 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
381 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
382 OUT HII_GUID_PACKAGE_INSTANCE **Package
383 )
384 {
385 HII_GUID_PACKAGE_INSTANCE *GuidPackage;
386 EFI_HII_PACKAGE_HEADER PackageHeader;
387
388 if (PackageHdr == NULL || PackageList == NULL) {
389 return EFI_INVALID_PARAMETER;
390 }
391
392 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
393
394 //
395 // Create a GUID package node
396 //
397 GuidPackage = (HII_GUID_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_GUID_PACKAGE_INSTANCE));
398 if (GuidPackage == NULL) {
399 return EFI_OUT_OF_RESOURCES;
400 }
401 GuidPackage->GuidPkg = (UINT8 *) AllocateZeroPool (PackageHeader.Length);
402 if (GuidPackage->GuidPkg == NULL) {
403 FreePool (GuidPackage);
404 return EFI_OUT_OF_RESOURCES;
405 }
406
407 GuidPackage->Signature = HII_GUID_PACKAGE_SIGNATURE;
408 CopyMem (GuidPackage->GuidPkg, PackageHdr, PackageHeader.Length);
409 InsertTailList (&PackageList->GuidPkgHdr, &GuidPackage->GuidEntry);
410 *Package = GuidPackage;
411
412 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
413 PackageList->PackageListHdr.PackageLength += PackageHeader.Length;
414 }
415
416 return EFI_SUCCESS;
417 }
418
419
420 /**
421 This function exports GUID packages to a buffer.
422 This is a internal function.
423
424 @param Private Hii database private structure.
425 @param Handle Identification of a package list.
426 @param PackageList Pointer to a package list which will be exported.
427 @param UsedSize The length of buffer be used.
428 @param BufferSize Length of the Buffer.
429 @param Buffer Allocated space for storing exported data.
430 @param ResultSize The size of the already exported content of this
431 package list.
432
433 @retval EFI_SUCCESS Guid Packages are exported successfully.
434 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
435
436 **/
437 EFI_STATUS
438 ExportGuidPackages (
439 IN HII_DATABASE_PRIVATE_DATA *Private,
440 IN EFI_HII_HANDLE Handle,
441 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
442 IN UINTN UsedSize,
443 IN UINTN BufferSize,
444 IN OUT VOID *Buffer,
445 IN OUT UINTN *ResultSize
446 )
447 {
448 HII_GUID_PACKAGE_INSTANCE *GuidPackage;
449 LIST_ENTRY *Link;
450 UINTN PackageLength;
451 EFI_HII_PACKAGE_HEADER PackageHeader;
452 EFI_STATUS Status;
453
454 if (PackageList == NULL || ResultSize == NULL) {
455 return EFI_INVALID_PARAMETER;
456 }
457
458 if (BufferSize > 0 && Buffer == NULL ) {
459 return EFI_INVALID_PARAMETER;
460 }
461
462 PackageLength = 0;
463 Status = EFI_SUCCESS;
464
465 for (Link = PackageList->GuidPkgHdr.ForwardLink; Link != &PackageList->GuidPkgHdr; Link = Link->ForwardLink) {
466 GuidPackage = CR (Link, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);
467 CopyMem (&PackageHeader, GuidPackage->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));
468 PackageLength += PackageHeader.Length;
469 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
470 Status = InvokeRegisteredFunction (
471 Private,
472 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
473 (VOID *) GuidPackage,
474 EFI_HII_PACKAGE_TYPE_GUID,
475 Handle
476 );
477 ASSERT_EFI_ERROR (Status);
478 CopyMem (Buffer, GuidPackage->GuidPkg, PackageHeader.Length);
479 Buffer = (UINT8 *) Buffer + PackageHeader.Length;
480 }
481 }
482
483 *ResultSize += PackageLength;
484 return EFI_SUCCESS;
485 }
486
487
488 /**
489 This function deletes all GUID packages from a package list node.
490 This is a internal function.
491
492 @param Private Hii database private data.
493 @param Handle Handle of the package list which contains the to
494 be removed GUID packages.
495 @param PackageList Pointer to a package list that contains removing
496 packages.
497
498 @retval EFI_SUCCESS GUID Package(s) is deleted successfully.
499 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
500
501 **/
502 EFI_STATUS
503 RemoveGuidPackages (
504 IN HII_DATABASE_PRIVATE_DATA *Private,
505 IN EFI_HII_HANDLE Handle,
506 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
507 )
508 {
509 LIST_ENTRY *ListHead;
510 HII_GUID_PACKAGE_INSTANCE *Package;
511 EFI_STATUS Status;
512 EFI_HII_PACKAGE_HEADER PackageHeader;
513
514 ListHead = &PackageList->GuidPkgHdr;
515
516 while (!IsListEmpty (ListHead)) {
517 Package = CR (
518 ListHead->ForwardLink,
519 HII_GUID_PACKAGE_INSTANCE,
520 GuidEntry,
521 HII_GUID_PACKAGE_SIGNATURE
522 );
523 Status = InvokeRegisteredFunction (
524 Private,
525 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
526 (VOID *) Package,
527 EFI_HII_PACKAGE_TYPE_GUID,
528 Handle
529 );
530 if (EFI_ERROR (Status)) {
531 return Status;
532 }
533
534 RemoveEntryList (&Package->GuidEntry);
535 CopyMem (&PackageHeader, Package->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));
536 PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;
537 FreePool (Package->GuidPkg);
538 FreePool (Package);
539 }
540
541 return EFI_SUCCESS;
542 }
543
544 /**
545 Check the input question related to EFI variable
546
547 @param IfrQuestionHdr Point to Question header
548 @param EfiVarStoreList Point to EFI VarStore List
549 @param EfiVarStoreNumber The number of EFI VarStore
550
551 @retval Index The index of the found EFI varstore in EFI varstore list
552 EfiVarStoreNumber will return if no EFI varstore is found.
553 **/
554 UINTN
555 IsEfiVarStoreQuestion (
556 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,
557 EFI_IFR_VARSTORE_EFI **EfiVarStoreList,
558 UINTN EfiVarStoreNumber
559 )
560 {
561 UINTN Index;
562 for (Index = 0; Index < EfiVarStoreNumber; Index ++) {
563 if (IfrQuestionHdr->VarStoreId == EfiVarStoreList[Index]->VarStoreId) {
564 return Index;
565 }
566 }
567
568 return EfiVarStoreNumber;
569 }
570
571 /**
572 Find the matched variable from the input variable storage.
573
574 @param[in] VariableStorage Point to the variable storage header.
575 @param[in] VarGuid A unique identifier for the variable.
576 @param[in] VarAttribute The attributes bitmask for the variable.
577 @param[in] VarName A Null-terminated ascii string that is the name of the variable.
578
579 @return Pointer to the matched variable header or NULL if not found.
580 **/
581 VARIABLE_HEADER *
582 FindVariableData (
583 IN VARIABLE_STORE_HEADER *VariableStorage,
584 IN EFI_GUID *VarGuid,
585 IN UINT32 VarAttribute,
586 IN CHAR16 *VarName
587 )
588 {
589 VARIABLE_HEADER *VariableHeader;
590 VARIABLE_HEADER *VariableEnd;
591
592 VariableEnd = (VARIABLE_HEADER *) ((UINT8 *) VariableStorage + VariableStorage->Size);
593 VariableHeader = (VARIABLE_HEADER *) (VariableStorage + 1);
594 VariableHeader = (VARIABLE_HEADER *) HEADER_ALIGN (VariableHeader);
595 while (VariableHeader < VariableEnd) {
596 if (CompareGuid (&VariableHeader->VendorGuid, VarGuid) &&
597 VariableHeader->Attributes == VarAttribute &&
598 StrCmp (VarName, (CHAR16 *) (VariableHeader + 1)) == 0) {
599 return VariableHeader;
600 }
601 VariableHeader = (VARIABLE_HEADER *) ((UINT8 *) VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + VariableHeader->DataSize);
602 VariableHeader = (VARIABLE_HEADER *) HEADER_ALIGN (VariableHeader);
603 }
604
605 return NULL;
606 }
607
608 /**
609 Find question default value from PcdNvStoreDefaultValueBuffer
610
611 @param DefaultId Default store ID
612 @param EfiVarStore Point to EFI VarStore header
613 @param IfrQuestionHdr Point to Question header
614 @param ValueBuffer Point to Buffer includes the found default setting
615 @param Width Width of the default value
616 @param BitFieldQuestion Whether the Question is stored in Bit field.
617
618 @retval EFI_SUCCESS Question default value is found.
619 @retval EFI_NOT_FOUND Question default value is not found.
620 **/
621 EFI_STATUS
622 FindQuestionDefaultSetting (
623 IN UINT16 DefaultId,
624 IN EFI_IFR_VARSTORE_EFI *EfiVarStore,
625 IN EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,
626 OUT VOID *ValueBuffer,
627 IN UINTN Width,
628 IN BOOLEAN BitFieldQuestion
629 )
630 {
631 VARIABLE_HEADER *VariableHeader;
632 VARIABLE_STORE_HEADER *VariableStorage;
633 LIST_ENTRY *Link;
634 VARSTORAGE_DEFAULT_DATA *Entry;
635 VARIABLE_STORE_HEADER *NvStoreBuffer;
636 UINT8 *DataBuffer;
637 UINT8 *BufferEnd;
638 BOOLEAN IsFound;
639 UINTN Index;
640 UINT32 BufferValue;
641 UINT32 BitFieldVal;
642 UINTN BitOffset;
643 UINTN ByteOffset;
644 UINTN BitWidth;
645 UINTN StartBit;
646 UINTN EndBit;
647 PCD_DEFAULT_DATA *DataHeader;
648 PCD_DEFAULT_INFO *DefaultInfo;
649 PCD_DATA_DELTA *DeltaData;
650
651 if (gSkuId == 0xFFFFFFFFFFFFFFFF) {
652 gSkuId = LibPcdGetSku ();
653 }
654
655 //
656 // Find the DefaultId setting from the full DefaultSetting
657 //
658 VariableStorage = NULL;
659 Link = gVarStorageList.ForwardLink;
660 while (Link != &gVarStorageList) {
661 Entry = BASE_CR (Link, VARSTORAGE_DEFAULT_DATA, Entry);
662 if (Entry->DefaultId == DefaultId) {
663 VariableStorage = Entry->VariableStorage;
664 break;
665 }
666 Link = Link->ForwardLink;
667 }
668
669 if (Link == &gVarStorageList) {
670 DataBuffer = (UINT8 *) PcdGetPtr (PcdNvStoreDefaultValueBuffer);
671 gNvDefaultStoreSize = ((PCD_NV_STORE_DEFAULT_BUFFER_HEADER *)DataBuffer)->Length;
672 //
673 // The first section data includes NV storage default setting.
674 //
675 DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER));
676 NvStoreBuffer = (VARIABLE_STORE_HEADER *) ((UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize);
677 VariableStorage = AllocatePool (NvStoreBuffer->Size);
678 ASSERT (VariableStorage != NULL);
679 CopyMem (VariableStorage, NvStoreBuffer, NvStoreBuffer->Size);
680
681 //
682 // Find the matched SkuId and DefaultId in the first section
683 //
684 IsFound = FALSE;
685 DefaultInfo = &(DataHeader->DefaultInfo[0]);
686 BufferEnd = (UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;
687 while ((UINT8 *) DefaultInfo < BufferEnd) {
688 if (DefaultInfo->DefaultId == DefaultId && DefaultInfo->SkuId == gSkuId) {
689 IsFound = TRUE;
690 break;
691 }
692 DefaultInfo ++;
693 }
694 //
695 // Find the matched SkuId and DefaultId in the remaining section
696 //
697 Index = sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER) + ((DataHeader->DataSize + 7) & (~7));
698 DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + Index);
699 while (!IsFound && Index < gNvDefaultStoreSize && DataHeader->DataSize != 0xFFFF) {
700 DefaultInfo = &(DataHeader->DefaultInfo[0]);
701 BufferEnd = (UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;
702 while ((UINT8 *) DefaultInfo < BufferEnd) {
703 if (DefaultInfo->DefaultId == DefaultId && DefaultInfo->SkuId == gSkuId) {
704 IsFound = TRUE;
705 break;
706 }
707 DefaultInfo ++;
708 }
709 if (IsFound) {
710 DeltaData = (PCD_DATA_DELTA *) BufferEnd;
711 BufferEnd = (UINT8 *) DataHeader + DataHeader->DataSize;
712 while ((UINT8 *) DeltaData < BufferEnd) {
713 *((UINT8 *) VariableStorage + DeltaData->Offset) = (UINT8) DeltaData->Value;
714 DeltaData ++;
715 }
716 break;
717 }
718 Index = (Index + DataHeader->DataSize + 7) & (~7);
719 DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + Index);
720 }
721 //
722 // Cache the found result in VarStorageList
723 //
724 if (!IsFound) {
725 FreePool (VariableStorage);
726 VariableStorage = NULL;
727 }
728 Entry = AllocatePool (sizeof (VARSTORAGE_DEFAULT_DATA));
729 if (Entry != NULL) {
730 Entry->DefaultId = DefaultId;
731 Entry->VariableStorage = VariableStorage;
732 InsertTailList (&gVarStorageList, &Entry->Entry);
733 } else if (VariableStorage != NULL) {
734 FreePool (VariableStorage);
735 VariableStorage = NULL;
736 }
737 }
738 //
739 // The matched variable storage is not found.
740 //
741 if (VariableStorage == NULL) {
742 return EFI_NOT_FOUND;
743 }
744
745 //
746 // Find the question default value from the variable storage
747 //
748 VariableHeader = FindVariableData (VariableStorage, &EfiVarStore->Guid, EfiVarStore->Attributes, (CHAR16 *) EfiVarStore->Name);
749 if (VariableHeader == NULL) {
750 return EFI_NOT_FOUND;
751 }
752 StartBit = 0;
753 EndBit = 0;
754 ByteOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
755 if (BitFieldQuestion) {
756 BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
757 ByteOffset = BitOffset / 8;
758 BitWidth = Width;
759 StartBit = BitOffset % 8;
760 EndBit = StartBit + BitWidth - 1;
761 Width = EndBit / 8 + 1;
762 }
763 if (VariableHeader->DataSize < ByteOffset + Width) {
764 return EFI_INVALID_PARAMETER;
765 }
766
767 //
768 // Copy the question value
769 //
770 if (ValueBuffer != NULL) {
771 if (BitFieldQuestion) {
772 CopyMem (&BufferValue, (UINT8 *) VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + ByteOffset, Width);
773 BitFieldVal = BitFieldRead32 (BufferValue, StartBit, EndBit);
774 CopyMem (ValueBuffer, &BitFieldVal, Width);
775 } else {
776 CopyMem (ValueBuffer, (UINT8 *) VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + IfrQuestionHdr->VarStoreInfo.VarOffset, Width);
777 }
778 }
779
780 return EFI_SUCCESS;
781 }
782
783 /**
784 Update IFR default setting in Form Package.
785
786 @param FormPackage Form Package to be updated
787
788 **/
789 VOID
790 UpdateDefaultSettingInFormPackage (
791 HII_IFR_PACKAGE_INSTANCE *FormPackage
792 )
793 {
794 UINTN IfrOffset;
795 UINTN PackageLength;
796 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
797 EFI_IFR_OP_HEADER *IfrOpHdr;
798 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
799 UINT8 IfrQuestionType;
800 UINT8 IfrScope;
801 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
802 EFI_IFR_VARSTORE_EFI **EfiVarStoreList;
803 UINTN EfiVarStoreMaxNum;
804 UINTN EfiVarStoreNumber;
805 UINT16 *DefaultIdList;
806 UINTN DefaultIdNumber;
807 UINTN DefaultIdMaxNum;
808 UINTN Index;
809 UINTN EfiVarStoreIndex;
810 EFI_IFR_TYPE_VALUE IfrValue;
811 EFI_IFR_TYPE_VALUE IfrManufactValue;
812 BOOLEAN StandardDefaultIsSet;
813 BOOLEAN ManufactDefaultIsSet;
814 EFI_IFR_CHECKBOX *IfrCheckBox;
815 EFI_STATUS Status;
816 EFI_IFR_DEFAULT *IfrDefault;
817 UINTN Width;
818 EFI_IFR_QUESTION_HEADER VarStoreQuestionHeader;
819 BOOLEAN QuestionReferBitField;
820
821 //
822 // If no default setting, do nothing
823 //
824 if (gNvDefaultStoreSize == 0) {
825 gNvDefaultStoreSize = PcdGetSize (PcdNvStoreDefaultValueBuffer);
826 }
827 if (gNvDefaultStoreSize < sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {
828 return;
829 }
830
831 ZeroMem (&VarStoreQuestionHeader, sizeof (VarStoreQuestionHeader));
832 PackageLength = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
833 Width = 0;
834 IfrOffset = 0;
835 IfrScope = 0;
836 IfrOpHdr = (EFI_IFR_OP_HEADER *) FormPackage->IfrData;
837 IfrQuestionHdr = NULL;
838 IfrQuestionType = 0;
839 EfiVarStoreMaxNum = 0;
840 EfiVarStoreNumber = 0;
841 DefaultIdMaxNum = 0;
842 DefaultIdNumber = 0;
843 EfiVarStoreList = NULL;
844 DefaultIdList = NULL;
845 StandardDefaultIsSet = FALSE;
846 ManufactDefaultIsSet = FALSE;
847 QuestionReferBitField = FALSE;
848
849 while (IfrOffset < PackageLength) {
850 switch (IfrOpHdr->OpCode) {
851 case EFI_IFR_VARSTORE_EFI_OP:
852 if (EfiVarStoreNumber >= EfiVarStoreMaxNum) {
853 //
854 // Reallocate EFI VarStore Buffer
855 //
856 EfiVarStoreList = ReallocatePool (EfiVarStoreMaxNum * sizeof (UINTN), (EfiVarStoreMaxNum + BASE_NUMBER) * sizeof (UINTN), EfiVarStoreList);
857 if (EfiVarStoreList == NULL) {
858 goto Done;
859 }
860 EfiVarStoreMaxNum = EfiVarStoreMaxNum + BASE_NUMBER;
861 }
862 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
863 //
864 // Convert VarStore Name from ASCII string to Unicode string.
865 //
866 EfiVarStoreList [EfiVarStoreNumber] = AllocatePool (IfrEfiVarStore->Header.Length + AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name));
867 if (EfiVarStoreList [EfiVarStoreNumber] == NULL) {
868 break;
869 }
870 CopyMem (EfiVarStoreList [EfiVarStoreNumber], IfrEfiVarStore, IfrEfiVarStore->Header.Length);
871 AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, (CHAR16 *) &(EfiVarStoreList [EfiVarStoreNumber]->Name[0]), AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
872 Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_STANDARD, EfiVarStoreList[EfiVarStoreNumber], &VarStoreQuestionHeader, NULL, IfrEfiVarStore->Size, FALSE);
873 if (!EFI_ERROR (Status)) {
874 EfiVarStoreNumber ++;
875 } else {
876 FreePool (EfiVarStoreList [EfiVarStoreNumber]);
877 EfiVarStoreList [EfiVarStoreNumber] = NULL;
878 }
879 break;
880 case EFI_IFR_DEFAULTSTORE_OP:
881 if (DefaultIdNumber >= DefaultIdMaxNum) {
882 //
883 // Reallocate DefaultIdNumber
884 //
885 DefaultIdList = ReallocatePool (DefaultIdMaxNum * sizeof (UINT16), (DefaultIdMaxNum + BASE_NUMBER) * sizeof (UINT16), DefaultIdList);
886 if (DefaultIdList == NULL) {
887 goto Done;
888 }
889 DefaultIdMaxNum = DefaultIdMaxNum + BASE_NUMBER;
890 }
891 DefaultIdList[DefaultIdNumber ++] = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;
892 break;
893 case EFI_IFR_FORM_OP:
894 case EFI_IFR_FORM_MAP_OP:
895 //
896 // No EFI varstore is found and directly return.
897 //
898 if (EfiVarStoreNumber == 0 || DefaultIdNumber == 0) {
899 goto Done;
900 }
901 break;
902 case EFI_IFR_CHECKBOX_OP:
903 IfrScope = IfrOpHdr->Scope;
904 IfrQuestionType = IfrOpHdr->OpCode;
905 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *) (IfrOpHdr + 1);
906 IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
907 EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
908 Width = sizeof (BOOLEAN);
909 if (EfiVarStoreIndex < EfiVarStoreNumber) {
910 for (Index = 0; Index < DefaultIdNumber; Index ++) {
911 if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_STANDARD) {
912 Status = FindQuestionDefaultSetting (DefaultIdList[Index], EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, sizeof (BOOLEAN), QuestionReferBitField);
913 if (!EFI_ERROR (Status)) {
914 if (IfrValue.b) {
915 IfrCheckBox->Flags = IfrCheckBox->Flags | EFI_IFR_CHECKBOX_DEFAULT;
916 } else {
917 IfrCheckBox->Flags = IfrCheckBox->Flags & (~EFI_IFR_CHECKBOX_DEFAULT);
918 }
919 }
920 } else if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
921 Status = FindQuestionDefaultSetting (DefaultIdList[Index], EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, sizeof (BOOLEAN), QuestionReferBitField);
922 if (!EFI_ERROR (Status)) {
923 if (IfrValue.b) {
924 IfrCheckBox->Flags = IfrCheckBox->Flags | EFI_IFR_CHECKBOX_DEFAULT_MFG;
925 } else {
926 IfrCheckBox->Flags = IfrCheckBox->Flags & (~EFI_IFR_CHECKBOX_DEFAULT_MFG);
927 }
928 }
929 }
930 }
931 }
932 break;
933 case EFI_IFR_NUMERIC_OP:
934 IfrScope = IfrOpHdr->Scope;
935 IfrQuestionType = IfrOpHdr->OpCode;
936 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *) (IfrOpHdr + 1);
937 if (QuestionReferBitField) {
938 Width = (UINTN) (((EFI_IFR_ONE_OF *) IfrOpHdr)->Flags & EDKII_IFR_NUMERIC_SIZE_BIT);
939 } else {
940 Width = (UINTN) ((UINT32) 1 << (((EFI_IFR_ONE_OF *) IfrOpHdr)->Flags & EFI_IFR_NUMERIC_SIZE));
941 }
942 break;
943 case EFI_IFR_ONE_OF_OP:
944 IfrScope = IfrOpHdr->Scope;
945 IfrQuestionType = IfrOpHdr->OpCode;
946 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *) (IfrOpHdr + 1);
947 if (QuestionReferBitField) {
948 Width = (UINTN) (((EFI_IFR_ONE_OF *) IfrOpHdr)->Flags & EDKII_IFR_NUMERIC_SIZE_BIT);
949 } else {
950 Width = (UINTN) ((UINT32) 1 << (((EFI_IFR_ONE_OF *) IfrOpHdr)->Flags & EFI_IFR_NUMERIC_SIZE));
951 }
952 EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
953 StandardDefaultIsSet = FALSE;
954 ManufactDefaultIsSet = FALSE;
955 //
956 // Find Default and Manufacturing default for OneOf question
957 //
958 if (EfiVarStoreIndex < EfiVarStoreNumber) {
959 for (Index = 0; Index < DefaultIdNumber; Index ++) {
960 if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_STANDARD) {
961 Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_STANDARD, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, Width, QuestionReferBitField);
962 if (!EFI_ERROR (Status)) {
963 StandardDefaultIsSet = TRUE;
964 }
965 } else if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
966 Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_MANUFACTURING, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrManufactValue, Width, QuestionReferBitField);
967 if (!EFI_ERROR (Status)) {
968 ManufactDefaultIsSet = TRUE;
969 }
970 }
971 }
972 }
973 break;
974 case EFI_IFR_ORDERED_LIST_OP:
975 IfrScope = IfrOpHdr->Scope;
976 IfrQuestionType = IfrOpHdr->OpCode;
977 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *) (IfrOpHdr + 1);
978 break;
979 case EFI_IFR_ONE_OF_OPTION_OP:
980 if (IfrQuestionHdr != NULL && IfrScope > 0) {
981 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
982 if (IfrQuestionType == EFI_IFR_ONE_OF_OP) {
983 Width = (UINTN) ((UINT32) 1 << (IfrOneOfOption->Flags & EFI_IFR_NUMERIC_SIZE));
984 if (StandardDefaultIsSet) {
985 if (CompareMem (&IfrOneOfOption->Value, &IfrValue, Width) == 0) {
986 IfrOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT;
987 } else {
988 IfrOneOfOption->Flags &= ~EFI_IFR_OPTION_DEFAULT;
989 }
990 }
991 if (ManufactDefaultIsSet) {
992 if (CompareMem (&IfrOneOfOption->Value, &IfrManufactValue, Width) == 0) {
993 IfrOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT_MFG;
994 } else {
995 IfrOneOfOption->Flags &= ~EFI_IFR_OPTION_DEFAULT_MFG;
996 }
997 }
998 }
999 }
1000 break;
1001 case EFI_IFR_DEFAULT_OP:
1002 if (IfrQuestionHdr != NULL && IfrScope > 0) {
1003 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;
1004 //
1005 // Collect default value width
1006 //
1007 if (!QuestionReferBitField) {
1008 Width = 0;
1009 if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrDefault->Type == EFI_IFR_TYPE_BOOLEAN) {
1010 Width = 1;
1011 } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
1012 Width = 2;
1013 } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
1014 Width = 4;
1015 } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
1016 Width = 8;
1017 } else if (IfrDefault->Type == EFI_IFR_TYPE_BUFFER) {
1018 Width = IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value);
1019 }
1020 }
1021 //
1022 // Update the default value
1023 //
1024 if (Width > 0) {
1025 EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
1026 if (EfiVarStoreIndex < EfiVarStoreNumber) {
1027 Status = FindQuestionDefaultSetting (IfrDefault->DefaultId, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrDefault->Value, Width, QuestionReferBitField);
1028 }
1029 }
1030 }
1031 break;
1032 case EFI_IFR_END_OP:
1033 if (IfrQuestionHdr != NULL) {
1034 if (IfrScope > 0) {
1035 IfrScope --;
1036 }
1037 if (IfrScope == 0) {
1038 IfrQuestionHdr = NULL;
1039 QuestionReferBitField = FALSE;
1040 }
1041 }
1042 break;
1043 case EFI_IFR_GUID_OP:
1044 if (CompareGuid ((EFI_GUID *)((UINT8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {
1045 QuestionReferBitField = TRUE;
1046 }
1047 break;
1048 default:
1049 break;
1050 }
1051 IfrOffset = IfrOffset + IfrOpHdr->Length;
1052 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrOpHdr + IfrOpHdr->Length);
1053 if (IfrScope > 0) {
1054 IfrScope += IfrOpHdr->Scope;
1055 }
1056 }
1057
1058 Done:
1059 if (EfiVarStoreList != NULL) {
1060 for (Index = 0; Index < EfiVarStoreNumber; Index ++) {
1061 FreePool (EfiVarStoreList [Index]);
1062 }
1063 }
1064 return;
1065 }
1066
1067 /**
1068 This function insert a Form package to a package list node.
1069 This is a internal function.
1070
1071 @param PackageHdr Pointer to a buffer stored with Form package
1072 information.
1073 @param NotifyType The type of change concerning the database.
1074 @param PackageList Pointer to a package list which will be inserted
1075 to.
1076 @param Package Created Form package
1077
1078 @retval EFI_SUCCESS Form Package is inserted successfully.
1079 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
1080 Form package.
1081 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
1082
1083 **/
1084 EFI_STATUS
1085 InsertFormPackage (
1086 IN VOID *PackageHdr,
1087 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
1088 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
1089 OUT HII_IFR_PACKAGE_INSTANCE **Package
1090 )
1091 {
1092 HII_IFR_PACKAGE_INSTANCE *FormPackage;
1093 EFI_HII_PACKAGE_HEADER PackageHeader;
1094
1095 if (PackageHdr == NULL || PackageList == NULL) {
1096 return EFI_INVALID_PARAMETER;
1097 }
1098
1099 //
1100 // Get the length of the package, including package header itself
1101 //
1102 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
1103
1104 //
1105 // Create a Form package node
1106 //
1107 FormPackage = (HII_IFR_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IFR_PACKAGE_INSTANCE));
1108 if (FormPackage == NULL) {
1109 return EFI_OUT_OF_RESOURCES;
1110 }
1111
1112 FormPackage->IfrData = (UINT8 *) AllocateZeroPool (PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER));
1113 if (FormPackage->IfrData == NULL) {
1114 FreePool (FormPackage);
1115 return EFI_OUT_OF_RESOURCES;
1116 }
1117
1118 FormPackage->Signature = HII_IFR_PACKAGE_SIGNATURE;
1119 //
1120 // Copy Package Header
1121 //
1122 CopyMem (&FormPackage->FormPkgHdr, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
1123
1124 //
1125 // Copy Ifr contents
1126 //
1127 CopyMem (
1128 FormPackage->IfrData,
1129 (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER),
1130 PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER)
1131 );
1132
1133 InsertTailList (&PackageList->FormPkgHdr, &FormPackage->IfrEntry);
1134 *Package = FormPackage;
1135
1136 //
1137 // Update FormPackage with the default setting
1138 //
1139 UpdateDefaultSettingInFormPackage (FormPackage);
1140
1141 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
1142 PackageList->PackageListHdr.PackageLength += FormPackage->FormPkgHdr.Length;
1143 }
1144 return EFI_SUCCESS;
1145 }
1146
1147
1148 /**
1149 This function exports Form packages to a buffer.
1150 This is a internal function.
1151
1152 @param Private Hii database private structure.
1153 @param Handle Identification of a package list.
1154 @param PackageList Pointer to a package list which will be exported.
1155 @param UsedSize The length of buffer be used.
1156 @param BufferSize Length of the Buffer.
1157 @param Buffer Allocated space for storing exported data.
1158 @param ResultSize The size of the already exported content of this
1159 package list.
1160
1161 @retval EFI_SUCCESS Form Packages are exported successfully.
1162 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1163
1164 **/
1165 EFI_STATUS
1166 ExportFormPackages (
1167 IN HII_DATABASE_PRIVATE_DATA *Private,
1168 IN EFI_HII_HANDLE Handle,
1169 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
1170 IN UINTN UsedSize,
1171 IN UINTN BufferSize,
1172 IN OUT VOID *Buffer,
1173 IN OUT UINTN *ResultSize
1174 )
1175 {
1176 HII_IFR_PACKAGE_INSTANCE *FormPackage;
1177 UINTN PackageLength;
1178 LIST_ENTRY *Link;
1179 EFI_STATUS Status;
1180
1181 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
1182 return EFI_INVALID_PARAMETER;
1183 }
1184
1185 if (BufferSize > 0 && Buffer == NULL ) {
1186 return EFI_INVALID_PARAMETER;
1187 }
1188
1189 PackageLength = 0;
1190 Status = EFI_SUCCESS;
1191
1192 //
1193 // Export Form packages.
1194 //
1195 for (Link = PackageList->FormPkgHdr.ForwardLink; Link != &PackageList->FormPkgHdr; Link = Link->ForwardLink) {
1196 FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
1197 PackageLength += FormPackage->FormPkgHdr.Length;
1198 if ((Buffer != NULL) && (PackageLength + *ResultSize + UsedSize <= BufferSize)) {
1199 //
1200 // Invoke registered notification if exists
1201 //
1202 Status = InvokeRegisteredFunction (
1203 Private,
1204 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
1205 (VOID *) FormPackage,
1206 EFI_HII_PACKAGE_FORMS,
1207 Handle
1208 );
1209 ASSERT_EFI_ERROR (Status);
1210 //
1211 // Copy the Form package content.
1212 //
1213 CopyMem (Buffer, (VOID *) (&FormPackage->FormPkgHdr), sizeof (EFI_HII_PACKAGE_HEADER));
1214 Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_PACKAGE_HEADER);
1215 CopyMem (
1216 Buffer,
1217 (VOID *) FormPackage->IfrData,
1218 FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER)
1219 );
1220 Buffer = (UINT8 *) Buffer + FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
1221 }
1222 }
1223
1224 *ResultSize += PackageLength;
1225
1226 return EFI_SUCCESS;
1227
1228 }
1229
1230
1231 /**
1232 This function deletes all Form packages from a package list node.
1233 This is a internal function.
1234
1235 @param Private Hii database private data.
1236 @param Handle Handle of the package list which contains the to
1237 be removed Form packages.
1238 @param PackageList Pointer to a package list that contains removing
1239 packages.
1240
1241 @retval EFI_SUCCESS Form Package(s) is deleted successfully.
1242 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
1243
1244 **/
1245 EFI_STATUS
1246 RemoveFormPackages (
1247 IN HII_DATABASE_PRIVATE_DATA *Private,
1248 IN EFI_HII_HANDLE Handle,
1249 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
1250 )
1251 {
1252 LIST_ENTRY *ListHead;
1253 HII_IFR_PACKAGE_INSTANCE *Package;
1254 EFI_STATUS Status;
1255
1256 ListHead = &PackageList->FormPkgHdr;
1257
1258 while (!IsListEmpty (ListHead)) {
1259 Package = CR (
1260 ListHead->ForwardLink,
1261 HII_IFR_PACKAGE_INSTANCE,
1262 IfrEntry,
1263 HII_IFR_PACKAGE_SIGNATURE
1264 );
1265 Status = InvokeRegisteredFunction (
1266 Private,
1267 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
1268 (VOID *) Package,
1269 EFI_HII_PACKAGE_FORMS,
1270 Handle
1271 );
1272 if (EFI_ERROR (Status)) {
1273 return Status;
1274 }
1275
1276 RemoveEntryList (&Package->IfrEntry);
1277 PackageList->PackageListHdr.PackageLength -= Package->FormPkgHdr.Length;
1278 FreePool (Package->IfrData);
1279 FreePool (Package);
1280 //
1281 // If Hii runtime support feature is enabled,
1282 // will export Hii info for runtime use after ReadyToBoot event triggered.
1283 // If some driver add/update/remove packages from HiiDatabase after ReadyToBoot,
1284 // will need to export the content of HiiDatabase.
1285 // But if form packages removed, also need to export the ConfigResp string
1286 //
1287 if (gExportAfterReadyToBoot) {
1288 gExportConfigResp = TRUE;
1289 }
1290 }
1291
1292 return EFI_SUCCESS;
1293 }
1294
1295
1296
1297 /**
1298 This function insert a String package to a package list node.
1299 This is a internal function.
1300
1301 @param Private Hii database private structure.
1302 @param PackageHdr Pointer to a buffer stored with String package
1303 information.
1304 @param NotifyType The type of change concerning the database.
1305 @param PackageList Pointer to a package list which will be inserted
1306 to.
1307 @param Package Created String package
1308
1309 @retval EFI_SUCCESS String Package is inserted successfully.
1310 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
1311 String package.
1312 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
1313 @retval EFI_UNSUPPORTED A string package with the same language already
1314 exists in current package list.
1315
1316 **/
1317 EFI_STATUS
1318 InsertStringPackage (
1319 IN HII_DATABASE_PRIVATE_DATA *Private,
1320 IN VOID *PackageHdr,
1321 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
1322 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
1323 OUT HII_STRING_PACKAGE_INSTANCE **Package
1324 )
1325 {
1326 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1327 UINT32 HeaderSize;
1328 EFI_STATUS Status;
1329 EFI_HII_PACKAGE_HEADER PackageHeader;
1330 CHAR8 *Language;
1331 UINT32 LanguageSize;
1332 LIST_ENTRY *Link;
1333
1334 if (Private == NULL || PackageHdr == NULL || PackageList == NULL) {
1335 return EFI_INVALID_PARAMETER;
1336 }
1337 if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
1338 return EFI_INVALID_PARAMETER;
1339 }
1340
1341 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
1342 CopyMem (&HeaderSize, (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));
1343
1344 //
1345 // It is illegal to have two string packages with same language within one packagelist
1346 // since the stringid will be duplicate if so. Check it to avoid this potential issue.
1347 //
1348 LanguageSize = HeaderSize - sizeof (EFI_HII_STRING_PACKAGE_HDR) + sizeof (CHAR8);
1349 Language = (CHAR8 *) AllocateZeroPool (LanguageSize);
1350 if (Language == NULL) {
1351 return EFI_OUT_OF_RESOURCES;
1352 }
1353 AsciiStrCpyS (Language, LanguageSize / sizeof (CHAR8), (CHAR8 *) PackageHdr + HeaderSize - LanguageSize);
1354 for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {
1355 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1356 if (HiiCompareLanguage (Language, StringPackage->StringPkgHdr->Language)) {
1357 FreePool (Language);
1358 return EFI_UNSUPPORTED;
1359 }
1360 }
1361 FreePool (Language);
1362
1363 //
1364 // Create a String package node
1365 //
1366 StringPackage = (HII_STRING_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
1367 if (StringPackage == NULL) {
1368 Status = EFI_OUT_OF_RESOURCES;
1369 goto Error;
1370 }
1371
1372 StringPackage->StringPkgHdr = (EFI_HII_STRING_PACKAGE_HDR *) AllocateZeroPool (HeaderSize);
1373 if (StringPackage->StringPkgHdr == NULL) {
1374 Status = EFI_OUT_OF_RESOURCES;
1375 goto Error;
1376 }
1377
1378 StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (PackageHeader.Length - HeaderSize);
1379 if (StringPackage->StringBlock == NULL) {
1380 Status = EFI_OUT_OF_RESOURCES;
1381 goto Error;
1382 }
1383
1384 StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
1385 StringPackage->FontId = 0;
1386 InitializeListHead (&StringPackage->FontInfoList);
1387
1388 //
1389 // Copy the String package header.
1390 //
1391 CopyMem (StringPackage->StringPkgHdr, PackageHdr, HeaderSize);
1392
1393 //
1394 // Copy the String blocks
1395 //
1396 CopyMem (
1397 StringPackage->StringBlock,
1398 (UINT8 *) PackageHdr + HeaderSize,
1399 PackageHeader.Length - HeaderSize
1400 );
1401
1402 //
1403 // Collect all font block info
1404 //
1405 Status = FindStringBlock (Private, StringPackage, (EFI_STRING_ID) (-1), NULL, NULL, NULL, &StringPackage->MaxStringId, NULL);
1406 if (EFI_ERROR (Status)) {
1407 return Status;
1408 }
1409
1410 //
1411 // Insert to String package array
1412 //
1413 InsertTailList (&PackageList->StringPkgHdr, &StringPackage->StringEntry);
1414 *Package = StringPackage;
1415
1416 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
1417 PackageList->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;
1418 }
1419
1420 return EFI_SUCCESS;
1421
1422 Error:
1423
1424 if (StringPackage != NULL) {
1425 if (StringPackage->StringBlock != NULL) {
1426 FreePool (StringPackage->StringBlock);
1427 }
1428 if (StringPackage->StringPkgHdr != NULL) {
1429 FreePool (StringPackage->StringPkgHdr);
1430 }
1431 FreePool (StringPackage);
1432 }
1433 return Status;
1434
1435 }
1436
1437 /**
1438 Adjust all string packages in a single package list to have the same max string ID.
1439
1440 @param PackageList Pointer to a package list which will be adjusted.
1441
1442 @retval EFI_SUCCESS Adjust all string packages successfully.
1443 @retval others Can't adjust string packages.
1444
1445 **/
1446 EFI_STATUS
1447 AdjustStringPackage (
1448 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
1449 )
1450 {
1451 LIST_ENTRY *Link;
1452 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1453 UINT32 Skip2BlockSize;
1454 UINT32 OldBlockSize;
1455 UINT8 *StringBlock;
1456 UINT8 *BlockPtr;
1457 EFI_STRING_ID MaxStringId;
1458 UINT16 SkipCount;
1459
1460 MaxStringId = 0;
1461 for (Link = PackageList->StringPkgHdr.ForwardLink;
1462 Link != &PackageList->StringPkgHdr;
1463 Link = Link->ForwardLink
1464 ) {
1465 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1466 if (MaxStringId < StringPackage->MaxStringId) {
1467 MaxStringId = StringPackage->MaxStringId;
1468 }
1469 }
1470
1471 for (Link = PackageList->StringPkgHdr.ForwardLink;
1472 Link != &PackageList->StringPkgHdr;
1473 Link = Link->ForwardLink
1474 ) {
1475 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1476 if (StringPackage->MaxStringId < MaxStringId) {
1477 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
1478 //
1479 // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCKs to reserve the missing string IDs.
1480 //
1481 SkipCount = (UINT16) (MaxStringId - StringPackage->MaxStringId);
1482 Skip2BlockSize = (UINT32) sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
1483
1484 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Skip2BlockSize);
1485 if (StringBlock == NULL) {
1486 return EFI_OUT_OF_RESOURCES;
1487 }
1488 //
1489 // Copy original string blocks, except the EFI_HII_SIBT_END.
1490 //
1491 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1492 //
1493 // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCK blocks
1494 //
1495 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1496 *BlockPtr = EFI_HII_SIBT_SKIP2;
1497 CopyMem (BlockPtr + 1, &SkipCount, sizeof (UINT16));
1498 BlockPtr += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
1499
1500 //
1501 // Append a EFI_HII_SIBT_END block to the end.
1502 //
1503 *BlockPtr = EFI_HII_SIBT_END;
1504 FreePool (StringPackage->StringBlock);
1505 StringPackage->StringBlock = StringBlock;
1506 StringPackage->StringPkgHdr->Header.Length += Skip2BlockSize;
1507 PackageList->PackageListHdr.PackageLength += Skip2BlockSize;
1508 StringPackage->MaxStringId = MaxStringId;
1509 }
1510 }
1511
1512 return EFI_SUCCESS;
1513 }
1514
1515 /**
1516 This function exports String packages to a buffer.
1517 This is a internal function.
1518
1519 @param Private Hii database private structure.
1520 @param Handle Identification of a package list.
1521 @param PackageList Pointer to a package list which will be exported.
1522 @param UsedSize The length of buffer be used.
1523 @param BufferSize Length of the Buffer.
1524 @param Buffer Allocated space for storing exported data.
1525 @param ResultSize The size of the already exported content of this
1526 package list.
1527
1528 @retval EFI_SUCCESS String Packages are exported successfully.
1529 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1530
1531 **/
1532 EFI_STATUS
1533 ExportStringPackages (
1534 IN HII_DATABASE_PRIVATE_DATA *Private,
1535 IN EFI_HII_HANDLE Handle,
1536 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
1537 IN UINTN UsedSize,
1538 IN UINTN BufferSize,
1539 IN OUT VOID *Buffer,
1540 IN OUT UINTN *ResultSize
1541 )
1542 {
1543 LIST_ENTRY *Link;
1544 UINTN PackageLength;
1545 EFI_STATUS Status;
1546 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1547
1548 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
1549 return EFI_INVALID_PARAMETER;
1550 }
1551
1552 if (BufferSize > 0 && Buffer == NULL ) {
1553 return EFI_INVALID_PARAMETER;
1554 }
1555
1556 PackageLength = 0;
1557 Status = EFI_SUCCESS;
1558
1559 for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {
1560 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1561 PackageLength += StringPackage->StringPkgHdr->Header.Length;
1562 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
1563 //
1564 // Invoke registered notification function with EXPORT_PACK notify type
1565 //
1566 Status = InvokeRegisteredFunction (
1567 Private,
1568 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
1569 (VOID *) StringPackage,
1570 EFI_HII_PACKAGE_STRINGS,
1571 Handle
1572 );
1573 ASSERT_EFI_ERROR (Status);
1574 //
1575 // Copy String package header
1576 //
1577 CopyMem (Buffer, StringPackage->StringPkgHdr, StringPackage->StringPkgHdr->HdrSize);
1578 Buffer = (UINT8 *) Buffer + StringPackage->StringPkgHdr->HdrSize;
1579
1580 //
1581 // Copy String blocks information
1582 //
1583 CopyMem (
1584 Buffer,
1585 StringPackage->StringBlock,
1586 StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize
1587 );
1588 Buffer = (UINT8 *) Buffer + StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
1589 }
1590 }
1591
1592 *ResultSize += PackageLength;
1593 return EFI_SUCCESS;
1594 }
1595
1596
1597 /**
1598 This function deletes all String packages from a package list node.
1599 This is a internal function.
1600
1601 @param Private Hii database private data.
1602 @param Handle Handle of the package list which contains the to
1603 be removed String packages.
1604 @param PackageList Pointer to a package list that contains removing
1605 packages.
1606
1607 @retval EFI_SUCCESS String Package(s) is deleted successfully.
1608 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
1609
1610 **/
1611 EFI_STATUS
1612 RemoveStringPackages (
1613 IN HII_DATABASE_PRIVATE_DATA *Private,
1614 IN EFI_HII_HANDLE Handle,
1615 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
1616 )
1617 {
1618 LIST_ENTRY *ListHead;
1619 HII_STRING_PACKAGE_INSTANCE *Package;
1620 HII_FONT_INFO *FontInfo;
1621 EFI_STATUS Status;
1622
1623 ListHead = &PackageList->StringPkgHdr;
1624
1625 while (!IsListEmpty (ListHead)) {
1626 Package = CR (
1627 ListHead->ForwardLink,
1628 HII_STRING_PACKAGE_INSTANCE,
1629 StringEntry,
1630 HII_STRING_PACKAGE_SIGNATURE
1631 );
1632 Status = InvokeRegisteredFunction (
1633 Private,
1634 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
1635 (VOID *) Package,
1636 EFI_HII_PACKAGE_STRINGS,
1637 Handle
1638 );
1639 if (EFI_ERROR (Status)) {
1640 return Status;
1641 }
1642
1643 RemoveEntryList (&Package->StringEntry);
1644 PackageList->PackageListHdr.PackageLength -= Package->StringPkgHdr->Header.Length;
1645 FreePool (Package->StringBlock);
1646 FreePool (Package->StringPkgHdr);
1647 //
1648 // Delete font information
1649 //
1650 while (!IsListEmpty (&Package->FontInfoList)) {
1651 FontInfo = CR (
1652 Package->FontInfoList.ForwardLink,
1653 HII_FONT_INFO,
1654 Entry,
1655 HII_FONT_INFO_SIGNATURE
1656 );
1657 RemoveEntryList (&FontInfo->Entry);
1658 FreePool (FontInfo);
1659 }
1660
1661 FreePool (Package);
1662 }
1663
1664 return EFI_SUCCESS;
1665 }
1666
1667
1668 /**
1669 This function insert a Font package to a package list node.
1670 This is a internal function.
1671
1672 @param Private Hii database private structure.
1673 @param PackageHdr Pointer to a buffer stored with Font package
1674 information.
1675 @param NotifyType The type of change concerning the database.
1676 @param PackageList Pointer to a package list which will be inserted
1677 to.
1678 @param Package Created Font package
1679
1680 @retval EFI_SUCCESS Font Package is inserted successfully.
1681 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
1682 Font package.
1683 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
1684 @retval EFI_UNSUPPORTED A font package with same EFI_FONT_INFO already
1685 exists in current hii database.
1686
1687 **/
1688 EFI_STATUS
1689 InsertFontPackage (
1690 IN HII_DATABASE_PRIVATE_DATA *Private,
1691 IN VOID *PackageHdr,
1692 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
1693 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
1694 OUT HII_FONT_PACKAGE_INSTANCE **Package
1695 )
1696 {
1697 HII_FONT_PACKAGE_INSTANCE *FontPackage;
1698 EFI_HII_FONT_PACKAGE_HDR *FontPkgHdr;
1699 UINT32 HeaderSize;
1700 EFI_STATUS Status;
1701 EFI_HII_PACKAGE_HEADER PackageHeader;
1702 EFI_FONT_INFO *FontInfo;
1703 UINT32 FontInfoSize;
1704 HII_GLOBAL_FONT_INFO *GlobalFont;
1705
1706 if (Private == NULL || PackageHdr == NULL || PackageList == NULL) {
1707 return EFI_INVALID_PARAMETER;
1708 }
1709
1710 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
1711 CopyMem (&HeaderSize, (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));
1712
1713 FontInfo = NULL;
1714 FontPackage = NULL;
1715 GlobalFont = NULL;
1716
1717 //
1718 // It is illegal to have two font packages with same EFI_FONT_INFO within hii
1719 // database. EFI_FONT_INFO (FontName, FontSize, FontStyle) describes font's
1720 // attributes and identify a font uniquely.
1721 //
1722 FontPkgHdr = (EFI_HII_FONT_PACKAGE_HDR *) AllocateZeroPool (HeaderSize);
1723 if (FontPkgHdr == NULL) {
1724 Status = EFI_OUT_OF_RESOURCES;
1725 goto Error;
1726 }
1727 CopyMem (FontPkgHdr, PackageHdr, HeaderSize);
1728
1729 FontInfoSize = sizeof (EFI_FONT_INFO) + HeaderSize - sizeof (EFI_HII_FONT_PACKAGE_HDR);
1730 FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoSize);
1731 if (FontInfo == NULL) {
1732 Status = EFI_OUT_OF_RESOURCES;
1733 goto Error;
1734 }
1735 FontInfo->FontStyle = FontPkgHdr->FontStyle;
1736 FontInfo->FontSize = FontPkgHdr->Cell.Height;
1737 StrCpyS (FontInfo->FontName, (FontInfoSize - OFFSET_OF(EFI_FONT_INFO,FontName)) / sizeof (CHAR16), FontPkgHdr->FontFamily);
1738
1739 if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, NULL)) {
1740 Status = EFI_UNSUPPORTED;
1741 goto Error;
1742 }
1743
1744 //
1745 // Create a Font package node
1746 //
1747 FontPackage = (HII_FONT_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_FONT_PACKAGE_INSTANCE));
1748 if (FontPackage == NULL) {
1749 Status = EFI_OUT_OF_RESOURCES;
1750 goto Error;
1751 }
1752 FontPackage->Signature = HII_FONT_PACKAGE_SIGNATURE;
1753 FontPackage->FontPkgHdr = FontPkgHdr;
1754 InitializeListHead (&FontPackage->GlyphInfoList);
1755
1756 FontPackage->GlyphBlock = (UINT8 *) AllocateZeroPool (PackageHeader.Length - HeaderSize);
1757 if (FontPackage->GlyphBlock == NULL) {
1758 Status = EFI_OUT_OF_RESOURCES;
1759 goto Error;
1760 }
1761 CopyMem (FontPackage->GlyphBlock, (UINT8 *) PackageHdr + HeaderSize, PackageHeader.Length - HeaderSize);
1762
1763 //
1764 // Collect all default character cell information and backup in GlyphInfoList.
1765 //
1766 Status = FindGlyphBlock (FontPackage, (CHAR16) (-1), NULL, NULL, NULL);
1767 if (EFI_ERROR (Status)) {
1768 goto Error;
1769 }
1770
1771 //
1772 // This font package describes an unique EFI_FONT_INFO. Backup it in global
1773 // font info list.
1774 //
1775 GlobalFont = (HII_GLOBAL_FONT_INFO *) AllocateZeroPool (sizeof (HII_GLOBAL_FONT_INFO));
1776 if (GlobalFont == NULL) {
1777 Status = EFI_OUT_OF_RESOURCES;
1778 goto Error;
1779 }
1780 GlobalFont->Signature = HII_GLOBAL_FONT_INFO_SIGNATURE;
1781 GlobalFont->FontPackage = FontPackage;
1782 GlobalFont->FontInfoSize = FontInfoSize;
1783 GlobalFont->FontInfo = FontInfo;
1784 InsertTailList (&Private->FontInfoList, &GlobalFont->Entry);
1785
1786 //
1787 // Insert this font package to Font package array
1788 //
1789 InsertTailList (&PackageList->FontPkgHdr, &FontPackage->FontEntry);
1790 *Package = FontPackage;
1791
1792 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
1793 PackageList->PackageListHdr.PackageLength += FontPackage->FontPkgHdr->Header.Length;
1794 }
1795
1796 return EFI_SUCCESS;
1797
1798 Error:
1799
1800 if (FontPkgHdr != NULL) {
1801 FreePool (FontPkgHdr);
1802 }
1803 if (FontInfo != NULL) {
1804 FreePool (FontInfo);
1805 }
1806 if (FontPackage != NULL) {
1807 if (FontPackage->GlyphBlock != NULL) {
1808 FreePool (FontPackage->GlyphBlock);
1809 }
1810 FreePool (FontPackage);
1811 }
1812 if (GlobalFont != NULL) {
1813 FreePool (GlobalFont);
1814 }
1815
1816 return Status;
1817
1818 }
1819
1820
1821 /**
1822 This function exports Font packages to a buffer.
1823 This is a internal function.
1824
1825 @param Private Hii database private structure.
1826 @param Handle Identification of a package list.
1827 @param PackageList Pointer to a package list which will be exported.
1828 @param UsedSize The length of buffer be used.
1829 @param BufferSize Length of the Buffer.
1830 @param Buffer Allocated space for storing exported data.
1831 @param ResultSize The size of the already exported content of this
1832 package list.
1833
1834 @retval EFI_SUCCESS Font Packages are exported successfully.
1835 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1836
1837 **/
1838 EFI_STATUS
1839 ExportFontPackages (
1840 IN HII_DATABASE_PRIVATE_DATA *Private,
1841 IN EFI_HII_HANDLE Handle,
1842 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
1843 IN UINTN UsedSize,
1844 IN UINTN BufferSize,
1845 IN OUT VOID *Buffer,
1846 IN OUT UINTN *ResultSize
1847 )
1848 {
1849 LIST_ENTRY *Link;
1850 UINTN PackageLength;
1851 EFI_STATUS Status;
1852 HII_FONT_PACKAGE_INSTANCE *Package;
1853
1854
1855 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
1856 return EFI_INVALID_PARAMETER;
1857 }
1858
1859 if (BufferSize > 0 && Buffer == NULL ) {
1860 return EFI_INVALID_PARAMETER;
1861 }
1862
1863 PackageLength = 0;
1864 Status = EFI_SUCCESS;
1865
1866 for (Link = PackageList->FontPkgHdr.ForwardLink; Link != &PackageList->FontPkgHdr; Link = Link->ForwardLink) {
1867 Package = CR (Link, HII_FONT_PACKAGE_INSTANCE, FontEntry, HII_FONT_PACKAGE_SIGNATURE);
1868 PackageLength += Package->FontPkgHdr->Header.Length;
1869 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
1870 //
1871 // Invoke registered notification function with EXPORT_PACK notify type
1872 //
1873 Status = InvokeRegisteredFunction (
1874 Private,
1875 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
1876 (VOID *) Package,
1877 EFI_HII_PACKAGE_FONTS,
1878 Handle
1879 );
1880 ASSERT_EFI_ERROR (Status);
1881 //
1882 // Copy Font package header
1883 //
1884 CopyMem (Buffer, Package->FontPkgHdr, Package->FontPkgHdr->HdrSize);
1885 Buffer = (UINT8 *) Buffer + Package->FontPkgHdr->HdrSize;
1886
1887 //
1888 // Copy Glyph blocks information
1889 //
1890 CopyMem (
1891 Buffer,
1892 Package->GlyphBlock,
1893 Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize
1894 );
1895 Buffer = (UINT8 *) Buffer + Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize;
1896 }
1897 }
1898
1899 *ResultSize += PackageLength;
1900 return EFI_SUCCESS;
1901 }
1902
1903
1904 /**
1905 This function deletes all Font packages from a package list node.
1906 This is a internal function.
1907
1908 @param Private Hii database private data.
1909 @param Handle Handle of the package list which contains the to
1910 be removed Font packages.
1911 @param PackageList Pointer to a package list that contains removing
1912 packages.
1913
1914 @retval EFI_SUCCESS Font Package(s) is deleted successfully.
1915 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
1916
1917 **/
1918 EFI_STATUS
1919 RemoveFontPackages (
1920 IN HII_DATABASE_PRIVATE_DATA *Private,
1921 IN EFI_HII_HANDLE Handle,
1922 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
1923 )
1924 {
1925 LIST_ENTRY *ListHead;
1926 HII_FONT_PACKAGE_INSTANCE *Package;
1927 EFI_STATUS Status;
1928 HII_GLYPH_INFO *GlyphInfo;
1929 LIST_ENTRY *Link;
1930 HII_GLOBAL_FONT_INFO *GlobalFont;
1931
1932 ListHead = &PackageList->FontPkgHdr;
1933
1934 while (!IsListEmpty (ListHead)) {
1935 Package = CR (
1936 ListHead->ForwardLink,
1937 HII_FONT_PACKAGE_INSTANCE,
1938 FontEntry,
1939 HII_FONT_PACKAGE_SIGNATURE
1940 );
1941 Status = InvokeRegisteredFunction (
1942 Private,
1943 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
1944 (VOID *) Package,
1945 EFI_HII_PACKAGE_FONTS,
1946 Handle
1947 );
1948 if (EFI_ERROR (Status)) {
1949 return Status;
1950 }
1951
1952 RemoveEntryList (&Package->FontEntry);
1953 PackageList->PackageListHdr.PackageLength -= Package->FontPkgHdr->Header.Length;
1954
1955 if (Package->GlyphBlock != NULL) {
1956 FreePool (Package->GlyphBlock);
1957 }
1958 FreePool (Package->FontPkgHdr);
1959 //
1960 // Delete default character cell information
1961 //
1962 while (!IsListEmpty (&Package->GlyphInfoList)) {
1963 GlyphInfo = CR (
1964 Package->GlyphInfoList.ForwardLink,
1965 HII_GLYPH_INFO,
1966 Entry,
1967 HII_GLYPH_INFO_SIGNATURE
1968 );
1969 RemoveEntryList (&GlyphInfo->Entry);
1970 FreePool (GlyphInfo);
1971 }
1972
1973 //
1974 // Remove corresponding global font info
1975 //
1976 for (Link = Private->FontInfoList.ForwardLink; Link != &Private->FontInfoList; Link = Link->ForwardLink) {
1977 GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
1978 if (GlobalFont->FontPackage == Package) {
1979 RemoveEntryList (&GlobalFont->Entry);
1980 FreePool (GlobalFont->FontInfo);
1981 FreePool (GlobalFont);
1982 break;
1983 }
1984 }
1985
1986 FreePool (Package);
1987 }
1988
1989 return EFI_SUCCESS;
1990 }
1991
1992
1993 /**
1994 This function insert a Image package to a package list node.
1995 This is a internal function.
1996
1997 @param PackageHdr Pointer to a buffer stored with Image package
1998 information.
1999 @param NotifyType The type of change concerning the database.
2000 @param PackageList Pointer to a package list which will be inserted
2001 to.
2002 @param Package Created Image package
2003
2004 @retval EFI_SUCCESS Image Package is inserted successfully.
2005 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
2006 Image package.
2007 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
2008
2009 **/
2010 EFI_STATUS
2011 InsertImagePackage (
2012 IN VOID *PackageHdr,
2013 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
2014 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2015 OUT HII_IMAGE_PACKAGE_INSTANCE **Package
2016 )
2017 {
2018 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
2019 UINT32 PaletteSize;
2020 UINT32 ImageSize;
2021 UINT16 Index;
2022 EFI_HII_IMAGE_PALETTE_INFO_HEADER *PaletteHdr;
2023 EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo;
2024 UINT32 PaletteInfoOffset;
2025 UINT32 ImageInfoOffset;
2026 UINT16 CurrentSize;
2027
2028 if (PackageHdr == NULL || PackageList == NULL) {
2029 return EFI_INVALID_PARAMETER;
2030 }
2031
2032 //
2033 // Less than one image package is allowed in one package list.
2034 //
2035 if (PackageList->ImagePkg != NULL) {
2036 return EFI_INVALID_PARAMETER;
2037 }
2038
2039 //
2040 // Create a Image package node
2041 //
2042 ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
2043 if (ImagePackage == NULL) {
2044 return EFI_OUT_OF_RESOURCES;
2045 }
2046
2047 //
2048 // Copy the Image package header.
2049 //
2050 CopyMem (&ImagePackage->ImagePkgHdr, PackageHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));
2051
2052 PaletteInfoOffset = ImagePackage->ImagePkgHdr.PaletteInfoOffset;
2053 ImageInfoOffset = ImagePackage->ImagePkgHdr.ImageInfoOffset;
2054
2055 //
2056 // If PaletteInfoOffset is zero, there are no palettes in this image package.
2057 //
2058 PaletteSize = 0;
2059 ImagePackage->PaletteBlock = NULL;
2060 if (PaletteInfoOffset != 0) {
2061 PaletteHdr = (EFI_HII_IMAGE_PALETTE_INFO_HEADER *) ((UINT8 *) PackageHdr + PaletteInfoOffset);
2062 PaletteSize = sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
2063 PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *) ((UINT8 *) PaletteHdr + PaletteSize);
2064
2065 for (Index = 0; Index < PaletteHdr->PaletteCount; Index++) {
2066 CopyMem (&CurrentSize, PaletteInfo, sizeof (UINT16));
2067 CurrentSize += sizeof (UINT16);
2068 PaletteSize += (UINT32) CurrentSize;
2069 PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *) ((UINT8 *) PaletteInfo + CurrentSize);
2070 }
2071
2072 ImagePackage->PaletteBlock = (UINT8 *) AllocateZeroPool (PaletteSize);
2073 if (ImagePackage->PaletteBlock == NULL) {
2074 FreePool (ImagePackage);
2075 return EFI_OUT_OF_RESOURCES;
2076 }
2077 CopyMem (
2078 ImagePackage->PaletteBlock,
2079 (UINT8 *) PackageHdr + PaletteInfoOffset,
2080 PaletteSize
2081 );
2082 }
2083
2084 //
2085 // If ImageInfoOffset is zero, there are no images in this package.
2086 //
2087 ImageSize = 0;
2088 ImagePackage->ImageBlock = NULL;
2089 if (ImageInfoOffset != 0) {
2090 ImageSize = ImagePackage->ImagePkgHdr.Header.Length -
2091 sizeof (EFI_HII_IMAGE_PACKAGE_HDR) - PaletteSize;
2092 ImagePackage->ImageBlock = AllocateZeroPool (ImageSize);
2093 if (ImagePackage->ImageBlock == NULL) {
2094 FreePool (ImagePackage->PaletteBlock);
2095 FreePool (ImagePackage);
2096 return EFI_OUT_OF_RESOURCES;
2097 }
2098 CopyMem (
2099 ImagePackage->ImageBlock,
2100 (UINT8 *) PackageHdr + ImageInfoOffset,
2101 ImageSize
2102 );
2103 }
2104
2105 ImagePackage->ImageBlockSize = ImageSize;
2106 ImagePackage->PaletteInfoSize = PaletteSize;
2107 PackageList->ImagePkg = ImagePackage;
2108 *Package = ImagePackage;
2109
2110 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
2111 PackageList->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
2112 }
2113
2114 return EFI_SUCCESS;
2115 }
2116
2117
2118 /**
2119 This function exports Image packages to a buffer.
2120 This is a internal function.
2121
2122 @param Private Hii database private structure.
2123 @param Handle Identification of a package list.
2124 @param PackageList Pointer to a package list which will be exported.
2125 @param UsedSize The length of buffer be used.
2126 @param BufferSize Length of the Buffer.
2127 @param Buffer Allocated space for storing exported data.
2128 @param ResultSize The size of the already exported content of this
2129 package list.
2130
2131 @retval EFI_SUCCESS Image Packages are exported successfully.
2132 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
2133
2134 **/
2135 EFI_STATUS
2136 ExportImagePackages (
2137 IN HII_DATABASE_PRIVATE_DATA *Private,
2138 IN EFI_HII_HANDLE Handle,
2139 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2140 IN UINTN UsedSize,
2141 IN UINTN BufferSize,
2142 IN OUT VOID *Buffer,
2143 IN OUT UINTN *ResultSize
2144 )
2145 {
2146 UINTN PackageLength;
2147 EFI_STATUS Status;
2148 HII_IMAGE_PACKAGE_INSTANCE *Package;
2149
2150
2151 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
2152 return EFI_INVALID_PARAMETER;
2153 }
2154
2155 if (BufferSize > 0 && Buffer == NULL ) {
2156 return EFI_INVALID_PARAMETER;
2157 }
2158
2159 Package = PackageList->ImagePkg;
2160
2161 if (Package == NULL) {
2162 return EFI_SUCCESS;
2163 }
2164
2165 PackageLength = Package->ImagePkgHdr.Header.Length;
2166
2167 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
2168 //
2169 // Invoke registered notification function with EXPORT_PACK notify type
2170 //
2171 Status = InvokeRegisteredFunction (
2172 Private,
2173 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
2174 (VOID *) Package,
2175 EFI_HII_PACKAGE_IMAGES,
2176 Handle
2177 );
2178 ASSERT_EFI_ERROR (Status);
2179 ASSERT (Package->ImagePkgHdr.Header.Length ==
2180 sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + Package->ImageBlockSize + Package->PaletteInfoSize);
2181 //
2182 // Copy Image package header,
2183 // then justify the offset for image info and palette info in the header.
2184 //
2185 CopyMem (Buffer, &Package->ImagePkgHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));
2186 Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
2187
2188 //
2189 // Copy Image blocks information
2190 //
2191 if (Package->ImageBlockSize != 0) {
2192 CopyMem (Buffer, Package->ImageBlock, Package->ImageBlockSize);
2193 Buffer = (UINT8 *) Buffer + Package->ImageBlockSize;
2194 }
2195 //
2196 // Copy Palette information
2197 //
2198 if (Package->PaletteInfoSize != 0) {
2199 CopyMem (Buffer, Package->PaletteBlock, Package->PaletteInfoSize);
2200 Buffer = (UINT8 *) Buffer + Package->PaletteInfoSize;
2201 }
2202 }
2203
2204 *ResultSize += PackageLength;
2205 return EFI_SUCCESS;
2206 }
2207
2208
2209 /**
2210 This function deletes Image package from a package list node.
2211 This is a internal function.
2212
2213 @param Private Hii database private data.
2214 @param Handle Handle of the package list which contains the to
2215 be removed Image packages.
2216 @param PackageList Package List which contains the to be removed
2217 Image package.
2218
2219 @retval EFI_SUCCESS Image Package(s) is deleted successfully.
2220 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
2221
2222 **/
2223 EFI_STATUS
2224 RemoveImagePackages (
2225 IN HII_DATABASE_PRIVATE_DATA *Private,
2226 IN EFI_HII_HANDLE Handle,
2227 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
2228 )
2229 {
2230 HII_IMAGE_PACKAGE_INSTANCE *Package;
2231 EFI_STATUS Status;
2232
2233 Package = PackageList->ImagePkg;
2234
2235 //
2236 // Image package does not exist, return directly.
2237 //
2238 if (Package == NULL) {
2239 return EFI_SUCCESS;
2240 }
2241
2242 Status = InvokeRegisteredFunction (
2243 Private,
2244 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
2245 (VOID *) Package,
2246 EFI_HII_PACKAGE_IMAGES,
2247 Handle
2248 );
2249 if (EFI_ERROR (Status)) {
2250 return Status;
2251 }
2252
2253 PackageList->PackageListHdr.PackageLength -= Package->ImagePkgHdr.Header.Length;
2254
2255 FreePool (Package->ImageBlock);
2256 if (Package->PaletteBlock != NULL) {
2257 FreePool (Package->PaletteBlock);
2258 }
2259 FreePool (Package);
2260
2261 PackageList->ImagePkg = NULL;
2262
2263 return EFI_SUCCESS;
2264 }
2265
2266
2267 /**
2268 This function insert a Simple Font package to a package list node.
2269 This is a internal function.
2270
2271 @param PackageHdr Pointer to a buffer stored with Simple Font
2272 package information.
2273 @param NotifyType The type of change concerning the database.
2274 @param PackageList Pointer to a package list which will be inserted
2275 to.
2276 @param Package Created Simple Font package
2277
2278 @retval EFI_SUCCESS Simple Font Package is inserted successfully.
2279 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
2280 Simple Font package.
2281 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
2282
2283 **/
2284 EFI_STATUS
2285 InsertSimpleFontPackage (
2286 IN VOID *PackageHdr,
2287 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
2288 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2289 OUT HII_SIMPLE_FONT_PACKAGE_INSTANCE **Package
2290 )
2291 {
2292 HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;
2293 EFI_STATUS Status;
2294 EFI_HII_PACKAGE_HEADER Header;
2295
2296 if (PackageHdr == NULL || PackageList == NULL) {
2297 return EFI_INVALID_PARAMETER;
2298 }
2299
2300 //
2301 // Create a Simple Font package node
2302 //
2303 SimpleFontPackage = AllocateZeroPool (sizeof (HII_SIMPLE_FONT_PACKAGE_INSTANCE));
2304 if (SimpleFontPackage == NULL) {
2305 Status = EFI_OUT_OF_RESOURCES;
2306 goto Error;
2307 }
2308 SimpleFontPackage->Signature = HII_S_FONT_PACKAGE_SIGNATURE;
2309
2310 //
2311 // Copy the Simple Font package.
2312 //
2313 CopyMem (&Header, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
2314
2315 SimpleFontPackage->SimpleFontPkgHdr = AllocateZeroPool (Header.Length);
2316 if (SimpleFontPackage->SimpleFontPkgHdr == NULL) {
2317 Status = EFI_OUT_OF_RESOURCES;
2318 goto Error;
2319 }
2320
2321 CopyMem (SimpleFontPackage->SimpleFontPkgHdr, PackageHdr, Header.Length);
2322
2323 //
2324 // Insert to Simple Font package array
2325 //
2326 InsertTailList (&PackageList->SimpleFontPkgHdr, &SimpleFontPackage->SimpleFontEntry);
2327 *Package = SimpleFontPackage;
2328
2329 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
2330 PackageList->PackageListHdr.PackageLength += Header.Length;
2331 }
2332
2333 return EFI_SUCCESS;
2334
2335 Error:
2336
2337 if (SimpleFontPackage != NULL) {
2338 if (SimpleFontPackage->SimpleFontPkgHdr != NULL) {
2339 FreePool (SimpleFontPackage->SimpleFontPkgHdr);
2340 }
2341 FreePool (SimpleFontPackage);
2342 }
2343 return Status;
2344 }
2345
2346
2347 /**
2348 This function exports SimpleFont packages to a buffer.
2349 This is a internal function.
2350
2351 @param Private Hii database private structure.
2352 @param Handle Identification of a package list.
2353 @param PackageList Pointer to a package list which will be exported.
2354 @param UsedSize The length of buffer be used.
2355 @param BufferSize Length of the Buffer.
2356 @param Buffer Allocated space for storing exported data.
2357 @param ResultSize The size of the already exported content of this
2358 package list.
2359
2360 @retval EFI_SUCCESS SimpleFont Packages are exported successfully.
2361 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
2362
2363 **/
2364 EFI_STATUS
2365 ExportSimpleFontPackages (
2366 IN HII_DATABASE_PRIVATE_DATA *Private,
2367 IN EFI_HII_HANDLE Handle,
2368 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2369 IN UINTN UsedSize,
2370 IN UINTN BufferSize,
2371 IN OUT VOID *Buffer,
2372 IN OUT UINTN *ResultSize
2373 )
2374 {
2375 LIST_ENTRY *Link;
2376 UINTN PackageLength;
2377 EFI_STATUS Status;
2378 HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;
2379
2380 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
2381 return EFI_INVALID_PARAMETER;
2382 }
2383
2384 if (BufferSize > 0 && Buffer == NULL ) {
2385 return EFI_INVALID_PARAMETER;
2386 }
2387
2388 PackageLength = 0;
2389 Status = EFI_SUCCESS;
2390
2391 for (Link = PackageList->SimpleFontPkgHdr.ForwardLink; Link != &PackageList->SimpleFontPkgHdr; Link = Link->ForwardLink) {
2392 Package = CR (Link, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);
2393 PackageLength += Package->SimpleFontPkgHdr->Header.Length;
2394 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
2395 //
2396 // Invoke registered notification function with EXPORT_PACK notify type
2397 //
2398 Status = InvokeRegisteredFunction (
2399 Private,
2400 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
2401 (VOID *) Package,
2402 EFI_HII_PACKAGE_SIMPLE_FONTS,
2403 Handle
2404 );
2405 ASSERT_EFI_ERROR (Status);
2406
2407 //
2408 // Copy SimpleFont package
2409 //
2410 CopyMem (Buffer, Package->SimpleFontPkgHdr, Package->SimpleFontPkgHdr->Header.Length);
2411 Buffer = (UINT8 *) Buffer + Package->SimpleFontPkgHdr->Header.Length;
2412 }
2413 }
2414
2415 *ResultSize += PackageLength;
2416 return EFI_SUCCESS;
2417 }
2418
2419
2420 /**
2421 This function deletes all Simple Font packages from a package list node.
2422 This is a internal function.
2423
2424 @param Private Hii database private data.
2425 @param Handle Handle of the package list which contains the to
2426 be removed Simple Font packages.
2427 @param PackageList Pointer to a package list that contains removing
2428 packages.
2429
2430 @retval EFI_SUCCESS Simple Font Package(s) is deleted successfully.
2431 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
2432
2433 **/
2434 EFI_STATUS
2435 RemoveSimpleFontPackages (
2436 IN HII_DATABASE_PRIVATE_DATA *Private,
2437 IN EFI_HII_HANDLE Handle,
2438 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
2439 )
2440 {
2441 LIST_ENTRY *ListHead;
2442 HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;
2443 EFI_STATUS Status;
2444
2445 ListHead = &PackageList->SimpleFontPkgHdr;
2446
2447 while (!IsListEmpty (ListHead)) {
2448 Package = CR (
2449 ListHead->ForwardLink,
2450 HII_SIMPLE_FONT_PACKAGE_INSTANCE,
2451 SimpleFontEntry,
2452 HII_S_FONT_PACKAGE_SIGNATURE
2453 );
2454 Status = InvokeRegisteredFunction (
2455 Private,
2456 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
2457 (VOID *) Package,
2458 EFI_HII_PACKAGE_SIMPLE_FONTS,
2459 Handle
2460 );
2461 if (EFI_ERROR (Status)) {
2462 return Status;
2463 }
2464
2465 RemoveEntryList (&Package->SimpleFontEntry);
2466 PackageList->PackageListHdr.PackageLength -= Package->SimpleFontPkgHdr->Header.Length;
2467 FreePool (Package->SimpleFontPkgHdr);
2468 FreePool (Package);
2469 }
2470
2471 return EFI_SUCCESS;
2472 }
2473
2474
2475 /**
2476 This function insert a Device path package to a package list node.
2477 This is a internal function.
2478
2479 @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol
2480 instance
2481 @param NotifyType The type of change concerning the database.
2482 @param PackageList Pointer to a package list which will be inserted
2483 to.
2484
2485 @retval EFI_SUCCESS Device path Package is inserted successfully.
2486 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
2487 Device path package.
2488 @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.
2489
2490 **/
2491 EFI_STATUS
2492 InsertDevicePathPackage (
2493 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
2494 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
2495 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
2496 )
2497 {
2498 UINT32 PackageLength;
2499 EFI_HII_PACKAGE_HEADER Header;
2500
2501 if (DevicePath == NULL || PackageList == NULL) {
2502 return EFI_INVALID_PARAMETER;
2503 }
2504 //
2505 // Less than one device path package is allowed in one package list.
2506 //
2507 if (PackageList->DevicePathPkg != NULL) {
2508 return EFI_INVALID_PARAMETER;
2509 }
2510
2511 PackageLength = (UINT32) GetDevicePathSize (DevicePath) + sizeof (EFI_HII_PACKAGE_HEADER);
2512 PackageList->DevicePathPkg = (UINT8 *) AllocateZeroPool (PackageLength);
2513 if (PackageList->DevicePathPkg == NULL) {
2514 return EFI_OUT_OF_RESOURCES;
2515 }
2516
2517 Header.Length = PackageLength;
2518 Header.Type = EFI_HII_PACKAGE_DEVICE_PATH;
2519 CopyMem (PackageList->DevicePathPkg, &Header, sizeof (EFI_HII_PACKAGE_HEADER));
2520 CopyMem (
2521 PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER),
2522 DevicePath,
2523 PackageLength - sizeof (EFI_HII_PACKAGE_HEADER)
2524 );
2525
2526 //
2527 // Since Device Path package is created by NewPackageList, either NEW_PACK
2528 // or ADD_PACK should increase the length of package list.
2529 //
2530 PackageList->PackageListHdr.PackageLength += PackageLength;
2531 return EFI_SUCCESS;
2532 }
2533
2534
2535 /**
2536 This function exports device path package to a buffer.
2537 This is a internal function.
2538
2539 @param Private Hii database private structure.
2540 @param Handle Identification of a package list.
2541 @param PackageList Pointer to a package list which will be exported.
2542 @param UsedSize The length of buffer be used.
2543 @param BufferSize Length of the Buffer.
2544 @param Buffer Allocated space for storing exported data.
2545 @param ResultSize The size of the already exported content of this
2546 package list.
2547
2548 @retval EFI_SUCCESS Device path Package is exported successfully.
2549 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
2550
2551 **/
2552 EFI_STATUS
2553 ExportDevicePathPackage (
2554 IN HII_DATABASE_PRIVATE_DATA *Private,
2555 IN EFI_HII_HANDLE Handle,
2556 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2557 IN UINTN UsedSize,
2558 IN UINTN BufferSize,
2559 IN OUT VOID *Buffer,
2560 IN OUT UINTN *ResultSize
2561 )
2562 {
2563 EFI_STATUS Status;
2564 UINT8 *Package;
2565 EFI_HII_PACKAGE_HEADER Header;
2566
2567 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
2568 return EFI_INVALID_PARAMETER;
2569 }
2570 if (BufferSize > 0 && Buffer == NULL ) {
2571 return EFI_INVALID_PARAMETER;
2572 }
2573
2574 Package = PackageList->DevicePathPkg;
2575
2576 if (Package == NULL) {
2577 return EFI_SUCCESS;
2578 }
2579
2580 CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2581
2582 if (Header.Length + *ResultSize + UsedSize <= BufferSize) {
2583 //
2584 // Invoke registered notification function with EXPORT_PACK notify type
2585 //
2586 Status = InvokeRegisteredFunction (
2587 Private,
2588 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
2589 (VOID *) Package,
2590 EFI_HII_PACKAGE_DEVICE_PATH,
2591 Handle
2592 );
2593 ASSERT_EFI_ERROR (Status);
2594
2595 //
2596 // Copy Device path package
2597 //
2598 CopyMem (Buffer, Package, Header.Length);
2599 }
2600
2601 *ResultSize += Header.Length;
2602 return EFI_SUCCESS;
2603 }
2604
2605
2606 /**
2607 This function deletes Device Path package from a package list node.
2608 This is a internal function.
2609
2610 @param Private Hii database private data.
2611 @param Handle Handle of the package list.
2612 @param PackageList Package List which contains the to be removed
2613 Device Path package.
2614
2615 @retval EFI_SUCCESS Device Path Package is deleted successfully.
2616 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
2617
2618 **/
2619 EFI_STATUS
2620 RemoveDevicePathPackage (
2621 IN HII_DATABASE_PRIVATE_DATA *Private,
2622 IN EFI_HII_HANDLE Handle,
2623 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
2624 )
2625 {
2626 EFI_STATUS Status;
2627 UINT8 *Package;
2628 EFI_HII_PACKAGE_HEADER Header;
2629
2630 Package = PackageList->DevicePathPkg;
2631
2632 //
2633 // No device path, return directly.
2634 //
2635 if (Package == NULL) {
2636 return EFI_SUCCESS;
2637 }
2638
2639 Status = InvokeRegisteredFunction (
2640 Private,
2641 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
2642 (VOID *) Package,
2643 EFI_HII_PACKAGE_DEVICE_PATH,
2644 Handle
2645 );
2646 if (EFI_ERROR (Status)) {
2647 return Status;
2648 }
2649
2650 CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2651 PackageList->PackageListHdr.PackageLength -= Header.Length;
2652
2653 FreePool (Package);
2654
2655 PackageList->DevicePathPkg = NULL;
2656
2657 return EFI_SUCCESS;
2658 }
2659
2660
2661 /**
2662 This function will insert a device path package to package list firstly then
2663 invoke notification functions if any.
2664 This is a internal function.
2665
2666 @param Private Hii database private structure.
2667 @param NotifyType The type of change concerning the database.
2668 @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol
2669 instance
2670 @param DatabaseRecord Pointer to a database record contains a package
2671 list which will be inserted to.
2672
2673 @retval EFI_SUCCESS Device path Package is inserted successfully.
2674 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
2675 Device path package.
2676 @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.
2677
2678 **/
2679 EFI_STATUS
2680 AddDevicePathPackage (
2681 IN HII_DATABASE_PRIVATE_DATA *Private,
2682 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
2683 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
2684 IN OUT HII_DATABASE_RECORD *DatabaseRecord
2685 )
2686 {
2687 EFI_STATUS Status;
2688
2689 if (DevicePath == NULL) {
2690 return EFI_SUCCESS;
2691 }
2692
2693 ASSERT (Private != NULL);
2694 ASSERT (DatabaseRecord != NULL);
2695
2696 //
2697 // Create a device path package and insert to packagelist
2698 //
2699 Status = InsertDevicePathPackage (
2700 DevicePath,
2701 NotifyType,
2702 DatabaseRecord->PackageList
2703 );
2704 if (EFI_ERROR (Status)) {
2705 return Status;
2706 }
2707
2708 return InvokeRegisteredFunction (
2709 Private,
2710 NotifyType,
2711 (VOID *) DatabaseRecord->PackageList->DevicePathPkg,
2712 EFI_HII_PACKAGE_DEVICE_PATH,
2713 DatabaseRecord->Handle
2714 );
2715 }
2716
2717
2718 /**
2719 This function insert a Keyboard Layout package to a package list node.
2720 This is a internal function.
2721
2722 @param PackageHdr Pointer to a buffer stored with Keyboard Layout
2723 package information.
2724 @param NotifyType The type of change concerning the database.
2725 @param PackageList Pointer to a package list which will be inserted
2726 to.
2727 @param Package Created Keyboard Layout package
2728
2729 @retval EFI_SUCCESS Keyboard Layout Package is inserted successfully.
2730 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
2731 Keyboard Layout package.
2732 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
2733
2734 **/
2735 EFI_STATUS
2736 InsertKeyboardLayoutPackage (
2737 IN VOID *PackageHdr,
2738 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
2739 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2740 OUT HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE **Package
2741 )
2742 {
2743 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;
2744 EFI_HII_PACKAGE_HEADER PackageHeader;
2745 EFI_STATUS Status;
2746
2747 if (PackageHdr == NULL || PackageList == NULL) {
2748 return EFI_INVALID_PARAMETER;
2749 }
2750
2751 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
2752
2753 //
2754 // Create a Keyboard Layout package node
2755 //
2756 KeyboardLayoutPackage = AllocateZeroPool (sizeof (HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE));
2757 if (KeyboardLayoutPackage == NULL) {
2758 Status = EFI_OUT_OF_RESOURCES;
2759 goto Error;
2760 }
2761 KeyboardLayoutPackage->Signature = HII_KB_LAYOUT_PACKAGE_SIGNATURE;
2762
2763 KeyboardLayoutPackage->KeyboardPkg = (UINT8 *) AllocateZeroPool (PackageHeader.Length);
2764 if (KeyboardLayoutPackage->KeyboardPkg == NULL) {
2765 Status = EFI_OUT_OF_RESOURCES;
2766 goto Error;
2767 }
2768
2769 CopyMem (KeyboardLayoutPackage->KeyboardPkg, PackageHdr, PackageHeader.Length);
2770 InsertTailList (&PackageList->KeyboardLayoutHdr, &KeyboardLayoutPackage->KeyboardEntry);
2771
2772 *Package = KeyboardLayoutPackage;
2773
2774 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
2775 PackageList->PackageListHdr.PackageLength += PackageHeader.Length;
2776 }
2777
2778 return EFI_SUCCESS;
2779
2780 Error:
2781
2782
2783 if (KeyboardLayoutPackage != NULL) {
2784 if (KeyboardLayoutPackage->KeyboardPkg != NULL) {
2785 FreePool (KeyboardLayoutPackage->KeyboardPkg);
2786 }
2787 FreePool (KeyboardLayoutPackage);
2788 }
2789
2790 return Status;
2791 }
2792
2793
2794 /**
2795 This function exports Keyboard Layout packages to a buffer.
2796 This is a internal function.
2797
2798 @param Private Hii database private structure.
2799 @param Handle Identification of a package list.
2800 @param PackageList Pointer to a package list which will be exported.
2801 @param UsedSize The length of buffer be used.
2802 @param BufferSize Length of the Buffer.
2803 @param Buffer Allocated space for storing exported data.
2804 @param ResultSize The size of the already exported content of this
2805 package list.
2806
2807 @retval EFI_SUCCESS Keyboard Layout Packages are exported
2808 successfully.
2809 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
2810
2811 **/
2812 EFI_STATUS
2813 ExportKeyboardLayoutPackages (
2814 IN HII_DATABASE_PRIVATE_DATA *Private,
2815 IN EFI_HII_HANDLE Handle,
2816 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2817 IN UINTN UsedSize,
2818 IN UINTN BufferSize,
2819 IN OUT VOID *Buffer,
2820 IN OUT UINTN *ResultSize
2821 )
2822 {
2823 LIST_ENTRY *Link;
2824 UINTN PackageLength;
2825 EFI_STATUS Status;
2826 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
2827 EFI_HII_PACKAGE_HEADER PackageHeader;
2828
2829 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
2830 return EFI_INVALID_PARAMETER;
2831 }
2832
2833 if (BufferSize > 0 && Buffer == NULL ) {
2834 return EFI_INVALID_PARAMETER;
2835 }
2836
2837 PackageLength = 0;
2838 Status = EFI_SUCCESS;
2839
2840 for (Link = PackageList->KeyboardLayoutHdr.ForwardLink; Link != &PackageList->KeyboardLayoutHdr; Link = Link->ForwardLink) {
2841 Package = CR (Link, HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE, KeyboardEntry, HII_KB_LAYOUT_PACKAGE_SIGNATURE);
2842 CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));
2843 PackageLength += PackageHeader.Length;
2844 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
2845 //
2846 // Invoke registered notification function with EXPORT_PACK notify type
2847 //
2848 Status = InvokeRegisteredFunction (
2849 Private,
2850 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
2851 (EFI_HII_PACKAGE_HEADER *) Package,
2852 EFI_HII_PACKAGE_KEYBOARD_LAYOUT,
2853 Handle
2854 );
2855 ASSERT_EFI_ERROR (Status);
2856
2857 //
2858 // Copy Keyboard Layout package
2859 //
2860 CopyMem (Buffer, Package->KeyboardPkg, PackageHeader.Length);
2861 Buffer = (UINT8 *) Buffer + PackageHeader.Length;
2862 }
2863 }
2864
2865 *ResultSize += PackageLength;
2866 return EFI_SUCCESS;
2867 }
2868
2869
2870 /**
2871 This function deletes all Keyboard Layout packages from a package list node.
2872 This is a internal function.
2873
2874 @param Private Hii database private data.
2875 @param Handle Handle of the package list which contains the to
2876 be removed Keyboard Layout packages.
2877 @param PackageList Pointer to a package list that contains removing
2878 packages.
2879
2880 @retval EFI_SUCCESS Keyboard Layout Package(s) is deleted
2881 successfully.
2882 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
2883
2884 **/
2885 EFI_STATUS
2886 RemoveKeyboardLayoutPackages (
2887 IN HII_DATABASE_PRIVATE_DATA *Private,
2888 IN EFI_HII_HANDLE Handle,
2889 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
2890 )
2891 {
2892 LIST_ENTRY *ListHead;
2893 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
2894 EFI_HII_PACKAGE_HEADER PackageHeader;
2895 EFI_STATUS Status;
2896
2897 ListHead = &PackageList->KeyboardLayoutHdr;
2898
2899 while (!IsListEmpty (ListHead)) {
2900 Package = CR (
2901 ListHead->ForwardLink,
2902 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
2903 KeyboardEntry,
2904 HII_KB_LAYOUT_PACKAGE_SIGNATURE
2905 );
2906 Status = InvokeRegisteredFunction (
2907 Private,
2908 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
2909 (VOID *) Package,
2910 EFI_HII_PACKAGE_KEYBOARD_LAYOUT,
2911 Handle
2912 );
2913 if (EFI_ERROR (Status)) {
2914 return Status;
2915 }
2916
2917 RemoveEntryList (&Package->KeyboardEntry);
2918 CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));
2919 PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;
2920 FreePool (Package->KeyboardPkg);
2921 FreePool (Package);
2922 }
2923
2924 return EFI_SUCCESS;
2925 }
2926
2927
2928 /**
2929 This function will insert a package list to hii database firstly then
2930 invoke notification functions if any. It is the worker function of
2931 HiiNewPackageList and HiiUpdatePackageList.
2932
2933 This is a internal function.
2934
2935 @param Private Hii database private structure.
2936 @param NotifyType The type of change concerning the database.
2937 @param PackageList Pointer to a package list.
2938 @param DatabaseRecord Pointer to a database record contains a package
2939 list instance which will be inserted to.
2940
2941 @retval EFI_SUCCESS All incoming packages are inserted to current
2942 database.
2943 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
2944 Device path package.
2945 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
2946
2947 **/
2948 EFI_STATUS
2949 AddPackages (
2950 IN HII_DATABASE_PRIVATE_DATA *Private,
2951 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
2952 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
2953 IN OUT HII_DATABASE_RECORD *DatabaseRecord
2954 )
2955 {
2956 EFI_STATUS Status;
2957 HII_GUID_PACKAGE_INSTANCE *GuidPackage;
2958 HII_IFR_PACKAGE_INSTANCE *FormPackage;
2959 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;
2960 HII_STRING_PACKAGE_INSTANCE *StringPackage;
2961 HII_FONT_PACKAGE_INSTANCE *FontPackage;
2962 HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;
2963 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
2964 EFI_HII_PACKAGE_HEADER *PackageHdrPtr;
2965 EFI_HII_PACKAGE_HEADER PackageHeader;
2966 UINT32 OldPackageListLen;
2967 BOOLEAN StringPkgIsAdd;
2968
2969 //
2970 // Initialize Variables
2971 //
2972 StringPkgIsAdd = FALSE;
2973 FontPackage = NULL;
2974 StringPackage = NULL;
2975 GuidPackage = NULL;
2976 FormPackage = NULL;
2977 ImagePackage = NULL;
2978 SimpleFontPackage = NULL;
2979 KeyboardLayoutPackage = NULL;
2980
2981 //
2982 // Process the package list header
2983 //
2984 OldPackageListLen = DatabaseRecord->PackageList->PackageListHdr.PackageLength;
2985 CopyMem (
2986 &DatabaseRecord->PackageList->PackageListHdr,
2987 (VOID *) PackageList,
2988 sizeof (EFI_HII_PACKAGE_LIST_HEADER)
2989 );
2990 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
2991 DatabaseRecord->PackageList->PackageListHdr.PackageLength = OldPackageListLen;
2992 }
2993
2994 PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
2995 CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
2996
2997 Status = EFI_SUCCESS;
2998
2999 while (PackageHeader.Type != EFI_HII_PACKAGE_END) {
3000 switch (PackageHeader.Type) {
3001 case EFI_HII_PACKAGE_TYPE_GUID:
3002 Status = InsertGuidPackage (
3003 PackageHdrPtr,
3004 NotifyType,
3005 DatabaseRecord->PackageList,
3006 &GuidPackage
3007 );
3008 if (EFI_ERROR (Status)) {
3009 return Status;
3010 }
3011 Status = InvokeRegisteredFunction (
3012 Private,
3013 NotifyType,
3014 (VOID *) GuidPackage,
3015 (UINT8) (PackageHeader.Type),
3016 DatabaseRecord->Handle
3017 );
3018 break;
3019 case EFI_HII_PACKAGE_FORMS:
3020 Status = InsertFormPackage (
3021 PackageHdrPtr,
3022 NotifyType,
3023 DatabaseRecord->PackageList,
3024 &FormPackage
3025 );
3026 if (EFI_ERROR (Status)) {
3027 return Status;
3028 }
3029 Status = InvokeRegisteredFunction (
3030 Private,
3031 NotifyType,
3032 (VOID *) FormPackage,
3033 (UINT8) (PackageHeader.Type),
3034 DatabaseRecord->Handle
3035 );
3036 //
3037 // If Hii runtime support feature is enabled,
3038 // will export Hii info for runtime use after ReadyToBoot event triggered.
3039 // If some driver add/update/remove packages from HiiDatabase after ReadyToBoot,
3040 // will need to export the content of HiiDatabase.
3041 // But if form packages added/updated, also need to export the ConfigResp string.
3042 //
3043 if (gExportAfterReadyToBoot) {
3044 gExportConfigResp = TRUE;
3045 }
3046 break;
3047 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
3048 Status = InsertKeyboardLayoutPackage (
3049 PackageHdrPtr,
3050 NotifyType,
3051 DatabaseRecord->PackageList,
3052 &KeyboardLayoutPackage
3053 );
3054 if (EFI_ERROR (Status)) {
3055 return Status;
3056 }
3057 Status = InvokeRegisteredFunction (
3058 Private,
3059 NotifyType,
3060 (VOID *) KeyboardLayoutPackage,
3061 (UINT8) (PackageHeader.Type),
3062 DatabaseRecord->Handle
3063 );
3064 break;
3065 case EFI_HII_PACKAGE_STRINGS:
3066 Status = InsertStringPackage (
3067 Private,
3068 PackageHdrPtr,
3069 NotifyType,
3070 DatabaseRecord->PackageList,
3071 &StringPackage
3072 );
3073 if (EFI_ERROR (Status)) {
3074 return Status;
3075 }
3076 ASSERT (StringPackage != NULL);
3077 Status = InvokeRegisteredFunction (
3078 Private,
3079 NotifyType,
3080 (VOID *) StringPackage,
3081 (UINT8) (PackageHeader.Type),
3082 DatabaseRecord->Handle
3083 );
3084 StringPkgIsAdd = TRUE;
3085 break;
3086 case EFI_HII_PACKAGE_FONTS:
3087 Status = InsertFontPackage (
3088 Private,
3089 PackageHdrPtr,
3090 NotifyType,
3091 DatabaseRecord->PackageList,
3092 &FontPackage
3093 );
3094 if (EFI_ERROR (Status)) {
3095 return Status;
3096 }
3097 Status = InvokeRegisteredFunction (
3098 Private,
3099 NotifyType,
3100 (VOID *) FontPackage,
3101 (UINT8) (PackageHeader.Type),
3102 DatabaseRecord->Handle
3103 );
3104 break;
3105 case EFI_HII_PACKAGE_IMAGES:
3106 Status = InsertImagePackage (
3107 PackageHdrPtr,
3108 NotifyType,
3109 DatabaseRecord->PackageList,
3110 &ImagePackage
3111 );
3112 if (EFI_ERROR (Status)) {
3113 return Status;
3114 }
3115 Status = InvokeRegisteredFunction (
3116 Private,
3117 NotifyType,
3118 (VOID *) ImagePackage,
3119 (UINT8) (PackageHeader.Type),
3120 DatabaseRecord->Handle
3121 );
3122 break;
3123 case EFI_HII_PACKAGE_SIMPLE_FONTS:
3124 Status = InsertSimpleFontPackage (
3125 PackageHdrPtr,
3126 NotifyType,
3127 DatabaseRecord->PackageList,
3128 &SimpleFontPackage
3129 );
3130 if (EFI_ERROR (Status)) {
3131 return Status;
3132 }
3133 Status = InvokeRegisteredFunction (
3134 Private,
3135 NotifyType,
3136 (VOID *) SimpleFontPackage,
3137 (UINT8) (PackageHeader.Type),
3138 DatabaseRecord->Handle
3139 );
3140 break;
3141 case EFI_HII_PACKAGE_DEVICE_PATH:
3142 Status = AddDevicePathPackage (
3143 Private,
3144 NotifyType,
3145 (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *) PackageHdrPtr + sizeof (EFI_HII_PACKAGE_HEADER)),
3146 DatabaseRecord
3147 );
3148 break;
3149 default:
3150 break;
3151 }
3152
3153 if (EFI_ERROR (Status)) {
3154 return Status;
3155 }
3156 //
3157 // goto header of next package
3158 //
3159 PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHdrPtr + PackageHeader.Length);
3160 CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
3161 }
3162
3163 //
3164 // Adjust String Package to make sure all string packages have the same max string ID.
3165 //
3166 if (!EFI_ERROR (Status) && StringPkgIsAdd) {
3167 Status = AdjustStringPackage (DatabaseRecord->PackageList);
3168 }
3169
3170 return Status;
3171 }
3172
3173
3174 /**
3175 This function exports a package list to a buffer. It is the worker function
3176 of HiiExportPackageList.
3177
3178 This is a internal function.
3179
3180 @param Private Hii database private structure.
3181 @param Handle Identification of a package list.
3182 @param PackageList Pointer to a package list which will be exported.
3183 @param UsedSize The length of buffer has been used by exporting
3184 package lists when Handle is NULL.
3185 @param BufferSize Length of the Buffer.
3186 @param Buffer Allocated space for storing exported data.
3187
3188 @retval EFI_SUCCESS Keyboard Layout Packages are exported
3189 successfully.
3190 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
3191
3192 **/
3193 EFI_STATUS
3194 ExportPackageList (
3195 IN HII_DATABASE_PRIVATE_DATA *Private,
3196 IN EFI_HII_HANDLE Handle,
3197 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
3198 IN OUT UINTN *UsedSize,
3199 IN UINTN BufferSize,
3200 OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
3201 )
3202 {
3203 EFI_STATUS Status;
3204 UINTN ResultSize;
3205 EFI_HII_PACKAGE_HEADER EndofPackageList;
3206
3207 ASSERT (Private != NULL && PackageList != NULL && UsedSize != NULL);
3208 ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
3209 ASSERT (IsHiiHandleValid (Handle));
3210
3211 if (BufferSize > 0 && Buffer == NULL ) {
3212 return EFI_INVALID_PARAMETER;
3213 }
3214
3215 //
3216 // Copy the package list header
3217 // ResultSize indicates the length of the exported bytes of this package list
3218 //
3219 ResultSize = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
3220 if (ResultSize + *UsedSize <= BufferSize) {
3221 CopyMem ((VOID *) Buffer, PackageList, ResultSize);
3222 }
3223 //
3224 // Copy the packages and invoke EXPORT_PACK notify functions if exists.
3225 //
3226 Status = ExportGuidPackages (
3227 Private,
3228 Handle,
3229 PackageList,
3230 *UsedSize,
3231 BufferSize,
3232 (VOID *) ((UINT8 *) Buffer + ResultSize),
3233 &ResultSize
3234 );
3235 if (EFI_ERROR (Status)) {
3236 return Status;
3237 }
3238 Status = ExportFormPackages (
3239 Private,
3240 Handle,
3241 PackageList,
3242 *UsedSize,
3243 BufferSize,
3244 (VOID *) ((UINT8 *) Buffer + ResultSize),
3245 &ResultSize
3246 );
3247 if (EFI_ERROR (Status)) {
3248 return Status;
3249 }
3250 Status = ExportKeyboardLayoutPackages (
3251 Private,
3252 Handle,
3253 PackageList,
3254 *UsedSize,
3255 BufferSize,
3256 (VOID *) ((UINT8 *) Buffer + ResultSize),
3257 &ResultSize
3258 );
3259 if (EFI_ERROR (Status)) {
3260 return Status;
3261 }
3262 Status = ExportStringPackages (
3263 Private,
3264 Handle,
3265 PackageList,
3266 *UsedSize,
3267 BufferSize,
3268 (VOID *) ((UINT8 *) Buffer + ResultSize),
3269 &ResultSize
3270 );
3271 if (EFI_ERROR (Status)) {
3272 return Status;
3273 }
3274 Status = ExportFontPackages (
3275 Private,
3276 Handle,
3277 PackageList,
3278 *UsedSize,
3279 BufferSize,
3280 (VOID *) ((UINT8 *) Buffer + ResultSize),
3281 &ResultSize
3282 );
3283 if (EFI_ERROR (Status)) {
3284 return Status;
3285 }
3286 Status = ExportImagePackages (
3287 Private,
3288 Handle,
3289 PackageList,
3290 *UsedSize,
3291 BufferSize,
3292 (VOID *) ((UINT8 *) Buffer + ResultSize),
3293 &ResultSize
3294 );
3295 if (EFI_ERROR (Status)) {
3296 return Status;
3297 }
3298 Status = ExportSimpleFontPackages (
3299 Private,
3300 Handle,
3301 PackageList,
3302 *UsedSize,
3303 BufferSize,
3304 (VOID *) ((UINT8 *) Buffer + ResultSize),
3305 &ResultSize
3306 );
3307 if (EFI_ERROR (Status)) {
3308 return Status;
3309 }
3310 Status = ExportDevicePathPackage (
3311 Private,
3312 Handle,
3313 PackageList,
3314 *UsedSize,
3315 BufferSize,
3316 (VOID *) ((UINT8 *) Buffer + ResultSize),
3317 &ResultSize
3318 );
3319 if (EFI_ERROR (Status)) {
3320 return Status;
3321 }
3322 //
3323 // Append the package list end.
3324 //
3325 EndofPackageList.Length = sizeof (EFI_HII_PACKAGE_HEADER);
3326 EndofPackageList.Type = EFI_HII_PACKAGE_END;
3327 if (ResultSize + *UsedSize + sizeof (EFI_HII_PACKAGE_HEADER) <= BufferSize) {
3328 CopyMem (
3329 (VOID *) ((UINT8 *) Buffer + ResultSize),
3330 (VOID *) &EndofPackageList,
3331 sizeof (EFI_HII_PACKAGE_HEADER)
3332 );
3333 }
3334
3335 *UsedSize += ResultSize + sizeof (EFI_HII_PACKAGE_HEADER);
3336
3337 return EFI_SUCCESS;
3338 }
3339
3340 /**
3341 This function mainly use to get and update ConfigResp string.
3342
3343 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
3344
3345 @retval EFI_SUCCESS Get the information successfully.
3346 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the Configuration Setting data.
3347
3348 **/
3349 EFI_STATUS
3350 HiiGetConfigRespInfo(
3351 IN CONST EFI_HII_DATABASE_PROTOCOL *This
3352 )
3353 {
3354 EFI_STATUS Status;
3355 HII_DATABASE_PRIVATE_DATA *Private;
3356 EFI_STRING ConfigAltResp;
3357 UINTN ConfigSize;
3358
3359 ConfigAltResp = NULL;
3360 ConfigSize = 0;
3361
3362 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3363
3364 //
3365 // Get ConfigResp string
3366 //
3367 Status = HiiConfigRoutingExportConfig(&Private->ConfigRouting,&ConfigAltResp);
3368
3369 if (!EFI_ERROR (Status)){
3370 ConfigSize = StrSize(ConfigAltResp);
3371 if (ConfigSize > gConfigRespSize){
3372 gConfigRespSize = ConfigSize;
3373 if (gRTConfigRespBuffer != NULL){
3374 FreePool(gRTConfigRespBuffer);
3375 }
3376 gRTConfigRespBuffer = (EFI_STRING)AllocateRuntimeZeroPool(ConfigSize);
3377 if (gRTConfigRespBuffer == NULL){
3378 FreePool(ConfigAltResp);
3379 DEBUG ((DEBUG_ERROR, "Not enough memory resource to get the ConfigResp string.\n"));
3380 return EFI_OUT_OF_RESOURCES;
3381 }
3382 } else {
3383 ZeroMem(gRTConfigRespBuffer,gConfigRespSize);
3384 }
3385 CopyMem(gRTConfigRespBuffer,ConfigAltResp,ConfigSize);
3386 gBS->InstallConfigurationTable (&gEfiHiiConfigRoutingProtocolGuid, gRTConfigRespBuffer);
3387 FreePool(ConfigAltResp);
3388 }
3389
3390 return EFI_SUCCESS;
3391
3392 }
3393
3394 /**
3395 This is an internal function,mainly use to get HiiDatabase information.
3396
3397 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
3398
3399 @retval EFI_SUCCESS Get the information successfully.
3400 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the Hiidatabase data.
3401
3402 **/
3403 EFI_STATUS
3404 HiiGetDatabaseInfo(
3405 IN CONST EFI_HII_DATABASE_PROTOCOL *This
3406 )
3407 {
3408 EFI_STATUS Status;
3409 EFI_HII_PACKAGE_LIST_HEADER *DatabaseInfo;
3410 UINTN DatabaseInfoSize;
3411
3412 DatabaseInfo = NULL;
3413 DatabaseInfoSize = 0;
3414
3415 //
3416 // Get HiiDatabase information.
3417 //
3418 Status = HiiExportPackageLists(This, NULL, &DatabaseInfoSize, DatabaseInfo);
3419
3420 ASSERT(Status == EFI_BUFFER_TOO_SMALL);
3421
3422 if(DatabaseInfoSize > gDatabaseInfoSize ) {
3423 gDatabaseInfoSize = DatabaseInfoSize;
3424 if (gRTDatabaseInfoBuffer != NULL){
3425 FreePool(gRTDatabaseInfoBuffer);
3426 }
3427 gRTDatabaseInfoBuffer = AllocateRuntimeZeroPool(DatabaseInfoSize);
3428 if (gRTDatabaseInfoBuffer == NULL){
3429 DEBUG ((DEBUG_ERROR, "Not enough memory resource to get the HiiDatabase info.\n"));
3430 return EFI_OUT_OF_RESOURCES;
3431 }
3432 } else {
3433 ZeroMem(gRTDatabaseInfoBuffer,gDatabaseInfoSize);
3434 }
3435 Status = HiiExportPackageLists(This, NULL, &DatabaseInfoSize, gRTDatabaseInfoBuffer);
3436 ASSERT_EFI_ERROR (Status);
3437 gBS->InstallConfigurationTable (&gEfiHiiDatabaseProtocolGuid, gRTDatabaseInfoBuffer);
3438
3439 return EFI_SUCCESS;
3440
3441 }
3442
3443 /**
3444 This function adds the packages in the package list to the database and returns a handle. If there is a
3445 EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will
3446 create a package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.
3447
3448 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
3449 instance.
3450 @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
3451 structure.
3452 @param DriverHandle Associate the package list with this EFI handle.
3453 If a NULL is specified, this data will not be associate
3454 with any drivers and cannot have a callback induced.
3455 @param Handle A pointer to the EFI_HII_HANDLE instance.
3456
3457 @retval EFI_SUCCESS The package list associated with the Handle was
3458 added to the HII database.
3459 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
3460 database contents.
3461 @retval EFI_INVALID_PARAMETER PackageList is NULL or Handle is NULL.
3462 @retval EFI_INVALID_PARAMETER PackageListGuid already exists in database.
3463
3464 **/
3465 EFI_STATUS
3466 EFIAPI
3467 HiiNewPackageList (
3468 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
3469 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
3470 IN CONST EFI_HANDLE DriverHandle, OPTIONAL
3471 OUT EFI_HII_HANDLE *Handle
3472 )
3473 {
3474 EFI_STATUS Status;
3475 HII_DATABASE_PRIVATE_DATA *Private;
3476 HII_DATABASE_RECORD *DatabaseRecord;
3477 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
3478 LIST_ENTRY *Link;
3479 EFI_GUID PackageListGuid;
3480
3481 if (This == NULL || PackageList == NULL || Handle == NULL) {
3482 return EFI_INVALID_PARAMETER;
3483 }
3484
3485 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3486 CopyMem (&PackageListGuid, (VOID *) PackageList, sizeof (EFI_GUID));
3487
3488 //
3489 // Check the Package list GUID to guarantee this GUID is unique in database.
3490 //
3491 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
3492 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
3493 if (CompareGuid (
3494 &(DatabaseRecord->PackageList->PackageListHdr.PackageListGuid),
3495 &PackageListGuid) &&
3496 DatabaseRecord->DriverHandle == DriverHandle) {
3497 return EFI_INVALID_PARAMETER;
3498 }
3499 }
3500
3501 EfiAcquireLock (&mHiiDatabaseLock);
3502
3503 //
3504 // Build a PackageList node
3505 //
3506 Status = GenerateHiiDatabaseRecord (Private, &DatabaseRecord);
3507 if (EFI_ERROR (Status)) {
3508 EfiReleaseLock (&mHiiDatabaseLock);
3509 return Status;
3510 }
3511
3512 //
3513 // Fill in information of the created Package List node
3514 // according to incoming package list.
3515 //
3516 Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, PackageList, DatabaseRecord);
3517 if (EFI_ERROR (Status)) {
3518 EfiReleaseLock (&mHiiDatabaseLock);
3519 return Status;
3520 }
3521
3522 DatabaseRecord->DriverHandle = DriverHandle;
3523
3524 //
3525 // Create a Device path package and add into the package list if exists.
3526 //
3527 Status = gBS->HandleProtocol (
3528 DriverHandle,
3529 &gEfiDevicePathProtocolGuid,
3530 (VOID **) &DevicePath
3531 );
3532 if (!EFI_ERROR (Status)) {
3533 Status = AddDevicePathPackage (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, DevicePath, DatabaseRecord);
3534 ASSERT_EFI_ERROR (Status);
3535 }
3536
3537 *Handle = DatabaseRecord->Handle;
3538
3539 //
3540 // Check whether need to get the Database info.
3541 // Only after ReadyToBoot, need to do the export.
3542 //
3543 if (gExportAfterReadyToBoot) {
3544 HiiGetDatabaseInfo (This);
3545 }
3546 EfiReleaseLock (&mHiiDatabaseLock);
3547
3548 //
3549 // Notes:
3550 // HiiGetDatabaseInfo () will get the contents of HII data base,
3551 // belong to the atomic behavior of Hii Database update.
3552 // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
3553 // we can not think it belong to the atomic behavior of Hii Database update.
3554 // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
3555 //
3556
3557 // Check whether need to get the configuration setting info from HII drivers.
3558 // When after ReadyToBoot and need to do the export for form package add.
3559 //
3560 if (gExportAfterReadyToBoot && gExportConfigResp) {
3561 HiiGetConfigRespInfo (This);
3562 }
3563
3564 return EFI_SUCCESS;
3565 }
3566
3567
3568 /**
3569 This function removes the package list that is associated with Handle
3570 from the HII database. Before removing the package, any registered functions
3571 with the notification type REMOVE_PACK and the same package type will be called.
3572
3573 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
3574 instance.
3575 @param Handle The handle that was registered to the data that is
3576 requested for removal.
3577
3578 @retval EFI_SUCCESS The data associated with the Handle was removed
3579 from the HII database.
3580 @retval EFI_NOT_FOUND The specified handle is not in database.
3581 @retval EFI_INVALID_PARAMETER The Handle was not valid.
3582
3583 **/
3584 EFI_STATUS
3585 EFIAPI
3586 HiiRemovePackageList (
3587 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
3588 IN EFI_HII_HANDLE Handle
3589 )
3590 {
3591 EFI_STATUS Status;
3592 HII_DATABASE_PRIVATE_DATA *Private;
3593 LIST_ENTRY *Link;
3594 HII_DATABASE_RECORD *Node;
3595 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
3596 HII_HANDLE *HiiHandle;
3597
3598 if (This == NULL) {
3599 return EFI_INVALID_PARAMETER;
3600 }
3601
3602 if (!IsHiiHandleValid (Handle)) {
3603 return EFI_NOT_FOUND;
3604 }
3605
3606 EfiAcquireLock (&mHiiDatabaseLock);
3607
3608 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3609
3610 //
3611 // Get the packagelist to be removed.
3612 //
3613 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
3614 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
3615 if (Node->Handle == Handle) {
3616 PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);
3617 ASSERT (PackageList != NULL);
3618
3619 //
3620 // Call registered functions with REMOVE_PACK before removing packages
3621 // then remove them.
3622 //
3623 Status = RemoveGuidPackages (Private, Handle, PackageList);
3624 if (EFI_ERROR (Status)) {
3625 EfiReleaseLock (&mHiiDatabaseLock);
3626 return Status;
3627 }
3628 Status = RemoveFormPackages (Private, Handle, PackageList);
3629 if (EFI_ERROR (Status)) {
3630 EfiReleaseLock (&mHiiDatabaseLock);
3631 return Status;
3632 }
3633 Status = RemoveKeyboardLayoutPackages (Private, Handle, PackageList);
3634 if (EFI_ERROR (Status)) {
3635 EfiReleaseLock (&mHiiDatabaseLock);
3636 return Status;
3637 }
3638 Status = RemoveStringPackages (Private, Handle, PackageList);
3639 if (EFI_ERROR (Status)) {
3640 EfiReleaseLock (&mHiiDatabaseLock);
3641 return Status;
3642 }
3643 Status = RemoveFontPackages (Private, Handle, PackageList);
3644 if (EFI_ERROR (Status)) {
3645 EfiReleaseLock (&mHiiDatabaseLock);
3646 return Status;
3647 }
3648 Status = RemoveImagePackages (Private, Handle, PackageList);
3649 if (EFI_ERROR (Status)) {
3650 EfiReleaseLock (&mHiiDatabaseLock);
3651 return Status;
3652 }
3653 Status = RemoveSimpleFontPackages (Private, Handle, PackageList);
3654 if (EFI_ERROR (Status)) {
3655 EfiReleaseLock (&mHiiDatabaseLock);
3656 return Status;
3657 }
3658 Status = RemoveDevicePathPackage (Private, Handle, PackageList);
3659 if (EFI_ERROR (Status)) {
3660 EfiReleaseLock (&mHiiDatabaseLock);
3661 return Status;
3662 }
3663
3664 //
3665 // Free resources of the package list
3666 //
3667 RemoveEntryList (&Node->DatabaseEntry);
3668
3669 HiiHandle = (HII_HANDLE *) Handle;
3670 RemoveEntryList (&HiiHandle->Handle);
3671 Private->HiiHandleCount--;
3672 ASSERT (Private->HiiHandleCount >= 0);
3673
3674 HiiHandle->Signature = 0;
3675 FreePool (HiiHandle);
3676 FreePool (Node->PackageList);
3677 FreePool (Node);
3678
3679 //
3680 // Check whether need to get the Database info.
3681 // Only after ReadyToBoot, need to do the export.
3682 //
3683 if (gExportAfterReadyToBoot) {
3684 HiiGetDatabaseInfo (This);
3685 }
3686 EfiReleaseLock (&mHiiDatabaseLock);
3687
3688 //
3689 // Notes:
3690 // HiiGetDatabaseInfo () will get the contents of HII data base,
3691 // belong to the atomic behavior of Hii Database update.
3692 // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
3693 // we can not think it belong to the atomic behavior of Hii Database update.
3694 // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
3695 //
3696
3697 //
3698 // Check whether need to get the configuration setting info from HII drivers.
3699 // When after ReadyToBoot and need to do the export for form package remove.
3700 //
3701 if (gExportAfterReadyToBoot && gExportConfigResp) {
3702 HiiGetConfigRespInfo (This);
3703 }
3704 return EFI_SUCCESS;
3705 }
3706 }
3707
3708 EfiReleaseLock (&mHiiDatabaseLock);
3709 return EFI_NOT_FOUND;
3710 }
3711
3712
3713 /**
3714 This function updates the existing package list (which has the specified Handle)
3715 in the HII databases, using the new package list specified by PackageList.
3716
3717 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
3718 instance.
3719 @param Handle The handle that was registered to the data that is
3720 requested to be updated.
3721 @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
3722 package.
3723
3724 @retval EFI_SUCCESS The HII database was successfully updated.
3725 @retval EFI_OUT_OF_RESOURCES Unable to allocate enough memory for the updated
3726 database.
3727 @retval EFI_INVALID_PARAMETER PackageList was NULL.
3728 @retval EFI_NOT_FOUND The specified Handle is not in database.
3729
3730 **/
3731 EFI_STATUS
3732 EFIAPI
3733 HiiUpdatePackageList (
3734 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
3735 IN EFI_HII_HANDLE Handle,
3736 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList
3737 )
3738 {
3739 EFI_STATUS Status;
3740 HII_DATABASE_PRIVATE_DATA *Private;
3741 LIST_ENTRY *Link;
3742 HII_DATABASE_RECORD *Node;
3743 EFI_HII_PACKAGE_HEADER *PackageHdrPtr;
3744 HII_DATABASE_PACKAGE_LIST_INSTANCE *OldPackageList;
3745 EFI_HII_PACKAGE_HEADER PackageHeader;
3746
3747 if (This == NULL || PackageList == NULL) {
3748 return EFI_INVALID_PARAMETER;
3749 }
3750
3751 if (!IsHiiHandleValid (Handle)) {
3752 return EFI_NOT_FOUND;
3753 }
3754
3755 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3756
3757 PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
3758
3759 Status = EFI_SUCCESS;
3760
3761 EfiAcquireLock (&mHiiDatabaseLock);
3762 //
3763 // Get original packagelist to be updated
3764 //
3765 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
3766 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
3767 if (Node->Handle == Handle) {
3768 OldPackageList = Node->PackageList;
3769 //
3770 // Remove the package if its type matches one of the package types which is
3771 // contained in the new package list.
3772 //
3773 CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
3774 while (PackageHeader.Type != EFI_HII_PACKAGE_END) {
3775 switch (PackageHeader.Type) {
3776 case EFI_HII_PACKAGE_TYPE_GUID:
3777 Status = RemoveGuidPackages (Private, Handle, OldPackageList);
3778 break;
3779 case EFI_HII_PACKAGE_FORMS:
3780 Status = RemoveFormPackages (Private, Handle, OldPackageList);
3781 break;
3782 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
3783 Status = RemoveKeyboardLayoutPackages (Private, Handle, OldPackageList);
3784 break;
3785 case EFI_HII_PACKAGE_STRINGS:
3786 Status = RemoveStringPackages (Private, Handle, OldPackageList);
3787 break;
3788 case EFI_HII_PACKAGE_FONTS:
3789 Status = RemoveFontPackages (Private, Handle, OldPackageList);
3790 break;
3791 case EFI_HII_PACKAGE_IMAGES:
3792 Status = RemoveImagePackages (Private, Handle, OldPackageList);
3793 break;
3794 case EFI_HII_PACKAGE_SIMPLE_FONTS:
3795 Status = RemoveSimpleFontPackages (Private, Handle, OldPackageList);
3796 break;
3797 case EFI_HII_PACKAGE_DEVICE_PATH:
3798 Status = RemoveDevicePathPackage (Private, Handle, OldPackageList);
3799 break;
3800 }
3801
3802 if (EFI_ERROR (Status)) {
3803 EfiReleaseLock (&mHiiDatabaseLock);
3804 return Status;
3805 }
3806
3807 PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHdrPtr + PackageHeader.Length);
3808 CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
3809 }
3810
3811 //
3812 // Add all of the packages within the new package list
3813 //
3814 Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_ADD_PACK, PackageList, Node);
3815
3816 //
3817 // Check whether need to get the Database info.
3818 // Only after ReadyToBoot, need to do the export.
3819 //
3820 if (gExportAfterReadyToBoot && Status == EFI_SUCCESS) {
3821 HiiGetDatabaseInfo (This);
3822 }
3823 EfiReleaseLock (&mHiiDatabaseLock);
3824
3825 //
3826 // Notes:
3827 // HiiGetDatabaseInfo () will get the contents of HII data base,
3828 // belong to the atomic behavior of Hii Database update.
3829 // And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
3830 // we can not think it belong to the atomic behavior of Hii Database update.
3831 // That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
3832 //
3833
3834 //
3835 // Check whether need to get the configuration setting info from HII drivers.
3836 // When after ReadyToBoot and need to do the export for form package update.
3837 //
3838 if (gExportAfterReadyToBoot && gExportConfigResp && Status == EFI_SUCCESS) {
3839 HiiGetConfigRespInfo (This);
3840 }
3841
3842 return Status;
3843 }
3844 }
3845 EfiReleaseLock (&mHiiDatabaseLock);
3846 return EFI_NOT_FOUND;
3847 }
3848
3849
3850 /**
3851 This function returns a list of the package handles of the specified type
3852 that are currently active in the database. The pseudo-type
3853 EFI_HII_PACKAGE_TYPE_ALL will cause all package handles to be listed.
3854
3855 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
3856 instance.
3857 @param PackageType Specifies the package type of the packages to list
3858 or EFI_HII_PACKAGE_TYPE_ALL for all packages to be
3859 listed.
3860 @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
3861 this is the pointer to the GUID which must match
3862 the Guid field of EFI_HII_GUID_PACKAGE_GUID_HDR.
3863 Otherwise, it must be NULL.
3864 @param HandleBufferLength On input, a pointer to the length of the handle
3865 buffer. On output, the length of the handle
3866 buffer that is required for the handles found.
3867 @param Handle An array of EFI_HII_HANDLE instances returned.
3868
3869 @retval EFI_SUCCESS The matching handles are outputted successfully.
3870 HandleBufferLength is updated with the actual length.
3871 @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
3872 Handle is too small to support the number of
3873 handles. HandleBufferLength is updated with a
3874 value that will enable the data to fit.
3875 @retval EFI_NOT_FOUND No matching handle could not be found in database.
3876 @retval EFI_INVALID_PARAMETER HandleBufferLength was NULL.
3877 @retval EFI_INVALID_PARAMETER The value referenced by HandleBufferLength was not
3878 zero and Handle was NULL.
3879 @retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but
3880 PackageGuid is not NULL, PackageType is a EFI_HII_
3881 PACKAGE_TYPE_GUID but PackageGuid is NULL.
3882
3883 **/
3884 EFI_STATUS
3885 EFIAPI
3886 HiiListPackageLists (
3887 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
3888 IN UINT8 PackageType,
3889 IN CONST EFI_GUID *PackageGuid,
3890 IN OUT UINTN *HandleBufferLength,
3891 OUT EFI_HII_HANDLE *Handle
3892 )
3893 {
3894 HII_GUID_PACKAGE_INSTANCE *GuidPackage;
3895 HII_DATABASE_PRIVATE_DATA *Private;
3896 HII_DATABASE_RECORD *Node;
3897 LIST_ENTRY *Link;
3898 BOOLEAN Matched;
3899 HII_HANDLE **Result;
3900 UINTN ResultSize;
3901 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
3902 LIST_ENTRY *Link1;
3903
3904 //
3905 // Check input parameters
3906 //
3907 if (This == NULL || HandleBufferLength == NULL) {
3908 return EFI_INVALID_PARAMETER;
3909 }
3910 if (*HandleBufferLength > 0 && Handle == NULL) {
3911 return EFI_INVALID_PARAMETER;
3912 }
3913 if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) ||
3914 (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL)) {
3915 return EFI_INVALID_PARAMETER;
3916 }
3917
3918 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
3919 Matched = FALSE;
3920 Result = (HII_HANDLE **) Handle;
3921 ResultSize = 0;
3922
3923 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
3924 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
3925 PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);
3926 switch (PackageType) {
3927 case EFI_HII_PACKAGE_TYPE_GUID:
3928 for (Link1 = PackageList->GuidPkgHdr.ForwardLink; Link1 != &PackageList->GuidPkgHdr; Link1 = Link1->ForwardLink) {
3929 GuidPackage = CR (Link1, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);
3930 if (CompareGuid (
3931 (EFI_GUID *) PackageGuid,
3932 (EFI_GUID *) (GuidPackage->GuidPkg + sizeof (EFI_HII_PACKAGE_HEADER))
3933 )) {
3934 Matched = TRUE;
3935 break;
3936 }
3937 }
3938 break;
3939 case EFI_HII_PACKAGE_FORMS:
3940 if (!IsListEmpty (&PackageList->FormPkgHdr)) {
3941 Matched = TRUE;
3942 }
3943 break;
3944 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
3945 if (!IsListEmpty (&PackageList->KeyboardLayoutHdr)) {
3946 Matched = TRUE;
3947 }
3948 break;
3949 case EFI_HII_PACKAGE_STRINGS:
3950 if (!IsListEmpty (&PackageList->StringPkgHdr)) {
3951 Matched = TRUE;
3952 }
3953 break;
3954 case EFI_HII_PACKAGE_FONTS:
3955 if (!IsListEmpty (&PackageList->FontPkgHdr)) {
3956 Matched = TRUE;
3957 }
3958 break;
3959 case EFI_HII_PACKAGE_IMAGES:
3960 if (PackageList->ImagePkg != NULL) {
3961 Matched = TRUE;
3962 }
3963 break;
3964 case EFI_HII_PACKAGE_SIMPLE_FONTS:
3965 if (!IsListEmpty (&PackageList->SimpleFontPkgHdr)) {
3966 Matched = TRUE;
3967 }
3968 break;
3969 case EFI_HII_PACKAGE_DEVICE_PATH:
3970 if (PackageList->DevicePathPkg != NULL) {
3971 Matched = TRUE;
3972 }
3973 break;
3974 //
3975 // Pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package handles
3976 // to be listed.
3977 //
3978 case EFI_HII_PACKAGE_TYPE_ALL:
3979 Matched = TRUE;
3980 break;
3981 default:
3982 break;
3983 }
3984
3985 //
3986 // This active package list has the specified package type, list it.
3987 //
3988 if (Matched) {
3989 ResultSize += sizeof (EFI_HII_HANDLE);
3990 if (ResultSize <= *HandleBufferLength) {
3991 *Result++ = Node->Handle;
3992 }
3993 }
3994 Matched = FALSE;
3995 }
3996
3997 if (ResultSize == 0) {
3998 return EFI_NOT_FOUND;
3999 }
4000
4001 if (*HandleBufferLength < ResultSize) {
4002 *HandleBufferLength = ResultSize;
4003 return EFI_BUFFER_TOO_SMALL;
4004 }
4005
4006 *HandleBufferLength = ResultSize;
4007 return EFI_SUCCESS;
4008 }
4009
4010
4011 /**
4012 This function will export one or all package lists in the database to a buffer.
4013 For each package list exported, this function will call functions registered
4014 with EXPORT_PACK and then copy the package list to the buffer.
4015
4016 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
4017 instance.
4018 @param Handle An EFI_HII_HANDLE that corresponds to the desired
4019 package list in the HII database to export or NULL
4020 to indicate all package lists should be exported.
4021 @param BufferSize On input, a pointer to the length of the buffer.
4022 On output, the length of the buffer that is
4023 required for the exported data.
4024 @param Buffer A pointer to a buffer that will contain the
4025 results of the export function.
4026
4027 @retval EFI_SUCCESS Package exported.
4028 @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
4029 Handle is too small to support the number of
4030 handles. HandleBufferLength is updated with a
4031 value that will enable the data to fit.
4032 @retval EFI_NOT_FOUND The specified Handle could not be found in the
4033 current database.
4034 @retval EFI_INVALID_PARAMETER BufferSize was NULL.
4035 @retval EFI_INVALID_PARAMETER The value referenced by BufferSize was not zero
4036 and Buffer was NULL.
4037
4038 **/
4039 EFI_STATUS
4040 EFIAPI
4041 HiiExportPackageLists (
4042 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
4043 IN EFI_HII_HANDLE Handle,
4044 IN OUT UINTN *BufferSize,
4045 OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
4046 )
4047 {
4048 LIST_ENTRY *Link;
4049 EFI_STATUS Status;
4050 HII_DATABASE_PRIVATE_DATA *Private;
4051 HII_DATABASE_RECORD *Node;
4052 UINTN UsedSize;
4053
4054 if (This == NULL || BufferSize == NULL) {
4055 return EFI_INVALID_PARAMETER;
4056 }
4057 if (*BufferSize > 0 && Buffer == NULL) {
4058 return EFI_INVALID_PARAMETER;
4059 }
4060 if ((Handle != NULL) && (!IsHiiHandleValid (Handle))) {
4061 return EFI_NOT_FOUND;
4062 }
4063
4064 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4065 UsedSize = 0;
4066
4067 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
4068 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4069 if (Handle == NULL) {
4070 //
4071 // Export all package lists in current hii database.
4072 //
4073 Status = ExportPackageList (
4074 Private,
4075 Node->Handle,
4076 (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList),
4077 &UsedSize,
4078 *BufferSize,
4079 (EFI_HII_PACKAGE_LIST_HEADER *)((UINT8 *) Buffer + UsedSize)
4080 );
4081 ASSERT_EFI_ERROR (Status);
4082 } else if (Handle != NULL && Node->Handle == Handle) {
4083 Status = ExportPackageList (
4084 Private,
4085 Handle,
4086 (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList),
4087 &UsedSize,
4088 *BufferSize,
4089 Buffer
4090 );
4091 ASSERT_EFI_ERROR (Status);
4092 if (*BufferSize < UsedSize) {
4093 *BufferSize = UsedSize;
4094 return EFI_BUFFER_TOO_SMALL;
4095 }
4096 return EFI_SUCCESS;
4097 }
4098 }
4099
4100 if (Handle == NULL && UsedSize != 0) {
4101 if (*BufferSize < UsedSize) {
4102 *BufferSize = UsedSize;
4103 return EFI_BUFFER_TOO_SMALL;
4104 }
4105 return EFI_SUCCESS;
4106 }
4107
4108 return EFI_NOT_FOUND;
4109 }
4110
4111
4112 /**
4113 This function registers a function which will be called when specified actions related to packages of
4114 the specified type occur in the HII database. By registering a function, other HII-related drivers are
4115 notified when specific package types are added, removed or updated in the HII database.
4116 Each driver or application which registers a notification should use
4117 EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before exiting.
4118
4119 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
4120 instance.
4121 @param PackageType Specifies the package type of the packages to list
4122 or EFI_HII_PACKAGE_TYPE_ALL for all packages to be
4123 listed.
4124 @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
4125 this is the pointer to the GUID which must match
4126 the Guid field of
4127 EFI_HII_GUID_PACKAGE_GUID_HDR. Otherwise, it must
4128 be NULL.
4129 @param PackageNotifyFn Points to the function to be called when the event
4130 specified by
4131 NotificationType occurs.
4132 @param NotifyType Describes the types of notification which this
4133 function will be receiving.
4134 @param NotifyHandle Points to the unique handle assigned to the
4135 registered notification. Can be used in
4136 EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify()
4137 to stop notifications.
4138
4139 @retval EFI_SUCCESS Notification registered successfully.
4140 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures
4141 @retval EFI_INVALID_PARAMETER NotifyHandle is NULL.
4142 @retval EFI_INVALID_PARAMETER PackageGuid is not NULL when PackageType is not
4143 EFI_HII_PACKAGE_TYPE_GUID.
4144 @retval EFI_INVALID_PARAMETER PackageGuid is NULL when PackageType is
4145 EFI_HII_PACKAGE_TYPE_GUID.
4146
4147 **/
4148 EFI_STATUS
4149 EFIAPI
4150 HiiRegisterPackageNotify (
4151 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
4152 IN UINT8 PackageType,
4153 IN CONST EFI_GUID *PackageGuid,
4154 IN CONST EFI_HII_DATABASE_NOTIFY PackageNotifyFn,
4155 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
4156 OUT EFI_HANDLE *NotifyHandle
4157 )
4158 {
4159 HII_DATABASE_PRIVATE_DATA *Private;
4160 HII_DATABASE_NOTIFY *Notify;
4161 EFI_STATUS Status;
4162
4163 if (This == NULL || NotifyHandle == NULL) {
4164 return EFI_INVALID_PARAMETER;
4165 }
4166 if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) ||
4167 (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL)) {
4168 return EFI_INVALID_PARAMETER;
4169 }
4170
4171 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4172
4173 //
4174 // Allocate a notification node
4175 //
4176 Notify = (HII_DATABASE_NOTIFY *) AllocateZeroPool (sizeof (HII_DATABASE_NOTIFY));
4177 if (Notify == NULL) {
4178 return EFI_OUT_OF_RESOURCES;
4179 }
4180
4181 //
4182 // Generate a notify handle
4183 //
4184 Status = gBS->InstallMultipleProtocolInterfaces (
4185 &Notify->NotifyHandle,
4186 &gEfiCallerIdGuid,
4187 NULL,
4188 NULL
4189 );
4190 ASSERT_EFI_ERROR (Status);
4191
4192 //
4193 // Fill in the information to the notification node
4194 //
4195 Notify->Signature = HII_DATABASE_NOTIFY_SIGNATURE;
4196 Notify->PackageType = PackageType;
4197 Notify->PackageGuid = (EFI_GUID *) PackageGuid;
4198 Notify->PackageNotifyFn = (EFI_HII_DATABASE_NOTIFY) PackageNotifyFn;
4199 Notify->NotifyType = NotifyType;
4200
4201 InsertTailList (&Private->DatabaseNotifyList, &Notify->DatabaseNotifyEntry);
4202 *NotifyHandle = Notify->NotifyHandle;
4203
4204 return EFI_SUCCESS;
4205 }
4206
4207
4208 /**
4209 Removes the specified HII database package-related notification.
4210
4211 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
4212 instance.
4213 @param NotificationHandle The handle of the notification function being
4214 unregistered.
4215
4216 @retval EFI_SUCCESS Notification is unregistered successfully.
4217 @retval EFI_INVALID_PARAMETER The Handle is invalid.
4218 @retval EFI_NOT_FOUND The incoming notification handle does not exist
4219 in current hii database.
4220
4221 **/
4222 EFI_STATUS
4223 EFIAPI
4224 HiiUnregisterPackageNotify (
4225 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
4226 IN EFI_HANDLE NotificationHandle
4227 )
4228 {
4229 HII_DATABASE_PRIVATE_DATA *Private;
4230 HII_DATABASE_NOTIFY *Notify;
4231 LIST_ENTRY *Link;
4232 EFI_STATUS Status;
4233
4234 if (This == NULL) {
4235 return EFI_INVALID_PARAMETER;
4236 }
4237
4238 if (NotificationHandle == NULL) {
4239 return EFI_NOT_FOUND;
4240 }
4241
4242 Status = gBS->OpenProtocol (
4243 NotificationHandle,
4244 &gEfiCallerIdGuid,
4245 NULL,
4246 NULL,
4247 NULL,
4248 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
4249 );
4250 if (EFI_ERROR (Status)) {
4251 return EFI_NOT_FOUND;
4252 }
4253
4254 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4255
4256 for (Link = Private->DatabaseNotifyList.ForwardLink; Link != &Private->DatabaseNotifyList; Link = Link->ForwardLink) {
4257 Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);
4258 if (Notify->NotifyHandle == NotificationHandle) {
4259 //
4260 // Remove the matching notification node
4261 //
4262 RemoveEntryList (&Notify->DatabaseNotifyEntry);
4263 Status = gBS->UninstallMultipleProtocolInterfaces (
4264 Notify->NotifyHandle,
4265 &gEfiCallerIdGuid,
4266 NULL,
4267 NULL
4268 );
4269 ASSERT_EFI_ERROR (Status);
4270 FreePool (Notify);
4271
4272 return EFI_SUCCESS;
4273 }
4274 }
4275
4276 return EFI_NOT_FOUND;
4277 }
4278
4279
4280 /**
4281 This routine retrieves an array of GUID values for each keyboard layout that
4282 was previously registered in the system.
4283
4284 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
4285 instance.
4286 @param KeyGuidBufferLength On input, a pointer to the length of the keyboard
4287 GUID buffer. On output, the length of the handle
4288 buffer that is required for the handles found.
4289 @param KeyGuidBuffer An array of keyboard layout GUID instances
4290 returned.
4291
4292 @retval EFI_SUCCESS KeyGuidBuffer was updated successfully.
4293 @retval EFI_BUFFER_TOO_SMALL The KeyGuidBufferLength parameter indicates
4294 that KeyGuidBuffer is too small to support the
4295 number of GUIDs. KeyGuidBufferLength is
4296 updated with a value that will enable the data to
4297 fit.
4298 @retval EFI_INVALID_PARAMETER The KeyGuidBufferLength is NULL.
4299 @retval EFI_INVALID_PARAMETER The value referenced by KeyGuidBufferLength is not
4300 zero and KeyGuidBuffer is NULL.
4301 @retval EFI_NOT_FOUND There was no keyboard layout.
4302
4303 **/
4304 EFI_STATUS
4305 EFIAPI
4306 HiiFindKeyboardLayouts (
4307 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
4308 IN OUT UINT16 *KeyGuidBufferLength,
4309 OUT EFI_GUID *KeyGuidBuffer
4310 )
4311 {
4312 HII_DATABASE_PRIVATE_DATA *Private;
4313 HII_DATABASE_RECORD *Node;
4314 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
4315 LIST_ENTRY *Link;
4316 LIST_ENTRY *Link1;
4317 UINT16 ResultSize;
4318 UINTN Index;
4319 UINT16 LayoutCount;
4320 UINT16 LayoutLength;
4321 UINT8 *Layout;
4322 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
4323
4324 if (This == NULL || KeyGuidBufferLength == NULL) {
4325 return EFI_INVALID_PARAMETER;
4326 }
4327
4328 if (*KeyGuidBufferLength > 0 && KeyGuidBuffer == NULL) {
4329 return EFI_INVALID_PARAMETER;
4330 }
4331
4332 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4333 ResultSize = 0;
4334
4335 //
4336 // Search all package lists in whole database to retrieve keyboard layout.
4337 //
4338 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
4339 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4340 PackageList = Node->PackageList;
4341 for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;
4342 Link1 != &PackageList->KeyboardLayoutHdr;
4343 Link1 = Link1->ForwardLink
4344 ) {
4345 //
4346 // Find out all Keyboard Layout packages in this package list.
4347 //
4348 Package = CR (
4349 Link1,
4350 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
4351 KeyboardEntry,
4352 HII_KB_LAYOUT_PACKAGE_SIGNATURE
4353 );
4354 Layout = (UINT8 *) Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);
4355 CopyMem (
4356 &LayoutCount,
4357 (UINT8 *) Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER),
4358 sizeof (UINT16)
4359 );
4360 for (Index = 0; Index < LayoutCount; Index++) {
4361 ResultSize += sizeof (EFI_GUID);
4362 if (ResultSize <= *KeyGuidBufferLength) {
4363 CopyMem (KeyGuidBuffer + (ResultSize / sizeof (EFI_GUID) - 1), Layout + sizeof (UINT16), sizeof (EFI_GUID));
4364 CopyMem (&LayoutLength, Layout, sizeof (UINT16));
4365 Layout = Layout + LayoutLength;
4366 }
4367 }
4368 }
4369 }
4370
4371 if (ResultSize == 0) {
4372 return EFI_NOT_FOUND;
4373 }
4374
4375 if (*KeyGuidBufferLength < ResultSize) {
4376 *KeyGuidBufferLength = ResultSize;
4377 return EFI_BUFFER_TOO_SMALL;
4378 }
4379
4380 *KeyGuidBufferLength = ResultSize;
4381 return EFI_SUCCESS;
4382 }
4383
4384
4385 /**
4386 This routine retrieves the requested keyboard layout. The layout is a physical description of the keys
4387 on a keyboard and the character(s) that are associated with a particular set of key strokes.
4388
4389 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
4390 instance.
4391 @param KeyGuid A pointer to the unique ID associated with a given
4392 keyboard layout. If KeyGuid is NULL then the
4393 current layout will be retrieved.
4394 @param KeyboardLayoutLength On input, a pointer to the length of the
4395 KeyboardLayout buffer. On output, the length of
4396 the data placed into KeyboardLayout.
4397 @param KeyboardLayout A pointer to a buffer containing the retrieved
4398 keyboard layout.
4399
4400 @retval EFI_SUCCESS The keyboard layout was retrieved successfully.
4401 @retval EFI_NOT_FOUND The requested keyboard layout was not found.
4402 @retval EFI_INVALID_PARAMETER The KeyboardLayout or KeyboardLayoutLength was
4403 NULL.
4404 @retval EFI_BUFFER_TOO_SMALL The KeyboardLayoutLength parameter indicates
4405 that KeyboardLayout is too small to support the
4406 requested keyboard layout. KeyboardLayoutLength is
4407 updated with a value that will enable the
4408 data to fit.
4409
4410 **/
4411 EFI_STATUS
4412 EFIAPI
4413 HiiGetKeyboardLayout (
4414 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
4415 IN CONST EFI_GUID *KeyGuid,
4416 IN OUT UINT16 *KeyboardLayoutLength,
4417 OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout
4418 )
4419 {
4420 HII_DATABASE_PRIVATE_DATA *Private;
4421 HII_DATABASE_RECORD *Node;
4422 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
4423 LIST_ENTRY *Link;
4424 LIST_ENTRY *Link1;
4425 UINTN Index;
4426 UINT8 *Layout;
4427 UINT16 LayoutCount;
4428 UINT16 LayoutLength;
4429 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
4430
4431 if (This == NULL || KeyboardLayoutLength == NULL) {
4432 return EFI_INVALID_PARAMETER;
4433 }
4434 if (*KeyboardLayoutLength > 0 && KeyboardLayout == NULL) {
4435 return EFI_INVALID_PARAMETER;
4436 }
4437
4438 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4439 //
4440 // Retrieve the current keyboard layout.
4441 //
4442 if (KeyGuid == NULL) {
4443 if (Private->CurrentLayout == NULL) {
4444 return EFI_NOT_FOUND;
4445 }
4446 CopyMem (&LayoutLength, Private->CurrentLayout, sizeof (UINT16));
4447 if (*KeyboardLayoutLength < LayoutLength) {
4448 *KeyboardLayoutLength = LayoutLength;
4449 return EFI_BUFFER_TOO_SMALL;
4450 }
4451 CopyMem (KeyboardLayout, Private->CurrentLayout, LayoutLength);
4452 return EFI_SUCCESS;
4453 }
4454
4455 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
4456 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4457 PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);
4458 for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;
4459 Link1 != &PackageList->KeyboardLayoutHdr;
4460 Link1 = Link1->ForwardLink
4461 ) {
4462 Package = CR (
4463 Link1,
4464 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
4465 KeyboardEntry,
4466 HII_KB_LAYOUT_PACKAGE_SIGNATURE
4467 );
4468
4469 Layout = (UINT8 *) Package->KeyboardPkg +
4470 sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);
4471 CopyMem (&LayoutCount, Layout - sizeof (UINT16), sizeof (UINT16));
4472 for (Index = 0; Index < LayoutCount; Index++) {
4473 CopyMem (&LayoutLength, Layout, sizeof (UINT16));
4474 if (CompareMem (Layout + sizeof (UINT16), KeyGuid, sizeof (EFI_GUID)) == 0) {
4475 if (LayoutLength <= *KeyboardLayoutLength) {
4476 CopyMem (KeyboardLayout, Layout, LayoutLength);
4477 return EFI_SUCCESS;
4478 } else {
4479 *KeyboardLayoutLength = LayoutLength;
4480 return EFI_BUFFER_TOO_SMALL;
4481 }
4482 }
4483 Layout = Layout + LayoutLength;
4484 }
4485 }
4486 }
4487
4488 return EFI_NOT_FOUND;
4489 }
4490
4491
4492 /**
4493 This routine sets the default keyboard layout to the one referenced by KeyGuid. When this routine
4494 is called, an event will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
4495 group type. This is so that agents which are sensitive to the current keyboard layout being changed
4496 can be notified of this change.
4497
4498 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
4499 instance.
4500 @param KeyGuid A pointer to the unique ID associated with a given
4501 keyboard layout.
4502
4503 @retval EFI_SUCCESS The current keyboard layout was successfully set.
4504 @retval EFI_NOT_FOUND The referenced keyboard layout was not found, so
4505 action was taken.
4506 @retval EFI_INVALID_PARAMETER The KeyGuid was NULL.
4507
4508 **/
4509 EFI_STATUS
4510 EFIAPI
4511 HiiSetKeyboardLayout (
4512 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
4513 IN CONST EFI_GUID *KeyGuid
4514 )
4515 {
4516 HII_DATABASE_PRIVATE_DATA *Private;
4517 EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
4518 UINT16 KeyboardLayoutLength;
4519 EFI_STATUS Status;
4520
4521 if (This == NULL || KeyGuid == NULL) {
4522 return EFI_INVALID_PARAMETER;
4523 }
4524
4525 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4526
4527 //
4528 // The specified GUID equals the current keyboard layout GUID,
4529 // return directly.
4530 //
4531 if (CompareGuid (&Private->CurrentLayoutGuid, KeyGuid)) {
4532 return EFI_SUCCESS;
4533 }
4534
4535 //
4536 // Try to find the incoming keyboard layout data in current database.
4537 //
4538 KeyboardLayoutLength = 0;
4539 KeyboardLayout = NULL;
4540 Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);
4541 if (Status != EFI_BUFFER_TOO_SMALL) {
4542 return Status;
4543 }
4544
4545 KeyboardLayout = (EFI_HII_KEYBOARD_LAYOUT *) AllocateZeroPool (KeyboardLayoutLength);
4546 ASSERT (KeyboardLayout != NULL);
4547 Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);
4548 ASSERT_EFI_ERROR (Status);
4549
4550 //
4551 // Backup current keyboard layout.
4552 //
4553 CopyMem (&Private->CurrentLayoutGuid, KeyGuid, sizeof (EFI_GUID));
4554 if (Private->CurrentLayout != NULL) {
4555 FreePool(Private->CurrentLayout);
4556 }
4557 Private->CurrentLayout = KeyboardLayout;
4558
4559 //
4560 // Signal EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group to notify
4561 // current keyboard layout is changed.
4562 //
4563 Status = gBS->SignalEvent (gHiiKeyboardLayoutChanged);
4564 ASSERT_EFI_ERROR (Status);
4565
4566 return EFI_SUCCESS;
4567 }
4568
4569
4570 /**
4571 Return the EFI handle associated with a package list.
4572
4573 @param This A pointer to the EFI_HII_DATABASE_PROTOCOL
4574 instance.
4575 @param PackageListHandle An EFI_HII_HANDLE that corresponds to the desired
4576 package list in the HIIdatabase.
4577 @param DriverHandle On return, contains the EFI_HANDLE which was
4578 registered with the package list in
4579 NewPackageList().
4580
4581 @retval EFI_SUCCESS The DriverHandle was returned successfully.
4582 @retval EFI_INVALID_PARAMETER The PackageListHandle was not valid or
4583 DriverHandle was NULL.
4584 @retval EFI_NOT_FOUND This PackageList handle can not be found in
4585 current database.
4586
4587 **/
4588 EFI_STATUS
4589 EFIAPI
4590 HiiGetPackageListHandle (
4591 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
4592 IN EFI_HII_HANDLE PackageListHandle,
4593 OUT EFI_HANDLE *DriverHandle
4594 )
4595 {
4596 HII_DATABASE_PRIVATE_DATA *Private;
4597 HII_DATABASE_RECORD *Node;
4598 LIST_ENTRY *Link;
4599
4600 if (This == NULL || DriverHandle == NULL) {
4601 return EFI_INVALID_PARAMETER;
4602 }
4603
4604 if (!IsHiiHandleValid (PackageListHandle)) {
4605 return EFI_INVALID_PARAMETER;
4606 }
4607
4608 Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
4609
4610 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
4611 Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
4612 if (Node->Handle == PackageListHandle) {
4613 *DriverHandle = Node->DriverHandle;
4614 return EFI_SUCCESS;
4615 }
4616 }
4617
4618 return EFI_NOT_FOUND;
4619 }
4620