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