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