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