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
InitializeHiiDatabase(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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
HiiFindHandles(IN EFI_HII_PROTOCOL * This,IN OUT UINT16 * HandleBufferLength,OUT FRAMEWORK_EFI_HII_HANDLE * Handle)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
HiiGetPrimaryLanguages(IN EFI_HII_PROTOCOL * This,IN FRAMEWORK_EFI_HII_HANDLE Handle,OUT EFI_STRING * LanguageString)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
HiiGetSupportedSecondaryLanguages(IN EFI_HII_HANDLE HiiHandle,IN CONST CHAR8 * PrimaryLanguage)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
HiiGetSecondaryLanguages(IN EFI_HII_PROTOCOL * This,IN FRAMEWORK_EFI_HII_HANDLE Handle,IN CHAR16 * PrimaryLanguage,OUT EFI_STRING * LanguageString)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