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 if ((*ConsoleInfo
) == NULL
) {
44 return (EFI_OUT_OF_RESOURCES
);
47 (*ConsoleInfo
)->Signature
= CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE
;
48 (*ConsoleInfo
)->OldConOut
= NULL
;
49 (*ConsoleInfo
)->OldConHandle
= NULL
;
50 (*ConsoleInfo
)->Buffer
= NULL
;
51 (*ConsoleInfo
)->BufferSize
= 0;
52 (*ConsoleInfo
)->OriginalStartRow
= 0;
53 (*ConsoleInfo
)->CurrentStartRow
= 0;
54 (*ConsoleInfo
)->RowsPerScreen
= 0;
55 (*ConsoleInfo
)->ColsPerScreen
= 0;
56 (*ConsoleInfo
)->Attributes
= NULL
;
57 (*ConsoleInfo
)->AttribSize
= 0;
58 (*ConsoleInfo
)->ScreenCount
= ScreensToSave
;
59 (*ConsoleInfo
)->HistoryMode
.MaxMode
= 1;
60 (*ConsoleInfo
)->HistoryMode
.Mode
= 0;
61 (*ConsoleInfo
)->HistoryMode
.Attribute
= 0;
62 (*ConsoleInfo
)->HistoryMode
.CursorColumn
= 0;
63 (*ConsoleInfo
)->HistoryMode
.CursorRow
= 0;
64 (*ConsoleInfo
)->HistoryMode
.CursorVisible
= FALSE
;
65 (*ConsoleInfo
)->OurConOut
.Reset
= ConsoleLoggerReset
;
66 (*ConsoleInfo
)->OurConOut
.OutputString
= ConsoleLoggerOutputString
;
67 (*ConsoleInfo
)->OurConOut
.TestString
= ConsoleLoggerTestString
;
68 (*ConsoleInfo
)->OurConOut
.QueryMode
= ConsoleLoggerQueryMode
;
69 (*ConsoleInfo
)->OurConOut
.SetMode
= ConsoleLoggerSetMode
;
70 (*ConsoleInfo
)->OurConOut
.SetAttribute
= ConsoleLoggerSetAttribute
;
71 (*ConsoleInfo
)->OurConOut
.ClearScreen
= ConsoleLoggerClearScreen
;
72 (*ConsoleInfo
)->OurConOut
.SetCursorPosition
= ConsoleLoggerSetCursorPosition
;
73 (*ConsoleInfo
)->OurConOut
.EnableCursor
= ConsoleLoggerEnableCursor
;
74 (*ConsoleInfo
)->OurConOut
.Mode
= NULL
;
75 (*ConsoleInfo
)->Enabled
= TRUE
;
77 Status
= ConsoleLoggerResetBuffers(*ConsoleInfo
);
78 if (EFI_ERROR(Status
)) {
79 SHELL_FREE_NON_NULL((*ConsoleInfo
));
84 Status
= gBS
->InstallProtocolInterface(&gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, EFI_NATIVE_INTERFACE
, (VOID
*)&((*ConsoleInfo
)->OurConOut
));
85 if (EFI_ERROR(Status
)) {
86 SHELL_FREE_NON_NULL((*ConsoleInfo
)->Buffer
);
87 SHELL_FREE_NON_NULL((*ConsoleInfo
)->Attributes
);
88 SHELL_FREE_NON_NULL((*ConsoleInfo
));
93 (*ConsoleInfo
)->OldConOut
= gST
->ConOut
;
94 (*ConsoleInfo
)->OldConHandle
= gST
->ConsoleOutHandle
;
96 gST
->ConsoleOutHandle
= gImageHandle
;
97 gST
->ConOut
= &(*ConsoleInfo
)->OurConOut
;
103 Return the system to the state it was before InstallConsoleLogger
106 @param[in,out] ConsoleInfo The object from the install function.
108 @retval EFI_SUCCESS The operation was successful
109 @return other The operation failed. This was from UninstallProtocolInterface.
113 ConsoleLoggerUninstall(
114 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
117 ASSERT(ConsoleInfo
!= NULL
);
118 ASSERT(ConsoleInfo
->OldConOut
!= NULL
);
120 if (ConsoleInfo
->Buffer
!= NULL
) {
121 FreePool(ConsoleInfo
->Buffer
);
122 DEBUG_CODE(ConsoleInfo
->Buffer
= NULL
;);
123 DEBUG_CODE(ConsoleInfo
->BufferSize
= 0;);
125 if (ConsoleInfo
->Attributes
!= NULL
) {
126 FreePool(ConsoleInfo
->Attributes
);
127 DEBUG_CODE(ConsoleInfo
->Attributes
= NULL
;);
128 DEBUG_CODE(ConsoleInfo
->AttribSize
= 0;);
131 gST
->ConsoleOutHandle
= ConsoleInfo
->OldConHandle
;
132 gST
->ConOut
= ConsoleInfo
->OldConOut
;
134 return (gBS
->UninstallProtocolInterface(gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, (VOID
*)&ConsoleInfo
->OurConOut
));
138 Displays previously logged output back to the screen.
140 This will scroll the screen forwards and backwards through the log of previous
141 output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows
142 is (UINTN)(-1) then the size of the screen will be scrolled.
144 @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer).
145 If FALSE then the log will be displayed backwards (scroll to older).
146 @param[in] Rows Determines how many rows the log should scroll.
147 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
151 ConsoleLoggerDisplayHistory(
152 IN CONST BOOLEAN Forward
,
154 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
159 ASSERT(ConsoleInfo
!= NULL
);
162 // Calculate the row number change
166 RowChange
= ConsoleInfo
->RowsPerScreen
;
169 RowChange
= ConsoleInfo
->RowsPerScreen
/ 2;
177 // Do the math for direction
180 if ((ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
) < RowChange
) {
181 RowChange
= ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
;
184 if (ConsoleInfo
->CurrentStartRow
< RowChange
) {
185 RowChange
= ConsoleInfo
->CurrentStartRow
;
190 // If we are already at one end or the other
192 if (RowChange
== 0) {
193 return (EFI_SUCCESS
);
199 ConsoleInfo
->OldConOut
->ClearScreen(ConsoleInfo
->OldConOut
);
202 // Set the new start row
205 ConsoleInfo
->CurrentStartRow
+= RowChange
;
207 ConsoleInfo
->CurrentStartRow
-= RowChange
;
213 return (UpdateDisplayFromHistory(ConsoleInfo
));
217 Function to return to normal output whent he scrolling is complete.
218 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
220 @retval EFI_SUCCESS The operation was successful.
221 @return other The operation failed. See UpdateDisplayFromHistory.
223 @sa UpdateDisplayFromHistory
227 ConsoleLoggerStopHistory(
228 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
231 ASSERT(ConsoleInfo
!= NULL
);
232 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
233 return (EFI_SUCCESS
);
235 ConsoleInfo
->CurrentStartRow
= ConsoleInfo
->OriginalStartRow
;
236 return (UpdateDisplayFromHistory(ConsoleInfo
));
240 Updates the hidden ConOut to be displaying the correct stuff.
241 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
243 @retval EFI_SUCCESS The operation was successful.
244 @return other The operation failed.
248 UpdateDisplayFromHistory(
249 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
257 CHAR16 TempCharHolder
;
261 CHAR16
*StringSegment
;
262 CHAR16
*StringSegmentEnd
;
263 CHAR16 StringSegmentEndChar
;
265 ASSERT(ConsoleInfo
!= NULL
);
266 TempCharHolder
= CHAR_NULL
;
267 RetVal
= EFI_SUCCESS
;
270 // Disable cursor visibility and move it to the top left corner
272 ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, FALSE
);
273 ConsoleInfo
->OldConOut
->SetCursorPosition (ConsoleInfo
->OldConOut
, 0, 0);
275 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
276 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
278 ; CurrentRow
< ConsoleInfo
->RowsPerScreen
280 , Screen
+= (ConsoleInfo
->ColsPerScreen
+ 2)
281 , Attributes
+= ConsoleInfo
->ColsPerScreen
284 // dont use the last char - prevents screen scroll
286 if (CurrentRow
== (ConsoleInfo
->RowsPerScreen
-1)){
287 TempCharHolder
= Screen
[ConsoleInfo
->ColsPerScreen
- 1];
288 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = CHAR_NULL
;
292 ; Column
< ConsoleInfo
->ColsPerScreen
295 if (Screen
[Column
] != CHAR_NULL
) {
296 CurrentAttrib
= Attributes
[Column
];
297 CurrentColumn
= Column
;
298 StringSegment
= &Screen
[Column
];
301 // Find the first char with a different arrribute and make that temporarily NULL
302 // so we can do fewer printout statements. (later) restore that one and we will
303 // start at that collumn on the next loop.
305 StringSegmentEndChar
= CHAR_NULL
;
306 for ( StringSegmentEnd
= StringSegment
307 ; StringSegmentEnd
!= CHAR_NULL
311 if (Attributes
[Column
] != CurrentAttrib
) {
312 StringSegmentEndChar
= *StringSegmentEnd
;
313 *StringSegmentEnd
= CHAR_NULL
;
316 } // StringSegmentEnd loop
319 // Now write out as much as had the same Attributes
322 ConsoleInfo
->OldConOut
->SetAttribute(ConsoleInfo
->OldConOut
, CurrentAttrib
);
323 ConsoleInfo
->OldConOut
->SetCursorPosition(ConsoleInfo
->OldConOut
, CurrentColumn
, CurrentRow
);
324 Status
= ConsoleInfo
->OldConOut
->OutputString(ConsoleInfo
->OldConOut
, StringSegment
);
326 if (EFI_ERROR(Status
)) {
332 // If we found a change in attribute put the character back and decrement the column
333 // so when it increments it will point at that character and we will start printing
334 // a segment with that new attribute
336 if (StringSegmentEndChar
!= CHAR_NULL
) {
337 *StringSegmentEnd
= StringSegmentEndChar
;
338 StringSegmentEndChar
= CHAR_NULL
;
345 // If we removed the last char and this was the last row put it back
347 if (TempCharHolder
!= CHAR_NULL
) {
348 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = TempCharHolder
;
349 TempCharHolder
= CHAR_NULL
;
354 // If we are setting the screen back to original turn on the cursor and make it visible
355 // and set the attributes back to what they were
357 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
358 ConsoleInfo
->OldConOut
->SetAttribute (
359 ConsoleInfo
->OldConOut
,
360 ConsoleInfo
->HistoryMode
.Attribute
362 ConsoleInfo
->OldConOut
->SetCursorPosition (
363 ConsoleInfo
->OldConOut
,
364 ConsoleInfo
->HistoryMode
.CursorColumn
,
365 ConsoleInfo
->HistoryMode
.CursorRow
- ConsoleInfo
->OriginalStartRow
368 Status
= ConsoleInfo
->OldConOut
->EnableCursor (
369 ConsoleInfo
->OldConOut
,
370 ConsoleInfo
->HistoryMode
.CursorVisible
372 if (EFI_ERROR (Status
)) {
381 Reset the text output device hardware and optionaly run diagnostics
383 @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
384 @param ExtendedVerification Indicates that a more extensive test may be performed
386 @retval EFI_SUCCESS The text output device was reset.
387 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
393 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
394 IN BOOLEAN ExtendedVerification
398 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
399 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
402 // Forward the request to the original ConOut
404 Status
= ConsoleInfo
->OldConOut
->Reset (ConsoleInfo
->OldConOut
, ExtendedVerification
);
407 // Check that the buffers are still correct for logging
409 if (!EFI_ERROR (Status
)) {
410 ConsoleLoggerResetBuffers(ConsoleInfo
);
417 Appends a string to the history buffer. If the buffer is full then the oldest
418 information in the buffer will be dropped. Information is added in a line by
419 line manner such that an empty line takes up just as much space as a full line.
421 @param[in] String String pointer to add.
422 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
426 AppendStringToHistory(
427 IN CONST CHAR16
*String
,
428 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
431 CONST CHAR16
*Walker
;
436 ASSERT(ConsoleInfo
!= NULL
);
438 for ( Walker
= String
439 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
443 case (CHAR_BACKSPACE
):
444 if (ConsoleInfo
->HistoryMode
.CursorColumn
> 0) {
445 ConsoleInfo
->HistoryMode
.CursorColumn
--;
448 case (CHAR_LINEFEED
):
449 if (ConsoleInfo
->HistoryMode
.CursorRow
>= (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1)) {
451 // Should never be bigger
453 ASSERT(ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1));
456 // scroll history attributes 'up' 1 row and set the last row to default attribute
458 CopySize
= ConsoleInfo
->ColsPerScreen
459 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
460 * sizeof(ConsoleInfo
->Attributes
[0]);
461 ASSERT(CopySize
< ConsoleInfo
->AttribSize
);
463 ConsoleInfo
->Attributes
,
464 ConsoleInfo
->Attributes
+ ConsoleInfo
->ColsPerScreen
,
469 ; Index
< ConsoleInfo
->ColsPerScreen
472 *(ConsoleInfo
->Attributes
+ (CopySize
/sizeof(ConsoleInfo
->Attributes
)) + Index
) = ConsoleInfo
->HistoryMode
.Attribute
;
476 // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
478 CopySize
= (ConsoleInfo
->ColsPerScreen
+ 2)
479 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
480 * sizeof(ConsoleInfo
->Buffer
[0]);
481 ASSERT(CopySize
< ConsoleInfo
->BufferSize
);
484 ConsoleInfo
->Buffer
+ (ConsoleInfo
->ColsPerScreen
+ 2),
489 // Set that last row of chars to spaces
491 SetMem16(((UINT8
*)ConsoleInfo
->Buffer
)+CopySize
, ConsoleInfo
->ColsPerScreen
*sizeof(CHAR16
), L
' ');
494 // we are not on the last row
498 // We should not be scrolling history
500 ASSERT (ConsoleInfo
->OriginalStartRow
== ConsoleInfo
->CurrentStartRow
);
502 // are we at the end of a row?
504 if (ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
) (ConsoleInfo
->OriginalStartRow
+ ConsoleInfo
->RowsPerScreen
- 1)) {
505 ConsoleInfo
->OriginalStartRow
++;
506 ConsoleInfo
->CurrentStartRow
++;
508 ConsoleInfo
->HistoryMode
.CursorRow
++;
511 case (CHAR_CARRIAGE_RETURN
):
513 // Move the cursor to the beginning of the current row.
515 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
519 // Acrtually print characters into the history buffer
522 PrintIndex
= ConsoleInfo
->HistoryMode
.CursorRow
* ConsoleInfo
->ColsPerScreen
+ ConsoleInfo
->HistoryMode
.CursorColumn
;
524 for ( // no initializer needed
525 ; ConsoleInfo
->HistoryMode
.CursorColumn
< (INT32
) ConsoleInfo
->ColsPerScreen
526 ; ConsoleInfo
->HistoryMode
.CursorColumn
++
530 if (*Walker
== CHAR_NULL
531 ||*Walker
== CHAR_BACKSPACE
532 ||*Walker
== CHAR_LINEFEED
533 ||*Walker
== CHAR_CARRIAGE_RETURN
539 // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
542 ASSERT(PrintIndex
+ ConsoleInfo
->HistoryMode
.CursorRow
< ConsoleInfo
->BufferSize
);
543 ConsoleInfo
->Buffer
[PrintIndex
+ (2*ConsoleInfo
->HistoryMode
.CursorRow
)] = *Walker
;
544 ASSERT(PrintIndex
< ConsoleInfo
->AttribSize
);
545 ConsoleInfo
->Attributes
[PrintIndex
] = ConsoleInfo
->HistoryMode
.Attribute
;
549 // Add the carriage return and line feed at the end of the lines
551 if (ConsoleInfo
->HistoryMode
.CursorColumn
>= (INT32
)ConsoleInfo
->ColsPerScreen
) {
552 AppendStringToHistory(L
"\r\n", ConsoleInfo
);
557 } // switch for character
560 return (EFI_SUCCESS
);
564 Worker function to handle printing the output to the screen
565 and the history buffer
567 @param[in] String The string to output
568 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
570 @retval EFI_SUCCESS The string was printed
571 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
573 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
575 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
576 characters in the Unicode string could not be
577 rendered and were skipped.
581 ConsoleLoggerOutputStringSplit(
582 IN CONST CHAR16
*String
,
583 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
589 // Forward the request to the original ConOut
591 Status
= ConsoleInfo
->OldConOut
->OutputString (ConsoleInfo
->OldConOut
, (CHAR16
*)String
);
593 if (EFI_ERROR(Status
)) {
597 return (AppendStringToHistory(String
, ConsoleInfo
));
601 Function to handle page break mode.
603 This function will prompt for continue or break.
605 @retval EFI_SUCCESS Continue was choosen
606 @return other Break was choosen
610 ConsoleLoggerDoPageBreak(
614 SHELL_PROMPT_RESPONSE
*Resp
;
618 ASSERT(ShellInfoObject
.PageBreakEnabled
);
619 ShellInfoObject
.PageBreakEnabled
= FALSE
;
620 Status
= ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue
, STRING_TOKEN(STR_SHELL_QUIT_CONT
), ShellInfoObject
.HiiHandle
, (VOID
**)&Resp
);
621 ShellInfoObject
.PageBreakEnabled
= TRUE
;
622 ASSERT(Resp
!= NULL
);
624 return (EFI_NOT_FOUND
);
626 if (EFI_ERROR(Status
)) {
632 if (*Resp
== ShellPromptResponseContinue
) {
634 ShellInfoObject
.ConsoleInfo
->RowCounter
= 0;
635 return (EFI_SUCCESS
);
636 } else if (*Resp
== ShellPromptResponseQuit
) {
638 ShellInfoObject
.ConsoleInfo
->Enabled
= FALSE
;
639 return (EFI_DEVICE_ERROR
);
643 return (EFI_SUCCESS
);
646 Worker function to handle printing the output with page breaks.
648 @param[in] String The string to output
649 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
651 @retval EFI_SUCCESS The string was printed
652 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
654 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
656 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
657 characters in the Unicode string could not be
658 rendered and were skipped.
662 ConsoleLoggerPrintWithPageBreak(
664 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
667 CONST CHAR16
*Walker
;
668 CONST CHAR16
*LineStart
;
671 for ( Walker
= String
673 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
677 case (CHAR_BACKSPACE
):
678 if (ConsoleInfo
->OurConOut
.Mode
->CursorColumn
> 0) {
679 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
--;
682 case (CHAR_LINEFEED
):
684 // add a temp NULL terminator
686 TempChar
= *(Walker
+ 1);
687 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
692 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
695 // restore the temp NULL terminator to it's original character
697 *((CHAR16
*)(Walker
+1)) = TempChar
;
700 // Update LineStart Variable
702 LineStart
= Walker
+ 1;
705 // increment row count
707 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
708 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
711 case (CHAR_CARRIAGE_RETURN
):
713 // Move the cursor to the beginning of the current row.
715 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
719 // increment column count
721 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
++;
723 // check if that is the last column
725 if ((INTN
)ConsoleInfo
->ColsPerScreen
== ConsoleInfo
->OurConOut
.Mode
->CursorColumn
- 1) {
727 // output a line similar to the linefeed character.
731 // add a temp NULL terminator
733 TempChar
= *(Walker
+ 1);
734 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
739 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
742 // restore the temp NULL terminator to it's original character
744 *((CHAR16
*)(Walker
+1)) = TempChar
;
747 // Update LineStart Variable
752 // increment row count and zero the column
754 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
755 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
756 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
757 } // last column on line
759 } // switch for character
762 // check if that was the last printable row. If yes handle PageBreak mode
764 if ((ConsoleInfo
->RowsPerScreen
) -1 == ShellInfoObject
.ConsoleInfo
->RowCounter
) {
765 if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
767 // We got an error which means 'break' and halt the printing
769 return (EFI_DEVICE_ERROR
);
774 if (LineStart
!= NULL
&& *LineStart
!= CHAR_NULL
) {
775 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
778 return (EFI_SUCCESS
);
782 Write a Unicode string to the output device.
784 @param[in] This Protocol instance pointer.
785 @param[in] WString The NULL-terminated Unicode string to be displayed on the output
786 device(s). All output devices must also support the Unicode
787 drawing defined in this file.
788 @retval EFI_SUCCESS The string was output to the device.
789 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
791 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
793 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
794 characters in the Unicode string could not be
795 rendered and were skipped.
799 ConsoleLoggerOutputString (
800 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
804 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
805 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
806 ASSERT(ShellInfoObject
.ConsoleInfo
== ConsoleInfo
);
807 if (!ShellInfoObject
.ConsoleInfo
->Enabled
) {
808 return (EFI_DEVICE_ERROR
);
809 } else if (ShellInfoObject
.PageBreakEnabled
) {
810 return (ConsoleLoggerPrintWithPageBreak(WString
, ConsoleInfo
));
812 return (ConsoleLoggerOutputStringSplit(WString
, ConsoleInfo
));
817 Verifies that all characters in a Unicode string can be output to the
820 @param[in] This Protocol instance pointer.
821 @param[in] WString The NULL-terminated Unicode string to be examined for the output
824 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
825 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
826 rendered by one or more of the output devices mapped
832 ConsoleLoggerTestString (
833 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
837 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
838 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
840 // Forward the request to the original ConOut
842 return (ConsoleInfo
->OldConOut
->TestString (ConsoleInfo
->OldConOut
, WString
));
846 Returns information for an available text mode that the output device(s)
849 @param[in] This Protocol instance pointer.
850 @param[in] ModeNumber The mode number to return information on.
851 @param[out] Columns Upon return, the number of columns in the selected geometry
852 @param[out] Rows Upon return, the number of rows in the selected geometry
854 @retval EFI_SUCCESS The requested mode information was returned.
855 @retval EFI_DEVICE_ERROR The device had an error and could not
856 complete the request.
857 @retval EFI_UNSUPPORTED The mode number was not valid.
861 ConsoleLoggerQueryMode (
862 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
868 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
869 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
871 // Forward the request to the original ConOut
873 return (ConsoleInfo
->OldConOut
->QueryMode (
874 ConsoleInfo
->OldConOut
,
882 Sets the output device(s) to a specified mode.
884 @param[in] This Protocol instance pointer.
885 @param[in] ModeNumber The mode number to set.
888 @retval EFI_SUCCESS The requested text mode was set.
889 @retval EFI_DEVICE_ERROR The device had an error and
890 could not complete the request.
891 @retval EFI_UNSUPPORTED The mode number was not valid.
895 ConsoleLoggerSetMode (
896 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
902 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
903 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
906 // Forward the request to the original ConOut
908 Status
= ConsoleInfo
->OldConOut
->SetMode (ConsoleInfo
->OldConOut
, ModeNumber
);
911 // Check that the buffers are still correct for logging
913 if (!EFI_ERROR (Status
)) {
914 ConsoleLoggerResetBuffers(ConsoleInfo
);
921 Sets the background and foreground colors for the OutputString () and
922 ClearScreen () functions.
924 @param[in] This Protocol instance pointer.
925 @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
926 bits 4..6 are the background color. All other bits are undefined
927 and must be zero. The valid Attributes are defined in this file.
929 @retval EFI_SUCCESS The attribute was set.
930 @retval EFI_DEVICE_ERROR The device had an error and
931 could not complete the request.
932 @retval EFI_UNSUPPORTED The attribute requested is not defined.
937 ConsoleLoggerSetAttribute (
938 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
944 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
945 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
948 // Forward the request to the original ConOut
950 Status
= ConsoleInfo
->OldConOut
->SetAttribute (ConsoleInfo
->OldConOut
, Attribute
);
953 // Record console output history
955 if (!EFI_ERROR (Status
)) {
956 ConsoleInfo
->HistoryMode
.Attribute
= (INT32
) Attribute
;
963 Clears the output device(s) display to the currently selected background
966 @param[in] This Protocol instance pointer.
968 @retval EFI_SUCCESS The operation completed successfully.
969 @retval EFI_DEVICE_ERROR The device had an error and
970 could not complete the request.
971 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
975 ConsoleLoggerClearScreen (
976 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
986 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
987 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
990 // Forward the request to the original ConOut
992 Status
= ConsoleInfo
->OldConOut
->ClearScreen (ConsoleInfo
->OldConOut
);
995 // Record console output history
997 if (!EFI_ERROR (Status
)) {
998 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 1) * ConsoleInfo
->CurrentStartRow
];
999 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
1000 for ( Row
= ConsoleInfo
->OriginalStartRow
1001 ; Row
< (ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)
1005 ; Column
< ConsoleInfo
->ColsPerScreen
1011 *Attributes
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
1014 // Skip the NULL on each column end in text buffer only
1018 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
1019 ConsoleInfo
->HistoryMode
.CursorRow
= 0;
1026 Sets the current coordinates of the cursor position
1028 @param[in] This Protocol instance pointer.
1029 @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
1030 @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
1032 @retval EFI_SUCCESS The operation completed successfully.
1033 @retval EFI_DEVICE_ERROR The device had an error and
1034 could not complete the request.
1035 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
1036 cursor position is invalid for the current mode.
1040 ConsoleLoggerSetCursorPosition (
1041 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1048 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1049 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1051 // Forward the request to the original ConOut
1053 Status
= ConsoleInfo
->OldConOut
->SetCursorPosition (
1054 ConsoleInfo
->OldConOut
,
1060 // Record console output history
1062 if (!EFI_ERROR (Status
)) {
1063 ConsoleInfo
->HistoryMode
.CursorColumn
= (INT32
)Column
;
1064 ConsoleInfo
->HistoryMode
.CursorRow
= (INT32
)(ConsoleInfo
->OriginalStartRow
+ Row
);
1071 Makes the cursor visible or invisible
1073 @param[in] This Protocol instance pointer.
1074 @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
1075 set to be invisible.
1077 @retval EFI_SUCCESS The operation completed successfully.
1078 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1079 request, or the device does not support changing
1081 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1085 ConsoleLoggerEnableCursor (
1086 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1092 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1093 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1095 // Forward the request to the original ConOut
1097 Status
= ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, Visible
);
1100 // Record console output history
1102 if (!EFI_ERROR (Status
)) {
1103 ConsoleInfo
->HistoryMode
.CursorVisible
= Visible
;
1110 Function to update and verify that the current buffers are correct.
1112 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
1114 This will be used when a mode has changed or a reset ocurred to verify all
1119 ConsoleLoggerResetBuffers(
1120 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
1125 if (ConsoleInfo
->Buffer
!= NULL
) {
1126 FreePool(ConsoleInfo
->Buffer
);
1127 ConsoleInfo
->Buffer
= NULL
;
1128 ConsoleInfo
->BufferSize
= 0;
1130 if (ConsoleInfo
->Attributes
!= NULL
) {
1131 FreePool(ConsoleInfo
->Attributes
);
1132 ConsoleInfo
->Attributes
= NULL
;
1133 ConsoleInfo
->AttribSize
= 0;
1136 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &ConsoleInfo
->ColsPerScreen
, &ConsoleInfo
->RowsPerScreen
);
1137 if (EFI_ERROR(Status
)){
1141 ConsoleInfo
->BufferSize
= (ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Buffer
[0]);
1142 ConsoleInfo
->AttribSize
= ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Attributes
[0]);
1144 ConsoleInfo
->Buffer
= (CHAR16
*)AllocateZeroPool(ConsoleInfo
->BufferSize
);
1146 if (ConsoleInfo
->Buffer
== NULL
) {
1147 return (EFI_OUT_OF_RESOURCES
);
1150 ConsoleInfo
->Attributes
= (INT32
*)AllocateZeroPool(ConsoleInfo
->AttribSize
);
1151 if (ConsoleInfo
->Attributes
== NULL
) {
1152 FreePool(ConsoleInfo
->Buffer
);
1153 ConsoleInfo
->Buffer
= NULL
;
1154 return (EFI_OUT_OF_RESOURCES
);
1157 ConsoleInfo
->OurConOut
.Mode
= gST
->ConOut
->Mode
;
1158 ConsoleInfo
->OldConOut
= gST
->ConOut
;
1159 CopyMem (&ConsoleInfo
->HistoryMode
, ConsoleInfo
->OldConOut
->Mode
, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE
));
1161 return (EFI_SUCCESS
);