Home | History | Annotate | Download | only in HiiDatabaseDxe
      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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