MdeModulePkg HiiDataBase: Fix the potential NULL pointer reference
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / Database.c
1 /** @file
2 Implementation for EFI_HII_DATABASE_PROTOCOL.
3
4 Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15
16 #include "HiiDatabase.h"
17
18 #define BASE_NUMBER 10
19
20 EFI_HII_PACKAGE_LIST_HEADER *gRTDatabaseInfoBuffer = NULL;
21 EFI_STRING gRTConfigRespBuffer = NULL;
22 UINTN gDatabaseInfoSize = 0;
23 UINTN gConfigRespSize = 0;
24 BOOLEAN gExportConfigResp = TRUE;
25 UINTN gNvDefaultStoreSize = 0;
26 SKU_ID gSkuId = 0xFFFFFFFFFFFFFFFF;
27 LIST_ENTRY gVarStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gVarStorageList);
28
29 /**
30 This function generates a HII_DATABASE_RECORD node and adds into hii database.
31 This is a internal function.
32
33 @param Private hii database private structure
34 @param DatabaseNode HII_DATABASE_RECORD node which is used to store a
35 package list
36
37 @retval EFI_SUCCESS A database record is generated successfully.
38 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
39 database contents.
40 @retval EFI_INVALID_PARAMETER Private is NULL or DatabaseRecord is NULL.
41
42 **/
43 EFI_STATUS
44 GenerateHiiDatabaseRecord (
45 IN HII_DATABASE_PRIVATE_DATA *Private,
46 OUT HII_DATABASE_RECORD **DatabaseNode
47 )
48 {
49 HII_DATABASE_RECORD *DatabaseRecord;
50 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
51 HII_HANDLE *HiiHandle;
52
53 if (Private == NULL || DatabaseNode == NULL) {
54 return EFI_INVALID_PARAMETER;
55 }
56
57 DatabaseRecord = (HII_DATABASE_RECORD *) AllocateZeroPool (sizeof (HII_DATABASE_RECORD));
58 if (DatabaseRecord == NULL) {
59 return EFI_OUT_OF_RESOURCES;
60 }
61 DatabaseRecord->Signature = HII_DATABASE_RECORD_SIGNATURE;
62
63 DatabaseRecord->PackageList = AllocateZeroPool (sizeof (HII_DATABASE_PACKAGE_LIST_INSTANCE));
64 if (DatabaseRecord->PackageList == NULL) {
65 FreePool (DatabaseRecord);
66 return EFI_OUT_OF_RESOURCES;
67 }
68
69 PackageList = DatabaseRecord->PackageList;
70
71 InitializeListHead (&PackageList->GuidPkgHdr);
72 InitializeListHead (&PackageList->FormPkgHdr);
73 InitializeListHead (&PackageList->KeyboardLayoutHdr);
74 InitializeListHead (&PackageList->StringPkgHdr);
75 InitializeListHead (&PackageList->FontPkgHdr);
76 InitializeListHead (&PackageList->SimpleFontPkgHdr);
77 PackageList->ImagePkg = NULL;
78 PackageList->DevicePathPkg = NULL;
79
80 //
81 // Create a new hii handle
82 //
83 HiiHandle = (HII_HANDLE *) AllocateZeroPool (sizeof (HII_HANDLE));
84 if (HiiHandle == NULL) {
85 FreePool (DatabaseRecord->PackageList);
86 FreePool (DatabaseRecord);
87 return EFI_OUT_OF_RESOURCES;
88 }
89 HiiHandle->Signature = HII_HANDLE_SIGNATURE;
90 //
91 // Backup the number of Hii handles
92 //
93 Private->HiiHandleCount++;
94 HiiHandle->Key = (UINTN) Private->HiiHandleCount;
95 //
96 // Insert the handle to hii handle list of the whole database.
97 //
98 InsertTailList (&Private->HiiHandleList, &HiiHandle->Handle);
99
100 DatabaseRecord->Handle = (EFI_HII_HANDLE) HiiHandle;
101
102 //
103 // Insert the Package List node to Package List link of the whole database.
104 //
105 InsertTailList (&Private->DatabaseList, &DatabaseRecord->DatabaseEntry);
106
107 *DatabaseNode = DatabaseRecord;
108
109 return EFI_SUCCESS;
110
111 }
112
113
114 /**
115 This function checks whether a handle is a valid EFI_HII_HANDLE
116 This is a internal function.
117
118 @param Handle Pointer to a EFI_HII_HANDLE
119
120 @retval TRUE Valid
121 @retval FALSE Invalid
122
123 **/
124 BOOLEAN
125 IsHiiHandleValid (
126 EFI_HII_HANDLE Handle
127 )
128 {
129 HII_HANDLE *HiiHandle;
130
131 HiiHandle = (HII_HANDLE *) Handle;
132
133 if (HiiHandle == NULL) {
134 return FALSE;
135 }
136
137 if (HiiHandle->Signature != HII_HANDLE_SIGNATURE) {
138 return FALSE;
139 }
140
141 return TRUE;
142 }
143
144
145 /**
146 This function invokes the matching registered function.
147 This is a internal function.
148
149 @param Private HII Database driver private structure.
150 @param NotifyType The type of change concerning the database.
151 @param PackageInstance Points to the package referred to by the
152 notification.
153 @param PackageType Package type
154 @param Handle The handle of the package list which contains the
155 specified package.
156
157 @retval EFI_SUCCESS Already checked all registered function and
158 invoked if matched.
159 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
160
161 **/
162 EFI_STATUS
163 InvokeRegisteredFunction (
164 IN HII_DATABASE_PRIVATE_DATA *Private,
165 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
166 IN VOID *PackageInstance,
167 IN UINT8 PackageType,
168 IN EFI_HII_HANDLE Handle
169 )
170 {
171 HII_DATABASE_NOTIFY *Notify;
172 LIST_ENTRY *Link;
173 EFI_HII_PACKAGE_HEADER *Package;
174 UINT8 *Buffer;
175 UINT32 BufferSize;
176 UINT32 HeaderSize;
177 UINT32 ImageBlockSize;
178 UINT32 PaletteInfoSize;
179
180 if (Private == NULL || (NotifyType & 0xF) == 0 || PackageInstance == NULL) {
181 return EFI_INVALID_PARAMETER;
182 }
183 if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
184 return EFI_INVALID_PARAMETER;
185 }
186 if (!IsHiiHandleValid (Handle)) {
187 return EFI_INVALID_PARAMETER;
188 }
189
190 Buffer = NULL;
191 Package = NULL;
192
193 //
194 // Convert the incoming package from hii database storage format to UEFI
195 // storage format. e.g. HII_GUID_PACKAGE_INSTANCE to EFI_HII_GUID_PACKAGE_HDR.
196 //
197 switch (PackageType) {
198 case EFI_HII_PACKAGE_TYPE_GUID:
199 Package = (EFI_HII_PACKAGE_HEADER *) (((HII_GUID_PACKAGE_INSTANCE *) PackageInstance)->GuidPkg);
200 break;
201
202 case EFI_HII_PACKAGE_FORMS:
203 BufferSize = ((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->FormPkgHdr.Length;
204 Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
205 ASSERT (Buffer != NULL);
206 CopyMem (
207 Buffer,
208 &((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->FormPkgHdr,
209 sizeof (EFI_HII_PACKAGE_HEADER)
210 );
211 CopyMem (
212 Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
213 ((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->IfrData,
214 BufferSize - sizeof (EFI_HII_PACKAGE_HEADER)
215 );
216 Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
217 break;
218
219 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
220 Package = (EFI_HII_PACKAGE_HEADER *) (((HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *) PackageInstance)->KeyboardPkg);
221 break;
222
223 case EFI_HII_PACKAGE_STRINGS:
224 BufferSize = ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr->Header.Length;
225 HeaderSize = ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr->HdrSize;
226 Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
227 ASSERT (Buffer != NULL);
228 CopyMem (
229 Buffer,
230 ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr,
231 HeaderSize
232 );
233 CopyMem (
234 Buffer + HeaderSize,
235 ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringBlock,
236 BufferSize - HeaderSize
237 );
238 Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
239 break;
240
241 case EFI_HII_PACKAGE_FONTS:
242 BufferSize = ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr->Header.Length;
243 HeaderSize = ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr->HdrSize;
244 Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
245 ASSERT (Buffer != NULL);
246 CopyMem (
247 Buffer,
248 ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr,
249 HeaderSize
250 );
251 CopyMem (
252 Buffer + HeaderSize,
253 ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->GlyphBlock,
254 BufferSize - HeaderSize
255 );
256 Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
257 break;
258
259 case EFI_HII_PACKAGE_IMAGES:
260 BufferSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImagePkgHdr.Header.Length;
261 HeaderSize = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
262 Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
263 ASSERT (Buffer != NULL);
264
265 CopyMem (
266 Buffer,
267 &((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImagePkgHdr,
268 HeaderSize
269 );
270 CopyMem (
271 Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
272 &HeaderSize,
273 sizeof (UINT32)
274 );
275
276 ImageBlockSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImageBlockSize;
277 if (ImageBlockSize != 0) {
278 CopyMem (
279 Buffer + HeaderSize,
280 ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImageBlock,
281 ImageBlockSize
282 );
283 }
284
285 PaletteInfoSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->PaletteInfoSize;
286 if (PaletteInfoSize != 0) {
287 CopyMem (
288 Buffer + HeaderSize + ImageBlockSize,
289 ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->PaletteBlock,
290 PaletteInfoSize
291 );
292 HeaderSize += ImageBlockSize;
293 CopyMem (
294 Buffer + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT32),
295 &HeaderSize,
296 sizeof (UINT32)
297 );
298 }
299 Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
300 break;
301
302 case EFI_HII_PACKAGE_SIMPLE_FONTS:
303 BufferSize = ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *) PackageInstance)->SimpleFontPkgHdr->Header.Length;
304 Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
305 ASSERT (Buffer != NULL);
306 CopyMem (
307 Buffer,
308 ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *) PackageInstance)->SimpleFontPkgHdr,
309 BufferSize
310 );
311 Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
312 break;
313
314 case EFI_HII_PACKAGE_DEVICE_PATH:
315 Package = (EFI_HII_PACKAGE_HEADER *) PackageInstance;
316 break;
317
318 default:
319 return EFI_INVALID_PARAMETER;
320 }
321
322 for (Link = Private->DatabaseNotifyList.ForwardLink;
323 Link != &Private->DatabaseNotifyList;
324 Link = Link->ForwardLink
325 ) {
326 Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);
327 if (Notify->NotifyType == NotifyType && Notify->PackageType == PackageType) {
328 //
329 // Check in case PackageGuid is not NULL when Package is GUID package
330 //
331 if (PackageType != EFI_HII_PACKAGE_TYPE_GUID) {
332 Notify->PackageGuid = NULL;
333 }
334 //
335 // Status of Registered Function is unknown so did not check it
336 //
337 Notify->PackageNotifyFn (
338 Notify->PackageType,
339 Notify->PackageGuid,
340 Package,
341 Handle,
342 NotifyType
343 );
344 }
345 }
346
347 if (Buffer != NULL) {
348 FreePool (Buffer);
349 }
350
351 return EFI_SUCCESS;
352 }
353
354
355 /**
356 This function insert a GUID package to a package list node.
357 This is a internal function.
358
359 @param PackageHdr Pointer to a buffer stored with GUID package
360 information.
361 @param NotifyType The type of change concerning the database.
362 @param PackageList Pointer to a package list which will be inserted
363 to.
364 @param Package Created GUID package
365
366 @retval EFI_SUCCESS Guid Package is inserted successfully.
367 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
368 Guid package.
369 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
370
371 **/
372 EFI_STATUS
373 InsertGuidPackage (
374 IN VOID *PackageHdr,
375 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
376 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
377 OUT HII_GUID_PACKAGE_INSTANCE **Package
378 )
379 {
380 HII_GUID_PACKAGE_INSTANCE *GuidPackage;
381 EFI_HII_PACKAGE_HEADER PackageHeader;
382
383 if (PackageHdr == NULL || PackageList == NULL) {
384 return EFI_INVALID_PARAMETER;
385 }
386
387 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
388
389 //
390 // Create a GUID package node
391 //
392 GuidPackage = (HII_GUID_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_GUID_PACKAGE_INSTANCE));
393 if (GuidPackage == NULL) {
394 return EFI_OUT_OF_RESOURCES;
395 }
396 GuidPackage->GuidPkg = (UINT8 *) AllocateZeroPool (PackageHeader.Length);
397 if (GuidPackage->GuidPkg == NULL) {
398 FreePool (GuidPackage);
399 return EFI_OUT_OF_RESOURCES;
400 }
401
402 GuidPackage->Signature = HII_GUID_PACKAGE_SIGNATURE;
403 CopyMem (GuidPackage->GuidPkg, PackageHdr, PackageHeader.Length);
404 InsertTailList (&PackageList->GuidPkgHdr, &GuidPackage->GuidEntry);
405 *Package = GuidPackage;
406
407 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
408 PackageList->PackageListHdr.PackageLength += PackageHeader.Length;
409 }
410
411 return EFI_SUCCESS;
412 }
413
414
415 /**
416 This function exports GUID packages to a buffer.
417 This is a internal function.
418
419 @param Private Hii database private structure.
420 @param Handle Identification of a package list.
421 @param PackageList Pointer to a package list which will be exported.
422 @param UsedSize The length of buffer be used.
423 @param BufferSize Length of the Buffer.
424 @param Buffer Allocated space for storing exported data.
425 @param ResultSize The size of the already exported content of this
426 package list.
427
428 @retval EFI_SUCCESS Guid Packages are exported successfully.
429 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
430
431 **/
432 EFI_STATUS
433 ExportGuidPackages (
434 IN HII_DATABASE_PRIVATE_DATA *Private,
435 IN EFI_HII_HANDLE Handle,
436 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
437 IN UINTN UsedSize,
438 IN UINTN BufferSize,
439 IN OUT VOID *Buffer,
440 IN OUT UINTN *ResultSize
441 )
442 {
443 HII_GUID_PACKAGE_INSTANCE *GuidPackage;
444 LIST_ENTRY *Link;
445 UINTN PackageLength;
446 EFI_HII_PACKAGE_HEADER PackageHeader;
447 EFI_STATUS Status;
448
449 if (PackageList == NULL || ResultSize == NULL) {
450 return EFI_INVALID_PARAMETER;
451 }
452
453 if (BufferSize > 0 && Buffer == NULL ) {
454 return EFI_INVALID_PARAMETER;
455 }
456
457 PackageLength = 0;
458 Status = EFI_SUCCESS;
459
460 for (Link = PackageList->GuidPkgHdr.ForwardLink; Link != &PackageList->GuidPkgHdr; Link = Link->ForwardLink) {
461 GuidPackage = CR (Link, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);
462 CopyMem (&PackageHeader, GuidPackage->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));
463 PackageLength += PackageHeader.Length;
464 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
465 Status = InvokeRegisteredFunction (
466 Private,
467 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
468 (VOID *) GuidPackage,
469 EFI_HII_PACKAGE_TYPE_GUID,
470 Handle
471 );
472 ASSERT_EFI_ERROR (Status);
473 CopyMem (Buffer, GuidPackage->GuidPkg, PackageHeader.Length);
474 Buffer = (UINT8 *) Buffer + PackageHeader.Length;
475 }
476 }
477
478 *ResultSize += PackageLength;
479 return EFI_SUCCESS;
480 }
481
482
483 /**
484 This function deletes all GUID packages from a package list node.
485 This is a internal function.
486
487 @param Private Hii database private data.
488 @param Handle Handle of the package list which contains the to
489 be removed GUID packages.
490 @param PackageList Pointer to a package list that contains removing
491 packages.
492
493 @retval EFI_SUCCESS GUID Package(s) is deleted successfully.
494 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
495
496 **/
497 EFI_STATUS
498 RemoveGuidPackages (
499 IN HII_DATABASE_PRIVATE_DATA *Private,
500 IN EFI_HII_HANDLE Handle,
501 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
502 )
503 {
504 LIST_ENTRY *ListHead;
505 HII_GUID_PACKAGE_INSTANCE *Package;
506 EFI_STATUS Status;
507 EFI_HII_PACKAGE_HEADER PackageHeader;
508
509 ListHead = &PackageList->GuidPkgHdr;
510
511 while (!IsListEmpty (ListHead)) {
512 Package = CR (
513 ListHead->ForwardLink,
514 HII_GUID_PACKAGE_INSTANCE,
515 GuidEntry,
516 HII_GUID_PACKAGE_SIGNATURE
517 );
518 Status = InvokeRegisteredFunction (
519 Private,
520 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
521 (VOID *) Package,
522 EFI_HII_PACKAGE_TYPE_GUID,
523 Handle
524 );
525 if (EFI_ERROR (Status)) {
526 return Status;
527 }
528
529 RemoveEntryList (&Package->GuidEntry);
530 CopyMem (&PackageHeader, Package->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));
531 PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;
532 FreePool (Package->GuidPkg);
533 FreePool (Package);
534 }
535
536 return EFI_SUCCESS;
537 }
538
539 /**
540 Check the input question related to EFI variable
541
542 @param IfrQuestionHdr Point to Question header
543 @param EfiVarStoreList Point to EFI VarStore List
544 @param EfiVarStoreNumber The number of EFI VarStore
545
546 @retval Index The index of the found EFI varstore in EFI varstore list
547 EfiVarStoreNumber will return if no EFI varstore is found.
548 **/
549 UINTN
550 IsEfiVarStoreQuestion (
551 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,
552 EFI_IFR_VARSTORE_EFI **EfiVarStoreList,
553 UINTN EfiVarStoreNumber
554 )
555 {
556 UINTN Index;
557 for (Index = 0; Index < EfiVarStoreNumber; Index ++) {
558 if (IfrQuestionHdr->VarStoreId == EfiVarStoreList[Index]->VarStoreId) {
559 return Index;
560 }
561 }
562
563 return EfiVarStoreNumber;
564 }
565
566 /**
567 Find the matched variable from the input variable storage.
568
569 @param[in] VariableStorage Point to the variable storage header.
570 @param[in] VarGuid A unique identifier for the variable.
571 @param[in] VarAttribute The attributes bitmask for the variable.
572 @param[in] VarName A Null-terminated ascii string that is the name of the variable.
573
574 @return Pointer to the matched variable header or NULL if not found.
575 **/
576 VARIABLE_HEADER *
577 FindVariableData (
578 IN VARIABLE_STORE_HEADER *VariableStorage,
579 IN EFI_GUID *VarGuid,
580 IN UINT32 VarAttribute,
581 IN CHAR16 *VarName
582 )
583 {
584 VARIABLE_HEADER *VariableHeader;
585 VARIABLE_HEADER *VariableEnd;
586
587 VariableEnd = (VARIABLE_HEADER *) ((UINT8 *) VariableStorage + VariableStorage->Size);
588 VariableHeader = (VARIABLE_HEADER *) (VariableStorage + 1);
589 VariableHeader = (VARIABLE_HEADER *) HEADER_ALIGN (VariableHeader);
590 while (VariableHeader < VariableEnd) {
591 if (CompareGuid (&VariableHeader->VendorGuid, VarGuid) &&
592 VariableHeader->Attributes == VarAttribute &&
593 StrCmp (VarName, (CHAR16 *) (VariableHeader + 1)) == 0) {
594 return VariableHeader;
595 }
596 VariableHeader = (VARIABLE_HEADER *) ((UINT8 *) VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + VariableHeader->DataSize);
597 VariableHeader = (VARIABLE_HEADER *) HEADER_ALIGN (VariableHeader);
598 }
599
600 return NULL;
601 }
602
603 /**
604 Find question default value from PcdNvStoreDefaultValueBuffer
605
606 @param DefaultId Default store ID
607 @param EfiVarStore Point to EFI VarStore header
608 @param IfrQuestionHdr Point to Question header
609 @param ValueBuffer Point to Buffer includes the found default setting
610 @param Width Width of the default value
611 @param BitFieldQuestion Whether the Question is stored in Bit field.
612
613 @retval EFI_SUCCESS Question default value is found.
614 @retval EFI_NOT_FOUND Question default value is not found.
615 **/
616 EFI_STATUS
617 FindQuestionDefaultSetting (
618 IN UINT16 DefaultId,
619 IN EFI_IFR_VARSTORE_EFI *EfiVarStore,
620 IN EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,
621 OUT VOID *ValueBuffer,
622 IN UINTN Width,
623 IN BOOLEAN BitFieldQuestion
624 )
625 {
626 VARIABLE_HEADER *VariableHeader;
627 VARIABLE_STORE_HEADER *VariableStorage;
628 LIST_ENTRY *Link;
629 VARSTORAGE_DEFAULT_DATA *Entry;
630 VARIABLE_STORE_HEADER *NvStoreBuffer;
631 UINT8 *DataBuffer;
632 UINT8 *BufferEnd;
633 BOOLEAN IsFound;
634 UINTN Index;
635 UINT32 BufferValue;
636 UINT32 BitFieldVal;
637 UINTN BitOffset;
638 UINTN ByteOffset;
639 UINTN BitWidth;
640 UINTN StartBit;
641 UINTN EndBit;
642 PCD_DEFAULT_DATA *DataHeader;
643 PCD_DEFAULT_INFO *DefaultInfo;
644 PCD_DATA_DELTA *DeltaData;
645
646 if (gSkuId == 0xFFFFFFFFFFFFFFFF) {
647 gSkuId = LibPcdGetSku ();
648 }
649
650 //
651 // Find the DefaultId setting from the full DefaultSetting
652 //
653 VariableStorage = NULL;
654 Link = gVarStorageList.ForwardLink;
655 while (Link != &gVarStorageList) {
656 Entry = BASE_CR (Link, VARSTORAGE_DEFAULT_DATA, Entry);
657 if (Entry->DefaultId == DefaultId) {
658 VariableStorage = Entry->VariableStorage;
659 break;
660 }
661 Link = Link->ForwardLink;
662 }
663
664 if (Link == &gVarStorageList) {
665 DataBuffer = (UINT8 *) PcdGetPtr (PcdNvStoreDefaultValueBuffer);
666 gNvDefaultStoreSize = ((PCD_NV_STORE_DEFAULT_BUFFER_HEADER *)DataBuffer)->Length;
667 //
668 // The first section data includes NV storage default setting.
669 //
670 DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER));
671 NvStoreBuffer = (VARIABLE_STORE_HEADER *) ((UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize);
672 VariableStorage = AllocatePool (NvStoreBuffer->Size);
673 ASSERT (VariableStorage != NULL);
674 CopyMem (VariableStorage, NvStoreBuffer, NvStoreBuffer->Size);
675
676 //
677 // Find the matched SkuId and DefaultId in the first section
678 //
679 IsFound = FALSE;
680 DefaultInfo = &(DataHeader->DefaultInfo[0]);
681 BufferEnd = (UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;
682 while ((UINT8 *) DefaultInfo < BufferEnd) {
683 if (DefaultInfo->DefaultId == DefaultId && DefaultInfo->SkuId == gSkuId) {
684 IsFound = TRUE;
685 break;
686 }
687 DefaultInfo ++;
688 }
689 //
690 // Find the matched SkuId and DefaultId in the remaining section
691 //
692 Index = sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER) + ((DataHeader->DataSize + 7) & (~7));
693 DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + Index);
694 while (!IsFound && Index < gNvDefaultStoreSize && DataHeader->DataSize != 0xFFFF) {
695 DefaultInfo = &(DataHeader->DefaultInfo[0]);
696 BufferEnd = (UINT8 *) DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;
697 while ((UINT8 *) DefaultInfo < BufferEnd) {
698 if (DefaultInfo->DefaultId == DefaultId && DefaultInfo->SkuId == gSkuId) {
699 IsFound = TRUE;
700 break;
701 }
702 DefaultInfo ++;
703 }
704 if (IsFound) {
705 DeltaData = (PCD_DATA_DELTA *) BufferEnd;
706 BufferEnd = (UINT8 *) DataHeader + DataHeader->DataSize;
707 while ((UINT8 *) DeltaData < BufferEnd) {
708 *((UINT8 *) VariableStorage + DeltaData->Offset) = (UINT8) DeltaData->Value;
709 DeltaData ++;
710 }
711 break;
712 }
713 Index = (Index + DataHeader->DataSize + 7) & (~7);
714 DataHeader = (PCD_DEFAULT_DATA *) (DataBuffer + Index);
715 }
716 //
717 // Cache the found result in VarStorageList
718 //
719 if (!IsFound) {
720 FreePool (VariableStorage);
721 VariableStorage = NULL;
722 }
723 Entry = AllocatePool (sizeof (VARSTORAGE_DEFAULT_DATA));
724 Entry->DefaultId = DefaultId;
725 Entry->VariableStorage = VariableStorage;
726 InsertTailList (&gVarStorageList, &Entry->Entry);
727 }
728 //
729 // The matched variable storage is not found.
730 //
731 if (VariableStorage == NULL) {
732 return EFI_NOT_FOUND;
733 }
734
735 //
736 // Find the question default value from the variable storage
737 //
738 VariableHeader = FindVariableData (VariableStorage, &EfiVarStore->Guid, EfiVarStore->Attributes, (CHAR16 *) EfiVarStore->Name);
739 if (VariableHeader == NULL) {
740 return EFI_NOT_FOUND;
741 }
742 StartBit = 0;
743 EndBit = 0;
744 ByteOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
745 if (BitFieldQuestion) {
746 BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
747 ByteOffset = BitOffset / 8;
748 BitWidth = Width;
749 StartBit = BitOffset % 8;
750 EndBit = StartBit + BitWidth - 1;
751 Width = EndBit / 8 + 1;
752 }
753 if (VariableHeader->DataSize < ByteOffset + Width) {
754 return EFI_INVALID_PARAMETER;
755 }
756
757 //
758 // Copy the question value
759 //
760 if (ValueBuffer != NULL) {
761 if (BitFieldQuestion) {
762 CopyMem (&BufferValue, (UINT8 *) VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + ByteOffset, Width);
763 BitFieldVal = BitFieldRead32 (BufferValue, StartBit, EndBit);
764 CopyMem (ValueBuffer, &BitFieldVal, Width);
765 } else {
766 CopyMem (ValueBuffer, (UINT8 *) VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + IfrQuestionHdr->VarStoreInfo.VarOffset, Width);
767 }
768 }
769
770 return EFI_SUCCESS;
771 }
772
773 /**
774 Update IFR default setting in Form Package.
775
776 @param FormPackage Form Package to be updated
777
778 **/
779 VOID
780 UpdateDefaultSettingInFormPackage (
781 HII_IFR_PACKAGE_INSTANCE *FormPackage
782 )
783 {
784 UINTN IfrOffset;
785 UINTN PackageLength;
786 EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
787 EFI_IFR_OP_HEADER *IfrOpHdr;
788 EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
789 UINT8 IfrQuestionType;
790 UINT8 IfrScope;
791 EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
792 EFI_IFR_VARSTORE_EFI **EfiVarStoreList;
793 UINTN EfiVarStoreMaxNum;
794 UINTN EfiVarStoreNumber;
795 UINT16 *DefaultIdList;
796 UINTN DefaultIdNumber;
797 UINTN DefaultIdMaxNum;
798 UINTN Index;
799 UINTN EfiVarStoreIndex;
800 EFI_IFR_TYPE_VALUE IfrValue;
801 EFI_IFR_TYPE_VALUE IfrManufactValue;
802 BOOLEAN StandardDefaultIsSet;
803 BOOLEAN ManufactDefaultIsSet;
804 EFI_IFR_CHECKBOX *IfrCheckBox;
805 EFI_STATUS Status;
806 EFI_IFR_DEFAULT *IfrDefault;
807 UINTN Width;
808 EFI_IFR_QUESTION_HEADER VarStoreQuestionHeader;
809 BOOLEAN QuestionReferBitField;
810
811 //
812 // If no default setting, do nothing
813 //
814 if (gNvDefaultStoreSize == 0) {
815 gNvDefaultStoreSize = PcdGetSize (PcdNvStoreDefaultValueBuffer);
816 }
817 if (gNvDefaultStoreSize < sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {
818 return;
819 }
820
821 ZeroMem (&VarStoreQuestionHeader, sizeof (VarStoreQuestionHeader));
822 PackageLength = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
823 Width = 0;
824 IfrOffset = 0;
825 IfrScope = 0;
826 IfrOpHdr = (EFI_IFR_OP_HEADER *) FormPackage->IfrData;
827 IfrQuestionHdr = NULL;
828 IfrQuestionType = 0;
829 EfiVarStoreMaxNum = 0;
830 EfiVarStoreNumber = 0;
831 DefaultIdMaxNum = 0;
832 DefaultIdNumber = 0;
833 EfiVarStoreList = NULL;
834 DefaultIdList = NULL;
835 StandardDefaultIsSet = FALSE;
836 ManufactDefaultIsSet = FALSE;
837 QuestionReferBitField = FALSE;
838
839 while (IfrOffset < PackageLength) {
840 switch (IfrOpHdr->OpCode) {
841 case EFI_IFR_VARSTORE_EFI_OP:
842 if (EfiVarStoreNumber >= EfiVarStoreMaxNum) {
843 //
844 // Reallocate EFI VarStore Buffer
845 //
846 EfiVarStoreList = ReallocatePool (EfiVarStoreMaxNum * sizeof (UINTN), (EfiVarStoreMaxNum + BASE_NUMBER) * sizeof (UINTN), EfiVarStoreList);
847 if (EfiVarStoreList == NULL) {
848 goto Done;
849 }
850 EfiVarStoreMaxNum = EfiVarStoreMaxNum + BASE_NUMBER;
851 }
852 IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
853 //
854 // Convert VarStore Name from ASCII string to Unicode string.
855 //
856 EfiVarStoreList [EfiVarStoreNumber] = AllocatePool (IfrEfiVarStore->Header.Length + AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name));
857 if (EfiVarStoreList [EfiVarStoreNumber] == NULL) {
858 break;
859 }
860 CopyMem (EfiVarStoreList [EfiVarStoreNumber], IfrEfiVarStore, IfrEfiVarStore->Header.Length);
861 AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, (CHAR16 *) &(EfiVarStoreList [EfiVarStoreNumber]->Name[0]), AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
862 Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_STANDARD, EfiVarStoreList[EfiVarStoreNumber], &VarStoreQuestionHeader, NULL, IfrEfiVarStore->Size, FALSE);
863 if (!EFI_ERROR (Status)) {
864 EfiVarStoreNumber ++;
865 } else {
866 FreePool (EfiVarStoreList [EfiVarStoreNumber]);
867 EfiVarStoreList [EfiVarStoreNumber] = NULL;
868 }
869 break;
870 case EFI_IFR_DEFAULTSTORE_OP:
871 if (DefaultIdNumber >= DefaultIdMaxNum) {
872 //
873 // Reallocate DefaultIdNumber
874 //
875 DefaultIdList = ReallocatePool (DefaultIdMaxNum * sizeof (UINT16), (DefaultIdMaxNum + BASE_NUMBER) * sizeof (UINT16), DefaultIdList);
876 if (DefaultIdList == NULL) {
877 goto Done;
878 }
879 DefaultIdMaxNum = DefaultIdMaxNum + BASE_NUMBER;
880 }
881 DefaultIdList[DefaultIdNumber ++] = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;
882 break;
883 case EFI_IFR_FORM_OP:
884 case EFI_IFR_FORM_MAP_OP:
885 //
886 // No EFI varstore is found and directly return.
887 //
888 if (EfiVarStoreNumber == 0 || DefaultIdNumber == 0) {
889 goto Done;
890 }
891 break;
892 case EFI_IFR_CHECKBOX_OP:
893 IfrScope = IfrOpHdr->Scope;
894 IfrQuestionType = IfrOpHdr->OpCode;
895 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *) (IfrOpHdr + 1);
896 IfrCheckBox = (EFI_IFR_CHECKBOX *) (IfrOpHdr + 1);
897 EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
898 Width = sizeof (BOOLEAN);
899 if (EfiVarStoreIndex < EfiVarStoreNumber) {
900 for (Index = 0; Index < DefaultIdNumber; Index ++) {
901 if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_STANDARD) {
902 Status = FindQuestionDefaultSetting (DefaultIdList[Index], EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, sizeof (BOOLEAN), QuestionReferBitField);
903 if (!EFI_ERROR (Status)) {
904 if (IfrValue.b) {
905 IfrCheckBox->Flags = IfrCheckBox->Flags | EFI_IFR_CHECKBOX_DEFAULT;
906 } else {
907 IfrCheckBox->Flags = IfrCheckBox->Flags & (~EFI_IFR_CHECKBOX_DEFAULT);
908 }
909 }
910 } else if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
911 Status = FindQuestionDefaultSetting (DefaultIdList[Index], EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, sizeof (BOOLEAN), QuestionReferBitField);
912 if (!EFI_ERROR (Status)) {
913 if (IfrValue.b) {
914 IfrCheckBox->Flags = IfrCheckBox->Flags | EFI_IFR_CHECKBOX_DEFAULT_MFG;
915 } else {
916 IfrCheckBox->Flags = IfrCheckBox->Flags & (~EFI_IFR_CHECKBOX_DEFAULT_MFG);
917 }
918 }
919 }
920 }
921 }
922 break;
923 case EFI_IFR_NUMERIC_OP:
924 IfrScope = IfrOpHdr->Scope;
925 IfrQuestionType = IfrOpHdr->OpCode;
926 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *) (IfrOpHdr + 1);
927 if (QuestionReferBitField) {
928 Width = (UINTN) (((EFI_IFR_ONE_OF *) IfrOpHdr)->Flags & EDKII_IFR_NUMERIC_SIZE_BIT);
929 } else {
930 Width = (UINTN) ((UINT32) 1 << (((EFI_IFR_ONE_OF *) IfrOpHdr)->Flags & EFI_IFR_NUMERIC_SIZE));
931 }
932 break;
933 case EFI_IFR_ONE_OF_OP:
934 IfrScope = IfrOpHdr->Scope;
935 IfrQuestionType = IfrOpHdr->OpCode;
936 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *) (IfrOpHdr + 1);
937 if (QuestionReferBitField) {
938 Width = (UINTN) (((EFI_IFR_ONE_OF *) IfrOpHdr)->Flags & EDKII_IFR_NUMERIC_SIZE_BIT);
939 } else {
940 Width = (UINTN) ((UINT32) 1 << (((EFI_IFR_ONE_OF *) IfrOpHdr)->Flags & EFI_IFR_NUMERIC_SIZE));
941 }
942 EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
943 StandardDefaultIsSet = FALSE;
944 ManufactDefaultIsSet = FALSE;
945 //
946 // Find Default and Manufacturing default for OneOf question
947 //
948 if (EfiVarStoreIndex < EfiVarStoreNumber) {
949 for (Index = 0; Index < DefaultIdNumber; Index ++) {
950 if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_STANDARD) {
951 Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_STANDARD, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, Width, QuestionReferBitField);
952 if (!EFI_ERROR (Status)) {
953 StandardDefaultIsSet = TRUE;
954 }
955 } else if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
956 Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_MANUFACTURING, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrManufactValue, Width, QuestionReferBitField);
957 if (!EFI_ERROR (Status)) {
958 ManufactDefaultIsSet = TRUE;
959 }
960 }
961 }
962 }
963 break;
964 case EFI_IFR_ORDERED_LIST_OP:
965 IfrScope = IfrOpHdr->Scope;
966 IfrQuestionType = IfrOpHdr->OpCode;
967 IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *) (IfrOpHdr + 1);
968 break;
969 case EFI_IFR_ONE_OF_OPTION_OP:
970 if (IfrQuestionHdr != NULL && IfrScope > 0) {
971 IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
972 if (IfrQuestionType == EFI_IFR_ONE_OF_OP) {
973 Width = (UINTN) ((UINT32) 1 << (IfrOneOfOption->Flags & EFI_IFR_NUMERIC_SIZE));
974 if (StandardDefaultIsSet) {
975 if (CompareMem (&IfrOneOfOption->Value, &IfrValue, Width) == 0) {
976 IfrOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT;
977 } else {
978 IfrOneOfOption->Flags &= ~EFI_IFR_OPTION_DEFAULT;
979 }
980 }
981 if (ManufactDefaultIsSet) {
982 if (CompareMem (&IfrOneOfOption->Value, &IfrManufactValue, Width) == 0) {
983 IfrOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT_MFG;
984 } else {
985 IfrOneOfOption->Flags &= ~EFI_IFR_OPTION_DEFAULT_MFG;
986 }
987 }
988 }
989 }
990 break;
991 case EFI_IFR_DEFAULT_OP:
992 if (IfrQuestionHdr != NULL && IfrScope > 0) {
993 IfrDefault = (EFI_IFR_DEFAULT *) IfrOpHdr;
994 //
995 // Collect default value width
996 //
997 if (!QuestionReferBitField) {
998 Width = 0;
999 if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrDefault->Type == EFI_IFR_TYPE_BOOLEAN) {
1000 Width = 1;
1001 } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
1002 Width = 2;
1003 } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
1004 Width = 4;
1005 } else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
1006 Width = 8;
1007 } else if (IfrDefault->Type == EFI_IFR_TYPE_BUFFER) {
1008 Width = IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value);
1009 }
1010 }
1011 //
1012 // Update the default value
1013 //
1014 if (Width > 0) {
1015 EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
1016 if (EfiVarStoreIndex < EfiVarStoreNumber) {
1017 Status = FindQuestionDefaultSetting (IfrDefault->DefaultId, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrDefault->Value, Width, QuestionReferBitField);
1018 }
1019 }
1020 }
1021 break;
1022 case EFI_IFR_END_OP:
1023 if (IfrQuestionHdr != NULL) {
1024 if (IfrScope > 0) {
1025 IfrScope --;
1026 }
1027 if (IfrScope == 0) {
1028 IfrQuestionHdr = NULL;
1029 QuestionReferBitField = FALSE;
1030 }
1031 }
1032 break;
1033 case EFI_IFR_GUID_OP:
1034 if (CompareGuid ((EFI_GUID *)((UINT8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {
1035 QuestionReferBitField = TRUE;
1036 }
1037 break;
1038 default:
1039 break;
1040 }
1041 IfrOffset = IfrOffset + IfrOpHdr->Length;
1042 IfrOpHdr = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrOpHdr + IfrOpHdr->Length);
1043 if (IfrScope > 0) {
1044 IfrScope += IfrOpHdr->Scope;
1045 }
1046 }
1047
1048 Done:
1049 if (EfiVarStoreList != NULL) {
1050 for (Index = 0; Index < EfiVarStoreNumber; Index ++) {
1051 FreePool (EfiVarStoreList [Index]);
1052 }
1053 }
1054 return;
1055 }
1056
1057 /**
1058 This function insert a Form package to a package list node.
1059 This is a internal function.
1060
1061 @param PackageHdr Pointer to a buffer stored with Form package
1062 information.
1063 @param NotifyType The type of change concerning the database.
1064 @param PackageList Pointer to a package list which will be inserted
1065 to.
1066 @param Package Created Form package
1067
1068 @retval EFI_SUCCESS Form Package is inserted successfully.
1069 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
1070 Form package.
1071 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
1072
1073 **/
1074 EFI_STATUS
1075 InsertFormPackage (
1076 IN VOID *PackageHdr,
1077 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
1078 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
1079 OUT HII_IFR_PACKAGE_INSTANCE **Package
1080 )
1081 {
1082 HII_IFR_PACKAGE_INSTANCE *FormPackage;
1083 EFI_HII_PACKAGE_HEADER PackageHeader;
1084
1085 if (PackageHdr == NULL || PackageList == NULL) {
1086 return EFI_INVALID_PARAMETER;
1087 }
1088
1089 //
1090 // Get the length of the package, including package header itself
1091 //
1092 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
1093
1094 //
1095 // Create a Form package node
1096 //
1097 FormPackage = (HII_IFR_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IFR_PACKAGE_INSTANCE));
1098 if (FormPackage == NULL) {
1099 return EFI_OUT_OF_RESOURCES;
1100 }
1101
1102 FormPackage->IfrData = (UINT8 *) AllocateZeroPool (PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER));
1103 if (FormPackage->IfrData == NULL) {
1104 FreePool (FormPackage);
1105 return EFI_OUT_OF_RESOURCES;
1106 }
1107
1108 FormPackage->Signature = HII_IFR_PACKAGE_SIGNATURE;
1109 //
1110 // Copy Package Header
1111 //
1112 CopyMem (&FormPackage->FormPkgHdr, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
1113
1114 //
1115 // Copy Ifr contents
1116 //
1117 CopyMem (
1118 FormPackage->IfrData,
1119 (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER),
1120 PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER)
1121 );
1122
1123 InsertTailList (&PackageList->FormPkgHdr, &FormPackage->IfrEntry);
1124 *Package = FormPackage;
1125
1126 //
1127 // Update FormPackage with the default setting
1128 //
1129 UpdateDefaultSettingInFormPackage (FormPackage);
1130
1131 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
1132 PackageList->PackageListHdr.PackageLength += FormPackage->FormPkgHdr.Length;
1133 }
1134 return EFI_SUCCESS;
1135 }
1136
1137
1138 /**
1139 This function exports Form packages to a buffer.
1140 This is a internal function.
1141
1142 @param Private Hii database private structure.
1143 @param Handle Identification of a package list.
1144 @param PackageList Pointer to a package list which will be exported.
1145 @param UsedSize The length of buffer be used.
1146 @param BufferSize Length of the Buffer.
1147 @param Buffer Allocated space for storing exported data.
1148 @param ResultSize The size of the already exported content of this
1149 package list.
1150
1151 @retval EFI_SUCCESS Form Packages are exported successfully.
1152 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1153
1154 **/
1155 EFI_STATUS
1156 ExportFormPackages (
1157 IN HII_DATABASE_PRIVATE_DATA *Private,
1158 IN EFI_HII_HANDLE Handle,
1159 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
1160 IN UINTN UsedSize,
1161 IN UINTN BufferSize,
1162 IN OUT VOID *Buffer,
1163 IN OUT UINTN *ResultSize
1164 )
1165 {
1166 HII_IFR_PACKAGE_INSTANCE *FormPackage;
1167 UINTN PackageLength;
1168 LIST_ENTRY *Link;
1169 EFI_STATUS Status;
1170
1171 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
1172 return EFI_INVALID_PARAMETER;
1173 }
1174
1175 if (BufferSize > 0 && Buffer == NULL ) {
1176 return EFI_INVALID_PARAMETER;
1177 }
1178
1179 PackageLength = 0;
1180 Status = EFI_SUCCESS;
1181
1182 //
1183 // Export Form packages.
1184 //
1185 for (Link = PackageList->FormPkgHdr.ForwardLink; Link != &PackageList->FormPkgHdr; Link = Link->ForwardLink) {
1186 FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
1187 PackageLength += FormPackage->FormPkgHdr.Length;
1188 if ((Buffer != NULL) && (PackageLength + *ResultSize + UsedSize <= BufferSize)) {
1189 //
1190 // Invoke registered notification if exists
1191 //
1192 Status = InvokeRegisteredFunction (
1193 Private,
1194 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
1195 (VOID *) FormPackage,
1196 EFI_HII_PACKAGE_FORMS,
1197 Handle
1198 );
1199 ASSERT_EFI_ERROR (Status);
1200 //
1201 // Copy the Form package content.
1202 //
1203 CopyMem (Buffer, (VOID *) (&FormPackage->FormPkgHdr), sizeof (EFI_HII_PACKAGE_HEADER));
1204 Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_PACKAGE_HEADER);
1205 CopyMem (
1206 Buffer,
1207 (VOID *) FormPackage->IfrData,
1208 FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER)
1209 );
1210 Buffer = (UINT8 *) Buffer + FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
1211 }
1212 }
1213
1214 *ResultSize += PackageLength;
1215
1216 return EFI_SUCCESS;
1217
1218 }
1219
1220
1221 /**
1222 This function deletes all Form packages from a package list node.
1223 This is a internal function.
1224
1225 @param Private Hii database private data.
1226 @param Handle Handle of the package list which contains the to
1227 be removed Form packages.
1228 @param PackageList Pointer to a package list that contains removing
1229 packages.
1230
1231 @retval EFI_SUCCESS Form Package(s) is deleted successfully.
1232 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
1233
1234 **/
1235 EFI_STATUS
1236 RemoveFormPackages (
1237 IN HII_DATABASE_PRIVATE_DATA *Private,
1238 IN EFI_HII_HANDLE Handle,
1239 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
1240 )
1241 {
1242 LIST_ENTRY *ListHead;
1243 HII_IFR_PACKAGE_INSTANCE *Package;
1244 EFI_STATUS Status;
1245
1246 ListHead = &PackageList->FormPkgHdr;
1247
1248 while (!IsListEmpty (ListHead)) {
1249 Package = CR (
1250 ListHead->ForwardLink,
1251 HII_IFR_PACKAGE_INSTANCE,
1252 IfrEntry,
1253 HII_IFR_PACKAGE_SIGNATURE
1254 );
1255 Status = InvokeRegisteredFunction (
1256 Private,
1257 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
1258 (VOID *) Package,
1259 EFI_HII_PACKAGE_FORMS,
1260 Handle
1261 );
1262 if (EFI_ERROR (Status)) {
1263 return Status;
1264 }
1265
1266 RemoveEntryList (&Package->IfrEntry);
1267 PackageList->PackageListHdr.PackageLength -= Package->FormPkgHdr.Length;
1268 FreePool (Package->IfrData);
1269 FreePool (Package);
1270 //
1271 // If Hii runtime support feature is enabled,
1272 // will export Hii info for runtime use after ReadyToBoot event triggered.
1273 // If some driver add/update/remove packages from HiiDatabase after ReadyToBoot,
1274 // will need to export the content of HiiDatabase.
1275 // But if form packages removed, also need to export the ConfigResp string
1276 //
1277 if (gExportAfterReadyToBoot) {
1278 gExportConfigResp = TRUE;
1279 }
1280 }
1281
1282 return EFI_SUCCESS;
1283 }
1284
1285
1286
1287 /**
1288 This function insert a String package to a package list node.
1289 This is a internal function.
1290
1291 @param Private Hii database private structure.
1292 @param PackageHdr Pointer to a buffer stored with String package
1293 information.
1294 @param NotifyType The type of change concerning the database.
1295 @param PackageList Pointer to a package list which will be inserted
1296 to.
1297 @param Package Created String package
1298
1299 @retval EFI_SUCCESS String Package is inserted successfully.
1300 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
1301 String package.
1302 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
1303 @retval EFI_UNSUPPORTED A string package with the same language already
1304 exists in current package list.
1305
1306 **/
1307 EFI_STATUS
1308 InsertStringPackage (
1309 IN HII_DATABASE_PRIVATE_DATA *Private,
1310 IN VOID *PackageHdr,
1311 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
1312 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
1313 OUT HII_STRING_PACKAGE_INSTANCE **Package
1314 )
1315 {
1316 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1317 UINT32 HeaderSize;
1318 EFI_STATUS Status;
1319 EFI_HII_PACKAGE_HEADER PackageHeader;
1320 CHAR8 *Language;
1321 UINT32 LanguageSize;
1322 LIST_ENTRY *Link;
1323
1324 if (Private == NULL || PackageHdr == NULL || PackageList == NULL) {
1325 return EFI_INVALID_PARAMETER;
1326 }
1327 if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
1328 return EFI_INVALID_PARAMETER;
1329 }
1330
1331 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
1332 CopyMem (&HeaderSize, (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));
1333
1334 //
1335 // It is illegal to have two string packages with same language within one packagelist
1336 // since the stringid will be duplicate if so. Check it to avoid this potential issue.
1337 //
1338 LanguageSize = HeaderSize - sizeof (EFI_HII_STRING_PACKAGE_HDR) + sizeof (CHAR8);
1339 Language = (CHAR8 *) AllocateZeroPool (LanguageSize);
1340 if (Language == NULL) {
1341 return EFI_OUT_OF_RESOURCES;
1342 }
1343 AsciiStrCpyS (Language, LanguageSize / sizeof (CHAR8), (CHAR8 *) PackageHdr + HeaderSize - LanguageSize);
1344 for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {
1345 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1346 if (HiiCompareLanguage (Language, StringPackage->StringPkgHdr->Language)) {
1347 FreePool (Language);
1348 return EFI_UNSUPPORTED;
1349 }
1350 }
1351 FreePool (Language);
1352
1353 //
1354 // Create a String package node
1355 //
1356 StringPackage = (HII_STRING_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
1357 if (StringPackage == NULL) {
1358 Status = EFI_OUT_OF_RESOURCES;
1359 goto Error;
1360 }
1361
1362 StringPackage->StringPkgHdr = (EFI_HII_STRING_PACKAGE_HDR *) AllocateZeroPool (HeaderSize);
1363 if (StringPackage->StringPkgHdr == NULL) {
1364 Status = EFI_OUT_OF_RESOURCES;
1365 goto Error;
1366 }
1367
1368 StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (PackageHeader.Length - HeaderSize);
1369 if (StringPackage->StringBlock == NULL) {
1370 Status = EFI_OUT_OF_RESOURCES;
1371 goto Error;
1372 }
1373
1374 StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
1375 StringPackage->FontId = 0;
1376 InitializeListHead (&StringPackage->FontInfoList);
1377
1378 //
1379 // Copy the String package header.
1380 //
1381 CopyMem (StringPackage->StringPkgHdr, PackageHdr, HeaderSize);
1382
1383 //
1384 // Copy the String blocks
1385 //
1386 CopyMem (
1387 StringPackage->StringBlock,
1388 (UINT8 *) PackageHdr + HeaderSize,
1389 PackageHeader.Length - HeaderSize
1390 );
1391
1392 //
1393 // Collect all font block info
1394 //
1395 Status = FindStringBlock (Private, StringPackage, (EFI_STRING_ID) (-1), NULL, NULL, NULL, &StringPackage->MaxStringId, NULL);
1396 if (EFI_ERROR (Status)) {
1397 return Status;
1398 }
1399
1400 //
1401 // Insert to String package array
1402 //
1403 InsertTailList (&PackageList->StringPkgHdr, &StringPackage->StringEntry);
1404 *Package = StringPackage;
1405
1406 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
1407 PackageList->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;
1408 }
1409
1410 return EFI_SUCCESS;
1411
1412 Error:
1413
1414 if (StringPackage != NULL) {
1415 if (StringPackage->StringBlock != NULL) {
1416 FreePool (StringPackage->StringBlock);
1417 }
1418 if (StringPackage->StringPkgHdr != NULL) {
1419 FreePool (StringPackage->StringPkgHdr);
1420 }
1421 FreePool (StringPackage);
1422 }
1423 return Status;
1424
1425 }
1426
1427 /**
1428 Adjust all string packages in a single package list to have the same max string ID.
1429
1430 @param PackageList Pointer to a package list which will be adjusted.
1431
1432 @retval EFI_SUCCESS Adjust all string packages successfully.
1433 @retval others Can't adjust string packages.
1434
1435 **/
1436 EFI_STATUS
1437 AdjustStringPackage (
1438 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
1439 )
1440 {
1441 LIST_ENTRY *Link;
1442 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1443 UINT32 Skip2BlockSize;
1444 UINT32 OldBlockSize;
1445 UINT8 *StringBlock;
1446 UINT8 *BlockPtr;
1447 EFI_STRING_ID MaxStringId;
1448 UINT16 SkipCount;
1449
1450 MaxStringId = 0;
1451 for (Link = PackageList->StringPkgHdr.ForwardLink;
1452 Link != &PackageList->StringPkgHdr;
1453 Link = Link->ForwardLink
1454 ) {
1455 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1456 if (MaxStringId < StringPackage->MaxStringId) {
1457 MaxStringId = StringPackage->MaxStringId;
1458 }
1459 }
1460
1461 for (Link = PackageList->StringPkgHdr.ForwardLink;
1462 Link != &PackageList->StringPkgHdr;
1463 Link = Link->ForwardLink
1464 ) {
1465 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1466 if (StringPackage->MaxStringId < MaxStringId) {
1467 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
1468 //
1469 // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCKs to reserve the missing string IDs.
1470 //
1471 SkipCount = (UINT16) (MaxStringId - StringPackage->MaxStringId);
1472 Skip2BlockSize = (UINT32) sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
1473
1474 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Skip2BlockSize);
1475 if (StringBlock == NULL) {
1476 return EFI_OUT_OF_RESOURCES;
1477 }
1478 //
1479 // Copy original string blocks, except the EFI_HII_SIBT_END.
1480 //
1481 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1482 //
1483 // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCK blocks
1484 //
1485 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1486 *BlockPtr = EFI_HII_SIBT_SKIP2;
1487 CopyMem (BlockPtr + 1, &SkipCount, sizeof (UINT16));
1488 BlockPtr += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
1489
1490 //
1491 // Append a EFI_HII_SIBT_END block to the end.
1492 //
1493 *BlockPtr = EFI_HII_SIBT_END;
1494 FreePool (StringPackage->StringBlock);
1495 StringPackage->StringBlock = StringBlock;
1496 StringPackage->StringPkgHdr->Header.Length += Skip2BlockSize;
1497 PackageList->PackageListHdr.PackageLength += Skip2BlockSize;
1498 StringPackage->MaxStringId = MaxStringId;
1499 }
1500 }
1501
1502 return EFI_SUCCESS;
1503 }
1504
1505 /**
1506 This function exports String packages to a buffer.
1507 This is a internal function.
1508
1509 @param Private Hii database private structure.
1510 @param Handle Identification of a package list.
1511 @param PackageList Pointer to a package list which will be exported.
1512 @param UsedSize The length of buffer be used.
1513 @param BufferSize Length of the Buffer.
1514 @param Buffer Allocated space for storing exported data.
1515 @param ResultSize The size of the already exported content of this
1516 package list.
1517
1518 @retval EFI_SUCCESS String Packages are exported successfully.
1519 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1520
1521 **/
1522 EFI_STATUS
1523 ExportStringPackages (
1524 IN HII_DATABASE_PRIVATE_DATA *Private,
1525 IN EFI_HII_HANDLE Handle,
1526 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
1527 IN UINTN UsedSize,
1528 IN UINTN BufferSize,
1529 IN OUT VOID *Buffer,
1530 IN OUT UINTN *ResultSize
1531 )
1532 {
1533 LIST_ENTRY *Link;
1534 UINTN PackageLength;
1535 EFI_STATUS Status;
1536 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1537
1538 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
1539 return EFI_INVALID_PARAMETER;
1540 }
1541
1542 if (BufferSize > 0 && Buffer == NULL ) {
1543 return EFI_INVALID_PARAMETER;
1544 }
1545
1546 PackageLength = 0;
1547 Status = EFI_SUCCESS;
1548
1549 for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {
1550 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1551 PackageLength += StringPackage->StringPkgHdr->Header.Length;
1552 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
1553 //
1554 // Invoke registered notification function with EXPORT_PACK notify type
1555 //
1556 Status = InvokeRegisteredFunction (
1557 Private,
1558 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
1559 (VOID *) StringPackage,
1560 EFI_HII_PACKAGE_STRINGS,
1561 Handle
1562 );
1563 ASSERT_EFI_ERROR (Status);
1564 //
1565 // Copy String package header
1566 //
1567 CopyMem (Buffer, StringPackage->StringPkgHdr, StringPackage->StringPkgHdr->HdrSize);
1568 Buffer = (UINT8 *) Buffer + StringPackage->StringPkgHdr->HdrSize;
1569
1570 //
1571 // Copy String blocks information
1572 //
1573 CopyMem (
1574 Buffer,
1575 StringPackage->StringBlock,
1576 StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize
1577 );
1578 Buffer = (UINT8 *) Buffer + StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
1579 }
1580 }
1581
1582 *ResultSize += PackageLength;
1583 return EFI_SUCCESS;
1584 }
1585
1586
1587 /**
1588 This function deletes all String packages from a package list node.
1589 This is a internal function.
1590
1591 @param Private Hii database private data.
1592 @param Handle Handle of the package list which contains the to
1593 be removed String packages.
1594 @param PackageList Pointer to a package list that contains removing
1595 packages.
1596
1597 @retval EFI_SUCCESS String Package(s) is deleted successfully.
1598 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
1599
1600 **/
1601 EFI_STATUS
1602 RemoveStringPackages (
1603 IN HII_DATABASE_PRIVATE_DATA *Private,
1604 IN EFI_HII_HANDLE Handle,
1605 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
1606 )
1607 {
1608 LIST_ENTRY *ListHead;
1609 HII_STRING_PACKAGE_INSTANCE *Package;
1610 HII_FONT_INFO *FontInfo;
1611 EFI_STATUS Status;
1612
1613 ListHead = &PackageList->StringPkgHdr;
1614
1615 while (!IsListEmpty (ListHead)) {
1616 Package = CR (
1617 ListHead->ForwardLink,
1618 HII_STRING_PACKAGE_INSTANCE,
1619 StringEntry,
1620 HII_STRING_PACKAGE_SIGNATURE
1621 );
1622 Status = InvokeRegisteredFunction (
1623 Private,
1624 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
1625 (VOID *) Package,
1626 EFI_HII_PACKAGE_STRINGS,
1627 Handle
1628 );
1629 if (EFI_ERROR (Status)) {
1630 return Status;
1631 }
1632
1633 RemoveEntryList (&Package->StringEntry);
1634 PackageList->PackageListHdr.PackageLength -= Package->StringPkgHdr->Header.Length;
1635 FreePool (Package->StringBlock);
1636 FreePool (Package->StringPkgHdr);
1637 //
1638 // Delete font information
1639 //
1640 while (!IsListEmpty (&Package->FontInfoList)) {
1641 FontInfo = CR (
1642 Package->FontInfoList.ForwardLink,
1643 HII_FONT_INFO,
1644 Entry,
1645 HII_FONT_INFO_SIGNATURE
1646 );
1647 RemoveEntryList (&FontInfo->Entry);
1648 FreePool (FontInfo);
1649 }
1650
1651 FreePool (Package);
1652 }
1653
1654 return EFI_SUCCESS;
1655 }
1656
1657
1658 /**
1659 This function insert a Font package to a package list node.
1660 This is a internal function.
1661
1662 @param Private Hii database private structure.
1663 @param PackageHdr Pointer to a buffer stored with Font package
1664 information.
1665 @param NotifyType The type of change concerning the database.
1666 @param PackageList Pointer to a package list which will be inserted
1667 to.
1668 @param Package Created Font package
1669
1670 @retval EFI_SUCCESS Font Package is inserted successfully.
1671 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
1672 Font package.
1673 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
1674 @retval EFI_UNSUPPORTED A font package with same EFI_FONT_INFO already
1675 exists in current hii database.
1676
1677 **/
1678 EFI_STATUS
1679 InsertFontPackage (
1680 IN HII_DATABASE_PRIVATE_DATA *Private,
1681 IN VOID *PackageHdr,
1682 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
1683 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
1684 OUT HII_FONT_PACKAGE_INSTANCE **Package
1685 )
1686 {
1687 HII_FONT_PACKAGE_INSTANCE *FontPackage;
1688 EFI_HII_FONT_PACKAGE_HDR *FontPkgHdr;
1689 UINT32 HeaderSize;
1690 EFI_STATUS Status;
1691 EFI_HII_PACKAGE_HEADER PackageHeader;
1692 EFI_FONT_INFO *FontInfo;
1693 UINT32 FontInfoSize;
1694 HII_GLOBAL_FONT_INFO *GlobalFont;
1695
1696 if (Private == NULL || PackageHdr == NULL || PackageList == NULL) {
1697 return EFI_INVALID_PARAMETER;
1698 }
1699
1700 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
1701 CopyMem (&HeaderSize, (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));
1702
1703 FontInfo = NULL;
1704 FontPackage = NULL;
1705 GlobalFont = NULL;
1706
1707 //
1708 // It is illegal to have two font packages with same EFI_FONT_INFO within hii
1709 // database. EFI_FONT_INFO (FontName, FontSize, FontStyle) describes font's
1710 // attributes and identify a font uniquely.
1711 //
1712 FontPkgHdr = (EFI_HII_FONT_PACKAGE_HDR *) AllocateZeroPool (HeaderSize);
1713 if (FontPkgHdr == NULL) {
1714 Status = EFI_OUT_OF_RESOURCES;
1715 goto Error;
1716 }
1717 CopyMem (FontPkgHdr, PackageHdr, HeaderSize);
1718
1719 FontInfoSize = sizeof (EFI_FONT_INFO) + HeaderSize - sizeof (EFI_HII_FONT_PACKAGE_HDR);
1720 FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoSize);
1721 if (FontInfo == NULL) {
1722 Status = EFI_OUT_OF_RESOURCES;
1723 goto Error;
1724 }
1725 FontInfo->FontStyle = FontPkgHdr->FontStyle;
1726 FontInfo->FontSize = FontPkgHdr->Cell.Height;
1727 StrCpyS (FontInfo->FontName, (FontInfoSize - OFFSET_OF(EFI_FONT_INFO,FontName)) / sizeof (CHAR16), FontPkgHdr->FontFamily);
1728
1729 if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, NULL)) {
1730 Status = EFI_UNSUPPORTED;
1731 goto Error;
1732 }
1733
1734 //
1735 // Create a Font package node
1736 //
1737 FontPackage = (HII_FONT_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_FONT_PACKAGE_INSTANCE));
1738 if (FontPackage == NULL) {
1739 Status = EFI_OUT_OF_RESOURCES;
1740 goto Error;
1741 }
1742 FontPackage->Signature = HII_FONT_PACKAGE_SIGNATURE;
1743 FontPackage->FontPkgHdr = FontPkgHdr;
1744 InitializeListHead (&FontPackage->GlyphInfoList);
1745
1746 FontPackage->GlyphBlock = (UINT8 *) AllocateZeroPool (PackageHeader.Length - HeaderSize);
1747 if (FontPackage->GlyphBlock == NULL) {
1748 Status = EFI_OUT_OF_RESOURCES;
1749 goto Error;
1750 }
1751 CopyMem (FontPackage->GlyphBlock, (UINT8 *) PackageHdr + HeaderSize, PackageHeader.Length - HeaderSize);
1752
1753 //
1754 // Collect all default character cell information and backup in GlyphInfoList.
1755 //
1756 Status = FindGlyphBlock (FontPackage, (CHAR16) (-1), NULL, NULL, NULL);
1757 if (EFI_ERROR (Status)) {
1758 goto Error;
1759 }
1760
1761 //
1762 // This font package describes an unique EFI_FONT_INFO. Backup it in global
1763 // font info list.
1764 //
1765 GlobalFont = (HII_GLOBAL_FONT_INFO *) AllocateZeroPool (sizeof (HII_GLOBAL_FONT_INFO));
1766 if (GlobalFont == NULL) {
1767 Status = EFI_OUT_OF_RESOURCES;
1768 goto Error;
1769 }
1770 GlobalFont->Signature = HII_GLOBAL_FONT_INFO_SIGNATURE;
1771 GlobalFont->FontPackage = FontPackage;
1772 GlobalFont->FontInfoSize = FontInfoSize;
1773 GlobalFont->FontInfo = FontInfo;
1774 InsertTailList (&Private->FontInfoList, &GlobalFont->Entry);
1775
1776 //
1777 // Insert this font package to Font package array
1778 //
1779 InsertTailList (&PackageList->FontPkgHdr, &FontPackage->FontEntry);
1780 *Package = FontPackage;
1781
1782 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
1783 PackageList->PackageListHdr.PackageLength += FontPackage->FontPkgHdr->Header.Length;
1784 }
1785
1786 return EFI_SUCCESS;
1787
1788 Error:
1789
1790 if (FontPkgHdr != NULL) {
1791 FreePool (FontPkgHdr);
1792 }
1793 if (FontInfo != NULL) {
1794 FreePool (FontInfo);
1795 }
1796 if (FontPackage != NULL) {
1797 if (FontPackage->GlyphBlock != NULL) {
1798 FreePool (FontPackage->GlyphBlock);
1799 }
1800 FreePool (FontPackage);
1801 }
1802 if (GlobalFont != NULL) {
1803 FreePool (GlobalFont);
1804 }
1805
1806 return Status;
1807
1808 }
1809
1810
1811 /**
1812 This function exports Font packages to a buffer.
1813 This is a internal function.
1814
1815 @param Private Hii database private structure.
1816 @param Handle Identification of a package list.
1817 @param PackageList Pointer to a package list which will be exported.
1818 @param UsedSize The length of buffer be used.
1819 @param BufferSize Length of the Buffer.
1820 @param Buffer Allocated space for storing exported data.
1821 @param ResultSize The size of the already exported content of this
1822 package list.
1823
1824 @retval EFI_SUCCESS Font Packages are exported successfully.
1825 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1826
1827 **/
1828 EFI_STATUS
1829 ExportFontPackages (
1830 IN HII_DATABASE_PRIVATE_DATA *Private,
1831 IN EFI_HII_HANDLE Handle,
1832 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
1833 IN UINTN UsedSize,
1834 IN UINTN BufferSize,
1835 IN OUT VOID *Buffer,
1836 IN OUT UINTN *ResultSize
1837 )
1838 {
1839 LIST_ENTRY *Link;
1840 UINTN PackageLength;
1841 EFI_STATUS Status;
1842 HII_FONT_PACKAGE_INSTANCE *Package;
1843
1844
1845 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
1846 return EFI_INVALID_PARAMETER;
1847 }
1848
1849 if (BufferSize > 0 && Buffer == NULL ) {
1850 return EFI_INVALID_PARAMETER;
1851 }
1852
1853 PackageLength = 0;
1854 Status = EFI_SUCCESS;
1855
1856 for (Link = PackageList->FontPkgHdr.ForwardLink; Link != &PackageList->FontPkgHdr; Link = Link->ForwardLink) {
1857 Package = CR (Link, HII_FONT_PACKAGE_INSTANCE, FontEntry, HII_FONT_PACKAGE_SIGNATURE);
1858 PackageLength += Package->FontPkgHdr->Header.Length;
1859 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
1860 //
1861 // Invoke registered notification function with EXPORT_PACK notify type
1862 //
1863 Status = InvokeRegisteredFunction (
1864 Private,
1865 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
1866 (VOID *) Package,
1867 EFI_HII_PACKAGE_FONTS,
1868 Handle
1869 );
1870 ASSERT_EFI_ERROR (Status);
1871 //
1872 // Copy Font package header
1873 //
1874 CopyMem (Buffer, Package->FontPkgHdr, Package->FontPkgHdr->HdrSize);
1875 Buffer = (UINT8 *) Buffer + Package->FontPkgHdr->HdrSize;
1876
1877 //
1878 // Copy Glyph blocks information
1879 //
1880 CopyMem (
1881 Buffer,
1882 Package->GlyphBlock,
1883 Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize
1884 );
1885 Buffer = (UINT8 *) Buffer + Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize;
1886 }
1887 }
1888
1889 *ResultSize += PackageLength;
1890 return EFI_SUCCESS;
1891 }
1892
1893
1894 /**
1895 This function deletes all Font packages from a package list node.
1896 This is a internal function.
1897
1898 @param Private Hii database private data.
1899 @param Handle Handle of the package list which contains the to
1900 be removed Font packages.
1901 @param PackageList Pointer to a package list that contains removing
1902 packages.
1903
1904 @retval EFI_SUCCESS Font Package(s) is deleted successfully.
1905 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
1906
1907 **/
1908 EFI_STATUS
1909 RemoveFontPackages (
1910 IN HII_DATABASE_PRIVATE_DATA *Private,
1911 IN EFI_HII_HANDLE Handle,
1912 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
1913 )
1914 {
1915 LIST_ENTRY *ListHead;
1916 HII_FONT_PACKAGE_INSTANCE *Package;
1917 EFI_STATUS Status;
1918 HII_GLYPH_INFO *GlyphInfo;
1919 LIST_ENTRY *Link;
1920 HII_GLOBAL_FONT_INFO *GlobalFont;
1921
1922 ListHead = &PackageList->FontPkgHdr;
1923
1924 while (!IsListEmpty (ListHead)) {
1925 Package = CR (
1926 ListHead->ForwardLink,
1927 HII_FONT_PACKAGE_INSTANCE,
1928 FontEntry,
1929 HII_FONT_PACKAGE_SIGNATURE
1930 );
1931 Status = InvokeRegisteredFunction (
1932 Private,
1933 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
1934 (VOID *) Package,
1935 EFI_HII_PACKAGE_FONTS,
1936 Handle
1937 );
1938 if (EFI_ERROR (Status)) {
1939 return Status;
1940 }
1941
1942 RemoveEntryList (&Package->FontEntry);
1943 PackageList->PackageListHdr.PackageLength -= Package->FontPkgHdr->Header.Length;
1944
1945 if (Package->GlyphBlock != NULL) {
1946 FreePool (Package->GlyphBlock);
1947 }
1948 FreePool (Package->FontPkgHdr);
1949 //
1950 // Delete default character cell information
1951 //
1952 while (!IsListEmpty (&Package->GlyphInfoList)) {
1953 GlyphInfo = CR (
1954 Package->GlyphInfoList.ForwardLink,
1955 HII_GLYPH_INFO,
1956 Entry,
1957 HII_GLYPH_INFO_SIGNATURE
1958 );
1959 RemoveEntryList (&GlyphInfo->Entry);
1960 FreePool (GlyphInfo);
1961 }
1962
1963 //
1964 // Remove corresponding global font info
1965 //
1966 for (Link = Private->FontInfoList.ForwardLink; Link != &Private->FontInfoList; Link = Link->ForwardLink) {
1967 GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
1968 if (GlobalFont->FontPackage == Package) {
1969 RemoveEntryList (&GlobalFont->Entry);
1970 FreePool (GlobalFont->FontInfo);
1971 FreePool (GlobalFont);
1972 break;
1973 }
1974 }
1975
1976 FreePool (Package);
1977 }
1978
1979 return EFI_SUCCESS;
1980 }
1981
1982
1983 /**
1984 This function insert a Image package to a package list node.
1985 This is a internal function.
1986
1987 @param PackageHdr Pointer to a buffer stored with Image package
1988 information.
1989 @param NotifyType The type of change concerning the database.
1990 @param PackageList Pointer to a package list which will be inserted
1991 to.
1992 @param Package Created Image package
1993
1994 @retval EFI_SUCCESS Image Package is inserted successfully.
1995 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
1996 Image package.
1997 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
1998
1999 **/
2000 EFI_STATUS
2001 InsertImagePackage (
2002 IN VOID *PackageHdr,
2003 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
2004 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2005 OUT HII_IMAGE_PACKAGE_INSTANCE **Package
2006 )
2007 {
2008 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
2009 UINT32 PaletteSize;
2010 UINT32 ImageSize;
2011 UINT16 Index;
2012 EFI_HII_IMAGE_PALETTE_INFO_HEADER *PaletteHdr;
2013 EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo;
2014 UINT32 PaletteInfoOffset;
2015 UINT32 ImageInfoOffset;
2016 UINT16 CurrentSize;
2017
2018 if (PackageHdr == NULL || PackageList == NULL) {
2019 return EFI_INVALID_PARAMETER;
2020 }
2021
2022 //
2023 // Less than one image package is allowed in one package list.
2024 //
2025 if (PackageList->ImagePkg != NULL) {
2026 return EFI_INVALID_PARAMETER;
2027 }
2028
2029 //
2030 // Create a Image package node
2031 //
2032 ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
2033 if (ImagePackage == NULL) {
2034 return EFI_OUT_OF_RESOURCES;
2035 }
2036
2037 //
2038 // Copy the Image package header.
2039 //
2040 CopyMem (&ImagePackage->ImagePkgHdr, PackageHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));
2041
2042 PaletteInfoOffset = ImagePackage->ImagePkgHdr.PaletteInfoOffset;
2043 ImageInfoOffset = ImagePackage->ImagePkgHdr.ImageInfoOffset;
2044
2045 //
2046 // If PaletteInfoOffset is zero, there are no palettes in this image package.
2047 //
2048 PaletteSize = 0;
2049 ImagePackage->PaletteBlock = NULL;
2050 if (PaletteInfoOffset != 0) {
2051 PaletteHdr = (EFI_HII_IMAGE_PALETTE_INFO_HEADER *) ((UINT8 *) PackageHdr + PaletteInfoOffset);
2052 PaletteSize = sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
2053 PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *) ((UINT8 *) PaletteHdr + PaletteSize);
2054
2055 for (Index = 0; Index < PaletteHdr->PaletteCount; Index++) {
2056 CopyMem (&CurrentSize, PaletteInfo, sizeof (UINT16));
2057 CurrentSize += sizeof (UINT16);
2058 PaletteSize += (UINT32) CurrentSize;
2059 PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *) ((UINT8 *) PaletteInfo + CurrentSize);
2060 }
2061
2062 ImagePackage->PaletteBlock = (UINT8 *) AllocateZeroPool (PaletteSize);
2063 if (ImagePackage->PaletteBlock == NULL) {
2064 FreePool (ImagePackage);
2065 return EFI_OUT_OF_RESOURCES;
2066 }
2067 CopyMem (
2068 ImagePackage->PaletteBlock,
2069 (UINT8 *) PackageHdr + PaletteInfoOffset,
2070 PaletteSize
2071 );
2072 }
2073
2074 //
2075 // If ImageInfoOffset is zero, there are no images in this package.
2076 //
2077 ImageSize = 0;
2078 ImagePackage->ImageBlock = NULL;
2079 if (ImageInfoOffset != 0) {
2080 ImageSize = ImagePackage->ImagePkgHdr.Header.Length -
2081 sizeof (EFI_HII_IMAGE_PACKAGE_HDR) - PaletteSize;
2082 ImagePackage->ImageBlock = AllocateZeroPool (ImageSize);
2083 if (ImagePackage->ImageBlock == NULL) {
2084 FreePool (ImagePackage->PaletteBlock);
2085 FreePool (ImagePackage);
2086 return EFI_OUT_OF_RESOURCES;
2087 }
2088 CopyMem (
2089 ImagePackage->ImageBlock,
2090 (UINT8 *) PackageHdr + ImageInfoOffset,
2091 ImageSize
2092 );
2093 }
2094
2095 ImagePackage->ImageBlockSize = ImageSize;
2096 ImagePackage->PaletteInfoSize = PaletteSize;
2097 PackageList->ImagePkg = ImagePackage;
2098 *Package = ImagePackage;
2099
2100 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
2101 PackageList->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
2102 }
2103
2104 return EFI_SUCCESS;
2105 }
2106
2107
2108 /**
2109 This function exports Image packages to a buffer.
2110 This is a internal function.
2111
2112 @param Private Hii database private structure.
2113 @param Handle Identification of a package list.
2114 @param PackageList Pointer to a package list which will be exported.
2115 @param UsedSize The length of buffer be used.
2116 @param BufferSize Length of the Buffer.
2117 @param Buffer Allocated space for storing exported data.
2118 @param ResultSize The size of the already exported content of this
2119 package list.
2120
2121 @retval EFI_SUCCESS Image Packages are exported successfully.
2122 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
2123
2124 **/
2125 EFI_STATUS
2126 ExportImagePackages (
2127 IN HII_DATABASE_PRIVATE_DATA *Private,
2128 IN EFI_HII_HANDLE Handle,
2129 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2130 IN UINTN UsedSize,
2131 IN UINTN BufferSize,
2132 IN OUT VOID *Buffer,
2133 IN OUT UINTN *ResultSize
2134 )
2135 {
2136 UINTN PackageLength;
2137 EFI_STATUS Status;
2138 HII_IMAGE_PACKAGE_INSTANCE *Package;
2139
2140
2141 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
2142 return EFI_INVALID_PARAMETER;
2143 }
2144
2145 if (BufferSize > 0 && Buffer == NULL ) {
2146 return EFI_INVALID_PARAMETER;
2147 }
2148
2149 Package = PackageList->ImagePkg;
2150
2151 if (Package == NULL) {
2152 return EFI_SUCCESS;
2153 }
2154
2155 PackageLength = Package->ImagePkgHdr.Header.Length;
2156
2157 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
2158 //
2159 // Invoke registered notification function with EXPORT_PACK notify type
2160 //
2161 Status = InvokeRegisteredFunction (
2162 Private,
2163 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
2164 (VOID *) Package,
2165 EFI_HII_PACKAGE_IMAGES,
2166 Handle
2167 );
2168 ASSERT_EFI_ERROR (Status);
2169 ASSERT (Package->ImagePkgHdr.Header.Length ==
2170 sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + Package->ImageBlockSize + Package->PaletteInfoSize);
2171 //
2172 // Copy Image package header,
2173 // then justify the offset for image info and palette info in the header.
2174 //
2175 CopyMem (Buffer, &Package->ImagePkgHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));
2176 Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
2177
2178 //
2179 // Copy Image blocks information
2180 //
2181 if (Package->ImageBlockSize != 0) {
2182 CopyMem (Buffer, Package->ImageBlock, Package->ImageBlockSize);
2183 Buffer = (UINT8 *) Buffer + Package->ImageBlockSize;
2184 }
2185 //
2186 // Copy Palette information
2187 //
2188 if (Package->PaletteInfoSize != 0) {
2189 CopyMem (Buffer, Package->PaletteBlock, Package->PaletteInfoSize);
2190 Buffer = (UINT8 *) Buffer + Package->PaletteInfoSize;
2191 }
2192 }
2193
2194 *ResultSize += PackageLength;
2195 return EFI_SUCCESS;
2196 }
2197
2198
2199 /**
2200 This function deletes Image package from a package list node.
2201 This is a internal function.
2202
2203 @param Private Hii database private data.
2204 @param Handle Handle of the package list which contains the to
2205 be removed Image packages.
2206 @param PackageList Package List which contains the to be removed
2207 Image package.
2208
2209 @retval EFI_SUCCESS Image Package(s) is deleted successfully.
2210 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
2211
2212 **/
2213 EFI_STATUS
2214 RemoveImagePackages (
2215 IN HII_DATABASE_PRIVATE_DATA *Private,
2216 IN EFI_HII_HANDLE Handle,
2217 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
2218 )
2219 {
2220 HII_IMAGE_PACKAGE_INSTANCE *Package;
2221 EFI_STATUS Status;
2222
2223 Package = PackageList->ImagePkg;
2224
2225 //
2226 // Image package does not exist, return directly.
2227 //
2228 if (Package == NULL) {
2229 return EFI_SUCCESS;
2230 }
2231
2232 Status = InvokeRegisteredFunction (
2233 Private,
2234 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
2235 (VOID *) Package,
2236 EFI_HII_PACKAGE_IMAGES,
2237 Handle
2238 );
2239 if (EFI_ERROR (Status)) {
2240 return Status;
2241 }
2242
2243 PackageList->PackageListHdr.PackageLength -= Package->ImagePkgHdr.Header.Length;
2244
2245 FreePool (Package->ImageBlock);
2246 if (Package->PaletteBlock != NULL) {
2247 FreePool (Package->PaletteBlock);
2248 }
2249 FreePool (Package);
2250
2251 PackageList->ImagePkg = NULL;
2252
2253 return EFI_SUCCESS;
2254 }
2255
2256
2257 /**
2258 This function insert a Simple Font package to a package list node.
2259 This is a internal function.
2260
2261 @param PackageHdr Pointer to a buffer stored with Simple Font
2262 package information.
2263 @param NotifyType The type of change concerning the database.
2264 @param PackageList Pointer to a package list which will be inserted
2265 to.
2266 @param Package Created Simple Font package
2267
2268 @retval EFI_SUCCESS Simple Font Package is inserted successfully.
2269 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
2270 Simple Font package.
2271 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
2272
2273 **/
2274 EFI_STATUS
2275 InsertSimpleFontPackage (
2276 IN VOID *PackageHdr,
2277 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
2278 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2279 OUT HII_SIMPLE_FONT_PACKAGE_INSTANCE **Package
2280 )
2281 {
2282 HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;
2283 EFI_STATUS Status;
2284 EFI_HII_PACKAGE_HEADER Header;
2285
2286 if (PackageHdr == NULL || PackageList == NULL) {
2287 return EFI_INVALID_PARAMETER;
2288 }
2289
2290 //
2291 // Create a Simple Font package node
2292 //
2293 SimpleFontPackage = AllocateZeroPool (sizeof (HII_SIMPLE_FONT_PACKAGE_INSTANCE));
2294 if (SimpleFontPackage == NULL) {
2295 Status = EFI_OUT_OF_RESOURCES;
2296 goto Error;
2297 }
2298 SimpleFontPackage->Signature = HII_S_FONT_PACKAGE_SIGNATURE;
2299
2300 //
2301 // Copy the Simple Font package.
2302 //
2303 CopyMem (&Header, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
2304
2305 SimpleFontPackage->SimpleFontPkgHdr = AllocateZeroPool (Header.Length);
2306 if (SimpleFontPackage->SimpleFontPkgHdr == NULL) {
2307 Status = EFI_OUT_OF_RESOURCES;
2308 goto Error;
2309 }
2310
2311 CopyMem (SimpleFontPackage->SimpleFontPkgHdr, PackageHdr, Header.Length);
2312
2313 //
2314 // Insert to Simple Font package array
2315 //
2316 InsertTailList (&PackageList->SimpleFontPkgHdr, &SimpleFontPackage->SimpleFontEntry);
2317 *Package = SimpleFontPackage;
2318
2319 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
2320 PackageList->PackageListHdr.PackageLength += Header.Length;
2321 }
2322
2323 return EFI_SUCCESS;
2324
2325 Error:
2326
2327 if (SimpleFontPackage != NULL) {
2328 if (SimpleFontPackage->SimpleFontPkgHdr != NULL) {
2329 FreePool (SimpleFontPackage->SimpleFontPkgHdr);
2330 }
2331 FreePool (SimpleFontPackage);
2332 }
2333 return Status;
2334 }
2335
2336
2337 /**
2338 This function exports SimpleFont packages to a buffer.
2339 This is a internal function.
2340
2341 @param Private Hii database private structure.
2342 @param Handle Identification of a package list.
2343 @param PackageList Pointer to a package list which will be exported.
2344 @param UsedSize The length of buffer be used.
2345 @param BufferSize Length of the Buffer.
2346 @param Buffer Allocated space for storing exported data.
2347 @param ResultSize The size of the already exported content of this
2348 package list.
2349
2350 @retval EFI_SUCCESS SimpleFont Packages are exported successfully.
2351 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
2352
2353 **/
2354 EFI_STATUS
2355 ExportSimpleFontPackages (
2356 IN HII_DATABASE_PRIVATE_DATA *Private,
2357 IN EFI_HII_HANDLE Handle,
2358 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2359 IN UINTN UsedSize,
2360 IN UINTN BufferSize,
2361 IN OUT VOID *Buffer,
2362 IN OUT UINTN *ResultSize
2363 )
2364 {
2365 LIST_ENTRY *Link;
2366 UINTN PackageLength;
2367 EFI_STATUS Status;
2368 HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;
2369
2370 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
2371 return EFI_INVALID_PARAMETER;
2372 }
2373
2374 if (BufferSize > 0 && Buffer == NULL ) {
2375 return EFI_INVALID_PARAMETER;
2376 }
2377
2378 PackageLength = 0;
2379 Status = EFI_SUCCESS;
2380
2381 for (Link = PackageList->SimpleFontPkgHdr.ForwardLink; Link != &PackageList->SimpleFontPkgHdr; Link = Link->ForwardLink) {
2382 Package = CR (Link, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);
2383 PackageLength += Package->SimpleFontPkgHdr->Header.Length;
2384 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
2385 //
2386 // Invoke registered notification function with EXPORT_PACK notify type
2387 //
2388 Status = InvokeRegisteredFunction (
2389 Private,
2390 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
2391 (VOID *) Package,
2392 EFI_HII_PACKAGE_SIMPLE_FONTS,
2393 Handle
2394 );
2395 ASSERT_EFI_ERROR (Status);
2396
2397 //
2398 // Copy SimpleFont package
2399 //
2400 CopyMem (Buffer, Package->SimpleFontPkgHdr, Package->SimpleFontPkgHdr->Header.Length);
2401 Buffer = (UINT8 *) Buffer + Package->SimpleFontPkgHdr->Header.Length;
2402 }
2403 }
2404
2405 *ResultSize += PackageLength;
2406 return EFI_SUCCESS;
2407 }
2408
2409
2410 /**
2411 This function deletes all Simple Font packages from a package list node.
2412 This is a internal function.
2413
2414 @param Private Hii database private data.
2415 @param Handle Handle of the package list which contains the to
2416 be removed Simple Font packages.
2417 @param PackageList Pointer to a package list that contains removing
2418 packages.
2419
2420 @retval EFI_SUCCESS Simple Font Package(s) is deleted successfully.
2421 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
2422
2423 **/
2424 EFI_STATUS
2425 RemoveSimpleFontPackages (
2426 IN HII_DATABASE_PRIVATE_DATA *Private,
2427 IN EFI_HII_HANDLE Handle,
2428 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
2429 )
2430 {
2431 LIST_ENTRY *ListHead;
2432 HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;
2433 EFI_STATUS Status;
2434
2435 ListHead = &PackageList->SimpleFontPkgHdr;
2436
2437 while (!IsListEmpty (ListHead)) {
2438 Package = CR (
2439 ListHead->ForwardLink,
2440 HII_SIMPLE_FONT_PACKAGE_INSTANCE,
2441 SimpleFontEntry,
2442 HII_S_FONT_PACKAGE_SIGNATURE
2443 );
2444 Status = InvokeRegisteredFunction (
2445 Private,
2446 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
2447 (VOID *) Package,
2448 EFI_HII_PACKAGE_SIMPLE_FONTS,
2449 Handle
2450 );
2451 if (EFI_ERROR (Status)) {
2452 return Status;
2453 }
2454
2455 RemoveEntryList (&Package->SimpleFontEntry);
2456 PackageList->PackageListHdr.PackageLength -= Package->SimpleFontPkgHdr->Header.Length;
2457 FreePool (Package->SimpleFontPkgHdr);
2458 FreePool (Package);
2459 }
2460
2461 return EFI_SUCCESS;
2462 }
2463
2464
2465 /**
2466 This function insert a Device path package to a package list node.
2467 This is a internal function.
2468
2469 @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol
2470 instance
2471 @param NotifyType The type of change concerning the database.
2472 @param PackageList Pointer to a package list which will be inserted
2473 to.
2474
2475 @retval EFI_SUCCESS Device path Package is inserted successfully.
2476 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
2477 Device path package.
2478 @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.
2479
2480 **/
2481 EFI_STATUS
2482 InsertDevicePathPackage (
2483 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
2484 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
2485 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
2486 )
2487 {
2488 UINT32 PackageLength;
2489 EFI_HII_PACKAGE_HEADER Header;
2490
2491 if (DevicePath == NULL || PackageList == NULL) {
2492 return EFI_INVALID_PARAMETER;
2493 }
2494 //
2495 // Less than one device path package is allowed in one package list.
2496 //
2497 if (PackageList->DevicePathPkg != NULL) {
2498 return EFI_INVALID_PARAMETER;
2499 }
2500
2501 PackageLength = (UINT32) GetDevicePathSize (DevicePath) + sizeof (EFI_HII_PACKAGE_HEADER);
2502 PackageList->DevicePathPkg = (UINT8 *) AllocateZeroPool (PackageLength);
2503 if (PackageList->DevicePathPkg == NULL) {
2504 return EFI_OUT_OF_RESOURCES;
2505 }
2506
2507 Header.Length = PackageLength;
2508 Header.Type = EFI_HII_PACKAGE_DEVICE_PATH;
2509 CopyMem (PackageList->DevicePathPkg, &Header, sizeof (EFI_HII_PACKAGE_HEADER));
2510 CopyMem (
2511 PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER),
2512 DevicePath,
2513 PackageLength - sizeof (EFI_HII_PACKAGE_HEADER)
2514 );
2515
2516 //
2517 // Since Device Path package is created by NewPackageList, either NEW_PACK
2518 // or ADD_PACK should increase the length of package list.
2519 //
2520 PackageList->PackageListHdr.PackageLength += PackageLength;
2521 return EFI_SUCCESS;
2522 }
2523
2524
2525 /**
2526 This function exports device path package to a buffer.
2527 This is a internal function.
2528
2529 @param Private Hii database private structure.
2530 @param Handle Identification of a package list.
2531 @param PackageList Pointer to a package list which will be exported.
2532 @param UsedSize The length of buffer be used.
2533 @param BufferSize Length of the Buffer.
2534 @param Buffer Allocated space for storing exported data.
2535 @param ResultSize The size of the already exported content of this
2536 package list.
2537
2538 @retval EFI_SUCCESS Device path Package is exported successfully.
2539 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
2540
2541 **/
2542 EFI_STATUS
2543 ExportDevicePathPackage (
2544 IN HII_DATABASE_PRIVATE_DATA *Private,
2545 IN EFI_HII_HANDLE Handle,
2546 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2547 IN UINTN UsedSize,
2548 IN UINTN BufferSize,
2549 IN OUT VOID *Buffer,
2550 IN OUT UINTN *ResultSize
2551 )
2552 {
2553 EFI_STATUS Status;
2554 UINT8 *Package;
2555 EFI_HII_PACKAGE_HEADER Header;
2556
2557 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
2558 return EFI_INVALID_PARAMETER;
2559 }
2560 if (BufferSize > 0 && Buffer == NULL ) {
2561 return EFI_INVALID_PARAMETER;
2562 }
2563
2564 Package = PackageList->DevicePathPkg;
2565
2566 if (Package == NULL) {
2567 return EFI_SUCCESS;
2568 }
2569
2570 CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2571
2572 if (Header.Length + *ResultSize + UsedSize <= BufferSize) {
2573 //
2574 // Invoke registered notification function with EXPORT_PACK notify type
2575 //
2576 Status = InvokeRegisteredFunction (
2577 Private,
2578 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
2579 (VOID *) Package,
2580 EFI_HII_PACKAGE_DEVICE_PATH,
2581 Handle
2582 );
2583 ASSERT_EFI_ERROR (Status);
2584
2585 //
2586 // Copy Device path package
2587 //
2588 CopyMem (Buffer, Package, Header.Length);
2589 }
2590
2591 *ResultSize += Header.Length;
2592 return EFI_SUCCESS;
2593 }
2594
2595
2596 /**
2597 This function deletes Device Path package from a package list node.
2598 This is a internal function.
2599
2600 @param Private Hii database private data.
2601 @param Handle Handle of the package list.
2602 @param PackageList Package List which contains the to be removed
2603 Device Path package.
2604
2605 @retval EFI_SUCCESS Device Path Package is deleted successfully.
2606 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
2607
2608 **/
2609 EFI_STATUS
2610 RemoveDevicePathPackage (
2611 IN HII_DATABASE_PRIVATE_DATA *Private,
2612 IN EFI_HII_HANDLE Handle,
2613 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
2614 )
2615 {
2616 EFI_STATUS Status;
2617 UINT8 *Package;
2618 EFI_HII_PACKAGE_HEADER Header;
2619
2620 Package = PackageList->DevicePathPkg;
2621
2622 //
2623 // No device path, return directly.
2624 //
2625 if (Package == NULL) {
2626 return EFI_SUCCESS;
2627 }
2628
2629 Status = InvokeRegisteredFunction (
2630 Private,
2631 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
2632 (VOID *) Package,
2633 EFI_HII_PACKAGE_DEVICE_PATH,
2634 Handle
2635 );
2636 if (EFI_ERROR (Status)) {
2637 return Status;
2638 }
2639
2640 CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));
2641 PackageList->PackageListHdr.PackageLength -= Header.Length;
2642
2643 FreePool (Package);
2644
2645 PackageList->DevicePathPkg = NULL;
2646
2647 return EFI_SUCCESS;
2648 }
2649
2650
2651 /**
2652 This function will insert a device path package to package list firstly then
2653 invoke notification functions if any.
2654 This is a internal function.
2655
2656 @param Private Hii database private structure.
2657 @param NotifyType The type of change concerning the database.
2658 @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol
2659 instance
2660 @param DatabaseRecord Pointer to a database record contains a package
2661 list which will be inserted to.
2662
2663 @retval EFI_SUCCESS Device path Package is inserted successfully.
2664 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
2665 Device path package.
2666 @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.
2667
2668 **/
2669 EFI_STATUS
2670 AddDevicePathPackage (
2671 IN HII_DATABASE_PRIVATE_DATA *Private,
2672 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
2673 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
2674 IN OUT HII_DATABASE_RECORD *DatabaseRecord
2675 )
2676 {
2677 EFI_STATUS Status;
2678
2679 if (DevicePath == NULL) {
2680 return EFI_SUCCESS;
2681 }
2682
2683 ASSERT (Private != NULL);
2684 ASSERT (DatabaseRecord != NULL);
2685
2686 //
2687 // Create a device path package and insert to packagelist
2688 //
2689 Status = InsertDevicePathPackage (
2690 DevicePath,
2691 NotifyType,
2692 DatabaseRecord->PackageList
2693 );
2694 if (EFI_ERROR (Status)) {
2695 return Status;
2696 }
2697
2698 return InvokeRegisteredFunction (
2699 Private,
2700 NotifyType,
2701 (VOID *) DatabaseRecord->PackageList->DevicePathPkg,
2702 EFI_HII_PACKAGE_DEVICE_PATH,
2703 DatabaseRecord->Handle
2704 );
2705 }
2706
2707
2708 /**
2709 This function insert a Keyboard Layout package to a package list node.
2710 This is a internal function.
2711
2712 @param PackageHdr Pointer to a buffer stored with Keyboard Layout
2713 package information.
2714 @param NotifyType The type of change concerning the database.
2715 @param PackageList Pointer to a package list which will be inserted
2716 to.
2717 @param Package Created Keyboard Layout package
2718
2719 @retval EFI_SUCCESS Keyboard Layout Package is inserted successfully.
2720 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
2721 Keyboard Layout package.
2722 @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
2723
2724 **/
2725 EFI_STATUS
2726 InsertKeyboardLayoutPackage (
2727 IN VOID *PackageHdr,
2728 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
2729 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2730 OUT HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE **Package
2731 )
2732 {
2733 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;
2734 EFI_HII_PACKAGE_HEADER PackageHeader;
2735 EFI_STATUS Status;
2736
2737 if (PackageHdr == NULL || PackageList == NULL) {
2738 return EFI_INVALID_PARAMETER;
2739 }
2740
2741 CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
2742
2743 //
2744 // Create a Keyboard Layout package node
2745 //
2746 KeyboardLayoutPackage = AllocateZeroPool (sizeof (HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE));
2747 if (KeyboardLayoutPackage == NULL) {
2748 Status = EFI_OUT_OF_RESOURCES;
2749 goto Error;
2750 }
2751 KeyboardLayoutPackage->Signature = HII_KB_LAYOUT_PACKAGE_SIGNATURE;
2752
2753 KeyboardLayoutPackage->KeyboardPkg = (UINT8 *) AllocateZeroPool (PackageHeader.Length);
2754 if (KeyboardLayoutPackage->KeyboardPkg == NULL) {
2755 Status = EFI_OUT_OF_RESOURCES;
2756 goto Error;
2757 }
2758
2759 CopyMem (KeyboardLayoutPackage->KeyboardPkg, PackageHdr, PackageHeader.Length);
2760 InsertTailList (&PackageList->KeyboardLayoutHdr, &KeyboardLayoutPackage->KeyboardEntry);
2761
2762 *Package = KeyboardLayoutPackage;
2763
2764 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
2765 PackageList->PackageListHdr.PackageLength += PackageHeader.Length;
2766 }
2767
2768 return EFI_SUCCESS;
2769
2770 Error:
2771
2772
2773 if (KeyboardLayoutPackage != NULL) {
2774 if (KeyboardLayoutPackage->KeyboardPkg != NULL) {
2775 FreePool (KeyboardLayoutPackage->KeyboardPkg);
2776 }
2777 FreePool (KeyboardLayoutPackage);
2778 }
2779
2780 return Status;
2781 }
2782
2783
2784 /**
2785 This function exports Keyboard Layout packages to a buffer.
2786 This is a internal function.
2787
2788 @param Private Hii database private structure.
2789 @param Handle Identification of a package list.
2790 @param PackageList Pointer to a package list which will be exported.
2791 @param UsedSize The length of buffer be used.
2792 @param BufferSize Length of the Buffer.
2793 @param Buffer Allocated space for storing exported data.
2794 @param ResultSize The size of the already exported content of this
2795 package list.
2796
2797 @retval EFI_SUCCESS Keyboard Layout Packages are exported
2798 successfully.
2799 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
2800
2801 **/
2802 EFI_STATUS
2803 ExportKeyboardLayoutPackages (
2804 IN HII_DATABASE_PRIVATE_DATA *Private,
2805 IN EFI_HII_HANDLE Handle,
2806 IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
2807 IN UINTN UsedSize,
2808 IN UINTN BufferSize,
2809 IN OUT VOID *Buffer,
2810 IN OUT UINTN *ResultSize
2811 )
2812 {
2813 LIST_ENTRY *Link;
2814 UINTN PackageLength;
2815 EFI_STATUS Status;
2816 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
2817 EFI_HII_PACKAGE_HEADER PackageHeader;
2818
2819 if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
2820 return EFI_INVALID_PARAMETER;
2821 }
2822
2823 if (BufferSize > 0 && Buffer == NULL ) {
2824 return EFI_INVALID_PARAMETER;
2825 }
2826
2827 PackageLength = 0;
2828 Status = EFI_SUCCESS;
2829
2830 for (Link = PackageList->KeyboardLayoutHdr.ForwardLink; Link != &PackageList->KeyboardLayoutHdr; Link = Link->ForwardLink) {
2831 Package = CR (Link, HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE, KeyboardEntry, HII_KB_LAYOUT_PACKAGE_SIGNATURE);
2832 CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));
2833 PackageLength += PackageHeader.Length;
2834 if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
2835 //
2836 // Invoke registered notification function with EXPORT_PACK notify type
2837 //
2838 Status = InvokeRegisteredFunction (
2839 Private,
2840 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
2841 (EFI_HII_PACKAGE_HEADER *) Package,
2842 EFI_HII_PACKAGE_KEYBOARD_LAYOUT,
2843 Handle
2844 );
2845 ASSERT_EFI_ERROR (Status);
2846
2847 //
2848 // Copy Keyboard Layout package
2849 //
2850 CopyMem (Buffer, Package->KeyboardPkg, PackageHeader.Length);
2851 Buffer = (UINT8 *) Buffer + PackageHeader.Length;
2852 }
2853 }
2854
2855 *ResultSize += PackageLength;
2856 return EFI_SUCCESS;
2857 }
2858
2859
2860 /**
2861 This function deletes all Keyboard Layout packages from a package list node.
2862 This is a internal function.
2863
2864 @param Private Hii database private data.
2865 @param Handle Handle of the package list which contains the to
2866 be removed Keyboard Layout packages.
2867 @param PackageList Pointer to a package list that contains removing
2868 packages.
2869
2870 @retval EFI_SUCCESS Keyboard Layout Package(s) is deleted
2871 successfully.
2872 @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
2873
2874 **/
2875 EFI_STATUS
2876 RemoveKeyboardLayoutPackages (
2877 IN HII_DATABASE_PRIVATE_DATA *Private,
2878 IN EFI_HII_HANDLE Handle,
2879 IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
2880 )
2881 {
2882 LIST_ENTRY *ListHead;
2883 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
2884 EFI_HII_PACKAGE_HEADER PackageHeader;
2885 EFI_STATUS Status;
2886
2887 ListHead = &PackageList->KeyboardLayoutHdr;
2888
2889 while (!IsListEmpty (ListHead)) {
2890 Package = CR (
2891 ListHead->ForwardLink,
2892 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
2893 KeyboardEntry,
2894 HII_KB_LAYOUT_PACKAGE_SIGNATURE
2895 );
2896 Status = InvokeRegisteredFunction (
2897 Private,
2898 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
2899 (VOID *) Package,
2900 EFI_HII_PACKAGE_KEYBOARD_LAYOUT,
2901 Handle
2902 );
2903 if (EFI_ERROR (Status)) {
2904 return Status;
2905 }
2906
2907 RemoveEntryList (&Package->KeyboardEntry);
2908 CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));
2909 PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;
2910 FreePool (Package->KeyboardPkg);
2911 FreePool (Package);
2912 }
2913
2914 return EFI_SUCCESS;
2915 }
2916
2917
2918 /**
2919 This function will insert a package list to hii database firstly then
2920 invoke notification functions if any. It is the worker function of
2921 HiiNewPackageList and HiiUpdatePackageList.
2922
2923 This is a internal function.
2924
2925 @param Private Hii database private structure.
2926 @param NotifyType The type of change concerning the database.
2927 @param PackageList Pointer to a package list.
2928 @param DatabaseRecord Pointer to a database record contains a package
2929 list instance which will be inserted to.
2930
2931 @retval EFI_SUCCESS All incoming packages are inserted to current
2932 database.
2933 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
2934 Device path package.
2935 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
2936
2937 **/
2938 EFI_STATUS
2939 AddPackages (
2940 IN HII_DATABASE_PRIVATE_DATA *Private,
2941 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
2942 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
2943 IN OUT HII_DATABASE_RECORD *DatabaseRecord
2944 )
2945 {
2946 EFI_STATUS Status;
2947 HII_GUID_PACKAGE_INSTANCE *GuidPackage;
2948 HII_IFR_PACKAGE_INSTANCE *FormPackage;
2949 HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;
2950 HII_STRING_PACKAGE_INSTANCE *StringPackage;
2951 HII_FONT_PACKAGE_INSTANCE *FontPackage;
2952 HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;
2953 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
2954 EFI_HII_PACKAGE_HEADER *PackageHdrPtr;
2955 EFI_HII_PACKAGE_HEADER PackageHeader;
2956 UINT32 OldPackageListLen;
2957 BOOLEAN StringPkgIsAdd;
2958
2959 //
2960 // Initialize Variables
2961 //
2962 StringPkgIsAdd = FALSE;
2963 FontPackage = NULL;
2964 StringPackage = NULL;
2965 GuidPackage = NULL;
2966 FormPackage = NULL;
2967 ImagePackage = NULL;
2968 SimpleFontPackage = NULL;
2969 KeyboardLayoutPackage = NULL;
2970
2971 //
2972 // Process the package list header
2973 //
2974 OldPackageListLen = DatabaseRecord->PackageList->PackageListHdr.PackageLength;
2975 CopyMem (
2976 &DatabaseRecord->PackageList->PackageListHdr,
2977 (VOID *) PackageList,
2978 sizeof (EFI_HII_PACKAGE_LIST_HEADER)
2979 );
2980 if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
2981 DatabaseRecord->PackageList->PackageListHdr.PackageLength = OldPackageListLen;
2982 }
2983
2984 PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
2985 CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
2986
2987 Status = EFI_SUCCESS;
2988
2989 while (PackageHeader.Type != EFI_HII_PACKAGE_END) {
2990 switch (PackageHeader.Type) {
2991 case EFI_HII_PACKAGE_TYPE_GUID:
2992 Status = InsertGuidPackage (
2993 PackageHdrPtr,
2994 NotifyType,
2995 DatabaseRecord->PackageList,
2996 &GuidPackage
2997 );
2998 if (EFI_ERROR (Status)) {
2999 return Status;
3000 }
3001 Status = InvokeRegisteredFunction (
3002 Private,
3003 NotifyType,
3004 (VOID *) GuidPackage,
3005 (UINT8) (PackageHeader.Type),
3006 DatabaseRecord->Handle
3007 );
3008 break;
3009 case EFI_HII_PACKAGE_FORMS:
3010 Status = InsertFormPackage (
3011 PackageHdrPtr,
3012 NotifyType,
3013 DatabaseRecord->PackageList,
3014 &FormPackage
3015 );
3016 if (EFI_ERROR (Status)) {
3017 return Status;
3018 }
3019 Status = InvokeRegisteredFunction (
3020 Private,
3021 NotifyType,
3022 (VOID *) FormPackage,
3023 (UINT8) (PackageHeader.Type),
3024 DatabaseRecord->Handle
3025 );
3026 //
3027 // If Hii runtime support feature is enabled,
3028 // will export Hii info for runtime use after ReadyToBoot event triggered.
3029 // If some driver add/update/remove packages from HiiDatabase after ReadyToBoot,
3030 // will need to export the content of HiiDatabase.
3031 // But if form packages added/updated, also need to export the ConfigResp string.
3032 //
3033 if (gExportAfterReadyToBoot) {
3034 gExportConfigResp = TRUE;
3035 }
3036 break;
3037 case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
3038 Status = InsertKeyboardLayoutPackage (
3039 PackageHdrPtr,
3040 NotifyType,
3041 DatabaseRecord->PackageList,
3042 &KeyboardLayoutPackage
3043 );
3044 if (EFI_ERROR (Status)) {
3045 return Status;
3046 }
3047 Status = InvokeRegisteredFunction (
3048 Private,
3049 NotifyType,
3050 (VOID *) KeyboardLayoutPackage,
3051 (UINT8) (PackageHeader.Type),
3052 DatabaseRecord->Handle
3053 );
3054 break;
3055 case EFI_HII_PACKAGE_STRINGS:
3056 Status = InsertStringPackage (
3057 Private,
3058 PackageHdrPtr,
3059 NotifyType,
3060 DatabaseRecord->PackageList,
3061 &StringPackage
3062 );
3063 if (EFI_ERROR (Status)) {
3064 return Status;
3065 }
3066 ASSERT (StringPackage != NULL);
3067 Status = InvokeRegisteredFunction (
3068 Private,
3069 NotifyType,
3070 (VOID *) StringPackage,
3071 (UINT8) (PackageHeader.Type),
3072 DatabaseRecord->Handle
3073 );
3074 StringPkgIsAdd = TRUE;
3075 break;
3076 case EFI_HII_PACKAGE_FONTS:
3077 Status = InsertFontPackage (
3078 Private,
3079 PackageHdrPtr,
3080 NotifyType,
3081 DatabaseRecord->PackageList,
3082 &FontPackage
3083 );
3084 if (EFI_ERROR (Status)) {
3085 return Status;
3086 }
3087 Status = InvokeRegisteredFunction (
3088 Private,
3089 NotifyType,
3090 (VOID *) FontPackage,
3091 (UINT8) (PackageHeader.Type),
3092 DatabaseRecord->Handle
3093 );
3094 break;
3095 case EFI_HII_PACKAGE_IMAGES:
3096 Status = InsertImagePackage (
3097 PackageHdrPtr,
3098 NotifyType,
3099 DatabaseRecord->PackageList,
3100 &ImagePackage
3101 );
3102 if (EFI_ERROR (Status)) {
3103 return Status;
3104 }
3105 Status = InvokeRegisteredFunction (
3106 Private,
3107 NotifyType,
3108 (VOID *) ImagePackage,
3109 (UINT8) (PackageHeader.Type),
3110 DatabaseRecord->Handle
3111 );
3112 break;
3113 case EFI_HII_PACKAGE_SIMPLE_FONTS:
3114 Status = InsertSimpleFontPackage (
3115 PackageHdrPtr,
3116 NotifyType,
3117 DatabaseRecord->PackageList,
3118 &SimpleFontPackage
3119 );
3120 if (EFI_ERROR (Status)) {
3121 return Status;
3122 }
3123 Status = InvokeRegisteredFunction (
3124 Private,
3125 NotifyType,
3126 (VOID *) SimpleFontPackage,
3127 (UINT8) (PackageHeader.Type),
3128 DatabaseRecord->Handle
3129 );
3130 break;
3131 case EFI_HII_PACKAGE_DEVICE_PATH:
3132 Status = AddDevicePathPackage (
3133 Private,
3134 NotifyType,
3135 (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *) PackageHdrPtr + sizeof (EFI_HII_PACKAGE_HEADER)),
3136 DatabaseRecord
3137 );
3138 break;
3139 default:
3140 break;
3141 }
3142
3143 if (EFI_ERROR (Status)) {
3144 return Status;
3145 }
3146 //
3147 // goto header of next package
3148 //
3149 PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHdrPtr + PackageHeader.Length);
3150 CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
3151 }
3152
3153 //
3154 // Adjust String Package to make sure all string packages have the same max string ID.
3155 //
3156 if (!EFI_ERROR (Status) && StringPkgIsAdd) {
3157 Status = AdjustStringPackage (DatabaseRecord->PackageList);
3158 }
3159
3160 return Status;
3161 }
3162
3163
3164 /**
3165 This function exports a package list to a buffer. It is the worker function