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 (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