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