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