2 Provides interface to shell console logger.
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 #include "ConsoleLogger.h"
17 STATIC CONST CHAR16 mCrLfString
[3] = { CHAR_CARRIAGE_RETURN
, CHAR_LINEFEED
, CHAR_NULL
};
20 Install our intermediate ConOut into the system table to
21 keep a log of all the info that is displayed to the user.
23 @param[in] ScreensToSave Sets how many screen-worths of data to save.
24 @param[out] ConsoleInfo The object to pass into later functions.
26 @retval EFI_SUCCESS The operation was successful.
27 @return other The operation failed.
29 @sa ConsoleLoggerResetBuffers
30 @sa InstallProtocolInterface
35 IN CONST UINTN ScreensToSave
,
36 OUT CONSOLE_LOGGER_PRIVATE_DATA
**ConsoleInfo
40 ASSERT(ConsoleInfo
!= NULL
);
42 *ConsoleInfo
= AllocatePool(sizeof(CONSOLE_LOGGER_PRIVATE_DATA
));
43 ASSERT(ConsoleInfo
!= NULL
);
45 (*ConsoleInfo
)->Signature
= CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE
;
46 (*ConsoleInfo
)->OldConOut
= NULL
;
47 (*ConsoleInfo
)->OldConHandle
= NULL
;
48 (*ConsoleInfo
)->Buffer
= NULL
;
49 (*ConsoleInfo
)->BufferSize
= 0;
50 (*ConsoleInfo
)->OriginalStartRow
= 0;
51 (*ConsoleInfo
)->CurrentStartRow
= 0;
52 (*ConsoleInfo
)->RowsPerScreen
= 0;
53 (*ConsoleInfo
)->ColsPerScreen
= 0;
54 (*ConsoleInfo
)->Attributes
= NULL
;
55 (*ConsoleInfo
)->AttribSize
= 0;
56 (*ConsoleInfo
)->ScreenCount
= ScreensToSave
;
57 (*ConsoleInfo
)->HistoryMode
.MaxMode
= 1;
58 (*ConsoleInfo
)->HistoryMode
.Mode
= 0;
59 (*ConsoleInfo
)->HistoryMode
.Attribute
= 0;
60 (*ConsoleInfo
)->HistoryMode
.CursorColumn
= 0;
61 (*ConsoleInfo
)->HistoryMode
.CursorRow
= 0;
62 (*ConsoleInfo
)->HistoryMode
.CursorVisible
= FALSE
;
63 (*ConsoleInfo
)->OurConOut
.Reset
= ConsoleLoggerReset
;
64 (*ConsoleInfo
)->OurConOut
.OutputString
= ConsoleLoggerOutputString
;
65 (*ConsoleInfo
)->OurConOut
.TestString
= ConsoleLoggerTestString
;
66 (*ConsoleInfo
)->OurConOut
.QueryMode
= ConsoleLoggerQueryMode
;
67 (*ConsoleInfo
)->OurConOut
.SetMode
= ConsoleLoggerSetMode
;
68 (*ConsoleInfo
)->OurConOut
.SetAttribute
= ConsoleLoggerSetAttribute
;
69 (*ConsoleInfo
)->OurConOut
.ClearScreen
= ConsoleLoggerClearScreen
;
70 (*ConsoleInfo
)->OurConOut
.SetCursorPosition
= ConsoleLoggerSetCursorPosition
;
71 (*ConsoleInfo
)->OurConOut
.EnableCursor
= ConsoleLoggerEnableCursor
;
72 (*ConsoleInfo
)->OurConOut
.Mode
= NULL
;
73 (*ConsoleInfo
)->Enabled
= TRUE
;
75 Status
= ConsoleLoggerResetBuffers(*ConsoleInfo
);
76 if (EFI_ERROR(Status
)) {
80 Status
= gBS
->InstallProtocolInterface(&gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, EFI_NATIVE_INTERFACE
, (VOID
*)&((*ConsoleInfo
)->OurConOut
));
82 (*ConsoleInfo
)->OldConOut
= gST
->ConOut
;
83 (*ConsoleInfo
)->OldConHandle
= gST
->ConsoleOutHandle
;
85 gST
->ConsoleOutHandle
= gImageHandle
;
86 gST
->ConOut
= &(*ConsoleInfo
)->OurConOut
;
92 Return the system to the state it was before InstallConsoleLogger
95 @param[in,out] ConsoleInfo The object from the install function.
97 @retval EFI_SUCCESS The operation was successful
98 @return other The operation failed. This was from UninstallProtocolInterface.
102 ConsoleLoggerUninstall(
103 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
106 ASSERT(ConsoleInfo
!= NULL
);
107 ASSERT(ConsoleInfo
->OldConOut
!= NULL
);
109 if (ConsoleInfo
->Buffer
!= NULL
) {
110 FreePool(ConsoleInfo
->Buffer
);
111 DEBUG_CODE(ConsoleInfo
->Buffer
= NULL
;);
112 DEBUG_CODE(ConsoleInfo
->BufferSize
= 0;);
114 if (ConsoleInfo
->Attributes
!= NULL
) {
115 FreePool(ConsoleInfo
->Attributes
);
116 DEBUG_CODE(ConsoleInfo
->Attributes
= NULL
;);
117 DEBUG_CODE(ConsoleInfo
->AttribSize
= 0;);
120 gST
->ConsoleOutHandle
= ConsoleInfo
->OldConHandle
;
121 gST
->ConOut
= ConsoleInfo
->OldConOut
;
123 return (gBS
->UninstallProtocolInterface(gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, (VOID
*)&ConsoleInfo
->OurConOut
));
127 Displays previously logged output back to the screen.
129 This will scroll the screen forwards and backwards through the log of previous
130 output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows
131 is (UINTN)(-1) then the size of the screen will be scrolled.
133 @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer).
134 If FALSE then the log will be displayed backwards (scroll to older).
135 @param[in] Rows Determines how many rows the log should scroll.
136 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
140 ConsoleLoggerDisplayHistory(
141 IN CONST BOOLEAN Forward
,
143 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
148 ASSERT(ConsoleInfo
!= NULL
);
151 // Calculate the row number change
155 RowChange
= ConsoleInfo
->RowsPerScreen
;
158 RowChange
= ConsoleInfo
->RowsPerScreen
/ 2;
166 // Do the math for direction
169 if ((ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
) < RowChange
) {
170 RowChange
= ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
;
173 if (ConsoleInfo
->CurrentStartRow
< RowChange
) {
174 RowChange
= ConsoleInfo
->CurrentStartRow
;
179 // If we are already at one end or the other
181 if (RowChange
== 0) {
182 return (EFI_SUCCESS
);
188 ConsoleInfo
->OldConOut
->ClearScreen(ConsoleInfo
->OldConOut
);
191 // Set the new start row
194 ConsoleInfo
->CurrentStartRow
+= RowChange
;
196 ConsoleInfo
->CurrentStartRow
-= RowChange
;
202 return (UpdateDisplayFromHistory(ConsoleInfo
));
206 Function to return to normal output whent he scrolling is complete.
207 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
209 @retval EFI_SUCCESS The operation was successful.
210 @return other The operation failed. See UpdateDisplayFromHistory.
212 @sa UpdateDisplayFromHistory
216 ConsoleLoggerStopHistory(
217 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
220 ASSERT(ConsoleInfo
!= NULL
);
221 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
222 return (EFI_SUCCESS
);
224 ConsoleInfo
->CurrentStartRow
= ConsoleInfo
->OriginalStartRow
;
225 return (UpdateDisplayFromHistory(ConsoleInfo
));
229 Updates the hidden ConOut to be displaying the correct stuff.
230 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
232 @retval EFI_SUCCESS The operation was successful.
233 @return other The operation failed.
237 UpdateDisplayFromHistory(
238 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
246 CHAR16 TempCharHolder
;
250 CHAR16
*StringSegment
;
251 CHAR16
*StringSegmentEnd
;
252 CHAR16 StringSegmentEndChar
;
254 ASSERT(ConsoleInfo
!= NULL
);
255 TempCharHolder
= CHAR_NULL
;
256 RetVal
= EFI_SUCCESS
;
259 // Disable cursor visibility and move it to the top left corner
261 ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, FALSE
);
262 ConsoleInfo
->OldConOut
->SetCursorPosition (ConsoleInfo
->OldConOut
, 0, 0);
264 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
265 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
267 ; CurrentRow
< ConsoleInfo
->RowsPerScreen
269 , Screen
+= (ConsoleInfo
->ColsPerScreen
+ 2)
270 , Attributes
+= ConsoleInfo
->ColsPerScreen
273 // dont use the last char - prevents screen scroll
275 if (CurrentRow
== (ConsoleInfo
->RowsPerScreen
-1)){
276 TempCharHolder
= Screen
[ConsoleInfo
->ColsPerScreen
- 1];
277 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = CHAR_NULL
;
281 ; Column
< ConsoleInfo
->ColsPerScreen
284 if (Screen
[Column
] != CHAR_NULL
) {
285 CurrentAttrib
= Attributes
[Column
];
286 CurrentColumn
= Column
;
287 StringSegment
= &Screen
[Column
];
290 // Find the first char with a different arrribute and make that temporarily NULL
291 // so we can do fewer printout statements. (later) restore that one and we will
292 // start at that collumn on the next loop.
294 StringSegmentEndChar
= CHAR_NULL
;
295 for ( StringSegmentEnd
= StringSegment
296 ; StringSegmentEnd
!= CHAR_NULL
300 if (Attributes
[Column
] != CurrentAttrib
) {
301 StringSegmentEndChar
= *StringSegmentEnd
;
302 *StringSegmentEnd
= CHAR_NULL
;
305 } // StringSegmentEnd loop
308 // Now write out as much as had the same Attributes
311 ConsoleInfo
->OldConOut
->SetAttribute(ConsoleInfo
->OldConOut
, CurrentAttrib
);
312 ConsoleInfo
->OldConOut
->SetCursorPosition(ConsoleInfo
->OldConOut
, CurrentColumn
, CurrentRow
);
313 Status
= ConsoleInfo
->OldConOut
->OutputString(ConsoleInfo
->OldConOut
, StringSegment
);
315 if (EFI_ERROR(Status
)) {
321 // If we found a change in attribute put the character back and decrement the column
322 // so when it increments it will point at that character and we will start printing
323 // a segment with that new attribute
325 if (StringSegmentEndChar
!= CHAR_NULL
) {
326 *StringSegmentEnd
= StringSegmentEndChar
;
327 StringSegmentEndChar
= CHAR_NULL
;
334 // If we removed the last char and this was the last row put it back
336 if (TempCharHolder
!= CHAR_NULL
) {
337 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = TempCharHolder
;
338 TempCharHolder
= CHAR_NULL
;
343 // If we are setting the screen back to original turn on the cursor and make it visible
344 // and set the attributes back to what they were
346 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
347 ConsoleInfo
->OldConOut
->SetAttribute (
348 ConsoleInfo
->OldConOut
,
349 ConsoleInfo
->HistoryMode
.Attribute
351 ConsoleInfo
->OldConOut
->SetCursorPosition (
352 ConsoleInfo
->OldConOut
,
353 ConsoleInfo
->HistoryMode
.CursorColumn
,
354 ConsoleInfo
->HistoryMode
.CursorRow
- ConsoleInfo
->OriginalStartRow
357 Status
= ConsoleInfo
->OldConOut
->EnableCursor (
358 ConsoleInfo
->OldConOut
,
359 ConsoleInfo
->HistoryMode
.CursorVisible
361 if (EFI_ERROR (Status
)) {
370 Reset the text output device hardware and optionaly run diagnostics
372 @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
373 @param ExtendedVerification Indicates that a more extensive test may be performed
375 @retval EFI_SUCCESS The text output device was reset.
376 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
382 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
383 IN BOOLEAN ExtendedVerification
387 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
388 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
391 // Forward the request to the original ConOut
393 Status
= ConsoleInfo
->OldConOut
->Reset (ConsoleInfo
->OldConOut
, ExtendedVerification
);
396 // Check that the buffers are still correct for logging
398 if (!EFI_ERROR (Status
)) {
399 ConsoleLoggerResetBuffers(ConsoleInfo
);
406 Appends a string to the history buffer. If the buffer is full then the oldest
407 information in the buffer will be dropped. Information is added in a line by
408 line manner such that an empty line takes up just as much space as a full line.
410 @param[in] String String pointer to add.
411 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
415 AppendStringToHistory(
416 IN CONST CHAR16
*String
,
417 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
420 CONST CHAR16
*Walker
;
425 ASSERT(ConsoleInfo
!= NULL
);
427 for ( Walker
= String
428 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
432 case (CHAR_BACKSPACE
):
433 if (ConsoleInfo
->HistoryMode
.CursorColumn
> 0) {
434 ConsoleInfo
->HistoryMode
.CursorColumn
--;
437 case (CHAR_LINEFEED
):
438 if (ConsoleInfo
->HistoryMode
.CursorRow
>= (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1)) {
440 // Should never be bigger
442 ASSERT(ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1));
445 // scroll history attributes 'up' 1 row and set the last row to default attribute
447 CopySize
= ConsoleInfo
->ColsPerScreen
448 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
449 * sizeof(ConsoleInfo
->Attributes
[0]);
450 ASSERT(CopySize
< ConsoleInfo
->AttribSize
);
452 ConsoleInfo
->Attributes
,
453 ConsoleInfo
->Attributes
+ ConsoleInfo
->ColsPerScreen
,
458 ; Index
< ConsoleInfo
->ColsPerScreen
461 *(ConsoleInfo
->Attributes
+ (CopySize
/sizeof(ConsoleInfo
->Attributes
)) + Index
) = ConsoleInfo
->HistoryMode
.Attribute
;
465 // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
467 CopySize
= (ConsoleInfo
->ColsPerScreen
+ 2)
468 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
469 * sizeof(ConsoleInfo
->Buffer
[0]);
470 ASSERT(CopySize
< ConsoleInfo
->BufferSize
);
473 ConsoleInfo
->Buffer
+ (ConsoleInfo
->ColsPerScreen
+ 2),
478 // Set that last row of chars to spaces
480 SetMem16(((UINT8
*)ConsoleInfo
->Buffer
)+CopySize
, ConsoleInfo
->ColsPerScreen
*sizeof(CHAR16
), L
' ');
483 // we are not on the last row
487 // We should not be scrolling history
489 ASSERT (ConsoleInfo
->OriginalStartRow
== ConsoleInfo
->CurrentStartRow
);
491 // are we at the end of a row?
493 if (ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
) (ConsoleInfo
->OriginalStartRow
+ ConsoleInfo
->RowsPerScreen
- 1)) {
494 ConsoleInfo
->OriginalStartRow
++;
495 ConsoleInfo
->CurrentStartRow
++;
497 ConsoleInfo
->HistoryMode
.CursorRow
++;
500 case (CHAR_CARRIAGE_RETURN
):
502 // Move the cursor to the beginning of the current row.
504 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
508 // Acrtually print characters into the history buffer
511 PrintIndex
= ConsoleInfo
->HistoryMode
.CursorRow
* ConsoleInfo
->ColsPerScreen
+ ConsoleInfo
->HistoryMode
.CursorColumn
;
513 for ( // no initializer needed
514 ; ConsoleInfo
->HistoryMode
.CursorColumn
< (INT32
) ConsoleInfo
->ColsPerScreen
515 ; ConsoleInfo
->HistoryMode
.CursorColumn
++
519 if (*Walker
== CHAR_NULL
520 ||*Walker
== CHAR_BACKSPACE
521 ||*Walker
== CHAR_LINEFEED
522 ||*Walker
== CHAR_CARRIAGE_RETURN
528 // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
531 ASSERT(PrintIndex
+ ConsoleInfo
->HistoryMode
.CursorRow
< ConsoleInfo
->BufferSize
);
532 ConsoleInfo
->Buffer
[PrintIndex
+ (2*ConsoleInfo
->HistoryMode
.CursorRow
)] = *Walker
;
533 ASSERT(PrintIndex
< ConsoleInfo
->AttribSize
);
534 ConsoleInfo
->Attributes
[PrintIndex
] = ConsoleInfo
->HistoryMode
.Attribute
;
538 // Add the carriage return and line feed at the end of the lines
540 if (ConsoleInfo
->HistoryMode
.CursorColumn
>= (INT32
)ConsoleInfo
->ColsPerScreen
) {
541 AppendStringToHistory(L
"\r\n", ConsoleInfo
);
546 } // switch for character
549 return (EFI_SUCCESS
);
553 Worker function to handle printing the output to the screen
554 and the history buffer
556 @param[in] String The string to output
557 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
559 @retval EFI_SUCCESS The string was printed
560 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
562 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
564 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
565 characters in the Unicode string could not be
566 rendered and were skipped.
570 ConsoleLoggerOutputStringSplit(
571 IN CONST CHAR16
*String
,
572 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
578 // Forward the request to the original ConOut
580 Status
= ConsoleInfo
->OldConOut
->OutputString (ConsoleInfo
->OldConOut
, (CHAR16
*)String
);
582 if (EFI_ERROR(Status
)) {
586 return (AppendStringToHistory(String
, ConsoleInfo
));
590 Function to handle page break mode.
592 This function will prompt for continue or break.
594 @retval EFI_SUCCESS Continue was choosen
595 @return other Break was choosen
599 ConsoleLoggerDoPageBreak(
603 SHELL_PROMPT_RESPONSE
*Resp
;
607 ASSERT(ShellInfoObject
.PageBreakEnabled
);
608 ShellInfoObject
.PageBreakEnabled
= FALSE
;
609 Status
= ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue
, STRING_TOKEN(STR_SHELL_QUIT_CONT
), ShellInfoObject
.HiiHandle
, (VOID
**)&Resp
);
610 ShellInfoObject
.PageBreakEnabled
= TRUE
;
611 ASSERT(Resp
!= NULL
);
613 return (EFI_NOT_FOUND
);
615 if (EFI_ERROR(Status
)) {
621 if (*Resp
== ShellPromptResponseContinue
) {
623 ShellInfoObject
.ConsoleInfo
->RowCounter
= 0;
624 return (EFI_SUCCESS
);
625 } else if (*Resp
== ShellPromptResponseQuit
) {
627 ShellInfoObject
.ConsoleInfo
->Enabled
= FALSE
;
628 return (EFI_DEVICE_ERROR
);
632 return (EFI_SUCCESS
);
635 Worker function to handle printing the output with page breaks.
637 @param[in] String The string to output
638 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
640 @retval EFI_SUCCESS The string was printed
641 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
643 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
645 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
646 characters in the Unicode string could not be
647 rendered and were skipped.
651 ConsoleLoggerPrintWithPageBreak(
653 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
656 CONST CHAR16
*Walker
;
657 CONST CHAR16
*LineStart
;
660 for ( Walker
= String
662 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
666 case (CHAR_BACKSPACE
):
667 if (ConsoleInfo
->OurConOut
.Mode
->CursorColumn
> 0) {
668 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
--;
671 case (CHAR_LINEFEED
):
673 // add a temp NULL terminator
675 TempChar
= *(Walker
+ 1);
676 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
681 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
684 // restore the temp NULL terminator to it's original character
686 *((CHAR16
*)(Walker
+1)) = TempChar
;
689 // Update LineStart Variable
691 LineStart
= Walker
+ 1;
694 // increment row count
696 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
697 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
700 case (CHAR_CARRIAGE_RETURN
):
702 // Move the cursor to the beginning of the current row.
704 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
708 // increment column count
710 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
++;
712 // check if that is the last column
714 if ((INTN
)ConsoleInfo
->ColsPerScreen
== ConsoleInfo
->OurConOut
.Mode
->CursorColumn
- 1) {
716 // output a line similar to the linefeed character.
720 // add a temp NULL terminator
722 TempChar
= *(Walker
+ 1);
723 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
728 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
731 // restore the temp NULL terminator to it's original character
733 *((CHAR16
*)(Walker
+1)) = TempChar
;
736 // Update LineStart Variable
741 // increment row count and zero the column
743 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
744 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
745 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
746 } // last column on line
748 } // switch for character
751 // check if that was the last printable row. If yes handle PageBreak mode
753 if ((ConsoleInfo
->RowsPerScreen
) -1 == ShellInfoObject
.ConsoleInfo
->RowCounter
) {
754 if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
756 // We got an error which means 'break' and halt the printing
758 return (EFI_DEVICE_ERROR
);
763 if (LineStart
!= NULL
&& *LineStart
!= CHAR_NULL
) {
764 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
767 return (EFI_SUCCESS
);
771 Write a Unicode string to the output device.
773 @param[in] This Protocol instance pointer.
774 @param[in] WString The NULL-terminated Unicode string to be displayed on the output
775 device(s). All output devices must also support the Unicode
776 drawing defined in this file.
777 @retval EFI_SUCCESS The string was output to the device.
778 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
780 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
782 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
783 characters in the Unicode string could not be
784 rendered and were skipped.
788 ConsoleLoggerOutputString (
789 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
793 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
794 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
795 ASSERT(ShellInfoObject
.ConsoleInfo
== ConsoleInfo
);
796 if (!ShellInfoObject
.ConsoleInfo
->Enabled
) {
797 return (EFI_DEVICE_ERROR
);
798 } else if (ShellInfoObject
.PageBreakEnabled
) {
799 return (ConsoleLoggerPrintWithPageBreak(WString
, ConsoleInfo
));
801 return (ConsoleLoggerOutputStringSplit(WString
, ConsoleInfo
));
806 Verifies that all characters in a Unicode string can be output to the
809 @param[in] This Protocol instance pointer.
810 @param[in] WString The NULL-terminated Unicode string to be examined for the output
813 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
814 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
815 rendered by one or more of the output devices mapped
821 ConsoleLoggerTestString (
822 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
826 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
827 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
829 // Forward the request to the original ConOut
831 return (ConsoleInfo
->OldConOut
->TestString (ConsoleInfo
->OldConOut
, WString
));
835 Returns information for an available text mode that the output device(s)
838 @param[in] This Protocol instance pointer.
839 @param[in] ModeNumber The mode number to return information on.
840 @param[out] Columns Upon return, the number of columns in the selected geometry
841 @param[out] Rows Upon return, the number of rows in the selected geometry
843 @retval EFI_SUCCESS The requested mode information was returned.
844 @retval EFI_DEVICE_ERROR The device had an error and could not
845 complete the request.
846 @retval EFI_UNSUPPORTED The mode number was not valid.
850 ConsoleLoggerQueryMode (
851 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
857 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
858 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
860 // Forward the request to the original ConOut
862 return (ConsoleInfo
->OldConOut
->QueryMode (
863 ConsoleInfo
->OldConOut
,
871 Sets the output device(s) to a specified mode.
873 @param[in] This Protocol instance pointer.
874 @param[in] ModeNumber The mode number to set.
877 @retval EFI_SUCCESS The requested text mode was set.
878 @retval EFI_DEVICE_ERROR The device had an error and
879 could not complete the request.
880 @retval EFI_UNSUPPORTED The mode number was not valid.
884 ConsoleLoggerSetMode (
885 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
891 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
892 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
895 // Forward the request to the original ConOut
897 Status
= ConsoleInfo
->OldConOut
->SetMode (ConsoleInfo
->OldConOut
, ModeNumber
);
900 // Check that the buffers are still correct for logging
902 if (!EFI_ERROR (Status
)) {
903 ConsoleLoggerResetBuffers(ConsoleInfo
);
910 Sets the background and foreground colors for the OutputString () and
911 ClearScreen () functions.
913 @param[in] This Protocol instance pointer.
914 @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
915 bits 4..6 are the background color. All other bits are undefined
916 and must be zero. The valid Attributes are defined in this file.
918 @retval EFI_SUCCESS The attribute was set.
919 @retval EFI_DEVICE_ERROR The device had an error and
920 could not complete the request.
921 @retval EFI_UNSUPPORTED The attribute requested is not defined.
926 ConsoleLoggerSetAttribute (
927 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
933 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
934 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
937 // Forward the request to the original ConOut
939 Status
= ConsoleInfo
->OldConOut
->SetAttribute (ConsoleInfo
->OldConOut
, Attribute
);
942 // Record console output history
944 if (!EFI_ERROR (Status
)) {
945 ConsoleInfo
->HistoryMode
.Attribute
= (INT32
) Attribute
;
952 Clears the output device(s) display to the currently selected background
955 @param[in] This Protocol instance pointer.
957 @retval EFI_SUCCESS The operation completed successfully.
958 @retval EFI_DEVICE_ERROR The device had an error and
959 could not complete the request.
960 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
964 ConsoleLoggerClearScreen (
965 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
975 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
976 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
979 // Forward the request to the original ConOut
981 Status
= ConsoleInfo
->OldConOut
->ClearScreen (ConsoleInfo
->OldConOut
);
984 // Record console output history
986 if (!EFI_ERROR (Status
)) {
987 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 1) * ConsoleInfo
->CurrentStartRow
];
988 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
989 for ( Row
= ConsoleInfo
->OriginalStartRow
990 ; Row
< (ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)
994 ; Column
< ConsoleInfo
->ColsPerScreen
1000 *Attributes
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
1003 // Skip the NULL on each column end in text buffer only
1007 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
1008 ConsoleInfo
->HistoryMode
.CursorRow
= 0;
1015 Sets the current coordinates of the cursor position
1017 @param[in] This Protocol instance pointer.
1018 @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
1019 @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
1021 @retval EFI_SUCCESS The operation completed successfully.
1022 @retval EFI_DEVICE_ERROR The device had an error and
1023 could not complete the request.
1024 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
1025 cursor position is invalid for the current mode.
1029 ConsoleLoggerSetCursorPosition (
1030 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1037 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1038 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1040 // Forward the request to the original ConOut
1042 Status
= ConsoleInfo
->OldConOut
->SetCursorPosition (
1043 ConsoleInfo
->OldConOut
,
1049 // Record console output history
1051 if (!EFI_ERROR (Status
)) {
1052 ConsoleInfo
->HistoryMode
.CursorColumn
= (INT32
)Column
;
1053 ConsoleInfo
->HistoryMode
.CursorRow
= (INT32
)(ConsoleInfo
->OriginalStartRow
+ Row
);
1060 Makes the cursor visible or invisible
1062 @param[in] This Protocol instance pointer.
1063 @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
1064 set to be invisible.
1066 @retval EFI_SUCCESS The operation completed successfully.
1067 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1068 request, or the device does not support changing
1070 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1074 ConsoleLoggerEnableCursor (
1075 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1081 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1082 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1084 // Forward the request to the original ConOut
1086 Status
= ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, Visible
);
1089 // Record console output history
1091 if (!EFI_ERROR (Status
)) {
1092 ConsoleInfo
->HistoryMode
.CursorVisible
= Visible
;
1099 Function to update and verify that the current buffers are correct.
1101 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
1103 This will be used when a mode has changed or a reset ocurred to verify all
1108 ConsoleLoggerResetBuffers(
1109 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
1114 if (ConsoleInfo
->Buffer
!= NULL
) {
1115 FreePool(ConsoleInfo
->Buffer
);
1116 ConsoleInfo
->Buffer
= NULL
;
1117 ConsoleInfo
->BufferSize
= 0;
1119 if (ConsoleInfo
->Attributes
!= NULL
) {
1120 FreePool(ConsoleInfo
->Attributes
);
1121 ConsoleInfo
->Attributes
= NULL
;
1122 ConsoleInfo
->AttribSize
= 0;
1125 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &ConsoleInfo
->ColsPerScreen
, &ConsoleInfo
->RowsPerScreen
);
1126 if (EFI_ERROR(Status
)){
1130 ConsoleInfo
->BufferSize
= (ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Buffer
[0]);
1131 ConsoleInfo
->AttribSize
= ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Attributes
[0]);
1133 ConsoleInfo
->Buffer
= (CHAR16
*)AllocateZeroPool(ConsoleInfo
->BufferSize
);
1135 if (ConsoleInfo
->Buffer
== NULL
) {
1136 return (EFI_OUT_OF_RESOURCES
);
1139 ConsoleInfo
->Attributes
= (INT32
*)AllocateZeroPool(ConsoleInfo
->AttribSize
);
1140 if (ConsoleInfo
->Attributes
== NULL
) {
1141 FreePool(ConsoleInfo
->Buffer
);
1142 ConsoleInfo
->Buffer
= NULL
;
1143 return (EFI_OUT_OF_RESOURCES
);
1146 ConsoleInfo
->OurConOut
.Mode
= gST
->ConOut
->Mode
;
1147 ConsoleInfo
->OldConOut
= gST
->ConOut
;
1148 CopyMem (&ConsoleInfo
->HistoryMode
, ConsoleInfo
->OldConOut
->Mode
, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE
));
1150 return (EFI_SUCCESS
);