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