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