]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c
Update code to support guid op nest in the statement.
[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, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available under
7 the terms and conditions of the BSD License that accompanies this distribution.
8 The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15 #include "CustomizedDisplayLibInternal.h"
16
17 EFI_SCREEN_DESCRIPTOR gScreenDimensions;
18 CHAR16 *mLibUnknownString;
19 extern EFI_HII_HANDLE mCDLStringPackHandle;
20 CHAR16 *mSpaceBuffer;
21 #define SPACE_BUFFER_SIZE 1000
22
23 //
24 // Browser Global Strings
25 //
26 CHAR16 *gEnterString;
27 CHAR16 *gEnterCommitString;
28 CHAR16 *gEnterEscapeString;
29 CHAR16 *gEscapeString;
30 CHAR16 *gMoveHighlight;
31 CHAR16 *gDecNumericInput;
32 CHAR16 *gHexNumericInput;
33 CHAR16 *gToggleCheckBox;
34 CHAR16 *gLibEmptyString;
35 CHAR16 *gAreYouSure;
36 CHAR16 *gYesResponse;
37 CHAR16 *gNoResponse;
38 CHAR16 *gPlusString;
39 CHAR16 *gMinusString;
40 CHAR16 *gAdjustNumber;
41 CHAR16 *gSaveChanges;
42 CHAR16 *gNvUpdateMessage;
43 CHAR16 *gInputErrorMessage;
44
45 /**
46
47 Print banner info for front page.
48
49 @param[in] FormData Form Data to be shown in Page
50
51 **/
52 VOID
53 PrintBannerInfo (
54 IN FORM_DISPLAY_ENGINE_FORM *FormData
55 )
56 {
57 UINT8 Line;
58 UINT8 Alignment;
59 CHAR16 *StrFrontPageBanner;
60 UINT8 RowIdx;
61 UINT8 ColumnIdx;
62
63 //
64 // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);
65 //
66 ClearLines (
67 gScreenDimensions.LeftColumn,
68 gScreenDimensions.RightColumn,
69 gScreenDimensions.TopRow,
70 FRONT_PAGE_HEADER_HEIGHT - 1 + gScreenDimensions.TopRow,
71 BANNER_TEXT | BANNER_BACKGROUND
72 );
73
74 //
75 // for (Line = 0; Line < BANNER_HEIGHT; Line++) {
76 //
77 for (Line = (UINT8) gScreenDimensions.TopRow; Line < BANNER_HEIGHT + (UINT8) gScreenDimensions.TopRow; Line++) {
78 //
79 // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {
80 //
81 for (Alignment = (UINT8) gScreenDimensions.LeftColumn;
82 Alignment < BANNER_COLUMNS + (UINT8) gScreenDimensions.LeftColumn;
83 Alignment++
84 ) {
85 RowIdx = (UINT8) (Line - (UINT8) gScreenDimensions.TopRow);
86 ColumnIdx = (UINT8) (Alignment - (UINT8) gScreenDimensions.LeftColumn);
87
88 ASSERT (RowIdx < BANNER_HEIGHT && ColumnIdx < BANNER_COLUMNS);
89
90 if (gBannerData!= NULL && gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {
91 StrFrontPageBanner = LibGetToken (gBannerData->Banner[RowIdx][ColumnIdx], FormData->HiiHandle);
92 } else {
93 continue;
94 }
95
96 switch (Alignment - gScreenDimensions.LeftColumn) {
97 case 0:
98 //
99 // Handle left column
100 //
101 PrintStringAt (gScreenDimensions.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner);
102 break;
103
104 case 1:
105 //
106 // Handle center column
107 //
108 PrintStringAt (
109 gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3,
110 Line,
111 StrFrontPageBanner
112 );
113 break;
114
115 case 2:
116 //
117 // Handle right column
118 //
119 PrintStringAt (
120 gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) * 2 / 3,
121 Line,
122 StrFrontPageBanner
123 );
124 break;
125 }
126
127 FreePool (StrFrontPageBanner);
128 }
129 }
130 }
131
132 /**
133 Print framework and form title for a page.
134
135 @param[in] FormData Form Data to be shown in Page
136 **/
137 VOID
138 PrintFramework (
139 IN FORM_DISPLAY_ENGINE_FORM *FormData
140 )
141 {
142 UINTN Index;
143 CHAR16 Character;
144 CHAR16 *Buffer;
145 UINTN Row;
146 CHAR16 *TitleStr;
147 UINTN TitleColumn;
148
149 if (gClassOfVfr != FORMSET_CLASS_PLATFORM_SETUP) {
150 //
151 // Only Setup page needs Framework
152 //
153 ClearLines (
154 gScreenDimensions.LeftColumn,
155 gScreenDimensions.RightColumn,
156 gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight,
157 gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1,
158 KEYHELP_TEXT | KEYHELP_BACKGROUND
159 );
160 return;
161 }
162
163 Buffer = AllocateZeroPool (0x10000);
164 ASSERT (Buffer != NULL);
165 Character = BOXDRAW_HORIZONTAL;
166 for (Index = 0; Index + 2 < (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn); Index++) {
167 Buffer[Index] = Character;
168 }
169
170 //
171 // Print Top border line
172 // +------------------------------------------------------------------------------+
173 // ? ?
174 // +------------------------------------------------------------------------------+
175 //
176 gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);
177 Character = BOXDRAW_DOWN_RIGHT;
178
179 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow, Character);
180 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);
181
182 Character = BOXDRAW_DOWN_LEFT;
183 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);
184
185 Character = BOXDRAW_VERTICAL;
186 for (Row = gScreenDimensions.TopRow + 1; Row <= gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {
187 PrintCharAt (gScreenDimensions.LeftColumn, Row, Character);
188 PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character);
189 }
190
191 //
192 // Print Form Title
193 //
194 TitleStr = LibGetToken (FormData->FormTitle, FormData->HiiHandle);
195 ASSERT (TitleStr != NULL);
196 TitleColumn = (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - LibGetStringWidth (TitleStr) / 2) / 2;
197 PrintStringAtWithWidth (gScreenDimensions.LeftColumn + 1, gScreenDimensions.TopRow + 1, gLibEmptyString, TitleColumn - gScreenDimensions.LeftColumn - 1);
198 PrintStringAtWithWidth (
199 TitleColumn,
200 gScreenDimensions.TopRow + 1,
201 TitleStr,
202 gScreenDimensions.RightColumn - 1 - TitleColumn
203 );
204 FreePool (TitleStr);
205
206 Character = BOXDRAW_UP_RIGHT;
207 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);
208 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);
209
210 Character = BOXDRAW_UP_LEFT;
211 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);
212
213 //
214 // Print Bottom border line
215 // +------------------------------------------------------------------------------+
216 // ? ?
217 // +------------------------------------------------------------------------------+
218 //
219 Character = BOXDRAW_DOWN_RIGHT;
220 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character);
221
222 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);
223
224 Character = BOXDRAW_DOWN_LEFT;
225 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);
226 Character = BOXDRAW_VERTICAL;
227 for (Row = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;
228 Row <= gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2;
229 Row++
230 ) {
231 PrintCharAt (gScreenDimensions.LeftColumn, Row, Character);
232 PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character);
233 }
234
235 Character = BOXDRAW_UP_RIGHT;
236 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1, Character);
237
238 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);
239
240 Character = BOXDRAW_UP_LEFT;
241 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);
242
243 FreePool (Buffer);
244 }
245
246 /**
247 Process some op code which is not recognized by browser core.
248
249 @param OpCodeData The pointer to the op code buffer.
250
251 @return EFI_SUCCESS Pass the statement success.
252
253 **/
254 VOID
255 ProcessUserOpcode(
256 IN EFI_IFR_OP_HEADER *OpCodeData
257 )
258 {
259 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 **/
319 VOID
320 ProcessExternedOpcode (
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 **/
364 EFI_STATUS
365 ScreenDiemensionInfoValidate (
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 **/
435 CHAR16 *
436 LibGetToken (
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 **/
469 UINTN
470 LibGetStringWidth (
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 **/
537 VOID
538 PrintHotKeyHelpString (
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 **/
640 UINT64
641 LibGetFieldFromNum (
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 **/
679 VOID
680 InitializeLibStrings (
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 **/
722 VOID
723 FreeLibStrings (
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 **/
760 EFI_STATUS
761 WaitForKeyStroke (
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 **/
792 VOID
793 LibSetUnicodeMem (
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 **/
821 UINTN
822 PrintInternal (
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 **/
941 UINTN
942 EFIAPI
943 PrintAt (
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