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