1 /** @file 2 3 This library class defines a set of interfaces to customize Display module 4 5 Copyright (c) 2013-2015, Intel Corporation. All rights reserved.<BR> 6 This program and the accompanying materials are licensed and made available under 7 the terms and conditions of the BSD License that accompanies this distribution. 8 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 #include "CustomizedDisplayLibInternal.h" 16 17 EFI_SCREEN_DESCRIPTOR gScreenDimensions; 18 CHAR16 *mLibUnknownString; 19 extern EFI_HII_HANDLE mCDLStringPackHandle; 20 CHAR16 *mSpaceBuffer; 21 #define SPACE_BUFFER_SIZE 1000 22 23 // 24 // Browser Global Strings 25 // 26 CHAR16 *gEnterString; 27 CHAR16 *gEnterCommitString; 28 CHAR16 *gEnterEscapeString; 29 CHAR16 *gEscapeString; 30 CHAR16 *gMoveHighlight; 31 CHAR16 *gDecNumericInput; 32 CHAR16 *gHexNumericInput; 33 CHAR16 *gToggleCheckBox; 34 CHAR16 *gLibEmptyString; 35 CHAR16 *gAreYouSure; 36 CHAR16 *gYesResponse; 37 CHAR16 *gNoResponse; 38 CHAR16 *gPlusString; 39 CHAR16 *gMinusString; 40 CHAR16 *gAdjustNumber; 41 CHAR16 *gSaveChanges; 42 CHAR16 *gNvUpdateMessage; 43 CHAR16 *gInputErrorMessage; 44 45 /** 46 47 Print banner info for front page. 48 49 @param[in] FormData Form Data to be shown in Page 50 51 **/ 52 VOID 53 PrintBannerInfo ( 54 IN FORM_DISPLAY_ENGINE_FORM *FormData 55 ) 56 { 57 UINT8 Line; 58 UINT8 Alignment; 59 CHAR16 *StrFrontPageBanner; 60 UINT8 RowIdx; 61 UINT8 ColumnIdx; 62 63 // 64 // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND); 65 // 66 ClearLines ( 67 gScreenDimensions.LeftColumn, 68 gScreenDimensions.RightColumn, 69 gScreenDimensions.TopRow, 70 FRONT_PAGE_HEADER_HEIGHT - 1 + gScreenDimensions.TopRow, 71 BANNER_TEXT | BANNER_BACKGROUND 72 ); 73 74 // 75 // for (Line = 0; Line < BANNER_HEIGHT; Line++) { 76 // 77 for (Line = (UINT8) gScreenDimensions.TopRow; Line < BANNER_HEIGHT + (UINT8) gScreenDimensions.TopRow; Line++) { 78 // 79 // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) { 80 // 81 for (Alignment = (UINT8) gScreenDimensions.LeftColumn; 82 Alignment < BANNER_COLUMNS + (UINT8) gScreenDimensions.LeftColumn; 83 Alignment++ 84 ) { 85 RowIdx = (UINT8) (Line - (UINT8) gScreenDimensions.TopRow); 86 ColumnIdx = (UINT8) (Alignment - (UINT8) gScreenDimensions.LeftColumn); 87 88 ASSERT (RowIdx < BANNER_HEIGHT && ColumnIdx < BANNER_COLUMNS); 89 90 if (gBannerData!= NULL && gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) { 91 StrFrontPageBanner = LibGetToken (gBannerData->Banner[RowIdx][ColumnIdx], FormData->HiiHandle); 92 } else { 93 continue; 94 } 95 96 switch (Alignment - gScreenDimensions.LeftColumn) { 97 case 0: 98 // 99 // Handle left column 100 // 101 PrintStringAt (gScreenDimensions.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner); 102 break; 103 104 case 1: 105 // 106 // Handle center column 107 // 108 PrintStringAt ( 109 gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3, 110 Line, 111 StrFrontPageBanner 112 ); 113 break; 114 115 case 2: 116 // 117 // Handle right column 118 // 119 PrintStringAt ( 120 gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) * 2 / 3, 121 Line, 122 StrFrontPageBanner 123 ); 124 break; 125 } 126 127 FreePool (StrFrontPageBanner); 128 } 129 } 130 } 131 132 /** 133 Print framework and form title for a page. 134 135 @param[in] FormData Form Data to be shown in Page 136 **/ 137 VOID 138 PrintFramework ( 139 IN FORM_DISPLAY_ENGINE_FORM *FormData 140 ) 141 { 142 UINTN Index; 143 CHAR16 Character; 144 CHAR16 *Buffer; 145 UINTN Row; 146 CHAR16 *TitleStr; 147 UINTN TitleColumn; 148 149 if (gClassOfVfr != FORMSET_CLASS_PLATFORM_SETUP) { 150 // 151 // Only Setup page needs Framework 152 // 153 ClearLines ( 154 gScreenDimensions.LeftColumn, 155 gScreenDimensions.RightColumn, 156 gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, 157 gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1, 158 KEYHELP_TEXT | KEYHELP_BACKGROUND 159 ); 160 return; 161 } 162 163 Buffer = AllocateZeroPool (0x10000); 164 ASSERT (Buffer != NULL); 165 Character = BOXDRAW_HORIZONTAL; 166 for (Index = 0; Index + 2 < (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn); Index++) { 167 Buffer[Index] = Character; 168 } 169 170 // 171 // Print Top border line 172 // +------------------------------------------------------------------------------+ 173 // ? ? 174 // +------------------------------------------------------------------------------+ 175 // 176 gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND); 177 Character = BOXDRAW_DOWN_RIGHT; 178 179 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow, Character); 180 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer); 181 182 Character = BOXDRAW_DOWN_LEFT; 183 PrintCharAt ((UINTN) -1, (UINTN) -1, Character); 184 185 Character = BOXDRAW_VERTICAL; 186 for (Row = gScreenDimensions.TopRow + 1; Row <= gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) { 187 PrintCharAt (gScreenDimensions.LeftColumn, Row, Character); 188 PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character); 189 } 190 191 // 192 // Print Form Title 193 // 194 TitleStr = LibGetToken (FormData->FormTitle, FormData->HiiHandle); 195 ASSERT (TitleStr != NULL); 196 TitleColumn = (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - LibGetStringWidth (TitleStr) / 2) / 2; 197 PrintStringAtWithWidth (gScreenDimensions.LeftColumn + 1, gScreenDimensions.TopRow + 1, gLibEmptyString, TitleColumn - gScreenDimensions.LeftColumn - 1); 198 PrintStringAtWithWidth ( 199 TitleColumn, 200 gScreenDimensions.TopRow + 1, 201 TitleStr, 202 gScreenDimensions.RightColumn - 1 - TitleColumn 203 ); 204 FreePool (TitleStr); 205 206 Character = BOXDRAW_UP_RIGHT; 207 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character); 208 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer); 209 210 Character = BOXDRAW_UP_LEFT; 211 PrintCharAt ((UINTN) -1, (UINTN) -1, Character); 212 213 // 214 // Print Bottom border line 215 // +------------------------------------------------------------------------------+ 216 // ? ? 217 // +------------------------------------------------------------------------------+ 218 // 219 Character = BOXDRAW_DOWN_RIGHT; 220 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character); 221 222 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer); 223 224 Character = BOXDRAW_DOWN_LEFT; 225 PrintCharAt ((UINTN) -1, (UINTN) -1, Character); 226 Character = BOXDRAW_VERTICAL; 227 for (Row = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1; 228 Row <= gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2; 229 Row++ 230 ) { 231 PrintCharAt (gScreenDimensions.LeftColumn, Row, Character); 232 PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character); 233 } 234 235 Character = BOXDRAW_UP_RIGHT; 236 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1, Character); 237 238 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer); 239 240 Character = BOXDRAW_UP_LEFT; 241 PrintCharAt ((UINTN) -1, (UINTN) -1, Character); 242 243 FreePool (Buffer); 244 } 245 246 /** 247 Process some op code which is not recognized by browser core. 248 249 @param OpCodeData The pointer to the op code buffer. 250 251 @return EFI_SUCCESS Pass the statement success. 252 253 **/ 254 VOID 255 ProcessUserOpcode( 256 IN EFI_IFR_OP_HEADER *OpCodeData 257 ) 258 { 259 EFI_GUID * ClassGuid; 260 UINT8 ClassGuidNum; 261 262 ClassGuid = NULL; 263 ClassGuidNum = 0; 264 265 switch (OpCodeData->OpCode) { 266 case EFI_IFR_FORM_SET_OP: 267 // 268 // process the statement outside of form,if it is formset op, get its formsetguid or classguid and compared with gFrontPageFormSetGuid 269 // 270 if (CompareMem (PcdGetPtr (PcdFrontPageFormSetGuid), &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) == 0){ 271 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE; 272 } else{ 273 ClassGuidNum = (UINT8)(((EFI_IFR_FORM_SET *)OpCodeData)->Flags & 0x3); 274 ClassGuid = (EFI_GUID *)(VOID *)((UINT8 *)OpCodeData + sizeof (EFI_IFR_FORM_SET)); 275 while (ClassGuidNum-- > 0){ 276 if (CompareGuid((EFI_GUID*)PcdGetPtr (PcdFrontPageFormSetGuid),ClassGuid)){ 277 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE; 278 break; 279 } 280 ClassGuid ++; 281 } 282 } 283 break; 284 285 case EFI_IFR_GUID_OP: 286 if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)((CHAR8*) OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { 287 // 288 // Tiano specific GUIDed opcodes 289 // 290 switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) { 291 case EFI_IFR_EXTEND_OP_LABEL: 292 // 293 // just ignore label 294 // 295 break; 296 297 case EFI_IFR_EXTEND_OP_BANNER: 298 // 299 // Only in front page form set, we care about the banner data. 300 // 301 if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) { 302 // 303 // Initialize Driver private data 304 // 305 if (gBannerData == NULL) { 306 gBannerData = AllocateZeroPool (sizeof (BANNER_DATA)); 307 ASSERT (gBannerData != NULL); 308 } 309 310 CopyMem ( 311 &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][ 312 ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment], 313 &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title, 314 sizeof (EFI_STRING_ID) 315 ); 316 } 317 break; 318 319 case EFI_IFR_EXTEND_OP_SUBCLASS: 320 if (((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass == EFI_FRONT_PAGE_SUBCLASS) { 321 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE; 322 } 323 break; 324 325 default: 326 break; 327 } 328 } 329 break; 330 331 default: 332 break; 333 } 334 } 335 336 /** 337 Process some op codes which is out side of current form. 338 339 @param FormData Pointer to the form data. 340 341 @return EFI_SUCCESS Pass the statement success. 342 343 **/ 344 VOID 345 ProcessExternedOpcode ( 346 IN FORM_DISPLAY_ENGINE_FORM *FormData 347 ) 348 { 349 LIST_ENTRY *Link; 350 LIST_ENTRY *NestLink; 351 FORM_DISPLAY_ENGINE_STATEMENT *Statement; 352 FORM_DISPLAY_ENGINE_STATEMENT *NestStatement; 353 354 Link = GetFirstNode (&FormData->StatementListOSF); 355 while (!IsNull (&FormData->StatementListOSF, Link)) { 356 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link); 357 Link = GetNextNode (&FormData->StatementListOSF, Link); 358 359 ProcessUserOpcode(Statement->OpCode); 360 } 361 362 Link = GetFirstNode (&FormData->StatementListHead); 363 while (!IsNull (&FormData->StatementListHead, Link)) { 364 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link); 365 Link = GetNextNode (&FormData->StatementListHead, Link); 366 367 ProcessUserOpcode(Statement->OpCode); 368 369 NestLink = GetFirstNode (&Statement->NestStatementList); 370 while (!IsNull (&Statement->NestStatementList, NestLink)) { 371 NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink); 372 NestLink = GetNextNode (&Statement->NestStatementList, NestLink); 373 374 ProcessUserOpcode(NestStatement->OpCode); 375 } 376 377 } 378 } 379 380 /** 381 Validate the input screen diemenstion info. 382 383 @param FormData The input form data info. 384 385 @return EFI_SUCCESS The input screen info is acceptable. 386 @return EFI_INVALID_PARAMETER The input screen info is not acceptable. 387 388 **/ 389 EFI_STATUS 390 ScreenDiemensionInfoValidate ( 391 IN FORM_DISPLAY_ENGINE_FORM *FormData 392 ) 393 { 394 LIST_ENTRY *Link; 395 UINTN Index; 396 397 // 398 // Calculate total number of Register HotKeys. 399 // 400 Index = 0; 401 if (!IsListEmpty (&FormData->HotKeyListHead)){ 402 Link = GetFirstNode (&FormData->HotKeyListHead); 403 while (!IsNull (&FormData->HotKeyListHead, Link)) { 404 Link = GetNextNode (&FormData->HotKeyListHead, Link); 405 Index ++; 406 } 407 } 408 409 // 410 // Show three HotKeys help information on one row. 411 // 412 gFooterHeight = FOOTER_HEIGHT + (Index / 3); 413 414 415 ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); 416 gST->ConOut->QueryMode ( 417 gST->ConOut, 418 gST->ConOut->Mode->Mode, 419 &gScreenDimensions.RightColumn, 420 &gScreenDimensions.BottomRow 421 ); 422 423 // 424 // Check local dimension vs. global dimension. 425 // 426 if (FormData->ScreenDimensions != NULL) { 427 if ((gScreenDimensions.RightColumn < FormData->ScreenDimensions->RightColumn) || 428 (gScreenDimensions.BottomRow < FormData->ScreenDimensions->BottomRow) 429 ) { 430 return EFI_INVALID_PARAMETER; 431 } else { 432 // 433 // Local dimension validation. 434 // 435 if ((FormData->ScreenDimensions->RightColumn > FormData->ScreenDimensions->LeftColumn) && 436 (FormData->ScreenDimensions->BottomRow > FormData->ScreenDimensions->TopRow) && 437 ((FormData->ScreenDimensions->RightColumn - FormData->ScreenDimensions->LeftColumn) > 2) && 438 ((FormData->ScreenDimensions->BottomRow - FormData->ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT + 439 FRONT_PAGE_HEADER_HEIGHT + gFooterHeight + 3)) { 440 CopyMem (&gScreenDimensions, (VOID *) FormData->ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); 441 } else { 442 return EFI_INVALID_PARAMETER; 443 } 444 } 445 } 446 447 return EFI_SUCCESS; 448 } 449 450 /** 451 Get the string based on the StringId and HII Package List Handle. 452 453 @param Token The String's ID. 454 @param HiiHandle The package list in the HII database to search for 455 the specified string. 456 457 @return The output string. 458 459 **/ 460 CHAR16 * 461 LibGetToken ( 462 IN EFI_STRING_ID Token, 463 IN EFI_HII_HANDLE HiiHandle 464 ) 465 { 466 EFI_STRING String; 467 468 String = HiiGetString (HiiHandle, Token, NULL); 469 if (String == NULL) { 470 String = AllocateCopyPool (StrSize (mLibUnknownString), mLibUnknownString); 471 ASSERT (String != NULL); 472 } 473 474 return (CHAR16 *) String; 475 } 476 477 478 /** 479 Count the storage space of a Unicode string. 480 481 This function handles the Unicode string with NARROW_CHAR 482 and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR 483 does not count in the resultant output. If a WIDE_CHAR is 484 hit, then 2 Unicode character will consume an output storage 485 space with size of CHAR16 till a NARROW_CHAR is hit. 486 487 If String is NULL, then ASSERT (). 488 489 @param String The input string to be counted. 490 491 @return Storage space for the input string. 492 493 **/ 494 UINTN 495 LibGetStringWidth ( 496 IN CHAR16 *String 497 ) 498 { 499 UINTN Index; 500 UINTN Count; 501 UINTN IncrementValue; 502 503 ASSERT (String != NULL); 504 if (String == NULL) { 505 return 0; 506 } 507 508 Index = 0; 509 Count = 0; 510 IncrementValue = 1; 511 512 do { 513 // 514 // Advance to the null-terminator or to the first width directive 515 // 516 for (; 517 (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0); 518 Index++, Count = Count + IncrementValue 519 ) 520 ; 521 522 // 523 // We hit the null-terminator, we now have a count 524 // 525 if (String[Index] == 0) { 526 break; 527 } 528 // 529 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed 530 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2) 531 // 532 if (String[Index] == NARROW_CHAR) { 533 // 534 // Skip to the next character 535 // 536 Index++; 537 IncrementValue = 1; 538 } else { 539 // 540 // Skip to the next character 541 // 542 Index++; 543 IncrementValue = 2; 544 } 545 } while (String[Index] != 0); 546 547 // 548 // Increment by one to include the null-terminator in the size 549 // 550 Count++; 551 552 return Count * sizeof (CHAR16); 553 } 554 555 /** 556 Show all registered HotKey help strings on bottom Rows. 557 558 @param FormData The curent input form data info. 559 @param SetState Set HotKey or Clear HotKey 560 561 **/ 562 VOID 563 PrintHotKeyHelpString ( 564 IN FORM_DISPLAY_ENGINE_FORM *FormData, 565 IN BOOLEAN SetState 566 ) 567 { 568 UINTN CurrentCol; 569 UINTN CurrentRow; 570 UINTN BottomRowOfHotKeyHelp; 571 UINTN ColumnIndexWidth; 572 UINTN ColumnWidth; 573 UINTN ColumnIndex; 574 UINTN Index; 575 EFI_SCREEN_DESCRIPTOR LocalScreen; 576 LIST_ENTRY *Link; 577 BROWSER_HOT_KEY *HotKey; 578 CHAR16 BakChar; 579 CHAR16 *ColumnStr; 580 581 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); 582 ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3; 583 BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3; 584 ColumnStr = gLibEmptyString; 585 586 // 587 // Calculate total number of Register HotKeys. 588 // 589 Index = 0; 590 Link = GetFirstNode (&FormData->HotKeyListHead); 591 while (!IsNull (&FormData->HotKeyListHead, Link)) { 592 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link); 593 // 594 // Calculate help information Column and Row. 595 // 596 ColumnIndex = Index % 3; 597 if (ColumnIndex == 0) { 598 CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth; 599 ColumnIndexWidth = ColumnWidth - 1; 600 } else if (ColumnIndex == 1) { 601 CurrentCol = LocalScreen.LeftColumn + ColumnWidth; 602 ColumnIndexWidth = ColumnWidth; 603 } else { 604 CurrentCol = LocalScreen.LeftColumn + 2; 605 ColumnIndexWidth = ColumnWidth - 2; 606 } 607 CurrentRow = BottomRowOfHotKeyHelp - Index / 3; 608 609 // 610 // Help string can't exceed ColumnWidth. One Row will show three Help information. 611 // 612 BakChar = L'\0'; 613 if (StrLen (HotKey->HelpString) > ColumnIndexWidth) { 614 BakChar = HotKey->HelpString[ColumnIndexWidth]; 615 HotKey->HelpString[ColumnIndexWidth] = L'\0'; 616 } 617 618 // 619 // Print HotKey help string on bottom Row. 620 // 621 if (SetState) { 622 ColumnStr = HotKey->HelpString; 623 } 624 PrintStringAtWithWidth (CurrentCol, CurrentRow, ColumnStr, ColumnIndexWidth); 625 626 if (BakChar != L'\0') { 627 HotKey->HelpString[ColumnIndexWidth] = BakChar; 628 } 629 // 630 // Get Next Hot Key. 631 // 632 Link = GetNextNode (&FormData->HotKeyListHead, Link); 633 Index ++; 634 } 635 636 if (SetState) { 637 // 638 // Clear KeyHelp 639 // 640 CurrentRow = BottomRowOfHotKeyHelp - Index / 3; 641 ColumnIndex = Index % 3; 642 if (ColumnIndex == 0) { 643 CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth; 644 ColumnIndexWidth = ColumnWidth - 1; 645 ColumnIndex ++; 646 PrintStringAtWithWidth (CurrentCol, CurrentRow, gLibEmptyString, ColumnIndexWidth); 647 } 648 if (ColumnIndex == 1) { 649 CurrentCol = LocalScreen.LeftColumn + ColumnWidth; 650 ColumnIndexWidth = ColumnWidth; 651 PrintStringAtWithWidth (CurrentCol, CurrentRow, gLibEmptyString, ColumnIndexWidth); 652 } 653 } 654 655 return; 656 } 657 658 /** 659 Get step info from numeric opcode. 660 661 @param[in] OpCode The input numeric op code. 662 663 @return step info for this opcode. 664 **/ 665 UINT64 666 LibGetFieldFromNum ( 667 IN EFI_IFR_OP_HEADER *OpCode 668 ) 669 { 670 EFI_IFR_NUMERIC *NumericOp; 671 UINT64 Step; 672 673 NumericOp = (EFI_IFR_NUMERIC *) OpCode; 674 675 switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) { 676 case EFI_IFR_NUMERIC_SIZE_1: 677 Step = NumericOp->data.u8.Step; 678 break; 679 680 case EFI_IFR_NUMERIC_SIZE_2: 681 Step = NumericOp->data.u16.Step; 682 break; 683 684 case EFI_IFR_NUMERIC_SIZE_4: 685 Step = NumericOp->data.u32.Step; 686 break; 687 688 case EFI_IFR_NUMERIC_SIZE_8: 689 Step = NumericOp->data.u64.Step; 690 break; 691 692 default: 693 Step = 0; 694 break; 695 } 696 697 return Step; 698 } 699 700 /** 701 Initialize the HII String Token to the correct values. 702 703 **/ 704 VOID 705 InitializeLibStrings ( 706 VOID 707 ) 708 { 709 mLibUnknownString = L"!"; 710 711 gEnterString = LibGetToken (STRING_TOKEN (ENTER_STRING), mCDLStringPackHandle); 712 gEnterCommitString = LibGetToken (STRING_TOKEN (ENTER_COMMIT_STRING), mCDLStringPackHandle); 713 gEnterEscapeString = LibGetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), mCDLStringPackHandle); 714 gEscapeString = LibGetToken (STRING_TOKEN (ESCAPE_STRING), mCDLStringPackHandle); 715 gMoveHighlight = LibGetToken (STRING_TOKEN (MOVE_HIGHLIGHT), mCDLStringPackHandle); 716 gDecNumericInput = LibGetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), mCDLStringPackHandle); 717 gHexNumericInput = LibGetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), mCDLStringPackHandle); 718 gToggleCheckBox = LibGetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), mCDLStringPackHandle); 719 720 gAreYouSure = LibGetToken (STRING_TOKEN (ARE_YOU_SURE), mCDLStringPackHandle); 721 gYesResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_YES), mCDLStringPackHandle); 722 gNoResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_NO), mCDLStringPackHandle); 723 gPlusString = LibGetToken (STRING_TOKEN (PLUS_STRING), mCDLStringPackHandle); 724 gMinusString = LibGetToken (STRING_TOKEN (MINUS_STRING), mCDLStringPackHandle); 725 gAdjustNumber = LibGetToken (STRING_TOKEN (ADJUST_NUMBER), mCDLStringPackHandle); 726 gSaveChanges = LibGetToken (STRING_TOKEN (SAVE_CHANGES), mCDLStringPackHandle); 727 728 gLibEmptyString = LibGetToken (STRING_TOKEN (EMPTY_STRING), mCDLStringPackHandle); 729 730 gNvUpdateMessage = LibGetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), mCDLStringPackHandle); 731 gInputErrorMessage = LibGetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), mCDLStringPackHandle); 732 733 // 734 // SpaceBuffer; 735 // 736 mSpaceBuffer = AllocatePool ((SPACE_BUFFER_SIZE + 1) * sizeof (CHAR16)); 737 ASSERT (mSpaceBuffer != NULL); 738 LibSetUnicodeMem (mSpaceBuffer, SPACE_BUFFER_SIZE, L' '); 739 mSpaceBuffer[SPACE_BUFFER_SIZE] = L'\0'; 740 } 741 742 743 /** 744 Free the HII String. 745 746 **/ 747 VOID 748 FreeLibStrings ( 749 VOID 750 ) 751 { 752 FreePool (gEnterString); 753 FreePool (gEnterCommitString); 754 FreePool (gEnterEscapeString); 755 FreePool (gEscapeString); 756 FreePool (gMoveHighlight); 757 FreePool (gDecNumericInput); 758 FreePool (gHexNumericInput); 759 FreePool (gToggleCheckBox); 760 761 FreePool (gAreYouSure); 762 FreePool (gYesResponse); 763 FreePool (gNoResponse); 764 FreePool (gPlusString); 765 FreePool (gMinusString); 766 FreePool (gAdjustNumber); 767 FreePool (gSaveChanges); 768 769 FreePool (gLibEmptyString); 770 771 FreePool (gNvUpdateMessage); 772 FreePool (gInputErrorMessage); 773 774 FreePool (mSpaceBuffer); 775 } 776 777 /** 778 Wait for a key to be pressed by user. 779 780 @param Key The key which is pressed by user. 781 782 @retval EFI_SUCCESS The function always completed successfully. 783 784 **/ 785 EFI_STATUS 786 WaitForKeyStroke ( 787 OUT EFI_INPUT_KEY *Key 788 ) 789 { 790 EFI_STATUS Status; 791 UINTN Index; 792 793 while (TRUE) { 794 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key); 795 if (!EFI_ERROR (Status)) { 796 break; 797 } 798 799 if (Status != EFI_NOT_READY) { 800 continue; 801 } 802 803 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index); 804 } 805 return Status; 806 } 807 808 809 /** 810 Set Buffer to Value for Size bytes. 811 812 @param Buffer Memory to set. 813 @param Size Number of bytes to set 814 @param Value Value of the set operation. 815 816 **/ 817 VOID 818 LibSetUnicodeMem ( 819 IN VOID *Buffer, 820 IN UINTN Size, 821 IN CHAR16 Value 822 ) 823 { 824 CHAR16 *Ptr; 825 826 Ptr = Buffer; 827 while ((Size--) != 0) { 828 *(Ptr++) = Value; 829 } 830 } 831 832 /** 833 The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL 834 protocol instance. 835 836 @param Width Width of string to be print. 837 @param Column The position of the output string. 838 @param Row The position of the output string. 839 @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. 840 @param Fmt The format string. 841 @param Args The additional argument for the variables in the format string. 842 843 @return Number of Unicode character printed. 844 845 **/ 846 UINTN 847 PrintInternal ( 848 IN UINTN Width, 849 IN UINTN Column, 850 IN UINTN Row, 851 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out, 852 IN CHAR16 *Fmt, 853 IN VA_LIST Args 854 ) 855 { 856 CHAR16 *Buffer; 857 CHAR16 *BackupBuffer; 858 UINTN Index; 859 UINTN PreviousIndex; 860 UINTN Count; 861 UINTN TotalCount; 862 UINTN PrintWidth; 863 UINTN CharWidth; 864 865 // 866 // For now, allocate an arbitrarily long buffer 867 // 868 Buffer = AllocateZeroPool (0x10000); 869 BackupBuffer = AllocateZeroPool (0x10000); 870 ASSERT (Buffer); 871 ASSERT (BackupBuffer); 872 873 if (Column != (UINTN) -1) { 874 Out->SetCursorPosition (Out, Column, Row); 875 } 876 877 UnicodeVSPrint (Buffer, 0x10000, Fmt, Args); 878 879 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; 880 881 Out->SetAttribute (Out, Out->Mode->Attribute); 882 883 Index = 0; 884 PreviousIndex = 0; 885 Count = 0; 886 TotalCount = 0; 887 PrintWidth = 0; 888 CharWidth = 1; 889 890 do { 891 for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) { 892 BackupBuffer[Index] = Buffer[Index]; 893 } 894 895 if (Buffer[Index] == 0) { 896 break; 897 } 898 899 // 900 // Print this out, we are about to switch widths 901 // 902 Out->OutputString (Out, &BackupBuffer[PreviousIndex]); 903 Count = StrLen (&BackupBuffer[PreviousIndex]); 904 PrintWidth += Count * CharWidth; 905 TotalCount += Count; 906 907 // 908 // Preserve the current index + 1, since this is where we will start printing from next 909 // 910 PreviousIndex = Index + 1; 911 912 // 913 // We are at a narrow or wide character directive. Set attributes and strip it and print it 914 // 915 if (Buffer[Index] == NARROW_CHAR) { 916 // 917 // Preserve bits 0 - 6 and zero out the rest 918 // 919 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; 920 Out->SetAttribute (Out, Out->Mode->Attribute); 921 CharWidth = 1; 922 } else { 923 // 924 // Must be wide, set bit 7 ON 925 // 926 Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE; 927 Out->SetAttribute (Out, Out->Mode->Attribute); 928 CharWidth = 2; 929 } 930 931 Index++; 932 933 } while (Buffer[Index] != 0); 934 935 // 936 // We hit the end of the string - print it 937 // 938 Out->OutputString (Out, &BackupBuffer[PreviousIndex]); 939 Count = StrLen (&BackupBuffer[PreviousIndex]); 940 PrintWidth += Count * CharWidth; 941 TotalCount += Count; 942 if (PrintWidth < Width) { 943 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; 944 Out->SetAttribute (Out, Out->Mode->Attribute); 945 Out->OutputString (Out, &mSpaceBuffer[SPACE_BUFFER_SIZE - Width + PrintWidth]); 946 } 947 948 FreePool (Buffer); 949 FreePool (BackupBuffer); 950 return TotalCount; 951 } 952 953 /** 954 Prints a formatted unicode string to the default console, at 955 the supplied cursor position. 956 957 @param Width Width of String to be printed. 958 @param Column The cursor position to print the string at. 959 @param Row The cursor position to print the string at. 960 @param Fmt Format string. 961 @param ... Variable argument list for format string. 962 963 @return Length of string printed to the console 964 965 **/ 966 UINTN 967 EFIAPI 968 PrintAt ( 969 IN UINTN Width, 970 IN UINTN Column, 971 IN UINTN Row, 972 IN CHAR16 *Fmt, 973 ... 974 ) 975 { 976 VA_LIST Args; 977 UINTN LengthOfPrinted; 978 979 VA_START (Args, Fmt); 980 LengthOfPrinted = PrintInternal (Width, Column, Row, gST->ConOut, Fmt, Args); 981 VA_END (Args); 982 return LengthOfPrinted; 983 } 984 985