2 Provides interface to shell console logger.
4 Copyright (c) 2009 - 2011, 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
) = AllocateZeroPool(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
= gST
->ConOut
;
49 (*ConsoleInfo
)->OldConHandle
= gST
->ConsoleOutHandle
;
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
= gST
->ConOut
->Mode
;
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 gST
->ConsoleOutHandle
= gImageHandle
;
94 gST
->ConOut
= &(*ConsoleInfo
)->OurConOut
;
100 Return the system to the state it was before InstallConsoleLogger
103 @param[in] ConsoleInfo The object from the install function.
105 @retval EFI_SUCCESS The operation was successful
106 @return other The operation failed. This was from UninstallProtocolInterface.
110 ConsoleLoggerUninstall(
111 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
114 ASSERT(ConsoleInfo
!= NULL
);
115 ASSERT(ConsoleInfo
->OldConOut
!= NULL
);
117 if (ConsoleInfo
->Buffer
!= NULL
) {
118 FreePool(ConsoleInfo
->Buffer
);
119 DEBUG_CODE(ConsoleInfo
->Buffer
= NULL
;);
120 DEBUG_CODE(ConsoleInfo
->BufferSize
= 0;);
122 if (ConsoleInfo
->Attributes
!= NULL
) {
123 FreePool(ConsoleInfo
->Attributes
);
124 DEBUG_CODE(ConsoleInfo
->Attributes
= NULL
;);
125 DEBUG_CODE(ConsoleInfo
->AttribSize
= 0;);
128 gST
->ConsoleOutHandle
= ConsoleInfo
->OldConHandle
;
129 gST
->ConOut
= ConsoleInfo
->OldConOut
;
131 return (gBS
->UninstallProtocolInterface(gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, (VOID
*)&ConsoleInfo
->OurConOut
));
135 Displays previously logged output back to the screen.
137 This will scroll the screen forwards and backwards through the log of previous
138 output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows
139 is (UINTN)(-1) then the size of the screen will be scrolled.
141 @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer).
142 If FALSE then the log will be displayed backwards (scroll to older).
143 @param[in] Rows Determines how many rows the log should scroll.
144 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
148 ConsoleLoggerDisplayHistory(
149 IN CONST BOOLEAN Forward
,
151 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
156 ASSERT(ConsoleInfo
!= NULL
);
159 // Calculate the row number change
163 RowChange
= ConsoleInfo
->RowsPerScreen
;
166 RowChange
= ConsoleInfo
->RowsPerScreen
/ 2;
174 // Do the math for direction
177 if ((ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
) < RowChange
) {
178 RowChange
= ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
;
181 if (ConsoleInfo
->CurrentStartRow
< RowChange
) {
182 RowChange
= ConsoleInfo
->CurrentStartRow
;
187 // If we are already at one end or the other
189 if (RowChange
== 0) {
190 return (EFI_SUCCESS
);
196 ConsoleInfo
->OldConOut
->ClearScreen(ConsoleInfo
->OldConOut
);
199 // Set the new start row
202 ConsoleInfo
->CurrentStartRow
+= RowChange
;
204 ConsoleInfo
->CurrentStartRow
-= RowChange
;
210 return (UpdateDisplayFromHistory(ConsoleInfo
));
214 Function to return to normal output whent he scrolling is complete.
215 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
217 @retval EFI_SUCCESS The operation was successful.
218 @return other The operation failed. See UpdateDisplayFromHistory.
220 @sa UpdateDisplayFromHistory
224 ConsoleLoggerStopHistory(
225 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
228 ASSERT(ConsoleInfo
!= NULL
);
229 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
230 return (EFI_SUCCESS
);
232 ConsoleInfo
->CurrentStartRow
= ConsoleInfo
->OriginalStartRow
;
233 return (UpdateDisplayFromHistory(ConsoleInfo
));
237 Updates the hidden ConOut to be displaying the correct stuff.
238 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
240 @retval EFI_SUCCESS The operation was successful.
241 @return other The operation failed.
245 UpdateDisplayFromHistory(
246 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
254 CHAR16 TempCharHolder
;
258 CHAR16
*StringSegment
;
259 CHAR16
*StringSegmentEnd
;
260 CHAR16 StringSegmentEndChar
;
262 ASSERT(ConsoleInfo
!= NULL
);
263 TempCharHolder
= CHAR_NULL
;
264 RetVal
= EFI_SUCCESS
;
267 // Disable cursor visibility and move it to the top left corner
269 ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, FALSE
);
270 ConsoleInfo
->OldConOut
->SetCursorPosition (ConsoleInfo
->OldConOut
, 0, 0);
272 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
273 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
275 ; CurrentRow
< ConsoleInfo
->RowsPerScreen
277 , Screen
+= (ConsoleInfo
->ColsPerScreen
+ 2)
278 , Attributes
+= ConsoleInfo
->ColsPerScreen
281 // dont use the last char - prevents screen scroll
283 if (CurrentRow
== (ConsoleInfo
->RowsPerScreen
-1)){
284 TempCharHolder
= Screen
[ConsoleInfo
->ColsPerScreen
- 1];
285 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = CHAR_NULL
;
289 ; Column
< ConsoleInfo
->ColsPerScreen
292 if (Screen
[Column
] != CHAR_NULL
) {
293 CurrentAttrib
= Attributes
[Column
];
294 CurrentColumn
= Column
;
295 StringSegment
= &Screen
[Column
];
298 // Find the first char with a different arrribute and make that temporarily NULL
299 // so we can do fewer printout statements. (later) restore that one and we will
300 // start at that collumn on the next loop.
302 StringSegmentEndChar
= CHAR_NULL
;
303 for ( StringSegmentEnd
= StringSegment
304 ; StringSegmentEnd
!= CHAR_NULL
308 if (Attributes
[Column
] != CurrentAttrib
) {
309 StringSegmentEndChar
= *StringSegmentEnd
;
310 *StringSegmentEnd
= CHAR_NULL
;
313 } // StringSegmentEnd loop
316 // Now write out as much as had the same Attributes
319 ConsoleInfo
->OldConOut
->SetAttribute(ConsoleInfo
->OldConOut
, CurrentAttrib
);
320 ConsoleInfo
->OldConOut
->SetCursorPosition(ConsoleInfo
->OldConOut
, CurrentColumn
, CurrentRow
);
321 Status
= ConsoleInfo
->OldConOut
->OutputString(ConsoleInfo
->OldConOut
, StringSegment
);
323 if (EFI_ERROR(Status
)) {
329 // If we found a change in attribute put the character back and decrement the column
330 // so when it increments it will point at that character and we will start printing
331 // a segment with that new attribute
333 if (StringSegmentEndChar
!= CHAR_NULL
) {
334 *StringSegmentEnd
= StringSegmentEndChar
;
335 StringSegmentEndChar
= CHAR_NULL
;
342 // If we removed the last char and this was the last row put it back
344 if (TempCharHolder
!= CHAR_NULL
) {
345 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = TempCharHolder
;
346 TempCharHolder
= CHAR_NULL
;
351 // If we are setting the screen back to original turn on the cursor and make it visible
352 // and set the attributes back to what they were
354 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
355 ConsoleInfo
->OldConOut
->SetAttribute (
356 ConsoleInfo
->OldConOut
,
357 ConsoleInfo
->HistoryMode
.Attribute
359 ConsoleInfo
->OldConOut
->SetCursorPosition (
360 ConsoleInfo
->OldConOut
,
361 ConsoleInfo
->HistoryMode
.CursorColumn
,
362 ConsoleInfo
->HistoryMode
.CursorRow
- ConsoleInfo
->OriginalStartRow
365 Status
= ConsoleInfo
->OldConOut
->EnableCursor (
366 ConsoleInfo
->OldConOut
,
367 ConsoleInfo
->HistoryMode
.CursorVisible
369 if (EFI_ERROR (Status
)) {
378 Reset the text output device hardware and optionaly run diagnostics
380 @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
381 @param ExtendedVerification Indicates that a more extensive test may be performed
383 @retval EFI_SUCCESS The text output device was reset.
384 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
390 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
391 IN BOOLEAN ExtendedVerification
395 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
396 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
399 // Forward the request to the original ConOut
401 Status
= ConsoleInfo
->OldConOut
->Reset (ConsoleInfo
->OldConOut
, ExtendedVerification
);
404 // Check that the buffers are still correct for logging
406 if (!EFI_ERROR (Status
)) {
407 ConsoleLoggerResetBuffers(ConsoleInfo
);
414 Appends a string to the history buffer. If the buffer is full then the oldest
415 information in the buffer will be dropped. Information is added in a line by
416 line manner such that an empty line takes up just as much space as a full line.
418 @param[in] String String pointer to add.
419 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
423 AppendStringToHistory(
424 IN CONST CHAR16
*String
,
425 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
428 CONST CHAR16
*Walker
;
433 ASSERT(ConsoleInfo
!= NULL
);
435 for ( Walker
= String
436 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
440 case (CHAR_BACKSPACE
):
441 if (ConsoleInfo
->HistoryMode
.CursorColumn
> 0) {
442 ConsoleInfo
->HistoryMode
.CursorColumn
--;
445 case (CHAR_LINEFEED
):
446 if (ConsoleInfo
->HistoryMode
.CursorRow
>= (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1)) {
448 // Should never be bigger
450 ASSERT(ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1));
453 // scroll history attributes 'up' 1 row and set the last row to default attribute
455 CopySize
= ConsoleInfo
->ColsPerScreen
456 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
457 * sizeof(ConsoleInfo
->Attributes
[0]);
458 ASSERT(CopySize
< ConsoleInfo
->AttribSize
);
460 ConsoleInfo
->Attributes
,
461 ConsoleInfo
->Attributes
+ ConsoleInfo
->ColsPerScreen
,
466 ; Index
< ConsoleInfo
->ColsPerScreen
469 *(ConsoleInfo
->Attributes
+ (CopySize
/sizeof(ConsoleInfo
->Attributes
)) + Index
) = ConsoleInfo
->HistoryMode
.Attribute
;
473 // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
475 CopySize
= (ConsoleInfo
->ColsPerScreen
+ 2)
476 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
477 * sizeof(ConsoleInfo
->Buffer
[0]);
478 ASSERT(CopySize
< ConsoleInfo
->BufferSize
);
481 ConsoleInfo
->Buffer
+ (ConsoleInfo
->ColsPerScreen
+ 2),
486 // Set that last row of chars to spaces
488 SetMem16(((UINT8
*)ConsoleInfo
->Buffer
)+CopySize
, ConsoleInfo
->ColsPerScreen
*sizeof(CHAR16
), L
' ');
491 // we are not on the last row
495 // We should not be scrolling history
497 ASSERT (ConsoleInfo
->OriginalStartRow
== ConsoleInfo
->CurrentStartRow
);
499 // are we at the end of a row?
501 if (ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
) (ConsoleInfo
->OriginalStartRow
+ ConsoleInfo
->RowsPerScreen
- 1)) {
502 ConsoleInfo
->OriginalStartRow
++;
503 ConsoleInfo
->CurrentStartRow
++;
505 ConsoleInfo
->HistoryMode
.CursorRow
++;
508 case (CHAR_CARRIAGE_RETURN
):
510 // Move the cursor to the beginning of the current row.
512 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
516 // Acrtually print characters into the history buffer
519 PrintIndex
= ConsoleInfo
->HistoryMode
.CursorRow
* ConsoleInfo
->ColsPerScreen
+ ConsoleInfo
->HistoryMode
.CursorColumn
;
521 for ( // no initializer needed
522 ; ConsoleInfo
->HistoryMode
.CursorColumn
< (INT32
) ConsoleInfo
->ColsPerScreen
523 ; ConsoleInfo
->HistoryMode
.CursorColumn
++
527 if (*Walker
== CHAR_NULL
528 ||*Walker
== CHAR_BACKSPACE
529 ||*Walker
== CHAR_LINEFEED
530 ||*Walker
== CHAR_CARRIAGE_RETURN
536 // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
539 ASSERT(PrintIndex
+ ConsoleInfo
->HistoryMode
.CursorRow
< ConsoleInfo
->BufferSize
);
540 ConsoleInfo
->Buffer
[PrintIndex
+ (2*ConsoleInfo
->HistoryMode
.CursorRow
)] = *Walker
;
541 ASSERT(PrintIndex
< ConsoleInfo
->AttribSize
);
542 ConsoleInfo
->Attributes
[PrintIndex
] = ConsoleInfo
->HistoryMode
.Attribute
;
546 // Add the carriage return and line feed at the end of the lines
548 if (ConsoleInfo
->HistoryMode
.CursorColumn
>= (INT32
)ConsoleInfo
->ColsPerScreen
) {
549 AppendStringToHistory(L
"\r\n", ConsoleInfo
);
554 } // switch for character
557 return (EFI_SUCCESS
);
561 Worker function to handle printing the output to the screen
562 and the history buffer
564 @param[in] String The string to output
565 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
567 @retval EFI_SUCCESS The string was printed
568 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
570 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
572 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
573 characters in the Unicode string could not be
574 rendered and were skipped.
578 ConsoleLoggerOutputStringSplit(
579 IN CONST CHAR16
*String
,
580 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
586 // Forward the request to the original ConOut
588 Status
= ConsoleInfo
->OldConOut
->OutputString (ConsoleInfo
->OldConOut
, (CHAR16
*)String
);
590 if (EFI_ERROR(Status
)) {
594 return (AppendStringToHistory(String
, ConsoleInfo
));
598 Function to handle page break mode.
600 This function will prompt for continue or break.
602 @retval EFI_SUCCESS Continue was choosen
603 @return other Break was choosen
607 ConsoleLoggerDoPageBreak(
611 SHELL_PROMPT_RESPONSE
*Resp
;
615 ASSERT(ShellInfoObject
.PageBreakEnabled
);
616 ShellInfoObject
.PageBreakEnabled
= FALSE
;
617 Status
= ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue
, STRING_TOKEN(STR_SHELL_QUIT_CONT
), ShellInfoObject
.HiiHandle
, (VOID
**)&Resp
);
618 ShellInfoObject
.PageBreakEnabled
= TRUE
;
619 ASSERT(Resp
!= NULL
);
621 return (EFI_NOT_FOUND
);
623 if (EFI_ERROR(Status
)) {
629 if (*Resp
== ShellPromptResponseContinue
) {
631 ShellInfoObject
.ConsoleInfo
->RowCounter
= 0;
632 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorRow = 0;
633 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorColumn = 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(
663 IN CONST CHAR16
*String
,
664 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
667 CONST CHAR16
*Walker
;
668 CONST CHAR16
*LineStart
;
673 StringCopy
= StrnCatGrow(&StringCopy
, NULL
, String
, 0);
674 if (StringCopy
== NULL
) {
675 return (EFI_OUT_OF_RESOURCES
);
678 for ( Walker
= StringCopy
679 , LineStart
= StringCopy
680 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
684 case (CHAR_BACKSPACE
):
685 if (ConsoleInfo
->OurConOut
.Mode
->CursorColumn
> 0) {
686 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
--;
689 case (CHAR_LINEFEED
):
691 // add a temp NULL terminator
693 TempChar
= *(Walker
+ 1);
694 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
699 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
702 // restore the temp NULL terminator to it's original character
704 *((CHAR16
*)(Walker
+1)) = TempChar
;
707 // Update LineStart Variable
709 LineStart
= Walker
+ 1;
712 // increment row count
714 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
715 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
718 case (CHAR_CARRIAGE_RETURN
):
720 // Move the cursor to the beginning of the current row.
722 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
726 // increment column count
728 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
++;
730 // check if that is the last column
732 if ((INTN
)ConsoleInfo
->ColsPerScreen
== ConsoleInfo
->OurConOut
.Mode
->CursorColumn
- 1) {
734 // output a line similar to the linefeed character.
738 // add a temp NULL terminator
740 TempChar
= *(Walker
+ 1);
741 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
746 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
749 // restore the temp NULL terminator to it's original character
751 *((CHAR16
*)(Walker
+1)) = TempChar
;
754 // Update LineStart Variable
759 // increment row count and zero the column
761 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
762 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
763 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
764 } // last column on line
766 } // switch for character
769 // check if that was the last printable row. If yes handle PageBreak mode
771 if ((ConsoleInfo
->RowsPerScreen
) -1 == ShellInfoObject
.ConsoleInfo
->RowCounter
) {
772 if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
774 // We got an error which means 'break' and halt the printing
776 SHELL_FREE_NON_NULL(StringCopy
);
777 return (EFI_DEVICE_ERROR
);
782 if (LineStart
!= NULL
&& *LineStart
!= CHAR_NULL
) {
783 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
786 SHELL_FREE_NON_NULL(StringCopy
);
787 return (EFI_SUCCESS
);
791 Write a Unicode string to the output device.
793 @param[in] This Protocol instance pointer.
794 @param[in] WString The NULL-terminated Unicode string to be displayed on the output
795 device(s). All output devices must also support the Unicode
796 drawing defined in this file.
797 @retval EFI_SUCCESS The string was output to the device.
798 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
800 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
802 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
803 characters in the Unicode string could not be
804 rendered and were skipped.
808 ConsoleLoggerOutputString (
809 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
813 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
814 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
815 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
816 return (EFI_UNSUPPORTED
);
818 ASSERT(ShellInfoObject
.ConsoleInfo
== ConsoleInfo
);
819 if (!ShellInfoObject
.ConsoleInfo
->Enabled
) {
820 return (EFI_DEVICE_ERROR
);
821 } else if (ShellInfoObject
.PageBreakEnabled
) {
822 return (ConsoleLoggerPrintWithPageBreak(WString
, ConsoleInfo
));
824 return (ConsoleLoggerOutputStringSplit(WString
, ConsoleInfo
));
829 Verifies that all characters in a Unicode string can be output to the
832 @param[in] This Protocol instance pointer.
833 @param[in] WString The NULL-terminated Unicode string to be examined for the output
836 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
837 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
838 rendered by one or more of the output devices mapped
844 ConsoleLoggerTestString (
845 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
849 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
850 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
852 // Forward the request to the original ConOut
854 return (ConsoleInfo
->OldConOut
->TestString (ConsoleInfo
->OldConOut
, WString
));
858 Returns information for an available text mode that the output device(s)
861 @param[in] This Protocol instance pointer.
862 @param[in] ModeNumber The mode number to return information on.
863 @param[out] Columns Upon return, the number of columns in the selected geometry
864 @param[out] Rows Upon return, the number of rows in the selected geometry
866 @retval EFI_SUCCESS The requested mode information was returned.
867 @retval EFI_DEVICE_ERROR The device had an error and could not
868 complete the request.
869 @retval EFI_UNSUPPORTED The mode number was not valid.
873 ConsoleLoggerQueryMode (
874 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
880 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
881 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
883 // Forward the request to the original ConOut
885 return (ConsoleInfo
->OldConOut
->QueryMode (
886 ConsoleInfo
->OldConOut
,
894 Sets the output device(s) to a specified mode.
896 @param[in] This Protocol instance pointer.
897 @param[in] ModeNumber The mode number to set.
900 @retval EFI_SUCCESS The requested text mode was set.
901 @retval EFI_DEVICE_ERROR The device had an error and
902 could not complete the request.
903 @retval EFI_UNSUPPORTED The mode number was not valid.
907 ConsoleLoggerSetMode (
908 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
914 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
915 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
918 // Forward the request to the original ConOut
920 Status
= ConsoleInfo
->OldConOut
->SetMode (ConsoleInfo
->OldConOut
, ModeNumber
);
923 // Check that the buffers are still correct for logging
925 if (!EFI_ERROR (Status
)) {
926 ConsoleInfo
->OurConOut
.Mode
= gST
->ConOut
->Mode
;
927 ConsoleLoggerResetBuffers(ConsoleInfo
);
934 Sets the background and foreground colors for the OutputString () and
935 ClearScreen () functions.
937 @param[in] This Protocol instance pointer.
938 @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
939 bits 4..6 are the background color. All other bits are undefined
940 and must be zero. The valid Attributes are defined in this file.
942 @retval EFI_SUCCESS The attribute was set.
943 @retval EFI_DEVICE_ERROR The device had an error and
944 could not complete the request.
945 @retval EFI_UNSUPPORTED The attribute requested is not defined.
950 ConsoleLoggerSetAttribute (
951 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
957 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
958 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
961 // Forward the request to the original ConOut
963 Status
= ConsoleInfo
->OldConOut
->SetAttribute (ConsoleInfo
->OldConOut
, Attribute
);
966 // Record console output history
968 if (!EFI_ERROR (Status
)) {
969 ConsoleInfo
->HistoryMode
.Attribute
= (INT32
) Attribute
;
976 Clears the output device(s) display to the currently selected background
979 @param[in] This Protocol instance pointer.
981 @retval EFI_SUCCESS The operation completed successfully.
982 @retval EFI_DEVICE_ERROR The device had an error and
983 could not complete the request.
984 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
988 ConsoleLoggerClearScreen (
989 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
997 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
999 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
1000 return (EFI_UNSUPPORTED
);
1003 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1006 // Forward the request to the original ConOut
1008 Status
= ConsoleInfo
->OldConOut
->ClearScreen (ConsoleInfo
->OldConOut
);
1011 // Record console output history
1013 if (!EFI_ERROR (Status
)) {
1014 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 1) * ConsoleInfo
->CurrentStartRow
];
1015 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
1016 for ( Row
= ConsoleInfo
->OriginalStartRow
1017 ; Row
< (ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)
1021 ; Column
< ConsoleInfo
->ColsPerScreen
1027 *Attributes
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
1030 // Skip the NULL on each column end in text buffer only
1034 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
1035 ConsoleInfo
->HistoryMode
.CursorRow
= 0;
1042 Sets the current coordinates of the cursor position
1044 @param[in] This Protocol instance pointer.
1045 @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
1046 @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
1048 @retval EFI_SUCCESS The operation completed successfully.
1049 @retval EFI_DEVICE_ERROR The device had an error and
1050 could not complete the request.
1051 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
1052 cursor position is invalid for the current mode.
1056 ConsoleLoggerSetCursorPosition (
1057 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1063 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1065 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
1066 return (EFI_UNSUPPORTED
);
1069 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1071 // Forward the request to the original ConOut
1073 Status
= ConsoleInfo
->OldConOut
->SetCursorPosition (
1074 ConsoleInfo
->OldConOut
,
1080 // Record console output history
1082 if (!EFI_ERROR (Status
)) {
1083 ConsoleInfo
->HistoryMode
.CursorColumn
= (INT32
)Column
;
1084 ConsoleInfo
->HistoryMode
.CursorRow
= (INT32
)(ConsoleInfo
->OriginalStartRow
+ Row
);
1091 Makes the cursor visible or invisible
1093 @param[in] This Protocol instance pointer.
1094 @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
1095 set to be invisible.
1097 @retval EFI_SUCCESS The operation completed successfully.
1098 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1099 request, or the device does not support changing
1101 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1105 ConsoleLoggerEnableCursor (
1106 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1112 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1113 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1115 // Forward the request to the original ConOut
1117 Status
= ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, Visible
);
1120 // Record console output history
1122 if (!EFI_ERROR (Status
)) {
1123 ConsoleInfo
->HistoryMode
.CursorVisible
= Visible
;
1130 Function to update and verify that the current buffers are correct.
1132 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
1134 This will be used when a mode has changed or a reset ocurred to verify all
1139 ConsoleLoggerResetBuffers(
1140 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
1145 if (ConsoleInfo
->Buffer
!= NULL
) {
1146 FreePool(ConsoleInfo
->Buffer
);
1147 ConsoleInfo
->Buffer
= NULL
;
1148 ConsoleInfo
->BufferSize
= 0;
1150 if (ConsoleInfo
->Attributes
!= NULL
) {
1151 FreePool(ConsoleInfo
->Attributes
);
1152 ConsoleInfo
->Attributes
= NULL
;
1153 ConsoleInfo
->AttribSize
= 0;
1156 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &ConsoleInfo
->ColsPerScreen
, &ConsoleInfo
->RowsPerScreen
);
1157 if (EFI_ERROR(Status
)){
1161 ConsoleInfo
->BufferSize
= (ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Buffer
[0]);
1162 ConsoleInfo
->AttribSize
= ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Attributes
[0]);
1164 ConsoleInfo
->Buffer
= (CHAR16
*)AllocateZeroPool(ConsoleInfo
->BufferSize
);
1166 if (ConsoleInfo
->Buffer
== NULL
) {
1167 return (EFI_OUT_OF_RESOURCES
);
1170 ConsoleInfo
->Attributes
= (INT32
*)AllocateZeroPool(ConsoleInfo
->AttribSize
);
1171 if (ConsoleInfo
->Attributes
== NULL
) {
1172 FreePool(ConsoleInfo
->Buffer
);
1173 ConsoleInfo
->Buffer
= NULL
;
1174 return (EFI_OUT_OF_RESOURCES
);
1177 CopyMem (&ConsoleInfo
->HistoryMode
, ConsoleInfo
->OldConOut
->Mode
, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE
));
1179 return (EFI_SUCCESS
);