Home | History | Annotate | Download | only in FrameworkHiiOnUefiHiiThunk
      1 /** @file
      2 Framework to UEFI 2.1 HII Thunk. The driver consume UEFI HII protocols
      3 to produce a Framework HII protocol.
      4 
      5 Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "HiiDatabase.h"
     17 #include "HiiHandle.h"
     18 
     19 HII_THUNK_PRIVATE_DATA *mHiiThunkPrivateData;
     20 
     21 HII_THUNK_PRIVATE_DATA mHiiThunkPrivateDataTempate = {
     22   HII_THUNK_PRIVATE_DATA_SIGNATURE,
     23   (EFI_HANDLE) NULL,
     24   {
     25     HiiNewPack,
     26     HiiRemovePack,
     27     HiiFindHandles,
     28     HiiExportDatabase,
     29 
     30     HiiTestString,
     31     HiiGetGlyph,
     32     HiiGlyphToBlt,
     33 
     34     HiiNewString,
     35     HiiGetPrimaryLanguages,
     36     HiiGetSecondaryLanguages,
     37     HiiThunkGetString,
     38     HiiResetStrings,
     39     HiiGetLine,
     40     HiiGetForms,
     41     HiiGetDefaultImage,
     42     HiiThunkUpdateForm,
     43 
     44     HiiGetKeyboardLayout
     45   },
     46 
     47   {
     48     ///
     49     /// HiiHandleLinkList
     50     ///
     51     NULL, NULL
     52   },
     53 };
     54 
     55 EFI_FORMBROWSER_THUNK_PRIVATE_DATA mBrowserThunkPrivateDataTemplate = {
     56   EFI_FORMBROWSER_THUNK_PRIVATE_DATA_SIGNATURE,
     57   (EFI_HANDLE) NULL,
     58   (HII_THUNK_PRIVATE_DATA *) NULL,
     59   {
     60     ThunkSendForm,
     61     ThunkCreatePopUp
     62   }
     63 };
     64 
     65 
     66 CONST EFI_HII_DATABASE_PROTOCOL            *mHiiDatabase;
     67 CONST EFI_HII_IMAGE_PROTOCOL               *mHiiImageProtocol;
     68 CONST EFI_HII_STRING_PROTOCOL              *mHiiStringProtocol;
     69 CONST EFI_HII_FONT_PROTOCOL                *mHiiFontProtocol;
     70 CONST EFI_HII_CONFIG_ROUTING_PROTOCOL      *mHiiConfigRoutingProtocol;
     71 CONST EFI_FORM_BROWSER2_PROTOCOL           *mFormBrowser2Protocol;
     72 
     73 
     74 /**
     75   This routine initializes the HII Database.
     76 
     77   @param ImageHandle     Image handle for PCD DXE driver.
     78   @param SystemTable     Pointer to SystemTable.
     79 
     80   @retval  EFI_SUCCESS   The entry point alwasy return successfully.
     81 **/
     82 EFI_STATUS
     83 EFIAPI
     84 InitializeHiiDatabase (
     85   IN EFI_HANDLE           ImageHandle,
     86   IN EFI_SYSTEM_TABLE     *SystemTable
     87   )
     88 {
     89   HII_THUNK_PRIVATE_DATA *Private;
     90   EFI_HANDLE              Handle;
     91   EFI_STATUS              Status;
     92   UINTN                   BufferLength;
     93   EFI_HII_HANDLE          *Buffer;
     94   UINTN                   Index;
     95   HII_THUNK_CONTEXT       *ThunkContext;
     96 
     97 
     98   ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiCompatibilityProtocolGuid);
     99   ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiFormBrowserCompatibilityProtocolGuid);
    100 
    101   Private = AllocateCopyPool (sizeof (HII_THUNK_PRIVATE_DATA), &mHiiThunkPrivateDataTempate);
    102   ASSERT (Private != NULL);
    103   InitializeListHead (&Private->ThunkContextListHead);
    104 
    105   InitHiiHandleDatabase ();
    106 
    107   mHiiThunkPrivateData = Private;
    108 
    109   Status = gBS->LocateProtocol (
    110                   &gEfiHiiDatabaseProtocolGuid,
    111                   NULL,
    112                   (VOID **) &mHiiDatabase
    113                   );
    114   ASSERT_EFI_ERROR (Status);
    115 
    116   Status = gBS->LocateProtocol (
    117                   &gEfiHiiStringProtocolGuid,
    118                   NULL,
    119                   (VOID **) &mHiiStringProtocol
    120                   );
    121   ASSERT_EFI_ERROR (Status);
    122 
    123   Status = gBS->LocateProtocol (
    124                   &gEfiHiiFontProtocolGuid,
    125                   NULL,
    126                   (VOID **) &mHiiFontProtocol
    127                   );
    128   ASSERT_EFI_ERROR (Status);
    129 
    130   Status = gBS->LocateProtocol (
    131                   &gEfiHiiConfigRoutingProtocolGuid,
    132                   NULL,
    133                   (VOID **) &mHiiConfigRoutingProtocol
    134                   );
    135   ASSERT_EFI_ERROR (Status);
    136 
    137 
    138   Status = gBS->LocateProtocol (
    139                   &gEfiFormBrowser2ProtocolGuid,
    140                   NULL,
    141                   (VOID **) &mFormBrowser2Protocol
    142                   );
    143   ASSERT_EFI_ERROR (Status);
    144 
    145 
    146 
    147 
    148   //
    149   // Install protocol interface
    150   //
    151   Status = gBS->InstallProtocolInterface (
    152                   &Private->Handle,
    153                   &gEfiHiiCompatibilityProtocolGuid,
    154                   EFI_NATIVE_INTERFACE,
    155                   (VOID *) &Private->Hii
    156                   );
    157   ASSERT_EFI_ERROR (Status);
    158 
    159   Status = ListPackageLists (EFI_HII_PACKAGE_STRINGS, NULL, &BufferLength, &Buffer);
    160   if (Status == EFI_SUCCESS) {
    161     ASSERT (Buffer != NULL);
    162     for (Index = 0; Index < BufferLength / sizeof (EFI_HII_HANDLE); Index++) {
    163       ThunkContext = CreateThunkContextForUefiHiiHandle (Buffer[Index]);
    164       ASSERT (ThunkContext!= NULL);
    165 
    166       InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
    167     }
    168 
    169     FreePool (Buffer);
    170   }
    171 
    172   Status = mHiiDatabase->RegisterPackageNotify (
    173                            mHiiDatabase,
    174                            EFI_HII_PACKAGE_STRINGS,
    175                            NULL,
    176                            NewOrAddPackNotify,
    177                            EFI_HII_DATABASE_NOTIFY_NEW_PACK,
    178                            &Handle
    179                            );
    180   ASSERT_EFI_ERROR (Status);
    181 
    182   Status = mHiiDatabase->RegisterPackageNotify (
    183                            mHiiDatabase,
    184                            EFI_HII_PACKAGE_STRINGS,
    185                            NULL,
    186                            NewOrAddPackNotify,
    187                            EFI_HII_DATABASE_NOTIFY_ADD_PACK,
    188                            &Handle
    189                            );
    190   ASSERT_EFI_ERROR (Status);
    191 
    192   Status = mHiiDatabase->RegisterPackageNotify (
    193                            mHiiDatabase,
    194                            EFI_HII_PACKAGE_FORMS,
    195                            NULL,
    196                            NewOrAddPackNotify,
    197                            EFI_HII_DATABASE_NOTIFY_NEW_PACK,
    198                            &Handle
    199                            );
    200   ASSERT_EFI_ERROR (Status);
    201 
    202   Status = mHiiDatabase->RegisterPackageNotify (
    203                            mHiiDatabase,
    204                            EFI_HII_PACKAGE_FORMS,
    205                            NULL,
    206                            NewOrAddPackNotify,
    207                            EFI_HII_DATABASE_NOTIFY_ADD_PACK,
    208                            &Handle
    209                            );
    210   ASSERT_EFI_ERROR (Status);
    211 
    212   Status = mHiiDatabase->RegisterPackageNotify (
    213                            mHiiDatabase,
    214                            EFI_HII_PACKAGE_STRINGS,
    215                            NULL,
    216                            RemovePackNotify,
    217                            EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
    218                            &Handle
    219                            );
    220   ASSERT_EFI_ERROR (Status);
    221 
    222   InitSetBrowserStrings ();
    223 
    224   mBrowserThunkPrivateDataTemplate.ThunkPrivate = Private;
    225   Status = gBS->InstallProtocolInterface (
    226                   &mBrowserThunkPrivateDataTemplate.Handle,
    227                   &gEfiFormBrowserCompatibilityProtocolGuid,
    228                   EFI_NATIVE_INTERFACE,
    229                   (VOID *) &mBrowserThunkPrivateDataTemplate.FormBrowser
    230                   );
    231   ASSERT_EFI_ERROR (Status);
    232 
    233   return Status;
    234 }
    235 
    236 /**
    237   Determines the handles that are currently active in the database.
    238 
    239   This function determines the handles that are currently active in the database.
    240   For example, a program wishing to create a Setup-like configuration utility would use this call
    241   to determine the handles that are available. It would then use calls defined in the forms section
    242   below to extract forms and then interpret them.
    243 
    244   @param This                 A pointer to the EFI_HII_PROTOCOL instance.
    245   @param HandleBufferLength   On input, a pointer to the length of the handle buffer.
    246                               On output, the length of the handle buffer that is required for the handles found.
    247   @param Handle               Pointer to an array of EFI_HII_HANDLE instances returned.
    248                               Type EFI_HII_HANDLE is defined in EFI_HII_PROTOCOL.NewPack() in the Packages section.
    249 
    250   @retval EFI_SUCCESS         Handle was updated successfully.
    251 
    252   @retval EFI_BUFFER_TOO_SMALL The HandleBufferLength parameter indicates that Handle is too small
    253                                to support the number of handles. HandleBufferLength is updated with a value that
    254                                will enable the data to fit.
    255 **/
    256 EFI_STATUS
    257 EFIAPI
    258 HiiFindHandles (
    259   IN     EFI_HII_PROTOCOL *This,
    260   IN OUT UINT16           *HandleBufferLength,
    261   OUT    FRAMEWORK_EFI_HII_HANDLE    *Handle
    262   )
    263 {
    264   UINT16                      Count;
    265   LIST_ENTRY                  *Link;
    266   HII_THUNK_CONTEXT           *ThunkContext;
    267   HII_THUNK_PRIVATE_DATA      *Private;
    268 
    269   if (HandleBufferLength == NULL) {
    270     return EFI_INVALID_PARAMETER;
    271   }
    272 
    273   Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
    274 
    275   //
    276   // Count the number of handles.
    277   //
    278   Count = 0;
    279   Link = GetFirstNode (&Private->ThunkContextListHead);
    280   while (!IsNull (&Private->ThunkContextListHead, Link)) {
    281     Count++;
    282     Link = GetNextNode (&Private->ThunkContextListHead, Link);
    283   }
    284 
    285   if (Count > *HandleBufferLength) {
    286     *HandleBufferLength = (UINT16) (Count * sizeof (FRAMEWORK_EFI_HII_HANDLE));
    287     return EFI_BUFFER_TOO_SMALL;
    288   }
    289 
    290   //
    291   // Output the handles.
    292   //
    293   Count = 0;
    294   Link = GetFirstNode (&Private->ThunkContextListHead);
    295   while (!IsNull (&Private->ThunkContextListHead, Link)) {
    296 
    297     ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
    298     Handle[Count] = ThunkContext->FwHiiHandle;
    299 
    300     Count++;
    301     Link = GetNextNode (&Private->ThunkContextListHead, Link);
    302 
    303   }
    304 
    305   *HandleBufferLength = (UINT16) (Count * sizeof (FRAMEWORK_EFI_HII_HANDLE));
    306   return EFI_SUCCESS;
    307 }
    308 
    309 /**
    310   Allows a program to determine the primary languages that are supported on a given handle.
    311 
    312   This routine is intended to be used by drivers to query the interface database for supported languages.
    313   This routine returns a string of concatenated 3-byte language identifiers, one per string package associated with the handle.
    314 
    315   @param This           A pointer to the EFI_HII_PROTOCOL instance.
    316   @param Handle         The handle on which the strings reside. Type EFI_HII_HANDLE is defined in EFI_HII_PROTOCOL.NewPack()
    317                         in the Packages section.
    318   @param LanguageString A string allocated by GetPrimaryLanguages() that contains a list of all primary languages
    319                         registered on the handle. The routine will not return the three-spaces language identifier used in
    320                         other functions to indicate non-language-specific strings.
    321 
    322   @retval EFI_SUCCESS            LanguageString was correctly returned.
    323 
    324   @retval EFI_INVALID_PARAMETER  The Handle was unknown.
    325 **/
    326 EFI_STATUS
    327 EFIAPI
    328 HiiGetPrimaryLanguages (
    329   IN  EFI_HII_PROTOCOL            *This,
    330   IN  FRAMEWORK_EFI_HII_HANDLE    Handle,
    331   OUT EFI_STRING                  *LanguageString
    332   )
    333 {
    334   HII_THUNK_PRIVATE_DATA     *Private;
    335   EFI_HII_HANDLE             UefiHiiHandle;
    336   CHAR8                      *LangCodes4646;
    337   CHAR16                     *UnicodeLangCodes639;
    338   CHAR8                      *LangCodes639;
    339   EFI_STATUS                 Status;
    340 
    341   Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
    342 
    343   UefiHiiHandle = FwHiiHandleToUefiHiiHandle (Private, Handle);
    344   if (UefiHiiHandle == NULL) {
    345     return EFI_INVALID_PARAMETER;
    346   }
    347 
    348   LangCodes4646 = HiiGetSupportedLanguages (UefiHiiHandle);
    349 
    350   if (LangCodes4646 == NULL) {
    351     return EFI_INVALID_PARAMETER;
    352   }
    353 
    354   LangCodes639 = ConvertLanguagesRfc4646ToIso639 (LangCodes4646);
    355   if (LangCodes639 == NULL) {
    356     Status = EFI_INVALID_PARAMETER;
    357     goto Done;
    358   }
    359 
    360   UnicodeLangCodes639 = AllocateZeroPool (AsciiStrSize (LangCodes639) * sizeof (CHAR16));
    361   if (UnicodeLangCodes639 == NULL) {
    362     Status =  EFI_OUT_OF_RESOURCES;
    363     goto Done;
    364   }
    365 
    366   //
    367   // The language returned is in RFC 639-2 format.
    368   //
    369   AsciiStrToUnicodeStr (LangCodes639, UnicodeLangCodes639);
    370   *LanguageString = UnicodeLangCodes639;
    371   Status = EFI_SUCCESS;
    372 
    373 Done:
    374   FreePool (LangCodes4646);
    375   if (LangCodes639 != NULL) {
    376     FreePool (LangCodes639);
    377   }
    378 
    379   return Status;
    380 }
    381 
    382 /**
    383   This function returns the list of supported 2nd languages, in the format specified
    384   in UEFI specification Appendix M.
    385 
    386   If HiiHandle is not a valid Handle in the HII database, then ASSERT.
    387   If not enough resource to complete the operation, then ASSERT.
    388 
    389   @param  HiiHandle              The HII package list handle.
    390   @param  PrimaryLanguage        Pointer to language name buffer.
    391 
    392   @return The supported languages.
    393 
    394 **/
    395 CHAR8 *
    396 EFIAPI
    397 HiiGetSupportedSecondaryLanguages (
    398   IN EFI_HII_HANDLE           HiiHandle,
    399   IN CONST CHAR8              *PrimaryLanguage
    400   )
    401 {
    402   EFI_STATUS  Status;
    403   UINTN       BufferSize;
    404   CHAR8       *LanguageString;
    405 
    406   ASSERT (HiiHandle != NULL);
    407 
    408   //
    409   // Collect current supported 2nd Languages for given HII handle
    410   // First try allocate 4K buffer to store the current supported 2nd languages.
    411   //
    412   BufferSize = 0x1000;
    413   LanguageString = AllocateZeroPool (BufferSize);
    414   if (LanguageString == NULL) {
    415     return NULL;
    416   }
    417 
    418   Status = mHiiStringProtocol->GetSecondaryLanguages (mHiiStringProtocol, HiiHandle, PrimaryLanguage, LanguageString, &BufferSize);
    419   ASSERT (Status != EFI_NOT_FOUND);
    420 
    421   if (Status == EFI_BUFFER_TOO_SMALL) {
    422     FreePool (LanguageString);
    423     LanguageString = AllocateZeroPool (BufferSize);
    424     if (LanguageString == NULL) {
    425       return NULL;
    426     }
    427 
    428     Status = mHiiStringProtocol->GetSecondaryLanguages (mHiiStringProtocol, HiiHandle, PrimaryLanguage, LanguageString, &BufferSize);
    429   }
    430 
    431   if (EFI_ERROR (Status)) {
    432     LanguageString = NULL;
    433   }
    434 
    435   return LanguageString;
    436 }
    437 
    438 /**
    439   Allows a program to determine which secondary languages are supported on a given handle for a given primary language
    440 
    441   This routine is intended to be used by drivers to query the interface database for supported languages.
    442   This routine returns a string of concatenated 3-byte language identifiers, one per string package associated with the handle.
    443 
    444   @param This           A pointer to the EFI_HII_PROTOCOL instance.
    445   @param Handle         The handle on which the strings reside. Type EFI_HII_HANDLE is defined in EFI_HII_PROTOCOL.NewPack()
    446                         in the Packages section.
    447   @param PrimaryLanguage Pointer to a NULL-terminated string containing a single ISO 639-2 language identifier, indicating
    448                          the primary language.
    449   @param LanguageString  A string allocated by GetSecondaryLanguages() containing a list of all secondary languages registered
    450                          on the handle. The routine will not return the three-spaces language identifier used in other functions
    451                          to indicate non-language-specific strings, nor will it return the primary language. This function succeeds
    452                          but returns a NULL LanguageString if there are no secondary languages associated with the input Handle and
    453                          PrimaryLanguage pair. Type EFI_STRING is defined in String.
    454 
    455   @retval EFI_SUCCESS            LanguageString was correctly returned.
    456   @retval EFI_INVALID_PARAMETER  The Handle was unknown.
    457 **/
    458 EFI_STATUS
    459 EFIAPI
    460 HiiGetSecondaryLanguages (
    461   IN  EFI_HII_PROTOCOL              *This,
    462   IN  FRAMEWORK_EFI_HII_HANDLE      Handle,
    463   IN  CHAR16                        *PrimaryLanguage,
    464   OUT EFI_STRING                    *LanguageString
    465   )
    466 {
    467   HII_THUNK_PRIVATE_DATA     *Private;
    468   EFI_HII_HANDLE             UefiHiiHandle;
    469   CHAR8                      *PrimaryLang4646;
    470   CHAR8                      *PrimaryLang639;
    471   CHAR8                      *SecLangCodes4646;
    472   CHAR8                      *SecLangCodes639;
    473   CHAR16                     *UnicodeSecLangCodes639;
    474   EFI_STATUS                 Status;
    475 
    476   Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
    477 
    478   SecLangCodes639        = NULL;
    479   SecLangCodes4646       = NULL;
    480   PrimaryLang4646        = NULL;
    481   UnicodeSecLangCodes639 = NULL;
    482 
    483   UefiHiiHandle = FwHiiHandleToUefiHiiHandle (Private, Handle);
    484   if (UefiHiiHandle == NULL) {
    485     return EFI_INVALID_PARAMETER;
    486   }
    487 
    488   PrimaryLang639 = AllocateZeroPool (StrLen (PrimaryLanguage) + 1);
    489   if (PrimaryLang639 == NULL) {
    490     Status = EFI_OUT_OF_RESOURCES;
    491     goto Done;
    492   }
    493 
    494   UnicodeStrToAsciiStr (PrimaryLanguage, PrimaryLang639);
    495 
    496   PrimaryLang4646 = ConvertLanguagesIso639ToRfc4646 (PrimaryLang639);
    497   ASSERT_EFI_ERROR (PrimaryLang4646 != NULL);
    498 
    499   SecLangCodes4646 = HiiGetSupportedSecondaryLanguages (UefiHiiHandle, PrimaryLang4646);
    500 
    501   if (SecLangCodes4646 == NULL) {
    502     Status =  EFI_INVALID_PARAMETER;
    503     goto Done;
    504   }
    505 
    506   SecLangCodes639 = ConvertLanguagesIso639ToRfc4646 (SecLangCodes4646);
    507   if (SecLangCodes639 == NULL) {
    508     Status =  EFI_INVALID_PARAMETER;
    509     goto Done;
    510   }
    511 
    512   UnicodeSecLangCodes639 = AllocateZeroPool (AsciiStrSize (SecLangCodes639) * sizeof (CHAR16));
    513   if (UnicodeSecLangCodes639 == NULL) {
    514     Status = EFI_OUT_OF_RESOURCES;
    515     goto Done;
    516   }
    517 
    518   //
    519   // The language returned is in RFC 4646 format.
    520   //
    521   *LanguageString = AsciiStrToUnicodeStr (SecLangCodes639, UnicodeSecLangCodes639);
    522   Status = EFI_SUCCESS;
    523 
    524 Done:
    525   if (PrimaryLang639 != NULL) {
    526     FreePool (PrimaryLang639);
    527   }
    528 
    529   if (SecLangCodes639 != NULL) {
    530     FreePool (SecLangCodes639);
    531   }
    532 
    533   if (PrimaryLang4646 != NULL) {
    534     FreePool (PrimaryLang4646);
    535   }
    536 
    537   if (SecLangCodes4646 != NULL) {
    538     FreePool (SecLangCodes4646);
    539   }
    540   if (UnicodeSecLangCodes639 != NULL) {
    541     FreePool (UnicodeSecLangCodes639);
    542   }
    543 
    544   return Status;
    545 }
    546 
    547