blob: ad4bc9ac90898a07def7570180f29397e274b8c2 [file] [log] [blame]
Vishal Bhoj82c80712015-12-15 21:13:33 +05301/** @file
2
3 This library class defines a set of interfaces to customize Display module
4
5Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
6This program and the accompanying materials are licensed and made available under
7the terms and conditions of the BSD License that accompanies this distribution.
8The full text of the license may be found at
9http://opensource.org/licenses/bsd-license.php.
10
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14**/
15#include "CustomizedDisplayLibInternal.h"
16
17EFI_SCREEN_DESCRIPTOR gScreenDimensions;
18CHAR16 *mLibUnknownString;
19extern EFI_HII_HANDLE mCDLStringPackHandle;
20CHAR16 *mSpaceBuffer;
21#define SPACE_BUFFER_SIZE 1000
22
23//
24// Browser Global Strings
25//
26CHAR16 *gEnterString;
27CHAR16 *gEnterCommitString;
28CHAR16 *gEnterEscapeString;
29CHAR16 *gEscapeString;
30CHAR16 *gMoveHighlight;
31CHAR16 *gDecNumericInput;
32CHAR16 *gHexNumericInput;
33CHAR16 *gToggleCheckBox;
34CHAR16 *gLibEmptyString;
35CHAR16 *gAreYouSure;
36CHAR16 *gYesResponse;
37CHAR16 *gNoResponse;
38CHAR16 *gPlusString;
39CHAR16 *gMinusString;
40CHAR16 *gAdjustNumber;
41CHAR16 *gSaveChanges;
42CHAR16 *gNvUpdateMessage;
43CHAR16 *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**/
52VOID
53PrintBannerInfo (
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**/
137VOID
138PrintFramework (
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**/
254VOID
255ProcessUserOpcode(
256 IN EFI_IFR_OP_HEADER *OpCodeData
257 )
258{
259 switch (OpCodeData->OpCode) {
260 case EFI_IFR_GUID_OP:
261 if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)((CHAR8*) OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
262 //
263 // Tiano specific GUIDed opcodes
264 //
265 switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {
266 case EFI_IFR_EXTEND_OP_LABEL:
267 //
268 // just ignore label
269 //
270 break;
271
272 case EFI_IFR_EXTEND_OP_BANNER:
273 //
274 // Only in front page form set, we care about the banner data.
275 //
276 if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {
277 //
278 // Initialize Driver private data
279 //
280 if (gBannerData == NULL) {
281 gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));
282 ASSERT (gBannerData != NULL);
283 }
284
285 CopyMem (
286 &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][
287 ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],
288 &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,
289 sizeof (EFI_STRING_ID)
290 );
291 }
292 break;
293
294 case EFI_IFR_EXTEND_OP_SUBCLASS:
295 if (((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass == EFI_FRONT_PAGE_SUBCLASS) {
296 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;
297 }
298 break;
299
300 default:
301 break;
302 }
303 }
304 break;
305
306 default:
307 break;
308 }
309}
310
311/**
312 Process some op codes which is out side of current form.
313
314 @param FormData Pointer to the form data.
315
316 @return EFI_SUCCESS Pass the statement success.
317
318**/
319VOID
320ProcessExternedOpcode (
321 IN FORM_DISPLAY_ENGINE_FORM *FormData
322 )
323{
324 LIST_ENTRY *Link;
325 LIST_ENTRY *NestLink;
326 FORM_DISPLAY_ENGINE_STATEMENT *Statement;
327 FORM_DISPLAY_ENGINE_STATEMENT *NestStatement;
328
329 Link = GetFirstNode (&FormData->StatementListOSF);
330 while (!IsNull (&FormData->StatementListOSF, Link)) {
331 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
332 Link = GetNextNode (&FormData->StatementListOSF, Link);
333
334 ProcessUserOpcode(Statement->OpCode);
335 }
336
337 Link = GetFirstNode (&FormData->StatementListHead);
338 while (!IsNull (&FormData->StatementListHead, Link)) {
339 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
340 Link = GetNextNode (&FormData->StatementListHead, Link);
341
342 ProcessUserOpcode(Statement->OpCode);
343
344 NestLink = GetFirstNode (&Statement->NestStatementList);
345 while (!IsNull (&Statement->NestStatementList, NestLink)) {
346 NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink);
347 NestLink = GetNextNode (&Statement->NestStatementList, NestLink);
348
349 ProcessUserOpcode(NestStatement->OpCode);
350 }
351
352 }
353}
354
355/**
356 Validate the input screen diemenstion info.
357
358 @param FormData The input form data info.
359
360 @return EFI_SUCCESS The input screen info is acceptable.
361 @return EFI_INVALID_PARAMETER The input screen info is not acceptable.
362
363**/
364EFI_STATUS
365ScreenDiemensionInfoValidate (
366 IN FORM_DISPLAY_ENGINE_FORM *FormData
367 )
368{
369 LIST_ENTRY *Link;
370 UINTN Index;
371
372 //
373 // Calculate total number of Register HotKeys.
374 //
375 Index = 0;
376 if (!IsListEmpty (&FormData->HotKeyListHead)){
377 Link = GetFirstNode (&FormData->HotKeyListHead);
378 while (!IsNull (&FormData->HotKeyListHead, Link)) {
379 Link = GetNextNode (&FormData->HotKeyListHead, Link);
380 Index ++;
381 }
382 }
383
384 //
385 // Show three HotKeys help information on one row.
386 //
387 gFooterHeight = FOOTER_HEIGHT + (Index / 3);
388
389
390 ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
391 gST->ConOut->QueryMode (
392 gST->ConOut,
393 gST->ConOut->Mode->Mode,
394 &gScreenDimensions.RightColumn,
395 &gScreenDimensions.BottomRow
396 );
397
398 //
399 // Check local dimension vs. global dimension.
400 //
401 if (FormData->ScreenDimensions != NULL) {
402 if ((gScreenDimensions.RightColumn < FormData->ScreenDimensions->RightColumn) ||
403 (gScreenDimensions.BottomRow < FormData->ScreenDimensions->BottomRow)
404 ) {
405 return EFI_INVALID_PARAMETER;
406 } else {
407 //
408 // Local dimension validation.
409 //
410 if ((FormData->ScreenDimensions->RightColumn > FormData->ScreenDimensions->LeftColumn) &&
411 (FormData->ScreenDimensions->BottomRow > FormData->ScreenDimensions->TopRow) &&
412 ((FormData->ScreenDimensions->RightColumn - FormData->ScreenDimensions->LeftColumn) > 2) &&
413 ((FormData->ScreenDimensions->BottomRow - FormData->ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +
414 FRONT_PAGE_HEADER_HEIGHT + gFooterHeight + 3)) {
415 CopyMem (&gScreenDimensions, (VOID *) FormData->ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
416 } else {
417 return EFI_INVALID_PARAMETER;
418 }
419 }
420 }
421
422 return EFI_SUCCESS;
423}
424
425/**
426 Get the string based on the StringId and HII Package List Handle.
427
428 @param Token The String's ID.
429 @param HiiHandle The package list in the HII database to search for
430 the specified string.
431
432 @return The output string.
433
434**/
435CHAR16 *
436LibGetToken (
437 IN EFI_STRING_ID Token,
438 IN EFI_HII_HANDLE HiiHandle
439 )
440{
441 EFI_STRING String;
442
443 String = HiiGetString (HiiHandle, Token, NULL);
444 if (String == NULL) {
445 String = AllocateCopyPool (StrSize (mLibUnknownString), mLibUnknownString);
446 ASSERT (String != NULL);
447 }
448
449 return (CHAR16 *) String;
450}
451
452
453/**
454 Count the storage space of a Unicode string.
455
456 This function handles the Unicode string with NARROW_CHAR
457 and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
458 does not count in the resultant output. If a WIDE_CHAR is
459 hit, then 2 Unicode character will consume an output storage
460 space with size of CHAR16 till a NARROW_CHAR is hit.
461
462 If String is NULL, then ASSERT ().
463
464 @param String The input string to be counted.
465
466 @return Storage space for the input string.
467
468**/
469UINTN
470LibGetStringWidth (
471 IN CHAR16 *String
472 )
473{
474 UINTN Index;
475 UINTN Count;
476 UINTN IncrementValue;
477
478 ASSERT (String != NULL);
479 if (String == NULL) {
480 return 0;
481 }
482
483 Index = 0;
484 Count = 0;
485 IncrementValue = 1;
486
487 do {
488 //
489 // Advance to the null-terminator or to the first width directive
490 //
491 for (;
492 (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
493 Index++, Count = Count + IncrementValue
494 )
495 ;
496
497 //
498 // We hit the null-terminator, we now have a count
499 //
500 if (String[Index] == 0) {
501 break;
502 }
503 //
504 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
505 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
506 //
507 if (String[Index] == NARROW_CHAR) {
508 //
509 // Skip to the next character
510 //
511 Index++;
512 IncrementValue = 1;
513 } else {
514 //
515 // Skip to the next character
516 //
517 Index++;
518 IncrementValue = 2;
519 }
520 } while (String[Index] != 0);
521
522 //
523 // Increment by one to include the null-terminator in the size
524 //
525 Count++;
526
527 return Count * sizeof (CHAR16);
528}
529
530/**
531 Show all registered HotKey help strings on bottom Rows.
532
533 @param FormData The curent input form data info.
534 @param SetState Set HotKey or Clear HotKey
535
536**/
537VOID
538PrintHotKeyHelpString (
539 IN FORM_DISPLAY_ENGINE_FORM *FormData,
540 IN BOOLEAN SetState
541 )
542{
543 UINTN CurrentCol;
544 UINTN CurrentRow;
545 UINTN BottomRowOfHotKeyHelp;
546 UINTN ColumnIndexWidth;
547 UINTN ColumnWidth;
548 UINTN ColumnIndex;
549 UINTN Index;
550 EFI_SCREEN_DESCRIPTOR LocalScreen;
551 LIST_ENTRY *Link;
552 BROWSER_HOT_KEY *HotKey;
553 CHAR16 BakChar;
554 CHAR16 *ColumnStr;
555
556 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
557 ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
558 BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3;
559 ColumnStr = gLibEmptyString;
560
561 //
562 // Calculate total number of Register HotKeys.
563 //
564 Index = 0;
565 Link = GetFirstNode (&FormData->HotKeyListHead);
566 while (!IsNull (&FormData->HotKeyListHead, Link)) {
567 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);
568 //
569 // Calculate help information Column and Row.
570 //
571 ColumnIndex = Index % 3;
572 if (ColumnIndex == 0) {
573 CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth;
574 ColumnIndexWidth = ColumnWidth - 1;
575 } else if (ColumnIndex == 1) {
576 CurrentCol = LocalScreen.LeftColumn + ColumnWidth;
577 ColumnIndexWidth = ColumnWidth;
578 } else {
579 CurrentCol = LocalScreen.LeftColumn + 2;
580 ColumnIndexWidth = ColumnWidth - 2;
581 }
582 CurrentRow = BottomRowOfHotKeyHelp - Index / 3;
583
584 //
585 // Help string can't exceed ColumnWidth. One Row will show three Help information.
586 //
587 BakChar = L'\0';
588 if (StrLen (HotKey->HelpString) > ColumnIndexWidth) {
589 BakChar = HotKey->HelpString[ColumnIndexWidth];
590 HotKey->HelpString[ColumnIndexWidth] = L'\0';
591 }
592
593 //
594 // Print HotKey help string on bottom Row.
595 //
596 if (SetState) {
597 ColumnStr = HotKey->HelpString;
598 }
599 PrintStringAtWithWidth (CurrentCol, CurrentRow, ColumnStr, ColumnIndexWidth);
600
601 if (BakChar != L'\0') {
602 HotKey->HelpString[ColumnIndexWidth] = BakChar;
603 }
604 //
605 // Get Next Hot Key.
606 //
607 Link = GetNextNode (&FormData->HotKeyListHead, Link);
608 Index ++;
609 }
610
611 if (SetState) {
612 //
613 // Clear KeyHelp
614 //
615 CurrentRow = BottomRowOfHotKeyHelp - Index / 3;
616 ColumnIndex = Index % 3;
617 if (ColumnIndex == 0) {
618 CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth;
619 ColumnIndexWidth = ColumnWidth - 1;
620 ColumnIndex ++;
621 PrintStringAtWithWidth (CurrentCol, CurrentRow, gLibEmptyString, ColumnIndexWidth);
622 }
623 if (ColumnIndex == 1) {
624 CurrentCol = LocalScreen.LeftColumn + ColumnWidth;
625 ColumnIndexWidth = ColumnWidth;
626 PrintStringAtWithWidth (CurrentCol, CurrentRow, gLibEmptyString, ColumnIndexWidth);
627 }
628 }
629
630 return;
631}
632
633/**
634 Get step info from numeric opcode.
635
636 @param[in] OpCode The input numeric op code.
637
638 @return step info for this opcode.
639**/
640UINT64
641LibGetFieldFromNum (
642 IN EFI_IFR_OP_HEADER *OpCode
643 )
644{
645 EFI_IFR_NUMERIC *NumericOp;
646 UINT64 Step;
647
648 NumericOp = (EFI_IFR_NUMERIC *) OpCode;
649
650 switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {
651 case EFI_IFR_NUMERIC_SIZE_1:
652 Step = NumericOp->data.u8.Step;
653 break;
654
655 case EFI_IFR_NUMERIC_SIZE_2:
656 Step = NumericOp->data.u16.Step;
657 break;
658
659 case EFI_IFR_NUMERIC_SIZE_4:
660 Step = NumericOp->data.u32.Step;
661 break;
662
663 case EFI_IFR_NUMERIC_SIZE_8:
664 Step = NumericOp->data.u64.Step;
665 break;
666
667 default:
668 Step = 0;
669 break;
670 }
671
672 return Step;
673}
674
675/**
676 Initialize the HII String Token to the correct values.
677
678**/
679VOID
680InitializeLibStrings (
681 VOID
682 )
683{
684 mLibUnknownString = L"!";
685
686 gEnterString = LibGetToken (STRING_TOKEN (ENTER_STRING), mCDLStringPackHandle);
687 gEnterCommitString = LibGetToken (STRING_TOKEN (ENTER_COMMIT_STRING), mCDLStringPackHandle);
688 gEnterEscapeString = LibGetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), mCDLStringPackHandle);
689 gEscapeString = LibGetToken (STRING_TOKEN (ESCAPE_STRING), mCDLStringPackHandle);
690 gMoveHighlight = LibGetToken (STRING_TOKEN (MOVE_HIGHLIGHT), mCDLStringPackHandle);
691 gDecNumericInput = LibGetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), mCDLStringPackHandle);
692 gHexNumericInput = LibGetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), mCDLStringPackHandle);
693 gToggleCheckBox = LibGetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), mCDLStringPackHandle);
694
695 gAreYouSure = LibGetToken (STRING_TOKEN (ARE_YOU_SURE), mCDLStringPackHandle);
696 gYesResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_YES), mCDLStringPackHandle);
697 gNoResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_NO), mCDLStringPackHandle);
698 gPlusString = LibGetToken (STRING_TOKEN (PLUS_STRING), mCDLStringPackHandle);
699 gMinusString = LibGetToken (STRING_TOKEN (MINUS_STRING), mCDLStringPackHandle);
700 gAdjustNumber = LibGetToken (STRING_TOKEN (ADJUST_NUMBER), mCDLStringPackHandle);
701 gSaveChanges = LibGetToken (STRING_TOKEN (SAVE_CHANGES), mCDLStringPackHandle);
702
703 gLibEmptyString = LibGetToken (STRING_TOKEN (EMPTY_STRING), mCDLStringPackHandle);
704
705 gNvUpdateMessage = LibGetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), mCDLStringPackHandle);
706 gInputErrorMessage = LibGetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), mCDLStringPackHandle);
707
708 //
709 // SpaceBuffer;
710 //
711 mSpaceBuffer = AllocatePool ((SPACE_BUFFER_SIZE + 1) * sizeof (CHAR16));
712 ASSERT (mSpaceBuffer != NULL);
713 LibSetUnicodeMem (mSpaceBuffer, SPACE_BUFFER_SIZE, L' ');
714 mSpaceBuffer[SPACE_BUFFER_SIZE] = L'\0';
715}
716
717
718/**
719 Free the HII String.
720
721**/
722VOID
723FreeLibStrings (
724 VOID
725 )
726{
727 FreePool (gEnterString);
728 FreePool (gEnterCommitString);
729 FreePool (gEnterEscapeString);
730 FreePool (gEscapeString);
731 FreePool (gMoveHighlight);
732 FreePool (gDecNumericInput);
733 FreePool (gHexNumericInput);
734 FreePool (gToggleCheckBox);
735
736 FreePool (gAreYouSure);
737 FreePool (gYesResponse);
738 FreePool (gNoResponse);
739 FreePool (gPlusString);
740 FreePool (gMinusString);
741 FreePool (gAdjustNumber);
742 FreePool (gSaveChanges);
743
744 FreePool (gLibEmptyString);
745
746 FreePool (gNvUpdateMessage);
747 FreePool (gInputErrorMessage);
748
749 FreePool (mSpaceBuffer);
750}
751
752/**
753 Wait for a key to be pressed by user.
754
755 @param Key The key which is pressed by user.
756
757 @retval EFI_SUCCESS The function always completed successfully.
758
759**/
760EFI_STATUS
761WaitForKeyStroke (
762 OUT EFI_INPUT_KEY *Key
763 )
764{
765 EFI_STATUS Status;
766 UINTN Index;
767
768 while (TRUE) {
769 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);
770 if (!EFI_ERROR (Status)) {
771 break;
772 }
773
774 if (Status != EFI_NOT_READY) {
775 continue;
776 }
777
778 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
779 }
780 return Status;
781}
782
783
784/**
785 Set Buffer to Value for Size bytes.
786
787 @param Buffer Memory to set.
788 @param Size Number of bytes to set
789 @param Value Value of the set operation.
790
791**/
792VOID
793LibSetUnicodeMem (
794 IN VOID *Buffer,
795 IN UINTN Size,
796 IN CHAR16 Value
797 )
798{
799 CHAR16 *Ptr;
800
801 Ptr = Buffer;
802 while ((Size--) != 0) {
803 *(Ptr++) = Value;
804 }
805}
806
807/**
808 The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
809 protocol instance.
810
811 @param Width Width of string to be print.
812 @param Column The position of the output string.
813 @param Row The position of the output string.
814 @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
815 @param Fmt The format string.
816 @param Args The additional argument for the variables in the format string.
817
818 @return Number of Unicode character printed.
819
820**/
821UINTN
822PrintInternal (
823 IN UINTN Width,
824 IN UINTN Column,
825 IN UINTN Row,
826 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out,
827 IN CHAR16 *Fmt,
828 IN VA_LIST Args
829 )
830{
831 CHAR16 *Buffer;
832 CHAR16 *BackupBuffer;
833 UINTN Index;
834 UINTN PreviousIndex;
835 UINTN Count;
836 UINTN TotalCount;
837 UINTN PrintWidth;
838 UINTN CharWidth;
839
840 //
841 // For now, allocate an arbitrarily long buffer
842 //
843 Buffer = AllocateZeroPool (0x10000);
844 BackupBuffer = AllocateZeroPool (0x10000);
845 ASSERT (Buffer);
846 ASSERT (BackupBuffer);
847
848 if (Column != (UINTN) -1) {
849 Out->SetCursorPosition (Out, Column, Row);
850 }
851
852 UnicodeVSPrint (Buffer, 0x10000, Fmt, Args);
853
854 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
855
856 Out->SetAttribute (Out, Out->Mode->Attribute);
857
858 Index = 0;
859 PreviousIndex = 0;
860 Count = 0;
861 TotalCount = 0;
862 PrintWidth = 0;
863 CharWidth = 1;
864
865 do {
866 for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {
867 BackupBuffer[Index] = Buffer[Index];
868 }
869
870 if (Buffer[Index] == 0) {
871 break;
872 }
873
874 //
875 // Print this out, we are about to switch widths
876 //
877 Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
878 Count = StrLen (&BackupBuffer[PreviousIndex]);
879 PrintWidth += Count * CharWidth;
880 TotalCount += Count;
881
882 //
883 // Preserve the current index + 1, since this is where we will start printing from next
884 //
885 PreviousIndex = Index + 1;
886
887 //
888 // We are at a narrow or wide character directive. Set attributes and strip it and print it
889 //
890 if (Buffer[Index] == NARROW_CHAR) {
891 //
892 // Preserve bits 0 - 6 and zero out the rest
893 //
894 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
895 Out->SetAttribute (Out, Out->Mode->Attribute);
896 CharWidth = 1;
897 } else {
898 //
899 // Must be wide, set bit 7 ON
900 //
901 Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;
902 Out->SetAttribute (Out, Out->Mode->Attribute);
903 CharWidth = 2;
904 }
905
906 Index++;
907
908 } while (Buffer[Index] != 0);
909
910 //
911 // We hit the end of the string - print it
912 //
913 Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
914 Count = StrLen (&BackupBuffer[PreviousIndex]);
915 PrintWidth += Count * CharWidth;
916 TotalCount += Count;
917 if (PrintWidth < Width) {
918 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
919 Out->SetAttribute (Out, Out->Mode->Attribute);
920 Out->OutputString (Out, &mSpaceBuffer[SPACE_BUFFER_SIZE - Width + PrintWidth]);
921 }
922
923 FreePool (Buffer);
924 FreePool (BackupBuffer);
925 return TotalCount;
926}
927
928/**
929 Prints a formatted unicode string to the default console, at
930 the supplied cursor position.
931
932 @param Width Width of String to be printed.
933 @param Column The cursor position to print the string at.
934 @param Row The cursor position to print the string at.
935 @param Fmt Format string.
936 @param ... Variable argument list for format string.
937
938 @return Length of string printed to the console
939
940**/
941UINTN
942EFIAPI
943PrintAt (
944 IN UINTN Width,
945 IN UINTN Column,
946 IN UINTN Row,
947 IN CHAR16 *Fmt,
948 ...
949 )
950{
951 VA_LIST Args;
952 UINTN LengthOfPrinted;
953
954 VA_START (Args, Fmt);
955 LengthOfPrinted = PrintInternal (Width, Column, Row, gST->ConOut, Fmt, Args);
956 VA_END (Args);
957 return LengthOfPrinted;
958}
959