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