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