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
PrintBannerInfo(IN FORM_DISPLAY_ENGINE_FORM * FormData)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
PrintFramework(IN FORM_DISPLAY_ENGINE_FORM * FormData)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
ProcessUserOpcode(IN EFI_IFR_OP_HEADER * OpCodeData)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
ProcessExternedOpcode(IN FORM_DISPLAY_ENGINE_FORM * FormData)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
ScreenDiemensionInfoValidate(IN FORM_DISPLAY_ENGINE_FORM * FormData)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 *
LibGetToken(IN EFI_STRING_ID Token,IN EFI_HII_HANDLE HiiHandle)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
LibGetStringWidth(IN CHAR16 * String)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
PrintHotKeyHelpString(IN FORM_DISPLAY_ENGINE_FORM * FormData,IN BOOLEAN SetState)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
LibGetFieldFromNum(IN EFI_IFR_OP_HEADER * OpCode)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
InitializeLibStrings(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
FreeLibStrings(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
WaitForKeyStroke(OUT EFI_INPUT_KEY * Key)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
LibSetUnicodeMem(IN VOID * Buffer,IN UINTN Size,IN CHAR16 Value)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
PrintInternal(IN UINTN Width,IN UINTN Column,IN UINTN Row,IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * Out,IN CHAR16 * Fmt,IN VA_LIST Args)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
PrintAt(IN UINTN Width,IN UINTN Column,IN UINTN Row,IN CHAR16 * Fmt,...)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