1 /** @file 2 Implementation for EFI_HII_STRING_PROTOCOL. 3 4 5 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR> 6 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> 7 This program and the accompanying materials 8 are licensed and made available under the terms and conditions of the BSD License 9 which accompanies this distribution. The full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 15 **/ 16 17 18 #include "HiiDatabase.h" 19 20 CHAR16 mLanguageWindow[16] = { 21 0x0000, 0x0080, 0x0100, 0x0300, 22 0x2000, 0x2080, 0x2100, 0x3000, 23 0x0080, 0x00C0, 0x0400, 0x0600, 24 0x0900, 0x3040, 0x30A0, 0xFF00 25 }; 26 27 28 /** 29 This function checks whether a global font info is referred by local 30 font info list or not. (i.e. HII_FONT_INFO is generated.) If not, create 31 a HII_FONT_INFO to refer it locally. 32 33 This is a internal function. 34 35 36 @param Private Hii database private structure. 37 @param StringPackage HII string package instance. 38 @param FontId Font identifer, which must be unique within the string package. 39 @param DuplicateEnable If true, duplicate HII_FONT_INFO which refers to 40 the same EFI_FONT_INFO is permitted. Otherwise it 41 is not allowed. 42 @param GlobalFontInfo Input a global font info which specify a 43 EFI_FONT_INFO. 44 @param LocalFontInfo Output a local font info which refers to a 45 EFI_FONT_INFO. 46 47 @retval TRUE Already referred before calling this function. 48 @retval FALSE Not referred before calling this function. 49 50 **/ 51 BOOLEAN 52 ReferFontInfoLocally ( 53 IN HII_DATABASE_PRIVATE_DATA *Private, 54 IN HII_STRING_PACKAGE_INSTANCE *StringPackage, 55 IN UINT8 FontId, 56 IN BOOLEAN DuplicateEnable, 57 IN HII_GLOBAL_FONT_INFO *GlobalFontInfo, 58 OUT HII_FONT_INFO **LocalFontInfo 59 ) 60 { 61 HII_FONT_INFO *LocalFont; 62 LIST_ENTRY *Link; 63 64 ASSERT (Private != NULL && StringPackage != NULL && GlobalFontInfo != NULL && LocalFontInfo != NULL); 65 66 if (!DuplicateEnable) { 67 for (Link = StringPackage->FontInfoList.ForwardLink; 68 Link != &StringPackage->FontInfoList; 69 Link = Link->ForwardLink 70 ) { 71 LocalFont = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE); 72 if (LocalFont->GlobalEntry == &GlobalFontInfo->Entry) { 73 // 74 // Already referred by local font info list, return directly. 75 // 76 *LocalFontInfo = LocalFont; 77 return TRUE; 78 } 79 } 80 } 81 // FontId identifies EFI_FONT_INFO in local string package uniquely. 82 // GlobalEntry points to a HII_GLOBAL_FONT_INFO which identifies 83 // EFI_FONT_INFO uniquely in whole hii database. 84 // 85 LocalFont = (HII_FONT_INFO *) AllocateZeroPool (sizeof (HII_FONT_INFO)); 86 ASSERT (LocalFont != NULL); 87 88 LocalFont->Signature = HII_FONT_INFO_SIGNATURE; 89 LocalFont->FontId = FontId; 90 LocalFont->GlobalEntry = &GlobalFontInfo->Entry; 91 InsertTailList (&StringPackage->FontInfoList, &LocalFont->Entry); 92 93 *LocalFontInfo = LocalFont; 94 return FALSE; 95 } 96 97 98 /** 99 Convert Ascii string text to unicode string test. 100 101 This is a internal function. 102 103 104 @param StringDest Buffer to store the string text. If it is NULL, 105 only the size will be returned. 106 @param StringSrc Points to current null-terminated string. 107 @param BufferSize Length of the buffer. 108 109 @retval EFI_SUCCESS The string text was outputted successfully. 110 @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string 111 text. BufferSize is updated to the required buffer 112 size. 113 114 **/ 115 EFI_STATUS 116 ConvertToUnicodeText ( 117 OUT EFI_STRING StringDest, 118 IN CHAR8 *StringSrc, 119 IN OUT UINTN *BufferSize 120 ) 121 { 122 UINTN StringSize; 123 UINTN Index; 124 125 ASSERT (StringSrc != NULL && BufferSize != NULL); 126 127 StringSize = AsciiStrSize (StringSrc) * 2; 128 if (*BufferSize < StringSize || StringDest == NULL) { 129 *BufferSize = StringSize; 130 return EFI_BUFFER_TOO_SMALL; 131 } 132 133 for (Index = 0; Index < AsciiStrLen (StringSrc); Index++) { 134 StringDest[Index] = (CHAR16) StringSrc[Index]; 135 } 136 137 StringDest[Index] = 0; 138 return EFI_SUCCESS; 139 } 140 141 142 /** 143 Calculate the size of StringSrc and output it. If StringDest is not NULL, 144 copy string text from src to dest. 145 146 This is a internal function. 147 148 @param StringDest Buffer to store the string text. If it is NULL, 149 only the size will be returned. 150 @param StringSrc Points to current null-terminated string. 151 @param BufferSize Length of the buffer. 152 153 @retval EFI_SUCCESS The string text was outputted successfully. 154 @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string 155 text. BufferSize is updated to the required buffer 156 size. 157 158 **/ 159 EFI_STATUS 160 GetUnicodeStringTextOrSize ( 161 OUT EFI_STRING StringDest, OPTIONAL 162 IN UINT8 *StringSrc, 163 IN OUT UINTN *BufferSize 164 ) 165 { 166 UINTN StringSize; 167 UINT8 *StringPtr; 168 169 ASSERT (StringSrc != NULL && BufferSize != NULL); 170 171 StringSize = sizeof (CHAR16); 172 StringPtr = StringSrc; 173 while (ReadUnaligned16 ((UINT16 *) StringPtr) != 0) { 174 StringSize += sizeof (CHAR16); 175 StringPtr += sizeof (CHAR16); 176 } 177 178 if (*BufferSize < StringSize) { 179 *BufferSize = StringSize; 180 return EFI_BUFFER_TOO_SMALL; 181 } 182 if (StringDest != NULL) { 183 CopyMem (StringDest, StringSrc, StringSize); 184 } 185 186 *BufferSize = StringSize; 187 return EFI_SUCCESS; 188 } 189 190 191 /** 192 Copy string font info to a buffer. 193 194 This is a internal function. 195 196 @param StringPackage Hii string package instance. 197 @param FontId Font identifier which is unique in a string 198 package. 199 @param StringFontInfo Buffer to record the output font info. It's 200 caller's responsibility to free this buffer. 201 202 @retval EFI_SUCCESS The string font is outputted successfully. 203 @retval EFI_NOT_FOUND The specified font id does not exist. 204 205 **/ 206 EFI_STATUS 207 GetStringFontInfo ( 208 IN HII_STRING_PACKAGE_INSTANCE *StringPackage, 209 IN UINT8 FontId, 210 OUT EFI_FONT_INFO **StringFontInfo 211 ) 212 { 213 LIST_ENTRY *Link; 214 HII_FONT_INFO *FontInfo; 215 HII_GLOBAL_FONT_INFO *GlobalFont; 216 217 ASSERT (StringFontInfo != NULL && StringPackage != NULL); 218 219 for (Link = StringPackage->FontInfoList.ForwardLink; Link != &StringPackage->FontInfoList; Link = Link->ForwardLink) { 220 FontInfo = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE); 221 if (FontInfo->FontId == FontId) { 222 GlobalFont = CR (FontInfo->GlobalEntry, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE); 223 *StringFontInfo = (EFI_FONT_INFO *) AllocateZeroPool (GlobalFont->FontInfoSize); 224 if (*StringFontInfo == NULL) { 225 return EFI_OUT_OF_RESOURCES; 226 } 227 CopyMem (*StringFontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize); 228 return EFI_SUCCESS; 229 } 230 } 231 232 return EFI_NOT_FOUND; 233 } 234 235 236 /** 237 Parse all string blocks to find a String block specified by StringId. 238 If StringId = (EFI_STRING_ID) (-1), find out all EFI_HII_SIBT_FONT blocks 239 within this string package and backup its information. If LastStringId is 240 specified, the string id of last string block will also be output. 241 If StringId = 0, output the string id of last string block (EFI_HII_SIBT_STRING). 242 243 @param Private Hii database private structure. 244 @param StringPackage Hii string package instance. 245 @param StringId The string's id, which is unique within 246 PackageList. 247 @param BlockType Output the block type of found string block. 248 @param StringBlockAddr Output the block address of found string block. 249 @param StringTextOffset Offset, relative to the found block address, of 250 the string text information. 251 @param LastStringId Output the last string id when StringId = 0 or StringId = -1. 252 @param StartStringId The first id in the skip block which StringId in the block. 253 254 @retval EFI_SUCCESS The string text and font is retrieved 255 successfully. 256 @retval EFI_NOT_FOUND The specified text or font info can not be found 257 out. 258 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the 259 task. 260 261 **/ 262 EFI_STATUS 263 FindStringBlock ( 264 IN HII_DATABASE_PRIVATE_DATA *Private, 265 IN HII_STRING_PACKAGE_INSTANCE *StringPackage, 266 IN EFI_STRING_ID StringId, 267 OUT UINT8 *BlockType, OPTIONAL 268 OUT UINT8 **StringBlockAddr, OPTIONAL 269 OUT UINTN *StringTextOffset, OPTIONAL 270 OUT EFI_STRING_ID *LastStringId, OPTIONAL 271 OUT EFI_STRING_ID *StartStringId OPTIONAL 272 ) 273 { 274 UINT8 *BlockHdr; 275 EFI_STRING_ID CurrentStringId; 276 UINTN BlockSize; 277 UINTN Index; 278 UINT8 *StringTextPtr; 279 UINTN Offset; 280 HII_FONT_INFO *LocalFont; 281 EFI_FONT_INFO *FontInfo; 282 HII_GLOBAL_FONT_INFO *GlobalFont; 283 UINTN FontInfoSize; 284 UINT16 StringCount; 285 UINT16 SkipCount; 286 EFI_HII_FONT_STYLE FontStyle; 287 UINT16 FontSize; 288 UINT8 Length8; 289 EFI_HII_SIBT_EXT2_BLOCK Ext2; 290 UINT8 FontId; 291 UINT32 Length32; 292 UINTN StringSize; 293 CHAR16 Zero; 294 295 ASSERT (StringPackage != NULL); 296 ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE); 297 298 CurrentStringId = 1; 299 StringSize = 0; 300 301 if (StringId != (EFI_STRING_ID) (-1) && StringId != 0) { 302 ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL); 303 if (StringId > StringPackage->MaxStringId) { 304 return EFI_NOT_FOUND; 305 } 306 } else { 307 ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE); 308 if (StringId == 0 && LastStringId != NULL) { 309 *LastStringId = StringPackage->MaxStringId; 310 return EFI_SUCCESS; 311 } 312 } 313 314 ZeroMem (&Zero, sizeof (CHAR16)); 315 316 // 317 // Parse the string blocks to get the string text and font. 318 // 319 BlockHdr = StringPackage->StringBlock; 320 BlockSize = 0; 321 Offset = 0; 322 while (*BlockHdr != EFI_HII_SIBT_END) { 323 switch (*BlockHdr) { 324 case EFI_HII_SIBT_STRING_SCSU: 325 Offset = sizeof (EFI_HII_STRING_BLOCK); 326 StringTextPtr = BlockHdr + Offset; 327 BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr); 328 CurrentStringId++; 329 break; 330 331 case EFI_HII_SIBT_STRING_SCSU_FONT: 332 Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8); 333 StringTextPtr = BlockHdr + Offset; 334 BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr); 335 CurrentStringId++; 336 break; 337 338 case EFI_HII_SIBT_STRINGS_SCSU: 339 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16)); 340 StringTextPtr = (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8)); 341 BlockSize += StringTextPtr - BlockHdr; 342 343 for (Index = 0; Index < StringCount; Index++) { 344 BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr); 345 if (CurrentStringId == StringId) { 346 ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL); 347 *BlockType = *BlockHdr; 348 *StringBlockAddr = BlockHdr; 349 *StringTextOffset = StringTextPtr - BlockHdr; 350 return EFI_SUCCESS; 351 } 352 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr); 353 CurrentStringId++; 354 } 355 break; 356 357 case EFI_HII_SIBT_STRINGS_SCSU_FONT: 358 CopyMem ( 359 &StringCount, 360 (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)), 361 sizeof (UINT16) 362 ); 363 StringTextPtr = (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8)); 364 BlockSize += StringTextPtr - BlockHdr; 365 366 for (Index = 0; Index < StringCount; Index++) { 367 BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr); 368 if (CurrentStringId == StringId) { 369 ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL); 370 *BlockType = *BlockHdr; 371 *StringBlockAddr = BlockHdr; 372 *StringTextOffset = StringTextPtr - BlockHdr; 373 return EFI_SUCCESS; 374 } 375 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr); 376 CurrentStringId++; 377 } 378 break; 379 380 case EFI_HII_SIBT_STRING_UCS2: 381 Offset = sizeof (EFI_HII_STRING_BLOCK); 382 StringTextPtr = BlockHdr + Offset; 383 // 384 // Use StringSize to store the size of the specified string, including the NULL 385 // terminator. 386 // 387 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize); 388 BlockSize += Offset + StringSize; 389 CurrentStringId++; 390 break; 391 392 case EFI_HII_SIBT_STRING_UCS2_FONT: 393 Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16); 394 StringTextPtr = BlockHdr + Offset; 395 // 396 // Use StrSize to store the size of the specified string, including the NULL 397 // terminator. 398 // 399 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize); 400 BlockSize += Offset + StringSize; 401 CurrentStringId++; 402 break; 403 404 case EFI_HII_SIBT_STRINGS_UCS2: 405 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16); 406 StringTextPtr = BlockHdr + Offset; 407 BlockSize += Offset; 408 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16)); 409 for (Index = 0; Index < StringCount; Index++) { 410 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize); 411 BlockSize += StringSize; 412 if (CurrentStringId == StringId) { 413 ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL); 414 *BlockType = *BlockHdr; 415 *StringBlockAddr = BlockHdr; 416 *StringTextOffset = StringTextPtr - BlockHdr; 417 return EFI_SUCCESS; 418 } 419 StringTextPtr = StringTextPtr + StringSize; 420 CurrentStringId++; 421 } 422 break; 423 424 case EFI_HII_SIBT_STRINGS_UCS2_FONT: 425 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16); 426 StringTextPtr = BlockHdr + Offset; 427 BlockSize += Offset; 428 CopyMem ( 429 &StringCount, 430 (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)), 431 sizeof (UINT16) 432 ); 433 for (Index = 0; Index < StringCount; Index++) { 434 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize); 435 BlockSize += StringSize; 436 if (CurrentStringId == StringId) { 437 ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL); 438 *BlockType = *BlockHdr; 439 *StringBlockAddr = BlockHdr; 440 *StringTextOffset = StringTextPtr - BlockHdr; 441 return EFI_SUCCESS; 442 } 443 StringTextPtr = StringTextPtr + StringSize; 444 CurrentStringId++; 445 } 446 break; 447 448 case EFI_HII_SIBT_DUPLICATE: 449 if (CurrentStringId == StringId) { 450 // 451 // Incoming StringId is an id of a duplicate string block. 452 // Update the StringId to be the previous string block. 453 // Go back to the header of string block to search. 454 // 455 CopyMem ( 456 &StringId, 457 BlockHdr + sizeof (EFI_HII_STRING_BLOCK), 458 sizeof (EFI_STRING_ID) 459 ); 460 ASSERT (StringId != CurrentStringId); 461 CurrentStringId = 1; 462 BlockSize = 0; 463 } else { 464 BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK); 465 CurrentStringId++; 466 } 467 break; 468 469 case EFI_HII_SIBT_SKIP1: 470 SkipCount = (UINT16) (*(UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK))); 471 CurrentStringId = (UINT16) (CurrentStringId + SkipCount); 472 BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK); 473 break; 474 475 case EFI_HII_SIBT_SKIP2: 476 CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16)); 477 CurrentStringId = (UINT16) (CurrentStringId + SkipCount); 478 BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK); 479 break; 480 481 case EFI_HII_SIBT_EXT1: 482 CopyMem ( 483 &Length8, 484 (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)), 485 sizeof (UINT8) 486 ); 487 BlockSize += Length8; 488 break; 489 490 case EFI_HII_SIBT_EXT2: 491 CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK)); 492 if (Ext2.BlockType2 == EFI_HII_SIBT_FONT && StringId == (EFI_STRING_ID) (-1)) { 493 // 494 // Find the relationship between global font info and the font info of 495 // this EFI_HII_SIBT_FONT block then backup its information in local package. 496 // 497 BlockHdr += sizeof (EFI_HII_SIBT_EXT2_BLOCK); 498 CopyMem (&FontId, BlockHdr, sizeof (UINT8)); 499 BlockHdr ++; 500 CopyMem (&FontSize, BlockHdr, sizeof (UINT16)); 501 BlockHdr += sizeof (UINT16); 502 CopyMem (&FontStyle, BlockHdr, sizeof (EFI_HII_FONT_STYLE)); 503 BlockHdr += sizeof (EFI_HII_FONT_STYLE); 504 GetUnicodeStringTextOrSize (NULL, BlockHdr, &StringSize); 505 506 FontInfoSize = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StringSize; 507 FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoSize); 508 if (FontInfo == NULL) { 509 return EFI_OUT_OF_RESOURCES; 510 } 511 FontInfo->FontStyle = FontStyle; 512 FontInfo->FontSize = FontSize; 513 CopyMem (FontInfo->FontName, BlockHdr, StringSize); 514 515 // 516 // If find the corresponding global font info, save the relationship. 517 // Otherwise ignore this EFI_HII_SIBT_FONT block. 518 // 519 if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) { 520 ReferFontInfoLocally (Private, StringPackage, FontId, TRUE, GlobalFont, &LocalFont); 521 } 522 523 // 524 // Since string package tool set FontId initially to 0 and increases it 525 // progressively by one, StringPackage->FondId always represents an unique 526 // and available FontId. 527 // 528 StringPackage->FontId++; 529 530 FreePool (FontInfo); 531 } 532 533 BlockSize += Ext2.Length; 534 535 break; 536 537 case EFI_HII_SIBT_EXT4: 538 CopyMem ( 539 &Length32, 540 (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)), 541 sizeof (UINT32) 542 ); 543 544 BlockSize += Length32; 545 break; 546 547 default: 548 break; 549 } 550 551 if (StringId > 0 && StringId != (EFI_STRING_ID)(-1)) { 552 ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL); 553 *BlockType = *BlockHdr; 554 *StringBlockAddr = BlockHdr; 555 *StringTextOffset = Offset; 556 557 if (StringId == CurrentStringId - 1) { 558 // 559 // if only one skip item, return EFI_NOT_FOUND. 560 // 561 if(*BlockType == EFI_HII_SIBT_SKIP2 || *BlockType == EFI_HII_SIBT_SKIP1) { 562 return EFI_NOT_FOUND; 563 } else { 564 return EFI_SUCCESS; 565 } 566 } 567 568 if (StringId < CurrentStringId - 1) { 569 return EFI_NOT_FOUND; 570 } 571 } 572 BlockHdr = StringPackage->StringBlock + BlockSize; 573 if (StartStringId != NULL) { 574 *StartStringId = CurrentStringId; 575 } 576 } 577 578 // 579 // Get last string ID 580 // 581 if (StringId == (EFI_STRING_ID) (-1) && LastStringId != NULL) { 582 *LastStringId = (EFI_STRING_ID) (CurrentStringId - 1); 583 return EFI_SUCCESS; 584 } 585 586 return EFI_NOT_FOUND; 587 } 588 589 590 /** 591 Parse all string blocks to get a string specified by StringId. 592 593 This is a internal function. 594 595 @param Private Hii database private structure. 596 @param StringPackage Hii string package instance. 597 @param StringId The string's id, which is unique within 598 PackageList. 599 @param String Points to retrieved null-terminated string. 600 @param StringSize On entry, points to the size of the buffer pointed 601 to by String, in bytes. On return, points to the 602 length of the string, in bytes. 603 @param StringFontInfo If not NULL, allocate a buffer to record the 604 output font info. It's caller's responsibility to 605 free this buffer. 606 607 @retval EFI_SUCCESS The string text and font is retrieved 608 successfully. 609 @retval EFI_NOT_FOUND The specified text or font info can not be found 610 out. 611 @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to 612 hold the string. 613 614 **/ 615 EFI_STATUS 616 GetStringWorker ( 617 IN HII_DATABASE_PRIVATE_DATA *Private, 618 IN HII_STRING_PACKAGE_INSTANCE *StringPackage, 619 IN EFI_STRING_ID StringId, 620 OUT EFI_STRING String, 621 IN OUT UINTN *StringSize, OPTIONAL 622 OUT EFI_FONT_INFO **StringFontInfo OPTIONAL 623 ) 624 { 625 UINT8 *StringTextPtr; 626 UINT8 BlockType; 627 UINT8 *StringBlockAddr; 628 UINTN StringTextOffset; 629 EFI_STATUS Status; 630 UINT8 FontId; 631 632 ASSERT (StringPackage != NULL); 633 ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE); 634 635 // 636 // Find the specified string block 637 // 638 Status = FindStringBlock ( 639 Private, 640 StringPackage, 641 StringId, 642 &BlockType, 643 &StringBlockAddr, 644 &StringTextOffset, 645 NULL, 646 NULL 647 ); 648 if (EFI_ERROR (Status)) { 649 return Status; 650 } 651 652 if (StringSize == NULL) { 653 // 654 // String text buffer is not requested 655 // 656 return EFI_SUCCESS; 657 } 658 659 // 660 // Get the string text. 661 // 662 StringTextPtr = StringBlockAddr + StringTextOffset; 663 switch (BlockType) { 664 case EFI_HII_SIBT_STRING_SCSU: 665 case EFI_HII_SIBT_STRING_SCSU_FONT: 666 case EFI_HII_SIBT_STRINGS_SCSU: 667 case EFI_HII_SIBT_STRINGS_SCSU_FONT: 668 Status = ConvertToUnicodeText (String, (CHAR8 *) StringTextPtr, StringSize); 669 break; 670 case EFI_HII_SIBT_STRING_UCS2: 671 case EFI_HII_SIBT_STRING_UCS2_FONT: 672 case EFI_HII_SIBT_STRINGS_UCS2: 673 case EFI_HII_SIBT_STRINGS_UCS2_FONT: 674 Status = GetUnicodeStringTextOrSize (String, StringTextPtr, StringSize); 675 break; 676 default: 677 return EFI_NOT_FOUND; 678 } 679 if (EFI_ERROR (Status)) { 680 return Status; 681 } 682 683 // 684 // Get the string font. The FontId 0 is the default font for those string blocks which 685 // do not specify a font identifier. If default font is not specified, return NULL. 686 // 687 if (StringFontInfo != NULL) { 688 switch (BlockType) { 689 case EFI_HII_SIBT_STRING_SCSU_FONT: 690 case EFI_HII_SIBT_STRINGS_SCSU_FONT: 691 case EFI_HII_SIBT_STRING_UCS2_FONT: 692 case EFI_HII_SIBT_STRINGS_UCS2_FONT: 693 FontId = *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK)); 694 break; 695 default: 696 FontId = 0; 697 } 698 Status = GetStringFontInfo (StringPackage, FontId, StringFontInfo); 699 if (Status == EFI_NOT_FOUND) { 700 *StringFontInfo = NULL; 701 } 702 } 703 704 return EFI_SUCCESS; 705 } 706 707 /** 708 If GetStringBlock find the StringId's string is not saved in the exist string block, 709 this function will create the UCS2 string block to save the string; also split the 710 skip block into two or one skip block. 711 712 This is a internal function. 713 714 @param StringPackage Hii string package instance. 715 @param StartStringId The first id in the skip block which StringId in the block. 716 @param StringId The string's id, which is unique within 717 PackageList. 718 @param BlockType Output the block type of found string block. 719 @param StringBlockAddr Output the block address of found string block. 720 @param FontBlock whether this string block has font info. 721 722 @retval EFI_SUCCESS The string font is outputted successfully. 723 @retval EFI_OUT_OF_RESOURCES NO resource for the memory to save the new string block. 724 725 **/ 726 EFI_STATUS 727 InsertLackStringBlock ( 728 IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage, 729 IN EFI_STRING_ID StartStringId, 730 IN EFI_STRING_ID StringId, 731 IN OUT UINT8 *BlockType, 732 IN OUT UINT8 **StringBlockAddr, 733 IN BOOLEAN FontBlock 734 ) 735 { 736 UINT8 *BlockPtr; 737 UINT8 *StringBlock; 738 UINT32 SkipLen; 739 UINT32 OldBlockSize; 740 UINT32 NewBlockSize; 741 UINT32 FrontSkipNum; 742 UINT32 NewUCSBlockLen; 743 UINT8 *OldStringAddr; 744 UINT32 IdCount; 745 746 FrontSkipNum = 0; 747 SkipLen = 0; 748 OldStringAddr = *StringBlockAddr; 749 750 ASSERT (*BlockType == EFI_HII_SIBT_SKIP1 || *BlockType == EFI_HII_SIBT_SKIP2); 751 // 752 // Old skip block size. 753 // 754 if (*BlockType == EFI_HII_SIBT_SKIP1) { 755 SkipLen = sizeof (EFI_HII_SIBT_SKIP1_BLOCK); 756 IdCount = *(UINT8*)(OldStringAddr + sizeof (EFI_HII_STRING_BLOCK)); 757 } else { 758 SkipLen = sizeof (EFI_HII_SIBT_SKIP2_BLOCK); 759 IdCount = *(UINT16*)(OldStringAddr + sizeof (EFI_HII_STRING_BLOCK)); 760 } 761 762 // 763 // New create UCS or UCS2 block size. 764 // 765 if (FontBlock) { 766 NewUCSBlockLen = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK); 767 } else { 768 NewUCSBlockLen = sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK); 769 } 770 771 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize; 772 773 if (StartStringId == StringId) { 774 // 775 // New block + [Skip block] 776 // 777 if (IdCount > 1) { 778 NewBlockSize = OldBlockSize + NewUCSBlockLen; 779 } else { 780 NewBlockSize = OldBlockSize + NewUCSBlockLen - SkipLen; 781 } 782 } else if (StartStringId + IdCount - 1 == StringId){ 783 // 784 // Skip block + New block 785 // 786 NewBlockSize = OldBlockSize + NewUCSBlockLen; 787 FrontSkipNum = StringId - StartStringId; 788 } else { 789 // 790 // Skip block + New block + [Skip block] 791 // 792 NewBlockSize = OldBlockSize + NewUCSBlockLen + SkipLen; 793 FrontSkipNum = StringId - StartStringId; 794 } 795 796 StringBlock = (UINT8 *) AllocateZeroPool (NewBlockSize); 797 if (StringBlock == NULL) { 798 return EFI_OUT_OF_RESOURCES; 799 } 800 801 // 802 // Copy old block in front of skip block. 803 // 804 CopyMem (StringBlock, StringPackage->StringBlock, OldStringAddr - StringPackage->StringBlock); 805 BlockPtr = StringBlock + (OldStringAddr - StringPackage->StringBlock); 806 807 if (FrontSkipNum > 0) { 808 *BlockPtr = *BlockType; 809 if (*BlockType == EFI_HII_SIBT_SKIP1) { 810 *(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT8) FrontSkipNum; 811 } else { 812 *(UINT16 *)(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT16) FrontSkipNum; 813 } 814 BlockPtr += SkipLen; 815 } 816 817 // 818 // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK 819 // 820 *StringBlockAddr = BlockPtr; 821 if (FontBlock) { 822 *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT; 823 } else { 824 *BlockPtr = EFI_HII_SIBT_STRING_UCS2; 825 } 826 BlockPtr += NewUCSBlockLen; 827 828 if (IdCount > FrontSkipNum + 1) { 829 *BlockPtr = *BlockType; 830 if (*BlockType == EFI_HII_SIBT_SKIP1) { 831 *(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT8) (IdCount - FrontSkipNum - 1); 832 } else { 833 *(UINT16 *)(BlockPtr + sizeof (EFI_HII_STRING_BLOCK)) = (UINT16) (IdCount - FrontSkipNum - 1); 834 } 835 BlockPtr += SkipLen; 836 } 837 838 // 839 // Append a EFI_HII_SIBT_END block to the end. 840 // 841 CopyMem (BlockPtr, OldStringAddr + SkipLen, OldBlockSize - (OldStringAddr - StringPackage->StringBlock) - SkipLen); 842 843 if (FontBlock) { 844 *BlockType = EFI_HII_SIBT_STRING_UCS2_FONT; 845 } else { 846 *BlockType = EFI_HII_SIBT_STRING_UCS2; 847 } 848 FreePool (StringPackage->StringBlock); 849 StringPackage->StringBlock = StringBlock; 850 StringPackage->StringPkgHdr->Header.Length += NewBlockSize - OldBlockSize; 851 852 return EFI_SUCCESS; 853 } 854 855 /** 856 Parse all string blocks to set a String specified by StringId. 857 858 This is a internal function. 859 860 @param Private HII database driver private structure. 861 @param StringPackage HII string package instance. 862 @param StringId The string's id, which is unique within 863 PackageList. 864 @param String Points to the new null-terminated string. 865 @param StringFontInfo Points to the input font info. 866 867 @retval EFI_SUCCESS The string was updated successfully. 868 @retval EFI_NOT_FOUND The string specified by StringId is not in the 869 database. 870 @retval EFI_INVALID_PARAMETER The String or Language was NULL. 871 @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in 872 current database. 873 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the 874 task. 875 876 **/ 877 EFI_STATUS 878 SetStringWorker ( 879 IN HII_DATABASE_PRIVATE_DATA *Private, 880 IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage, 881 IN EFI_STRING_ID StringId, 882 IN EFI_STRING String, 883 IN EFI_FONT_INFO *StringFontInfo OPTIONAL 884 ) 885 { 886 UINT8 *StringTextPtr; 887 UINT8 BlockType; 888 UINT8 *StringBlockAddr; 889 UINTN StringTextOffset; 890 EFI_STATUS Status; 891 UINT8 *Block; 892 UINT8 *BlockPtr; 893 UINTN BlockSize; 894 UINTN OldBlockSize; 895 HII_FONT_INFO *LocalFont; 896 HII_GLOBAL_FONT_INFO *GlobalFont; 897 BOOLEAN Referred; 898 EFI_HII_SIBT_EXT2_BLOCK Ext2; 899 UINTN StringSize; 900 UINTN TmpSize; 901 EFI_STRING_ID StartStringId; 902 903 StartStringId = 0; 904 StringSize = 0; 905 ASSERT (Private != NULL && StringPackage != NULL && String != NULL); 906 ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE); 907 // 908 // Find the specified string block 909 // 910 Status = FindStringBlock ( 911 Private, 912 StringPackage, 913 StringId, 914 &BlockType, 915 &StringBlockAddr, 916 &StringTextOffset, 917 NULL, 918 &StartStringId 919 ); 920 if (EFI_ERROR (Status) && (BlockType == EFI_HII_SIBT_SKIP1 || BlockType == EFI_HII_SIBT_SKIP2)) { 921 Status = InsertLackStringBlock(StringPackage, 922 StartStringId, 923 StringId, 924 &BlockType, 925 &StringBlockAddr, 926 (BOOLEAN)(StringFontInfo != NULL) 927 ); 928 if (EFI_ERROR (Status)) { 929 return Status; 930 } 931 if (StringFontInfo != NULL) { 932 StringTextOffset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16); 933 } else { 934 StringTextOffset = sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16); 935 } 936 } 937 938 LocalFont = NULL; 939 GlobalFont = NULL; 940 Referred = FALSE; 941 942 // 943 // The input StringFontInfo should exist in current database if specified. 944 // 945 if (StringFontInfo != NULL) { 946 if (!IsFontInfoExisted (Private, StringFontInfo, NULL, NULL, &GlobalFont)) { 947 return EFI_INVALID_PARAMETER; 948 } else { 949 Referred = ReferFontInfoLocally ( 950 Private, 951 StringPackage, 952 StringPackage->FontId, 953 FALSE, 954 GlobalFont, 955 &LocalFont 956 ); 957 if (!Referred) { 958 StringPackage->FontId++; 959 } 960 } 961 // 962 // Update the FontId of the specified string block to input font info. 963 // 964 switch (BlockType) { 965 case EFI_HII_SIBT_STRING_SCSU_FONT: 966 case EFI_HII_SIBT_STRINGS_SCSU_FONT: 967 case EFI_HII_SIBT_STRING_UCS2_FONT: 968 case EFI_HII_SIBT_STRINGS_UCS2_FONT: 969 *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK)) = LocalFont->FontId; 970 break; 971 default: 972 // 973 // When modify the font info of these blocks, the block type should be updated 974 // to contain font info thus the whole structure should be revised. 975 // It is recommended to use tool to modify the block type not in the code. 976 // 977 return EFI_UNSUPPORTED; 978 } 979 } 980 981 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize; 982 983 // 984 // Set the string text and font. 985 // 986 StringTextPtr = StringBlockAddr + StringTextOffset; 987 switch (BlockType) { 988 case EFI_HII_SIBT_STRING_SCSU: 989 case EFI_HII_SIBT_STRING_SCSU_FONT: 990 case EFI_HII_SIBT_STRINGS_SCSU: 991 case EFI_HII_SIBT_STRINGS_SCSU_FONT: 992 BlockSize = OldBlockSize + StrLen (String); 993 BlockSize -= AsciiStrSize ((CHAR8 *) StringTextPtr); 994 Block = AllocateZeroPool (BlockSize); 995 if (Block == NULL) { 996 return EFI_OUT_OF_RESOURCES; 997 } 998 999 CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock); 1000 BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock); 1001 1002 while (*String != 0) { 1003 *BlockPtr++ = (CHAR8) *String++; 1004 } 1005 *BlockPtr++ = 0; 1006 1007 1008 TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *) StringTextPtr); 1009 CopyMem ( 1010 BlockPtr, 1011 StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr), 1012 TmpSize 1013 ); 1014 1015 FreePool (StringPackage->StringBlock); 1016 StringPackage->StringBlock = Block; 1017 StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize); 1018 break; 1019 1020 case EFI_HII_SIBT_STRING_UCS2: 1021 case EFI_HII_SIBT_STRING_UCS2_FONT: 1022 case EFI_HII_SIBT_STRINGS_UCS2: 1023 case EFI_HII_SIBT_STRINGS_UCS2_FONT: 1024 // 1025 // Use StrSize to store the size of the specified string, including the NULL 1026 // terminator. 1027 // 1028 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize); 1029 1030 BlockSize = OldBlockSize + StrSize (String) - StringSize; 1031 Block = AllocateZeroPool (BlockSize); 1032 if (Block == NULL) { 1033 return EFI_OUT_OF_RESOURCES; 1034 } 1035 1036 CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock); 1037 BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock); 1038 1039 CopyMem (BlockPtr, String, StrSize (String)); 1040 BlockPtr += StrSize (String); 1041 1042 CopyMem ( 1043 BlockPtr, 1044 StringTextPtr + StringSize, 1045 OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - StringSize 1046 ); 1047 1048 FreePool (StringPackage->StringBlock); 1049 StringPackage->StringBlock = Block; 1050 StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize); 1051 break; 1052 1053 default: 1054 return EFI_NOT_FOUND; 1055 } 1056 1057 // 1058 // Insert a new EFI_HII_SIBT_FONT_BLOCK to the header of string block, if incoming 1059 // StringFontInfo does not exist in current string package. 1060 // 1061 // This new block does not impact on the value of StringId. 1062 // 1063 // 1064 if (StringFontInfo == NULL || Referred) { 1065 return EFI_SUCCESS; 1066 } 1067 1068 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize; 1069 BlockSize = OldBlockSize + sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16) + 1070 StrSize (GlobalFont->FontInfo->FontName); 1071 1072 Block = AllocateZeroPool (BlockSize); 1073 if (Block == NULL) { 1074 return EFI_OUT_OF_RESOURCES; 1075 } 1076 1077 BlockPtr = Block; 1078 Ext2.Header.BlockType = EFI_HII_SIBT_EXT2; 1079 Ext2.BlockType2 = EFI_HII_SIBT_FONT; 1080 Ext2.Length = (UINT16) (BlockSize - OldBlockSize); 1081 CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK)); 1082 BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK); 1083 1084 *BlockPtr = LocalFont->FontId; 1085 BlockPtr ++; 1086 CopyMem (BlockPtr, &GlobalFont->FontInfo->FontSize, sizeof (UINT16)); 1087 BlockPtr += sizeof (UINT16); 1088 CopyMem (BlockPtr, &GlobalFont->FontInfo->FontStyle, sizeof (UINT32)); 1089 BlockPtr += sizeof (UINT32); 1090 CopyMem ( 1091 BlockPtr, 1092 GlobalFont->FontInfo->FontName, 1093 StrSize (GlobalFont->FontInfo->FontName) 1094 ); 1095 BlockPtr += StrSize (GlobalFont->FontInfo->FontName); 1096 1097 CopyMem (BlockPtr, StringPackage->StringBlock, OldBlockSize); 1098 1099 FreePool (StringPackage->StringBlock); 1100 StringPackage->StringBlock = Block; 1101 StringPackage->StringPkgHdr->Header.Length += Ext2.Length; 1102 1103 return EFI_SUCCESS; 1104 1105 } 1106 1107 1108 /** 1109 This function adds the string String to the group of strings owned by PackageList, with the 1110 specified font information StringFontInfo and returns a new string id. 1111 The new string identifier is guaranteed to be unique within the package list. 1112 That new string identifier is reserved for all languages in the package list. 1113 1114 1115 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. 1116 @param PackageList Handle of the package list where this string will 1117 be added. 1118 @param StringId On return, contains the new strings id, which is 1119 unique within PackageList. 1120 @param Language Points to the language for the new string. 1121 @param LanguageName Points to the printable language name to associate 1122 with the passed in Language field.If LanguageName 1123 is not NULL and the string package header's 1124 LanguageName associated with a given Language is 1125 not zero, the LanguageName being passed in will 1126 be ignored. 1127 @param String Points to the new null-terminated string. 1128 @param StringFontInfo Points to the new string's font information or 1129 NULL if the string should have the default system 1130 font, size and style. 1131 1132 @retval EFI_SUCCESS The new string was added successfully. 1133 @retval EFI_NOT_FOUND The specified PackageList could not be found in 1134 database. 1135 @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of resources. 1136 @retval EFI_INVALID_PARAMETER String is NULL or StringId is NULL or Language is 1137 NULL. 1138 @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in 1139 current database. 1140 1141 **/ 1142 EFI_STATUS 1143 EFIAPI 1144 HiiNewString ( 1145 IN CONST EFI_HII_STRING_PROTOCOL *This, 1146 IN EFI_HII_HANDLE PackageList, 1147 OUT EFI_STRING_ID *StringId, 1148 IN CONST CHAR8 *Language, 1149 IN CONST CHAR16 *LanguageName, OPTIONAL 1150 IN CONST EFI_STRING String, 1151 IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL 1152 ) 1153 { 1154 EFI_STATUS Status; 1155 LIST_ENTRY *Link; 1156 HII_DATABASE_PRIVATE_DATA *Private; 1157 HII_DATABASE_RECORD *DatabaseRecord; 1158 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode; 1159 HII_STRING_PACKAGE_INSTANCE *StringPackage; 1160 UINT32 HeaderSize; 1161 UINT32 BlockSize; 1162 UINT32 OldBlockSize; 1163 UINT8 *StringBlock; 1164 UINT8 *BlockPtr; 1165 UINT32 Ucs2BlockSize; 1166 UINT32 FontBlockSize; 1167 UINT32 Ucs2FontBlockSize; 1168 EFI_HII_SIBT_EXT2_BLOCK Ext2; 1169 HII_FONT_INFO *LocalFont; 1170 HII_GLOBAL_FONT_INFO *GlobalFont; 1171 EFI_STRING_ID NewStringId; 1172 EFI_STRING_ID NextStringId; 1173 EFI_STRING_ID Index; 1174 HII_STRING_PACKAGE_INSTANCE *MatchStringPackage; 1175 BOOLEAN NewStringPackageCreated; 1176 1177 1178 if (This == NULL || String == NULL || StringId == NULL || Language == NULL || PackageList == NULL) { 1179 return EFI_INVALID_PARAMETER; 1180 } 1181 1182 if (!IsHiiHandleValid (PackageList)) { 1183 return EFI_NOT_FOUND; 1184 } 1185 1186 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This); 1187 GlobalFont = NULL; 1188 1189 // 1190 // If StringFontInfo specify a paritcular font, it should exist in current database. 1191 // 1192 if (StringFontInfo != NULL) { 1193 if (!IsFontInfoExisted (Private, (EFI_FONT_INFO *) StringFontInfo, NULL, NULL, &GlobalFont)) { 1194 return EFI_INVALID_PARAMETER; 1195 } 1196 } 1197 1198 // 1199 // Get the matching package list. 1200 // 1201 PackageListNode = NULL; 1202 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) { 1203 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); 1204 if (DatabaseRecord->Handle == PackageList) { 1205 PackageListNode = DatabaseRecord->PackageList; 1206 break; 1207 } 1208 } 1209 if (PackageListNode == NULL) { 1210 return EFI_NOT_FOUND; 1211 } 1212 1213 Status = EFI_SUCCESS; 1214 NewStringPackageCreated = FALSE; 1215 NewStringId = 0; 1216 NextStringId = 0; 1217 StringPackage = NULL; 1218 MatchStringPackage = NULL; 1219 for (Link = PackageListNode->StringPkgHdr.ForwardLink; 1220 Link != &PackageListNode->StringPkgHdr; 1221 Link = Link->ForwardLink 1222 ) { 1223 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); 1224 // 1225 // Create a string block and corresponding font block if exists, then append them 1226 // to the end of the string package. 1227 // 1228 Status = FindStringBlock ( 1229 Private, 1230 StringPackage, 1231 0, 1232 NULL, 1233 NULL, 1234 NULL, 1235 &NextStringId, 1236 NULL 1237 ); 1238 if (EFI_ERROR (Status)) { 1239 goto Done; 1240 } 1241 // 1242 // Make sure that new StringId is same in all String Packages for the different language. 1243 // 1244 if (NewStringId != 0 && NewStringId != NextStringId) { 1245 ASSERT (FALSE); 1246 Status = EFI_INVALID_PARAMETER; 1247 goto Done; 1248 } 1249 NewStringId = NextStringId; 1250 // 1251 // Get the matched string package with language. 1252 // 1253 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) { 1254 MatchStringPackage = StringPackage; 1255 } else { 1256 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize; 1257 // 1258 // Create a blank EFI_HII_SIBT_STRING_UCS2_BLOCK to reserve new string ID. 1259 // 1260 Ucs2BlockSize = (UINT32) sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK); 1261 1262 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2BlockSize); 1263 if (StringBlock == NULL) { 1264 Status = EFI_OUT_OF_RESOURCES; 1265 goto Done; 1266 } 1267 // 1268 // Copy original string blocks, except the EFI_HII_SIBT_END. 1269 // 1270 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK)); 1271 // 1272 // Create a blank EFI_HII_SIBT_STRING_UCS2 block 1273 // 1274 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK); 1275 *BlockPtr = EFI_HII_SIBT_STRING_UCS2; 1276 BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK); 1277 1278 // 1279 // Append a EFI_HII_SIBT_END block to the end. 1280 // 1281 *BlockPtr = EFI_HII_SIBT_END; 1282 FreePool (StringPackage->StringBlock); 1283 StringPackage->StringBlock = StringBlock; 1284 StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize; 1285 PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize; 1286 } 1287 } 1288 if (NewStringId == 0) { 1289 // 1290 // No string package is found. 1291 // Create new string package. StringId 1 is reserved for Language Name string. 1292 // 1293 *StringId = 2; 1294 } else { 1295 // 1296 // Set new StringId 1297 // 1298 *StringId = (EFI_STRING_ID) (NewStringId + 1); 1299 } 1300 1301 if (MatchStringPackage != NULL) { 1302 StringPackage = MatchStringPackage; 1303 } else { 1304 // 1305 // LanguageName is required to create a new string package. 1306 // 1307 if (LanguageName == NULL) { 1308 Status = EFI_INVALID_PARAMETER; 1309 goto Done; 1310 } 1311 1312 StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE)); 1313 if (StringPackage == NULL) { 1314 Status = EFI_OUT_OF_RESOURCES; 1315 goto Done; 1316 } 1317 1318 StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE; 1319 StringPackage->MaxStringId = *StringId; 1320 StringPackage->FontId = 0; 1321 InitializeListHead (&StringPackage->FontInfoList); 1322 1323 // 1324 // Fill in the string package header 1325 // 1326 HeaderSize = (UINT32) (AsciiStrSize ((CHAR8 *) Language) - 1 + sizeof (EFI_HII_STRING_PACKAGE_HDR)); 1327 StringPackage->StringPkgHdr = AllocateZeroPool (HeaderSize); 1328 if (StringPackage->StringPkgHdr == NULL) { 1329 FreePool (StringPackage); 1330 Status = EFI_OUT_OF_RESOURCES; 1331 goto Done; 1332 } 1333 StringPackage->StringPkgHdr->Header.Type = EFI_HII_PACKAGE_STRINGS; 1334 StringPackage->StringPkgHdr->HdrSize = HeaderSize; 1335 StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize; 1336 CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16)); 1337 StringPackage->StringPkgHdr->LanguageName = 1; 1338 AsciiStrCpyS (StringPackage->StringPkgHdr->Language, (HeaderSize - OFFSET_OF(EFI_HII_STRING_PACKAGE_HDR,Language)) / sizeof (CHAR8), (CHAR8 *) Language); 1339 1340 // 1341 // Calculate the length of the string blocks, including string block to record 1342 // printable language full name and EFI_HII_SIBT_END_BLOCK. 1343 // 1344 Ucs2BlockSize = (UINT32) (StrSize ((CHAR16 *) LanguageName) + 1345 (*StringId - 1) * sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16)); 1346 1347 BlockSize = Ucs2BlockSize + sizeof (EFI_HII_SIBT_END_BLOCK); 1348 StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (BlockSize); 1349 if (StringPackage->StringBlock == NULL) { 1350 FreePool (StringPackage->StringPkgHdr); 1351 FreePool (StringPackage); 1352 Status = EFI_OUT_OF_RESOURCES; 1353 goto Done; 1354 } 1355 1356 // 1357 // Insert the string block of printable language full name 1358 // 1359 BlockPtr = StringPackage->StringBlock; 1360 *BlockPtr = EFI_HII_SIBT_STRING_UCS2; 1361 BlockPtr += sizeof (EFI_HII_STRING_BLOCK); 1362 CopyMem (BlockPtr, (EFI_STRING) LanguageName, StrSize ((EFI_STRING) LanguageName)); 1363 BlockPtr += StrSize ((EFI_STRING) LanguageName); 1364 for (Index = 2; Index <= *StringId - 1; Index ++) { 1365 *BlockPtr = EFI_HII_SIBT_STRING_UCS2; 1366 BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK); 1367 } 1368 // 1369 // Insert the end block 1370 // 1371 *BlockPtr = EFI_HII_SIBT_END; 1372 1373 // 1374 // Append this string package node to string package array in this package list. 1375 // 1376 StringPackage->StringPkgHdr->Header.Length = HeaderSize + BlockSize; 1377 PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length; 1378 InsertTailList (&PackageListNode->StringPkgHdr, &StringPackage->StringEntry); 1379 NewStringPackageCreated = TRUE; 1380 } 1381 1382 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize; 1383 1384 if (StringFontInfo == NULL) { 1385 // 1386 // Create a EFI_HII_SIBT_STRING_UCS2_BLOCK since font info is not specified. 1387 // 1388 Ucs2BlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) 1389 - sizeof (CHAR16)); 1390 1391 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2BlockSize); 1392 if (StringBlock == NULL) { 1393 Status = EFI_OUT_OF_RESOURCES; 1394 goto Done; 1395 } 1396 // 1397 // Copy original string blocks, except the EFI_HII_SIBT_END. 1398 // 1399 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK)); 1400 // 1401 // Create a EFI_HII_SIBT_STRING_UCS2 block 1402 // 1403 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK); 1404 *BlockPtr = EFI_HII_SIBT_STRING_UCS2; 1405 BlockPtr += sizeof (EFI_HII_STRING_BLOCK); 1406 CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String)); 1407 BlockPtr += StrSize ((EFI_STRING) String); 1408 1409 // 1410 // Append a EFI_HII_SIBT_END block to the end. 1411 // 1412 *BlockPtr = EFI_HII_SIBT_END; 1413 FreePool (StringPackage->StringBlock); 1414 StringPackage->StringBlock = StringBlock; 1415 StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize; 1416 PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize; 1417 1418 } else { 1419 // 1420 // StringFontInfo is specified here. If there is a EFI_HII_SIBT_FONT_BLOCK 1421 // which refers to this font info, create a EFI_HII_SIBT_STRING_UCS2_FONT block 1422 // only. Otherwise create a EFI_HII_SIBT_FONT block with a EFI_HII_SIBT_STRING 1423 // _UCS2_FONT block. 1424 // 1425 Ucs2FontBlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - 1426 sizeof (CHAR16)); 1427 if (ReferFontInfoLocally (Private, StringPackage, StringPackage->FontId, FALSE, GlobalFont, &LocalFont)) { 1428 // 1429 // Create a EFI_HII_SIBT_STRING_UCS2_FONT block only. 1430 // 1431 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2FontBlockSize); 1432 if (StringBlock == NULL) { 1433 Status = EFI_OUT_OF_RESOURCES; 1434 goto Done; 1435 } 1436 // 1437 // Copy original string blocks, except the EFI_HII_SIBT_END. 1438 // 1439 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK)); 1440 // 1441 // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK 1442 // 1443 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK); 1444 *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT; 1445 BlockPtr += sizeof (EFI_HII_STRING_BLOCK); 1446 *BlockPtr = LocalFont->FontId; 1447 BlockPtr ++; 1448 CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String)); 1449 BlockPtr += StrSize ((EFI_STRING) String); 1450 1451 // 1452 // Append a EFI_HII_SIBT_END block to the end. 1453 // 1454 *BlockPtr = EFI_HII_SIBT_END; 1455 FreePool (StringPackage->StringBlock); 1456 StringPackage->StringBlock = StringBlock; 1457 StringPackage->StringPkgHdr->Header.Length += Ucs2FontBlockSize; 1458 PackageListNode->PackageListHdr.PackageLength += Ucs2FontBlockSize; 1459 1460 } else { 1461 // 1462 // EFI_HII_SIBT_FONT_BLOCK does not exist in current string package, so 1463 // create a EFI_HII_SIBT_FONT block to record the font info, then generate 1464 // a EFI_HII_SIBT_STRING_UCS2_FONT block to record the incoming string. 1465 // 1466 FontBlockSize = (UINT32) (StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName) + 1467 sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16)); 1468 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + FontBlockSize + Ucs2FontBlockSize); 1469 if (StringBlock == NULL) { 1470 Status = EFI_OUT_OF_RESOURCES; 1471 goto Done; 1472 } 1473 // 1474 // Copy original string blocks, except the EFI_HII_SIBT_END. 1475 // 1476 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK)); 1477 1478 // 1479 // Create a EFI_HII_SIBT_FONT block firstly and then backup its info in string 1480 // package instance for future reference. 1481 // 1482 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK); 1483 1484 Ext2.Header.BlockType = EFI_HII_SIBT_EXT2; 1485 Ext2.BlockType2 = EFI_HII_SIBT_FONT; 1486 Ext2.Length = (UINT16) FontBlockSize; 1487 CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK)); 1488 BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK); 1489 1490 *BlockPtr = LocalFont->FontId; 1491 BlockPtr ++; 1492 CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontSize, sizeof (UINT16)); 1493 BlockPtr += sizeof (UINT16); 1494 CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontStyle, sizeof (EFI_HII_FONT_STYLE)); 1495 BlockPtr += sizeof (EFI_HII_FONT_STYLE); 1496 CopyMem ( 1497 BlockPtr, 1498 &((EFI_FONT_INFO *) StringFontInfo)->FontName, 1499 StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName) 1500 ); 1501 BlockPtr += StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName); 1502 // 1503 // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK 1504 // 1505 *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT; 1506 BlockPtr += sizeof (EFI_HII_STRING_BLOCK); 1507 *BlockPtr = LocalFont->FontId; 1508 BlockPtr ++; 1509 CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String)); 1510 BlockPtr += StrSize ((EFI_STRING) String); 1511 1512 // 1513 // Append a EFI_HII_SIBT_END block to the end. 1514 // 1515 *BlockPtr = EFI_HII_SIBT_END; 1516 FreePool (StringPackage->StringBlock); 1517 StringPackage->StringBlock = StringBlock; 1518 StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize; 1519 PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize; 1520 1521 // 1522 // Increase the FontId to make it unique since we already add 1523 // a EFI_HII_SIBT_FONT block to this string package. 1524 // 1525 StringPackage->FontId++; 1526 } 1527 } 1528 1529 Done: 1530 if (!EFI_ERROR (Status) && NewStringPackageCreated) { 1531 // 1532 // Trigger any registered notification function for new string package 1533 // 1534 Status = InvokeRegisteredFunction ( 1535 Private, 1536 EFI_HII_DATABASE_NOTIFY_NEW_PACK, 1537 (VOID *) StringPackage, 1538 EFI_HII_PACKAGE_STRINGS, 1539 PackageList 1540 ); 1541 } 1542 1543 if (!EFI_ERROR (Status)) { 1544 // 1545 // Update MaxString Id to new StringId 1546 // 1547 for (Link = PackageListNode->StringPkgHdr.ForwardLink; 1548 Link != &PackageListNode->StringPkgHdr; 1549 Link = Link->ForwardLink 1550 ) { 1551 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); 1552 StringPackage->MaxStringId = *StringId; 1553 } 1554 } else if (NewStringPackageCreated) { 1555 // 1556 // Free the allocated new string Package when new string can't be added. 1557 // 1558 RemoveEntryList (&StringPackage->StringEntry); 1559 FreePool (StringPackage->StringBlock); 1560 FreePool (StringPackage->StringPkgHdr); 1561 FreePool (StringPackage); 1562 } 1563 // 1564 // The contents of HiiDataBase may updated,need to check. 1565 // 1566 // 1567 // Check whether need to get the contents of HiiDataBase. 1568 // Only after ReadyToBoot to do the export. 1569 // 1570 if (gExportAfterReadyToBoot) { 1571 if (!EFI_ERROR (Status)) { 1572 HiiGetDatabaseInfo(&Private->HiiDatabase); 1573 } 1574 } 1575 1576 return Status; 1577 } 1578 1579 1580 /** 1581 This function retrieves the string specified by StringId which is associated 1582 with the specified PackageList in the language Language and copies it into 1583 the buffer specified by String. 1584 1585 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. 1586 @param Language Points to the language for the retrieved string. 1587 @param PackageList The package list in the HII database to search for 1588 the specified string. 1589 @param StringId The string's id, which is unique within 1590 PackageList. 1591 @param String Points to the new null-terminated string. 1592 @param StringSize On entry, points to the size of the buffer pointed 1593 to by String, in bytes. On return, points to the 1594 length of the string, in bytes. 1595 @param StringFontInfo If not NULL, points to the string's font 1596 information. It's caller's responsibility to free 1597 this buffer. 1598 1599 @retval EFI_SUCCESS The string was returned successfully. 1600 @retval EFI_NOT_FOUND The string specified by StringId is not available. 1601 @retval EFI_NOT_FOUND The string specified by StringId is available but 1602 not in the specified language. 1603 The specified PackageList is not in the database. 1604 @retval EFI_INVALID_LANGUAGE - The string specified by StringId is available but 1605 @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to 1606 hold the string. 1607 @retval EFI_INVALID_PARAMETER The Language or StringSize was NULL. 1608 @retval EFI_INVALID_PARAMETER The value referenced by StringSize was not zero and String was NULL. 1609 @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the 1610 request. 1611 1612 **/ 1613 EFI_STATUS 1614 EFIAPI 1615 HiiGetString ( 1616 IN CONST EFI_HII_STRING_PROTOCOL *This, 1617 IN CONST CHAR8 *Language, 1618 IN EFI_HII_HANDLE PackageList, 1619 IN EFI_STRING_ID StringId, 1620 OUT EFI_STRING String, 1621 IN OUT UINTN *StringSize, 1622 OUT EFI_FONT_INFO **StringFontInfo OPTIONAL 1623 ) 1624 { 1625 EFI_STATUS Status; 1626 LIST_ENTRY *Link; 1627 HII_DATABASE_PRIVATE_DATA *Private; 1628 HII_DATABASE_RECORD *DatabaseRecord; 1629 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode; 1630 HII_STRING_PACKAGE_INSTANCE *StringPackage; 1631 1632 if (This == NULL || Language == NULL || StringId < 1 || StringSize == NULL || PackageList == NULL) { 1633 return EFI_INVALID_PARAMETER; 1634 } 1635 1636 if (String == NULL && *StringSize != 0) { 1637 return EFI_INVALID_PARAMETER; 1638 } 1639 1640 if (!IsHiiHandleValid (PackageList)) { 1641 return EFI_NOT_FOUND; 1642 } 1643 1644 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This); 1645 PackageListNode = NULL; 1646 1647 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) { 1648 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); 1649 if (DatabaseRecord->Handle == PackageList) { 1650 PackageListNode = DatabaseRecord->PackageList; 1651 break; 1652 } 1653 } 1654 1655 if (PackageListNode != NULL) { 1656 // 1657 // First search: to match the StringId in the specified language. 1658 // 1659 for (Link = PackageListNode->StringPkgHdr.ForwardLink; 1660 Link != &PackageListNode->StringPkgHdr; 1661 Link = Link->ForwardLink 1662 ) { 1663 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); 1664 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) { 1665 Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo); 1666 if (Status != EFI_NOT_FOUND) { 1667 return Status; 1668 } 1669 } 1670 } 1671 // 1672 // Second search: to match the StringId in other available languages if exist. 1673 // 1674 for (Link = PackageListNode->StringPkgHdr.ForwardLink; 1675 Link != &PackageListNode->StringPkgHdr; 1676 Link = Link->ForwardLink 1677 ) { 1678 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); 1679 Status = GetStringWorker (Private, StringPackage, StringId, NULL, NULL, NULL); 1680 if (!EFI_ERROR (Status)) { 1681 return EFI_INVALID_LANGUAGE; 1682 } 1683 } 1684 } 1685 1686 return EFI_NOT_FOUND; 1687 } 1688 1689 1690 1691 /** 1692 This function updates the string specified by StringId in the specified PackageList to the text 1693 specified by String and, optionally, the font information specified by StringFontInfo. 1694 1695 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. 1696 @param PackageList The package list containing the strings. 1697 @param StringId The string's id, which is unique within 1698 PackageList. 1699 @param Language Points to the language for the updated string. 1700 @param String Points to the new null-terminated string. 1701 @param StringFontInfo Points to the string's font information or NULL if 1702 the string font information is not changed. 1703 1704 @retval EFI_SUCCESS The string was updated successfully. 1705 @retval EFI_NOT_FOUND The string specified by StringId is not in the 1706 database. 1707 @retval EFI_INVALID_PARAMETER The String or Language was NULL. 1708 @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in 1709 current database. 1710 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the 1711 task. 1712 1713 **/ 1714 EFI_STATUS 1715 EFIAPI 1716 HiiSetString ( 1717 IN CONST EFI_HII_STRING_PROTOCOL *This, 1718 IN EFI_HII_HANDLE PackageList, 1719 IN EFI_STRING_ID StringId, 1720 IN CONST CHAR8 *Language, 1721 IN CONST EFI_STRING String, 1722 IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL 1723 ) 1724 { 1725 EFI_STATUS Status; 1726 LIST_ENTRY *Link; 1727 HII_DATABASE_PRIVATE_DATA *Private; 1728 HII_DATABASE_RECORD *DatabaseRecord; 1729 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode; 1730 HII_STRING_PACKAGE_INSTANCE *StringPackage; 1731 UINT32 OldPackageLen; 1732 1733 if (This == NULL || Language == NULL || StringId < 1 || String == NULL || PackageList == NULL) { 1734 return EFI_INVALID_PARAMETER; 1735 } 1736 1737 if (!IsHiiHandleValid (PackageList)) { 1738 return EFI_NOT_FOUND; 1739 } 1740 1741 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This); 1742 PackageListNode = NULL; 1743 1744 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) { 1745 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); 1746 if (DatabaseRecord->Handle == PackageList) { 1747 PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList); 1748 } 1749 } 1750 1751 if (PackageListNode != NULL) { 1752 for (Link = PackageListNode->StringPkgHdr.ForwardLink; 1753 Link != &PackageListNode->StringPkgHdr; 1754 Link = Link->ForwardLink 1755 ) { 1756 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); 1757 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) { 1758 OldPackageLen = StringPackage->StringPkgHdr->Header.Length; 1759 Status = SetStringWorker ( 1760 Private, 1761 StringPackage, 1762 StringId, 1763 (EFI_STRING) String, 1764 (EFI_FONT_INFO *) StringFontInfo 1765 ); 1766 if (EFI_ERROR (Status)) { 1767 return Status; 1768 } 1769 PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen; 1770 // 1771 // Check whether need to get the contents of HiiDataBase. 1772 // Only after ReadyToBoot to do the export. 1773 // 1774 if (gExportAfterReadyToBoot) { 1775 HiiGetDatabaseInfo(&Private->HiiDatabase); 1776 } 1777 return EFI_SUCCESS; 1778 } 1779 } 1780 } 1781 1782 return EFI_NOT_FOUND; 1783 } 1784 1785 1786 1787 /** 1788 This function returns the list of supported languages, in the format specified 1789 in Appendix M of UEFI 2.1 spec. 1790 1791 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. 1792 @param PackageList The package list to examine. 1793 @param Languages Points to the buffer to hold the returned 1794 null-terminated ASCII string. 1795 @param LanguagesSize On entry, points to the size of the buffer pointed 1796 to by Languages, in bytes. On return, points to 1797 the length of Languages, in bytes. 1798 1799 @retval EFI_SUCCESS The languages were returned successfully. 1800 @retval EFI_INVALID_PARAMETER The LanguagesSize was NULL. 1801 @retval EFI_INVALID_PARAMETER The value referenced by LanguagesSize is not zero and Languages is NULL. 1802 @retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list of 1803 supported languages. LanguageSize is updated to 1804 contain the required size. 1805 @retval EFI_NOT_FOUND Could not find string package in specified 1806 packagelist. 1807 1808 **/ 1809 EFI_STATUS 1810 EFIAPI 1811 HiiGetLanguages ( 1812 IN CONST EFI_HII_STRING_PROTOCOL *This, 1813 IN EFI_HII_HANDLE PackageList, 1814 IN OUT CHAR8 *Languages, 1815 IN OUT UINTN *LanguagesSize 1816 ) 1817 { 1818 LIST_ENTRY *Link; 1819 HII_DATABASE_PRIVATE_DATA *Private; 1820 HII_DATABASE_RECORD *DatabaseRecord; 1821 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode; 1822 HII_STRING_PACKAGE_INSTANCE *StringPackage; 1823 UINTN ResultSize; 1824 1825 if (This == NULL || LanguagesSize == NULL || PackageList == NULL) { 1826 return EFI_INVALID_PARAMETER; 1827 } 1828 if (*LanguagesSize != 0 && Languages == NULL) { 1829 return EFI_INVALID_PARAMETER; 1830 } 1831 if (!IsHiiHandleValid (PackageList)) { 1832 return EFI_NOT_FOUND; 1833 } 1834 1835 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This); 1836 1837 PackageListNode = NULL; 1838 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) { 1839 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); 1840 if (DatabaseRecord->Handle == PackageList) { 1841 PackageListNode = DatabaseRecord->PackageList; 1842 break; 1843 } 1844 } 1845 if (PackageListNode == NULL) { 1846 return EFI_NOT_FOUND; 1847 } 1848 1849 // 1850 // Search the languages in the specified packagelist. 1851 // 1852 ResultSize = 0; 1853 for (Link = PackageListNode->StringPkgHdr.ForwardLink; 1854 Link != &PackageListNode->StringPkgHdr; 1855 Link = Link->ForwardLink 1856 ) { 1857 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); 1858 ResultSize += AsciiStrSize (StringPackage->StringPkgHdr->Language); 1859 if (ResultSize <= *LanguagesSize) { 1860 AsciiStrCpyS (Languages, *LanguagesSize / sizeof (CHAR8), StringPackage->StringPkgHdr->Language); 1861 Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language); 1862 *(Languages - 1) = L';'; 1863 } 1864 } 1865 if (ResultSize == 0) { 1866 return EFI_NOT_FOUND; 1867 } 1868 1869 if (*LanguagesSize < ResultSize) { 1870 *LanguagesSize = ResultSize; 1871 return EFI_BUFFER_TOO_SMALL; 1872 } 1873 1874 *(Languages - 1) = 0; 1875 return EFI_SUCCESS; 1876 } 1877 1878 1879 /** 1880 Each string package has associated with it a single primary language and zero 1881 or more secondary languages. This routine returns the secondary languages 1882 associated with a package list. 1883 1884 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. 1885 @param PackageList The package list to examine. 1886 @param PrimaryLanguage Points to the null-terminated ASCII string that specifies 1887 the primary language. Languages are specified in the 1888 format specified in Appendix M of the UEFI 2.0 specification. 1889 @param SecondaryLanguages Points to the buffer to hold the returned null-terminated 1890 ASCII string that describes the list of 1891 secondary languages for the specified 1892 PrimaryLanguage. If there are no secondary 1893 languages, the function returns successfully, but 1894 this is set to NULL. 1895 @param SecondaryLanguagesSize On entry, points to the size of the buffer pointed 1896 to by SecondaryLanguages, in bytes. On return, 1897 points to the length of SecondaryLanguages in bytes. 1898 1899 @retval EFI_SUCCESS Secondary languages were correctly returned. 1900 @retval EFI_INVALID_PARAMETER PrimaryLanguage or SecondaryLanguagesSize was NULL. 1901 @retval EFI_INVALID_PARAMETER The value referenced by SecondaryLanguagesSize is not 1902 zero and SecondaryLanguages is NULL. 1903 @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is 1904 too small to hold the returned information. 1905 SecondaryLanguageSize is updated to hold the size of 1906 the buffer required. 1907 @retval EFI_INVALID_LANGUAGE The language specified by PrimaryLanguage is not 1908 present in the specified package list. 1909 @retval EFI_NOT_FOUND The specified PackageList is not in the Database. 1910 1911 **/ 1912 EFI_STATUS 1913 EFIAPI 1914 HiiGetSecondaryLanguages ( 1915 IN CONST EFI_HII_STRING_PROTOCOL *This, 1916 IN EFI_HII_HANDLE PackageList, 1917 IN CONST CHAR8 *PrimaryLanguage, 1918 IN OUT CHAR8 *SecondaryLanguages, 1919 IN OUT UINTN *SecondaryLanguagesSize 1920 ) 1921 { 1922 LIST_ENTRY *Link; 1923 LIST_ENTRY *Link1; 1924 HII_DATABASE_PRIVATE_DATA *Private; 1925 HII_DATABASE_RECORD *DatabaseRecord; 1926 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode; 1927 HII_STRING_PACKAGE_INSTANCE *StringPackage; 1928 CHAR8 *Languages; 1929 UINTN ResultSize; 1930 1931 if (This == NULL || PackageList == NULL || PrimaryLanguage == NULL || SecondaryLanguagesSize == NULL) { 1932 return EFI_INVALID_PARAMETER; 1933 } 1934 if (SecondaryLanguages == NULL && *SecondaryLanguagesSize != 0) { 1935 return EFI_INVALID_PARAMETER; 1936 } 1937 if (!IsHiiHandleValid (PackageList)) { 1938 return EFI_NOT_FOUND; 1939 } 1940 1941 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This); 1942 1943 PackageListNode = NULL; 1944 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) { 1945 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE); 1946 if (DatabaseRecord->Handle == PackageList) { 1947 PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList); 1948 break; 1949 } 1950 } 1951 if (PackageListNode == NULL) { 1952 return EFI_NOT_FOUND; 1953 } 1954 1955 Languages = NULL; 1956 ResultSize = 0; 1957 for (Link1 = PackageListNode->StringPkgHdr.ForwardLink; 1958 Link1 != &PackageListNode->StringPkgHdr; 1959 Link1 = Link1->ForwardLink 1960 ) { 1961 StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE); 1962 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) PrimaryLanguage)) { 1963 Languages = StringPackage->StringPkgHdr->Language; 1964 // 1965 // Language is a series of ';' terminated strings, first one is primary 1966 // language and following with other secondary languages or NULL if no 1967 // secondary languages any more. 1968 // 1969 Languages = AsciiStrStr (Languages, ";"); 1970 if (Languages == NULL) { 1971 break; 1972 } 1973 Languages++; 1974 1975 ResultSize = AsciiStrSize (Languages); 1976 if (ResultSize <= *SecondaryLanguagesSize) { 1977 AsciiStrCpyS (SecondaryLanguages, *SecondaryLanguagesSize / sizeof (CHAR8), Languages); 1978 } else { 1979 *SecondaryLanguagesSize = ResultSize; 1980 return EFI_BUFFER_TOO_SMALL; 1981 } 1982 1983 return EFI_SUCCESS; 1984 } 1985 } 1986 1987 return EFI_INVALID_LANGUAGE; 1988 } 1989 1990 /** 1991 Converts the ascii character of the string from uppercase to lowercase. 1992 This is a internal function. 1993 1994 @param ConfigString String to be converted 1995 1996 **/ 1997 VOID 1998 EFIAPI 1999 AsciiHiiToLower ( 2000 IN CHAR8 *ConfigString 2001 ) 2002 { 2003 ASSERT (ConfigString != NULL); 2004 2005 // 2006 // Convert all hex digits in range [A-F] in the configuration header to [a-f] 2007 // 2008 for (; *ConfigString != '\0'; ConfigString++) { 2009 if ( *ConfigString >= 'A' && *ConfigString <= 'Z') { 2010 *ConfigString = (CHAR8) (*ConfigString - 'A' + 'a'); 2011 } 2012 } 2013 } 2014 2015 /** 2016 Compare whether two names of languages are identical. 2017 2018 @param Language1 Name of language 1 from StringPackage 2019 @param Language2 Name of language 2 to be compared with language 1. 2020 2021 @retval TRUE same 2022 @retval FALSE not same 2023 2024 **/ 2025 BOOLEAN 2026 HiiCompareLanguage ( 2027 IN CHAR8 *Language1, 2028 IN CHAR8 *Language2 2029 ) 2030 { 2031 UINTN Index; 2032 UINTN StrLen; 2033 CHAR8 *Lan1; 2034 CHAR8 *Lan2; 2035 2036 // 2037 // Convert to lower to compare. 2038 // 2039 StrLen = AsciiStrSize (Language1); 2040 Lan1 = AllocateZeroPool (StrLen); 2041 ASSERT (Lan1 != NULL); 2042 AsciiStrCpyS(Lan1, StrLen / sizeof (CHAR8), Language1); 2043 AsciiHiiToLower (Lan1); 2044 2045 StrLen = AsciiStrSize (Language2); 2046 Lan2 = AllocateZeroPool (StrLen); 2047 ASSERT (Lan2 != NULL); 2048 AsciiStrCpyS(Lan2, StrLen / sizeof (CHAR8), Language2); 2049 AsciiHiiToLower (Lan2); 2050 2051 // 2052 // Compare the Primary Language in Language1 to Language2 2053 // 2054 for (Index = 0; Lan1[Index] != 0 && Lan1[Index] != ';'; Index++) { 2055 if (Lan1[Index] != Lan2[Index]) { 2056 // 2057 // Return FALSE if any characters are different. 2058 // 2059 FreePool (Lan1); 2060 FreePool (Lan2); 2061 return FALSE; 2062 } 2063 } 2064 2065 FreePool (Lan1); 2066 FreePool (Lan2); 2067 2068 // 2069 // Only return TRUE if Language2[Index] is a Null-terminator which means 2070 // the Primary Language in Language1 is the same length as Language2. If 2071 // Language2[Index] is not a Null-terminator, then Language2 is longer than 2072 // the Primary Language in Language1, and FALSE must be returned. 2073 // 2074 return (BOOLEAN) (Language2[Index] == 0); 2075 } 2076