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