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