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