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