]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiDatabase.c
HII Library Class interface refine.
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiOnUefiHiiThunk / HiiDatabase.c
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, Intel Corporation
6 All rights reserved. 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 for (Index = 0; Index < BufferLength / sizeof (EFI_HII_HANDLE); Index++) {
162 ThunkContext = CreateThunkContextForUefiHiiHandle (Buffer[Index]);
163 ASSERT (ThunkContext!= NULL);
164
165 InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
166 }
167
168 FreePool (Buffer);
169 }
170
171 Status = mHiiDatabase->RegisterPackageNotify (
172 mHiiDatabase,
173 EFI_HII_PACKAGE_STRINGS,
174 NULL,
175 NewOrAddPackNotify,
176 EFI_HII_DATABASE_NOTIFY_NEW_PACK,
177 &Handle
178 );
179 ASSERT_EFI_ERROR (Status);
180
181 Status = mHiiDatabase->RegisterPackageNotify (
182 mHiiDatabase,
183 EFI_HII_PACKAGE_STRINGS,
184 NULL,
185 NewOrAddPackNotify,
186 EFI_HII_DATABASE_NOTIFY_ADD_PACK,
187 &Handle
188 );
189 ASSERT_EFI_ERROR (Status);
190
191 Status = mHiiDatabase->RegisterPackageNotify (
192 mHiiDatabase,
193 EFI_HII_PACKAGE_FORMS,
194 NULL,
195 NewOrAddPackNotify,
196 EFI_HII_DATABASE_NOTIFY_NEW_PACK,
197 &Handle
198 );
199 ASSERT_EFI_ERROR (Status);
200
201 Status = mHiiDatabase->RegisterPackageNotify (
202 mHiiDatabase,
203 EFI_HII_PACKAGE_FORMS,
204 NULL,
205 NewOrAddPackNotify,
206 EFI_HII_DATABASE_NOTIFY_ADD_PACK,
207 &Handle
208 );
209 ASSERT_EFI_ERROR (Status);
210
211 Status = mHiiDatabase->RegisterPackageNotify (
212 mHiiDatabase,
213 EFI_HII_PACKAGE_STRINGS,
214 NULL,
215 RemovePackNotify,
216 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
217 &Handle
218 );
219 ASSERT_EFI_ERROR (Status);
220
221 InitSetBrowserStrings ();
222
223 mBrowserThunkPrivateDataTemplate.ThunkPrivate = Private;
224 Status = gBS->InstallProtocolInterface (
225 &mBrowserThunkPrivateDataTemplate.Handle,
226 &gEfiFormBrowserCompatibilityProtocolGuid,
227 EFI_NATIVE_INTERFACE,
228 (VOID *) &mBrowserThunkPrivateDataTemplate.FormBrowser
229 );
230 ASSERT_EFI_ERROR (Status);
231
232 return Status;
233 }
234
235 /**
236 Determines the handles that are currently active in the database.
237
238 This function determines the handles that are currently active in the database.
239 For example, a program wishing to create a Setup-like configuration utility would use this call
240 to determine the handles that are available. It would then use calls defined in the forms section
241 below to extract forms and then interpret them.
242
243 @param This A pointer to the EFI_HII_PROTOCOL instance.
244 @param HandleBufferLength On input, a pointer to the length of the handle buffer.
245 On output, the length of the handle buffer that is required for the handles found.
246 @param Handle An array of EFI_HII_HANDLE instances returned.
247 Type EFI_HII_HANDLE is defined in EFI_HII_PROTOCOL.NewPack() in the Packages section.
248
249 @retval EFI_SUCCESS Handle was updated successfully.
250
251 @retval EFI_BUFFER_TOO_SMALL The HandleBufferLength parameter indicates that Handle is too small
252 to support the number of handles. HandleBufferLength is updated with a value that
253 will enable the data to fit.
254 **/
255 EFI_STATUS
256 EFIAPI
257 HiiFindHandles (
258 IN EFI_HII_PROTOCOL *This,
259 IN OUT UINT16 *HandleBufferLength,
260 OUT FRAMEWORK_EFI_HII_HANDLE Handle[1]
261 )
262 {
263 UINT16 Count;
264 LIST_ENTRY *Link;
265 HII_THUNK_CONTEXT *ThunkContext;
266 HII_THUNK_PRIVATE_DATA *Private;
267
268 if (HandleBufferLength == NULL) {
269 return EFI_INVALID_PARAMETER;
270 }
271
272 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
273
274 //
275 // Count the number of handles.
276 //
277 Count = 0;
278 Link = GetFirstNode (&Private->ThunkContextListHead);
279 while (!IsNull (&Private->ThunkContextListHead, Link)) {
280 Count++;
281 Link = GetNextNode (&Private->ThunkContextListHead, Link);
282 }
283
284 if (Count > *HandleBufferLength) {
285 *HandleBufferLength = (UINT16) (Count * sizeof (FRAMEWORK_EFI_HII_HANDLE));
286 return EFI_BUFFER_TOO_SMALL;
287 }
288
289 //
290 // Output the handles.
291 //
292 Count = 0;
293 Link = GetFirstNode (&Private->ThunkContextListHead);
294 while (!IsNull (&Private->ThunkContextListHead, Link)) {
295
296 ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
297 Handle[Count] = ThunkContext->FwHiiHandle;
298
299 Count++;
300 Link = GetNextNode (&Private->ThunkContextListHead, Link);
301
302 }
303
304 *HandleBufferLength = (UINT16) (Count * sizeof (FRAMEWORK_EFI_HII_HANDLE));
305 return EFI_SUCCESS;
306 }
307
308 EFI_STATUS
309 LangCodes3066To639 (
310 IN CHAR8 *LangCodes3066,
311 IN CHAR8 **LangCodes639
312 )
313 {
314 CHAR8 *AsciiLangCodes;
315 CHAR8 *Lang;
316 UINTN Index;
317 UINTN Count;
318 EFI_STATUS Status;
319
320 ASSERT (LangCodes3066 != NULL);
321 ASSERT (LangCodes639 != NULL);
322
323 //
324 // Allocate working buffer to contain substring of LangCodes3066.
325 //
326 Lang = AllocatePool (AsciiStrSize (LangCodes3066));
327 if (Lang == NULL) {
328 return EFI_OUT_OF_RESOURCES;
329 }
330
331 //
332 // Count the number of RFC 3066 language codes.
333 //
334 Index = 0;
335 AsciiLangCodes = LangCodes3066;
336 while (AsciiStrLen (AsciiLangCodes) != 0) {
337 HiiLibGetNextLanguage (&AsciiLangCodes, Lang);
338 Index++;
339 }
340
341 Count = Index;
342
343 //
344 //
345 //
346 *LangCodes639 = AllocateZeroPool (ISO_639_2_ENTRY_SIZE * Count + 1);
347 if (*LangCodes639 == NULL) {
348 Status = EFI_OUT_OF_RESOURCES;
349 goto Done;
350 }
351
352 AsciiLangCodes = LangCodes3066;
353
354 for (Index = 0; Index < Count; Index++) {
355 HiiLibGetNextLanguage (&AsciiLangCodes, Lang);
356 Status = ConvertRfc3066LanguageToIso639Language (Lang, *LangCodes639 + Index * ISO_639_2_ENTRY_SIZE);
357 ASSERT_EFI_ERROR (Status);
358 }
359
360 Status = EFI_SUCCESS;
361
362 Done:
363 FreePool (Lang);
364 return Status;
365 }
366
367 /**
368 Allows a program to determine the primary languages that are supported on a given handle.
369
370 This routine is intended to be used by drivers to query the interface database for supported languages.
371 This routine returns a string of concatenated 3-byte language identifiers, one per string package associated with the handle.
372
373 @param This A pointer to the EFI_HII_PROTOCOL instance.
374 @param Handle The handle on which the strings reside. Type EFI_HII_HANDLE is defined in EFI_HII_PROTOCOL.NewPack()
375 in the Packages section.
376 @param LanguageString A string allocated by GetPrimaryLanguages() that contains a list of all primary languages
377 registered on the handle. The routine will not return the three-spaces language identifier used in
378 other functions to indicate non-language-specific strings.
379
380 @reval EFI_SUCCESS LanguageString was correctly returned.
381
382 @reval EFI_INVALID_PARAMETER The Handle was unknown.
383 **/
384 EFI_STATUS
385 EFIAPI
386 HiiGetPrimaryLanguages (
387 IN EFI_HII_PROTOCOL *This,
388 IN FRAMEWORK_EFI_HII_HANDLE Handle,
389 OUT EFI_STRING *LanguageString
390 )
391 {
392 HII_THUNK_PRIVATE_DATA *Private;
393 EFI_HII_HANDLE UefiHiiHandle;
394 CHAR8 *LangCodes3066;
395 CHAR16 *UnicodeLangCodes639;
396 CHAR8 *LangCodes639;
397 EFI_STATUS Status;
398
399 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
400
401 UefiHiiHandle = FwHiiHandleToUefiHiiHandle (Private, Handle);
402 if (UefiHiiHandle == NULL) {
403 return EFI_INVALID_PARAMETER;
404 }
405
406 LangCodes3066 = HiiGetSupportedLanguages (UefiHiiHandle);
407
408 if (LangCodes3066 == NULL) {
409 return EFI_INVALID_PARAMETER;
410 }
411
412
413 LangCodes639 = NULL;
414 Status = LangCodes3066To639 (LangCodes3066, &LangCodes639);
415 if (EFI_ERROR (Status)) {
416 goto Done;
417 }
418
419 UnicodeLangCodes639 = AllocateZeroPool (AsciiStrSize (LangCodes639) * sizeof (CHAR16));
420 if (UnicodeLangCodes639 == NULL) {
421 Status = EFI_OUT_OF_RESOURCES;
422 goto Done;
423 }
424
425 //
426 // The language returned is in RFC 639-2 format.
427 //
428 AsciiStrToUnicodeStr (LangCodes639, UnicodeLangCodes639);
429 *LanguageString = UnicodeLangCodes639;
430
431 Done:
432 FreePool (LangCodes3066);
433 if (LangCodes639 != NULL) {
434 FreePool (LangCodes639);
435 }
436
437 return Status;
438 }
439
440 /**
441 This function returns the list of supported 2nd languages, in the format specified
442 in UEFI specification Appendix M.
443
444 If HiiHandle is not a valid Handle in the HII database, then ASSERT.
445 If not enough resource to complete the operation, then ASSERT.
446
447 @param HiiHandle The HII package list handle.
448 @param FirstLanguage Pointer to language name buffer.
449
450 @return The supported languages.
451
452 **/
453 CHAR8 *
454 EFIAPI
455 HiiGetSupportedSecondaryLanguages (
456 IN EFI_HII_HANDLE HiiHandle,
457 IN CONST CHAR8 *FirstLanguage
458 )
459 {
460 EFI_STATUS Status;
461 UINTN BufferSize;
462 CHAR8 *LanguageString;
463
464 ASSERT (HiiHandle != NULL);
465
466 //
467 // Collect current supported 2nd Languages for given HII handle
468 // First try allocate 4K buffer to store the current supported 2nd languages.
469 //
470 BufferSize = 0x1000;
471 LanguageString = AllocateZeroPool (BufferSize);
472 if (LanguageString == NULL) {
473 return NULL;
474 }
475
476 Status = mHiiStringProtocol->GetSecondaryLanguages (mHiiStringProtocol, HiiHandle, FirstLanguage, LanguageString, &BufferSize);
477 ASSERT (Status != EFI_NOT_FOUND);
478
479 if (Status == EFI_BUFFER_TOO_SMALL) {
480 FreePool (LanguageString);
481 LanguageString = AllocateZeroPool (BufferSize);
482 if (LanguageString == NULL) {
483 return NULL;
484 }
485
486 Status = mHiiStringProtocol->GetSecondaryLanguages (mHiiStringProtocol, HiiHandle, FirstLanguage, LanguageString, &BufferSize);
487 }
488
489 if (EFI_ERROR (Status)) {
490 LanguageString = NULL;
491 }
492
493 return LanguageString;
494 }
495
496 /**
497 Allows a program to determine which secondary languages are supported on a given handle for a given primary language
498
499 This routine is intended to be used by drivers to query the interface database for supported languages.
500 This routine returns a string of concatenated 3-byte language identifiers, one per string package associated with the handle.
501
502 @param This A pointer to the EFI_HII_PROTOCOL instance.
503 @param Handle The handle on which the strings reside. Type EFI_HII_HANDLE is defined in EFI_HII_PROTOCOL.NewPack()
504 in the Packages section.
505 @param PrimaryLanguage Pointer to a NULL-terminated string containing a single ISO 639-2 language identifier, indicating
506 the primary language.
507 @param LanguageString A string allocated by GetSecondaryLanguages() containing a list of all secondary languages registered
508 on the handle. The routine will not return the three-spaces language identifier used in other functions
509 to indicate non-language-specific strings, nor will it return the primary language. This function succeeds
510 but returns a NULL LanguageString if there are no secondary languages associated with the input Handle and
511 PrimaryLanguage pair. Type EFI_STRING is defined in String.
512
513 @reval EFI_SUCCESS LanguageString was correctly returned.
514 @reval EFI_INVALID_PARAMETER The Handle was unknown.
515 **/
516 EFI_STATUS
517 EFIAPI
518 HiiGetSecondaryLanguages (
519 IN EFI_HII_PROTOCOL *This,
520 IN FRAMEWORK_EFI_HII_HANDLE Handle,
521 IN CHAR16 *PrimaryLanguage,
522 OUT EFI_STRING *LanguageString
523 )
524 {
525 HII_THUNK_PRIVATE_DATA *Private;
526 EFI_HII_HANDLE UefiHiiHandle;
527 CHAR8 *PrimaryLang3066;
528 CHAR8 *PrimaryLang639;
529 CHAR8 *SecLangCodes3066;
530 CHAR8 *SecLangCodes639;
531 CHAR16 *UnicodeSecLangCodes639;
532 EFI_STATUS Status;
533
534 Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
535
536 SecLangCodes639 = NULL;
537 SecLangCodes3066 = NULL;
538 PrimaryLang3066 = NULL;
539 UnicodeSecLangCodes639 = NULL;
540
541 UefiHiiHandle = FwHiiHandleToUefiHiiHandle (Private, Handle);
542 if (UefiHiiHandle == NULL) {
543 return EFI_INVALID_PARAMETER;
544 }
545
546 PrimaryLang639 = AllocateZeroPool (StrLen (PrimaryLanguage) + 1);
547 if (PrimaryLang639 == NULL) {
548 Status = EFI_OUT_OF_RESOURCES;
549 goto Done;
550 }
551
552 UnicodeStrToAsciiStr (PrimaryLanguage, PrimaryLang639);
553
554 PrimaryLang3066 = ConvertIso639LanguageToRfc3066Language (PrimaryLang639);
555 ASSERT_EFI_ERROR (PrimaryLang3066 != NULL);
556
557 SecLangCodes3066 = HiiGetSupportedSecondaryLanguages (UefiHiiHandle, PrimaryLang3066);
558
559 if (SecLangCodes3066 == NULL) {
560 Status = EFI_INVALID_PARAMETER;
561 goto Done;
562 }
563
564 Status = LangCodes3066To639 (SecLangCodes3066, &SecLangCodes639);
565 if (EFI_ERROR (Status)) {
566 goto Done;
567 }
568
569 UnicodeSecLangCodes639 = AllocateZeroPool (AsciiStrSize (SecLangCodes639) * sizeof (CHAR16));
570 if (UnicodeSecLangCodes639 == NULL) {
571 Status = EFI_OUT_OF_RESOURCES;
572 goto Done;
573 }
574
575 //
576 // The language returned is in RFC 3066 format.
577 //
578 *LanguageString = AsciiStrToUnicodeStr (SecLangCodes639, UnicodeSecLangCodes639);
579
580 Done:
581 if (PrimaryLang639 != NULL) {
582 FreePool (PrimaryLang639);
583 }
584
585 if (SecLangCodes639 != NULL) {
586 FreePool (SecLangCodes639);
587 }
588
589 if (PrimaryLang3066 != NULL) {
590 FreePool (PrimaryLang3066);
591 }
592
593 if (SecLangCodes3066 != NULL) {
594 FreePool (SecLangCodes3066);
595 }
596 if (UnicodeSecLangCodes639 != NULL) {
597 FreePool (UnicodeSecLangCodes639);
598 }
599
600 return Status;
601 }
602
603