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
)) {
82 Status
= gBS
->InstallProtocolInterface(&gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, EFI_NATIVE_INTERFACE
, (VOID
*)&((*ConsoleInfo
)->OurConOut
));
84 (*ConsoleInfo
)->OldConOut
= gST
->ConOut
;
85 (*ConsoleInfo
)->OldConHandle
= gST
->ConsoleOutHandle
;
87 gST
->ConsoleOutHandle
= gImageHandle
;
88 gST
->ConOut
= &(*ConsoleInfo
)->OurConOut
;
94 Return the system to the state it was before InstallConsoleLogger
97 @param[in,out] ConsoleInfo The object from the install function.
99 @retval EFI_SUCCESS The operation was successful
100 @return other The operation failed. This was from UninstallProtocolInterface.
104 ConsoleLoggerUninstall(
105 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
108 ASSERT(ConsoleInfo
!= NULL
);
109 ASSERT(ConsoleInfo
->OldConOut
!= NULL
);
111 if (ConsoleInfo
->Buffer
!= NULL
) {
112 FreePool(ConsoleInfo
->Buffer
);
113 DEBUG_CODE(ConsoleInfo
->Buffer
= NULL
;);
114 DEBUG_CODE(ConsoleInfo
->BufferSize
= 0;);
116 if (ConsoleInfo
->Attributes
!= NULL
) {
117 FreePool(ConsoleInfo
->Attributes
);
118 DEBUG_CODE(ConsoleInfo
->Attributes
= NULL
;);
119 DEBUG_CODE(ConsoleInfo
->AttribSize
= 0;);
122 gST
->ConsoleOutHandle
= ConsoleInfo
->OldConHandle
;
123 gST
->ConOut
= ConsoleInfo
->OldConOut
;
125 return (gBS
->UninstallProtocolInterface(gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, (VOID
*)&ConsoleInfo
->OurConOut
));
129 Displays previously logged output back to the screen.
131 This will scroll the screen forwards and backwards through the log of previous
132 output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows
133 is (UINTN)(-1) then the size of the screen will be scrolled.
135 @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer).
136 If FALSE then the log will be displayed backwards (scroll to older).
137 @param[in] Rows Determines how many rows the log should scroll.
138 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
142 ConsoleLoggerDisplayHistory(
143 IN CONST BOOLEAN Forward
,
145 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
150 ASSERT(ConsoleInfo
!= NULL
);
153 // Calculate the row number change
157 RowChange
= ConsoleInfo
->RowsPerScreen
;
160 RowChange
= ConsoleInfo
->RowsPerScreen
/ 2;
168 // Do the math for direction
171 if ((ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
) < RowChange
) {
172 RowChange
= ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
;
175 if (ConsoleInfo
->CurrentStartRow
< RowChange
) {
176 RowChange
= ConsoleInfo
->CurrentStartRow
;
181 // If we are already at one end or the other
183 if (RowChange
== 0) {
184 return (EFI_SUCCESS
);
190 ConsoleInfo
->OldConOut
->ClearScreen(ConsoleInfo
->OldConOut
);
193 // Set the new start row
196 ConsoleInfo
->CurrentStartRow
+= RowChange
;
198 ConsoleInfo
->CurrentStartRow
-= RowChange
;
204 return (UpdateDisplayFromHistory(ConsoleInfo
));
208 Function to return to normal output whent he scrolling is complete.
209 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
211 @retval EFI_SUCCESS The operation was successful.
212 @return other The operation failed. See UpdateDisplayFromHistory.
214 @sa UpdateDisplayFromHistory
218 ConsoleLoggerStopHistory(
219 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
222 ASSERT(ConsoleInfo
!= NULL
);
223 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
224 return (EFI_SUCCESS
);
226 ConsoleInfo
->CurrentStartRow
= ConsoleInfo
->OriginalStartRow
;
227 return (UpdateDisplayFromHistory(ConsoleInfo
));
231 Updates the hidden ConOut to be displaying the correct stuff.
232 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
234 @retval EFI_SUCCESS The operation was successful.
235 @return other The operation failed.
239 UpdateDisplayFromHistory(
240 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
248 CHAR16 TempCharHolder
;
252 CHAR16
*StringSegment
;
253 CHAR16
*StringSegmentEnd
;
254 CHAR16 StringSegmentEndChar
;
256 ASSERT(ConsoleInfo
!= NULL
);
257 TempCharHolder
= CHAR_NULL
;
258 RetVal
= EFI_SUCCESS
;
261 // Disable cursor visibility and move it to the top left corner
263 ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, FALSE
);
264 ConsoleInfo
->OldConOut
->SetCursorPosition (ConsoleInfo
->OldConOut
, 0, 0);
266 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
267 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
269 ; CurrentRow
< ConsoleInfo
->RowsPerScreen
271 , Screen
+= (ConsoleInfo
->ColsPerScreen
+ 2)
272 , Attributes
+= ConsoleInfo
->ColsPerScreen
275 // dont use the last char - prevents screen scroll
277 if (CurrentRow
== (ConsoleInfo
->RowsPerScreen
-1)){
278 TempCharHolder
= Screen
[ConsoleInfo
->ColsPerScreen
- 1];
279 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = CHAR_NULL
;
283 ; Column
< ConsoleInfo
->ColsPerScreen
286 if (Screen
[Column
] != CHAR_NULL
) {
287 CurrentAttrib
= Attributes
[Column
];
288 CurrentColumn
= Column
;
289 StringSegment
= &Screen
[Column
];
292 // Find the first char with a different arrribute and make that temporarily NULL
293 // so we can do fewer printout statements. (later) restore that one and we will
294 // start at that collumn on the next loop.
296 StringSegmentEndChar
= CHAR_NULL
;
297 for ( StringSegmentEnd
= StringSegment
298 ; StringSegmentEnd
!= CHAR_NULL
302 if (Attributes
[Column
] != CurrentAttrib
) {
303 StringSegmentEndChar
= *StringSegmentEnd
;
304 *StringSegmentEnd
= CHAR_NULL
;
307 } // StringSegmentEnd loop
310 // Now write out as much as had the same Attributes
313 ConsoleInfo
->OldConOut
->SetAttribute(ConsoleInfo
->OldConOut
, CurrentAttrib
);
314 ConsoleInfo
->OldConOut
->SetCursorPosition(ConsoleInfo
->OldConOut
, CurrentColumn
, CurrentRow
);
315 Status
= ConsoleInfo
->OldConOut
->OutputString(ConsoleInfo
->OldConOut
, StringSegment
);
317 if (EFI_ERROR(Status
)) {
323 // If we found a change in attribute put the character back and decrement the column
324 // so when it increments it will point at that character and we will start printing
325 // a segment with that new attribute
327 if (StringSegmentEndChar
!= CHAR_NULL
) {
328 *StringSegmentEnd
= StringSegmentEndChar
;
329 StringSegmentEndChar
= CHAR_NULL
;
336 // If we removed the last char and this was the last row put it back
338 if (TempCharHolder
!= CHAR_NULL
) {
339 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = TempCharHolder
;
340 TempCharHolder
= CHAR_NULL
;
345 // If we are setting the screen back to original turn on the cursor and make it visible
346 // and set the attributes back to what they were
348 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
349 ConsoleInfo
->OldConOut
->SetAttribute (
350 ConsoleInfo
->OldConOut
,
351 ConsoleInfo
->HistoryMode
.Attribute
353 ConsoleInfo
->OldConOut
->SetCursorPosition (
354 ConsoleInfo
->OldConOut
,
355 ConsoleInfo
->HistoryMode
.CursorColumn
,
356 ConsoleInfo
->HistoryMode
.CursorRow
- ConsoleInfo
->OriginalStartRow
359 Status
= ConsoleInfo
->OldConOut
->EnableCursor (
360 ConsoleInfo
->OldConOut
,
361 ConsoleInfo
->HistoryMode
.CursorVisible
363 if (EFI_ERROR (Status
)) {
372 Reset the text output device hardware and optionaly run diagnostics
374 @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
375 @param ExtendedVerification Indicates that a more extensive test may be performed
377 @retval EFI_SUCCESS The text output device was reset.
378 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
384 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
385 IN BOOLEAN ExtendedVerification
389 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
390 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
393 // Forward the request to the original ConOut
395 Status
= ConsoleInfo
->OldConOut
->Reset (ConsoleInfo
->OldConOut
, ExtendedVerification
);
398 // Check that the buffers are still correct for logging
400 if (!EFI_ERROR (Status
)) {
401 ConsoleLoggerResetBuffers(ConsoleInfo
);
408 Appends a string to the history buffer. If the buffer is full then the oldest
409 information in the buffer will be dropped. Information is added in a line by
410 line manner such that an empty line takes up just as much space as a full line.
412 @param[in] String String pointer to add.
413 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
417 AppendStringToHistory(
418 IN CONST CHAR16
*String
,
419 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
422 CONST CHAR16
*Walker
;
427 ASSERT(ConsoleInfo
!= NULL
);
429 for ( Walker
= String
430 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
434 case (CHAR_BACKSPACE
):
435 if (ConsoleInfo
->HistoryMode
.CursorColumn
> 0) {
436 ConsoleInfo
->HistoryMode
.CursorColumn
--;
439 case (CHAR_LINEFEED
):
440 if (ConsoleInfo
->HistoryMode
.CursorRow
>= (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1)) {
442 // Should never be bigger
444 ASSERT(ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1));
447 // scroll history attributes 'up' 1 row and set the last row to default attribute
449 CopySize
= ConsoleInfo
->ColsPerScreen
450 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
451 * sizeof(ConsoleInfo
->Attributes
[0]);
452 ASSERT(CopySize
< ConsoleInfo
->AttribSize
);
454 ConsoleInfo
->Attributes
,
455 ConsoleInfo
->Attributes
+ ConsoleInfo
->ColsPerScreen
,
460 ; Index
< ConsoleInfo
->ColsPerScreen
463 *(ConsoleInfo
->Attributes
+ (CopySize
/sizeof(ConsoleInfo
->Attributes
)) + Index
) = ConsoleInfo
->HistoryMode
.Attribute
;
467 // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
469 CopySize
= (ConsoleInfo
->ColsPerScreen
+ 2)
470 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
471 * sizeof(ConsoleInfo
->Buffer
[0]);
472 ASSERT(CopySize
< ConsoleInfo
->BufferSize
);
475 ConsoleInfo
->Buffer
+ (ConsoleInfo
->ColsPerScreen
+ 2),
480 // Set that last row of chars to spaces
482 SetMem16(((UINT8
*)ConsoleInfo
->Buffer
)+CopySize
, ConsoleInfo
->ColsPerScreen
*sizeof(CHAR16
), L
' ');
485 // we are not on the last row
489 // We should not be scrolling history
491 ASSERT (ConsoleInfo
->OriginalStartRow
== ConsoleInfo
->CurrentStartRow
);
493 // are we at the end of a row?
495 if (ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
) (ConsoleInfo
->OriginalStartRow
+ ConsoleInfo
->RowsPerScreen
- 1)) {
496 ConsoleInfo
->OriginalStartRow
++;
497 ConsoleInfo
->CurrentStartRow
++;
499 ConsoleInfo
->HistoryMode
.CursorRow
++;
502 case (CHAR_CARRIAGE_RETURN
):
504 // Move the cursor to the beginning of the current row.
506 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
510 // Acrtually print characters into the history buffer
513 PrintIndex
= ConsoleInfo
->HistoryMode
.CursorRow
* ConsoleInfo
->ColsPerScreen
+ ConsoleInfo
->HistoryMode
.CursorColumn
;
515 for ( // no initializer needed
516 ; ConsoleInfo
->HistoryMode
.CursorColumn
< (INT32
) ConsoleInfo
->ColsPerScreen
517 ; ConsoleInfo
->HistoryMode
.CursorColumn
++
521 if (*Walker
== CHAR_NULL
522 ||*Walker
== CHAR_BACKSPACE
523 ||*Walker
== CHAR_LINEFEED
524 ||*Walker
== CHAR_CARRIAGE_RETURN
530 // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
533 ASSERT(PrintIndex
+ ConsoleInfo
->HistoryMode
.CursorRow
< ConsoleInfo
->BufferSize
);
534 ConsoleInfo
->Buffer
[PrintIndex
+ (2*ConsoleInfo
->HistoryMode
.CursorRow
)] = *Walker
;
535 ASSERT(PrintIndex
< ConsoleInfo
->AttribSize
);
536 ConsoleInfo
->Attributes
[PrintIndex
] = ConsoleInfo
->HistoryMode
.Attribute
;
540 // Add the carriage return and line feed at the end of the lines
542 if (ConsoleInfo
->HistoryMode
.CursorColumn
>= (INT32
)ConsoleInfo
->ColsPerScreen
) {
543 AppendStringToHistory(L
"\r\n", ConsoleInfo
);
548 } // switch for character
551 return (EFI_SUCCESS
);
555 Worker function to handle printing the output to the screen
556 and the history buffer
558 @param[in] String The string to output
559 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
561 @retval EFI_SUCCESS The string was printed
562 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
564 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
566 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
567 characters in the Unicode string could not be
568 rendered and were skipped.
572 ConsoleLoggerOutputStringSplit(
573 IN CONST CHAR16
*String
,
574 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
580 // Forward the request to the original ConOut
582 Status
= ConsoleInfo
->OldConOut
->OutputString (ConsoleInfo
->OldConOut
, (CHAR16
*)String
);
584 if (EFI_ERROR(Status
)) {
588 return (AppendStringToHistory(String
, ConsoleInfo
));
592 Function to handle page break mode.
594 This function will prompt for continue or break.
596 @retval EFI_SUCCESS Continue was choosen
597 @return other Break was choosen
601 ConsoleLoggerDoPageBreak(
605 SHELL_PROMPT_RESPONSE
*Resp
;
609 ASSERT(ShellInfoObject
.PageBreakEnabled
);
610 ShellInfoObject
.PageBreakEnabled
= FALSE
;
611 Status
= ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue
, STRING_TOKEN(STR_SHELL_QUIT_CONT
), ShellInfoObject
.HiiHandle
, (VOID
**)&Resp
);
612 ShellInfoObject
.PageBreakEnabled
= TRUE
;
613 ASSERT(Resp
!= NULL
);
615 return (EFI_NOT_FOUND
);
617 if (EFI_ERROR(Status
)) {
623 if (*Resp
== ShellPromptResponseContinue
) {
625 ShellInfoObject
.ConsoleInfo
->RowCounter
= 0;
626 return (EFI_SUCCESS
);
627 } else if (*Resp
== ShellPromptResponseQuit
) {
629 ShellInfoObject
.ConsoleInfo
->Enabled
= FALSE
;
630 return (EFI_DEVICE_ERROR
);
634 return (EFI_SUCCESS
);
637 Worker function to handle printing the output with page breaks.
639 @param[in] String The string to output
640 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
642 @retval EFI_SUCCESS The string was printed
643 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
645 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
647 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
648 characters in the Unicode string could not be
649 rendered and were skipped.
653 ConsoleLoggerPrintWithPageBreak(
655 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
658 CONST CHAR16
*Walker
;
659 CONST CHAR16
*LineStart
;
662 for ( Walker
= String
664 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
668 case (CHAR_BACKSPACE
):
669 if (ConsoleInfo
->OurConOut
.Mode
->CursorColumn
> 0) {
670 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
--;
673 case (CHAR_LINEFEED
):
675 // add a temp NULL terminator
677 TempChar
= *(Walker
+ 1);
678 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
683 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
686 // restore the temp NULL terminator to it's original character
688 *((CHAR16
*)(Walker
+1)) = TempChar
;
691 // Update LineStart Variable
693 LineStart
= Walker
+ 1;
696 // increment row count
698 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
699 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
702 case (CHAR_CARRIAGE_RETURN
):
704 // Move the cursor to the beginning of the current row.
706 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
710 // increment column count
712 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
++;
714 // check if that is the last column
716 if ((INTN
)ConsoleInfo
->ColsPerScreen
== ConsoleInfo
->OurConOut
.Mode
->CursorColumn
- 1) {
718 // output a line similar to the linefeed character.
722 // add a temp NULL terminator
724 TempChar
= *(Walker
+ 1);
725 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
730 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
733 // restore the temp NULL terminator to it's original character
735 *((CHAR16
*)(Walker
+1)) = TempChar
;
738 // Update LineStart Variable
743 // increment row count and zero the column
745 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
746 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
747 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
748 } // last column on line
750 } // switch for character
753 // check if that was the last printable row. If yes handle PageBreak mode
755 if ((ConsoleInfo
->RowsPerScreen
) -1 == ShellInfoObject
.ConsoleInfo
->RowCounter
) {
756 if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
758 // We got an error which means 'break' and halt the printing
760 return (EFI_DEVICE_ERROR
);
765 if (LineStart
!= NULL
&& *LineStart
!= CHAR_NULL
) {
766 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
769 return (EFI_SUCCESS
);
773 Write a Unicode string to the output device.
775 @param[in] This Protocol instance pointer.
776 @param[in] WString The NULL-terminated Unicode string to be displayed on the output
777 device(s). All output devices must also support the Unicode
778 drawing defined in this file.
779 @retval EFI_SUCCESS The string was output to the device.
780 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
782 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
784 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
785 characters in the Unicode string could not be
786 rendered and were skipped.
790 ConsoleLoggerOutputString (
791 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
795 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
796 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
797 ASSERT(ShellInfoObject
.ConsoleInfo
== ConsoleInfo
);
798 if (!ShellInfoObject
.ConsoleInfo
->Enabled
) {
799 return (EFI_DEVICE_ERROR
);
800 } else if (ShellInfoObject
.PageBreakEnabled
) {
801 return (ConsoleLoggerPrintWithPageBreak(WString
, ConsoleInfo
));
803 return (ConsoleLoggerOutputStringSplit(WString
, ConsoleInfo
));
808 Verifies that all characters in a Unicode string can be output to the
811 @param[in] This Protocol instance pointer.
812 @param[in] WString The NULL-terminated Unicode string to be examined for the output
815 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
816 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
817 rendered by one or more of the output devices mapped
823 ConsoleLoggerTestString (
824 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
828 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
829 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
831 // Forward the request to the original ConOut
833 return (ConsoleInfo
->OldConOut
->TestString (ConsoleInfo
->OldConOut
, WString
));
837 Returns information for an available text mode that the output device(s)
840 @param[in] This Protocol instance pointer.
841 @param[in] ModeNumber The mode number to return information on.
842 @param[out] Columns Upon return, the number of columns in the selected geometry
843 @param[out] Rows Upon return, the number of rows in the selected geometry
845 @retval EFI_SUCCESS The requested mode information was returned.
846 @retval EFI_DEVICE_ERROR The device had an error and could not
847 complete the request.
848 @retval EFI_UNSUPPORTED The mode number was not valid.
852 ConsoleLoggerQueryMode (
853 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
859 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
860 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
862 // Forward the request to the original ConOut
864 return (ConsoleInfo
->OldConOut
->QueryMode (
865 ConsoleInfo
->OldConOut
,
873 Sets the output device(s) to a specified mode.
875 @param[in] This Protocol instance pointer.
876 @param[in] ModeNumber The mode number to set.
879 @retval EFI_SUCCESS The requested text mode was set.
880 @retval EFI_DEVICE_ERROR The device had an error and
881 could not complete the request.
882 @retval EFI_UNSUPPORTED The mode number was not valid.
886 ConsoleLoggerSetMode (
887 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
893 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
894 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
897 // Forward the request to the original ConOut
899 Status
= ConsoleInfo
->OldConOut
->SetMode (ConsoleInfo
->OldConOut
, ModeNumber
);
902 // Check that the buffers are still correct for logging
904 if (!EFI_ERROR (Status
)) {
905 ConsoleLoggerResetBuffers(ConsoleInfo
);
912 Sets the background and foreground colors for the OutputString () and
913 ClearScreen () functions.
915 @param[in] This Protocol instance pointer.
916 @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
917 bits 4..6 are the background color. All other bits are undefined
918 and must be zero. The valid Attributes are defined in this file.
920 @retval EFI_SUCCESS The attribute was set.
921 @retval EFI_DEVICE_ERROR The device had an error and
922 could not complete the request.
923 @retval EFI_UNSUPPORTED The attribute requested is not defined.
928 ConsoleLoggerSetAttribute (
929 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
935 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
936 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
939 // Forward the request to the original ConOut
941 Status
= ConsoleInfo
->OldConOut
->SetAttribute (ConsoleInfo
->OldConOut
, Attribute
);
944 // Record console output history
946 if (!EFI_ERROR (Status
)) {
947 ConsoleInfo
->HistoryMode
.Attribute
= (INT32
) Attribute
;
954 Clears the output device(s) display to the currently selected background
957 @param[in] This Protocol instance pointer.
959 @retval EFI_SUCCESS The operation completed successfully.
960 @retval EFI_DEVICE_ERROR The device had an error and
961 could not complete the request.
962 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
966 ConsoleLoggerClearScreen (
967 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
977 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
978 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
981 // Forward the request to the original ConOut
983 Status
= ConsoleInfo
->OldConOut
->ClearScreen (ConsoleInfo
->OldConOut
);
986 // Record console output history
988 if (!EFI_ERROR (Status
)) {
989 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 1) * ConsoleInfo
->CurrentStartRow
];
990 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
991 for ( Row
= ConsoleInfo
->OriginalStartRow
992 ; Row
< (ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)
996 ; Column
< ConsoleInfo
->ColsPerScreen
1002 *Attributes
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
1005 // Skip the NULL on each column end in text buffer only
1009 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
1010 ConsoleInfo
->HistoryMode
.CursorRow
= 0;
1017 Sets the current coordinates of the cursor position
1019 @param[in] This Protocol instance pointer.
1020 @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
1021 @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
1023 @retval EFI_SUCCESS The operation completed successfully.
1024 @retval EFI_DEVICE_ERROR The device had an error and
1025 could not complete the request.
1026 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
1027 cursor position is invalid for the current mode.
1031 ConsoleLoggerSetCursorPosition (
1032 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1039 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1040 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1042 // Forward the request to the original ConOut
1044 Status
= ConsoleInfo
->OldConOut
->SetCursorPosition (
1045 ConsoleInfo
->OldConOut
,
1051 // Record console output history
1053 if (!EFI_ERROR (Status
)) {
1054 ConsoleInfo
->HistoryMode
.CursorColumn
= (INT32
)Column
;
1055 ConsoleInfo
->HistoryMode
.CursorRow
= (INT32
)(ConsoleInfo
->OriginalStartRow
+ Row
);
1062 Makes the cursor visible or invisible
1064 @param[in] This Protocol instance pointer.
1065 @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
1066 set to be invisible.
1068 @retval EFI_SUCCESS The operation completed successfully.
1069 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1070 request, or the device does not support changing
1072 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1076 ConsoleLoggerEnableCursor (
1077 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1083 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1084 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1086 // Forward the request to the original ConOut
1088 Status
= ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, Visible
);
1091 // Record console output history
1093 if (!EFI_ERROR (Status
)) {
1094 ConsoleInfo
->HistoryMode
.CursorVisible
= Visible
;
1101 Function to update and verify that the current buffers are correct.
1103 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
1105 This will be used when a mode has changed or a reset ocurred to verify all
1110 ConsoleLoggerResetBuffers(
1111 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
1116 if (ConsoleInfo
->Buffer
!= NULL
) {
1117 FreePool(ConsoleInfo
->Buffer
);
1118 ConsoleInfo
->Buffer
= NULL
;
1119 ConsoleInfo
->BufferSize
= 0;
1121 if (ConsoleInfo
->Attributes
!= NULL
) {
1122 FreePool(ConsoleInfo
->Attributes
);
1123 ConsoleInfo
->Attributes
= NULL
;
1124 ConsoleInfo
->AttribSize
= 0;
1127 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &ConsoleInfo
->ColsPerScreen
, &ConsoleInfo
->RowsPerScreen
);
1128 if (EFI_ERROR(Status
)){
1132 ConsoleInfo
->BufferSize
= (ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Buffer
[0]);
1133 ConsoleInfo
->AttribSize
= ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Attributes
[0]);
1135 ConsoleInfo
->Buffer
= (CHAR16
*)AllocateZeroPool(ConsoleInfo
->BufferSize
);
1137 if (ConsoleInfo
->Buffer
== NULL
) {
1138 return (EFI_OUT_OF_RESOURCES
);
1141 ConsoleInfo
->Attributes
= (INT32
*)AllocateZeroPool(ConsoleInfo
->AttribSize
);
1142 if (ConsoleInfo
->Attributes
== NULL
) {
1143 FreePool(ConsoleInfo
->Buffer
);
1144 ConsoleInfo
->Buffer
= NULL
;
1145 return (EFI_OUT_OF_RESOURCES
);
1148 ConsoleInfo
->OurConOut
.Mode
= gST
->ConOut
->Mode
;
1149 ConsoleInfo
->OldConOut
= gST
->ConOut
;
1150 CopyMem (&ConsoleInfo
->HistoryMode
, ConsoleInfo
->OldConOut
->Mode
, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE
));
1152 return (EFI_SUCCESS
);