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