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