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