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
;
263 ASSERT(ConsoleInfo
!= NULL
);
264 TempCharHolder
= CHAR_NULL
;
265 RetVal
= EFI_SUCCESS
;
266 OrigAttribute
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
269 // Disable cursor visibility and move it to the top left corner
271 ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, FALSE
);
272 ConsoleInfo
->OldConOut
->SetCursorPosition (ConsoleInfo
->OldConOut
, 0, 0);
274 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
275 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
277 ; CurrentRow
< ConsoleInfo
->RowsPerScreen
279 , Screen
+= (ConsoleInfo
->ColsPerScreen
+ 2)
280 , Attributes
+= ConsoleInfo
->ColsPerScreen
283 // dont use the last char - prevents screen scroll
285 if (CurrentRow
== (ConsoleInfo
->RowsPerScreen
-1)){
286 TempCharHolder
= Screen
[ConsoleInfo
->ColsPerScreen
- 1];
287 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = CHAR_NULL
;
291 ; Column
< ConsoleInfo
->ColsPerScreen
294 if (Screen
[Column
] != CHAR_NULL
) {
295 CurrentAttrib
= Attributes
[Column
];
296 CurrentColumn
= Column
;
297 StringSegment
= &Screen
[Column
];
300 // Find the first char with a different arrribute and make that temporarily NULL
301 // so we can do fewer printout statements. (later) restore that one and we will
302 // start at that collumn on the next loop.
304 StringSegmentEndChar
= CHAR_NULL
;
305 for ( StringSegmentEnd
= StringSegment
306 ; StringSegmentEnd
!= CHAR_NULL
310 if (Attributes
[Column
] != CurrentAttrib
) {
311 StringSegmentEndChar
= *StringSegmentEnd
;
312 *StringSegmentEnd
= CHAR_NULL
;
315 } // StringSegmentEnd loop
318 // Now write out as much as had the same Attributes
321 ConsoleInfo
->OldConOut
->SetAttribute(ConsoleInfo
->OldConOut
, CurrentAttrib
);
322 ConsoleInfo
->OldConOut
->SetCursorPosition(ConsoleInfo
->OldConOut
, CurrentColumn
, CurrentRow
);
323 Status
= ConsoleInfo
->OldConOut
->OutputString(ConsoleInfo
->OldConOut
, StringSegment
);
325 if (EFI_ERROR(Status
)) {
331 // If we found a change in attribute put the character back and decrement the column
332 // so when it increments it will point at that character and we will start printing
333 // a segment with that new attribute
335 if (StringSegmentEndChar
!= CHAR_NULL
) {
336 *StringSegmentEnd
= StringSegmentEndChar
;
337 StringSegmentEndChar
= CHAR_NULL
;
344 // If we removed the last char and this was the last row put it back
346 if (TempCharHolder
!= CHAR_NULL
) {
347 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = TempCharHolder
;
348 TempCharHolder
= CHAR_NULL
;
353 // If we are setting the screen back to original turn on the cursor and make it visible
354 // and set the attributes back to what they were
356 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
357 ConsoleInfo
->OldConOut
->SetAttribute (
358 ConsoleInfo
->OldConOut
,
359 ConsoleInfo
->HistoryMode
.Attribute
361 ConsoleInfo
->OldConOut
->SetCursorPosition (
362 ConsoleInfo
->OldConOut
,
363 ConsoleInfo
->HistoryMode
.CursorColumn
,
364 ConsoleInfo
->HistoryMode
.CursorRow
- ConsoleInfo
->OriginalStartRow
367 Status
= ConsoleInfo
->OldConOut
->EnableCursor (
368 ConsoleInfo
->OldConOut
,
369 ConsoleInfo
->HistoryMode
.CursorVisible
371 if (EFI_ERROR (Status
)) {
375 ConsoleInfo
->OldConOut
->SetAttribute (
376 ConsoleInfo
->OldConOut
,
385 Reset the text output device hardware and optionaly run diagnostics
387 @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
388 @param ExtendedVerification Indicates that a more extensive test may be performed
390 @retval EFI_SUCCESS The text output device was reset.
391 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
397 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
398 IN BOOLEAN ExtendedVerification
402 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
403 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
406 // Forward the request to the original ConOut
408 Status
= ConsoleInfo
->OldConOut
->Reset (ConsoleInfo
->OldConOut
, ExtendedVerification
);
411 // Check that the buffers are still correct for logging
413 if (!EFI_ERROR (Status
)) {
414 ConsoleLoggerResetBuffers(ConsoleInfo
);
421 Appends a string to the history buffer. If the buffer is full then the oldest
422 information in the buffer will be dropped. Information is added in a line by
423 line manner such that an empty line takes up just as much space as a full line.
425 @param[in] String String pointer to add.
426 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
430 AppendStringToHistory(
431 IN CONST CHAR16
*String
,
432 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
435 CONST CHAR16
*Walker
;
440 ASSERT(ConsoleInfo
!= NULL
);
442 for ( Walker
= String
443 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
447 case (CHAR_BACKSPACE
):
448 if (ConsoleInfo
->HistoryMode
.CursorColumn
> 0) {
449 ConsoleInfo
->HistoryMode
.CursorColumn
--;
452 case (CHAR_LINEFEED
):
453 if (ConsoleInfo
->HistoryMode
.CursorRow
>= (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1)) {
455 // Should never be bigger
457 ASSERT(ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1));
460 // scroll history attributes 'up' 1 row and set the last row to default attribute
462 CopySize
= ConsoleInfo
->ColsPerScreen
463 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
464 * sizeof(ConsoleInfo
->Attributes
[0]);
465 ASSERT(CopySize
< ConsoleInfo
->AttribSize
);
467 ConsoleInfo
->Attributes
,
468 ConsoleInfo
->Attributes
+ ConsoleInfo
->ColsPerScreen
,
473 ; Index
< ConsoleInfo
->ColsPerScreen
476 *(ConsoleInfo
->Attributes
+ (CopySize
/sizeof(ConsoleInfo
->Attributes
[0])) + Index
) = ConsoleInfo
->HistoryMode
.Attribute
;
480 // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
482 CopySize
= (ConsoleInfo
->ColsPerScreen
+ 2)
483 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
484 * sizeof(ConsoleInfo
->Buffer
[0]);
485 ASSERT(CopySize
< ConsoleInfo
->BufferSize
);
488 ConsoleInfo
->Buffer
+ (ConsoleInfo
->ColsPerScreen
+ 2),
493 // Set that last row of chars to spaces
495 SetMem16(((UINT8
*)ConsoleInfo
->Buffer
)+CopySize
, ConsoleInfo
->ColsPerScreen
*sizeof(CHAR16
), L
' ');
498 // we are not on the last row
502 // We should not be scrolling history
504 ASSERT (ConsoleInfo
->OriginalStartRow
== ConsoleInfo
->CurrentStartRow
);
506 // are we at the end of a row?
508 if (ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
) (ConsoleInfo
->OriginalStartRow
+ ConsoleInfo
->RowsPerScreen
- 1)) {
509 ConsoleInfo
->OriginalStartRow
++;
510 ConsoleInfo
->CurrentStartRow
++;
512 ConsoleInfo
->HistoryMode
.CursorRow
++;
515 case (CHAR_CARRIAGE_RETURN
):
517 // Move the cursor to the beginning of the current row.
519 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
523 // Acrtually print characters into the history buffer
526 PrintIndex
= ConsoleInfo
->HistoryMode
.CursorRow
* ConsoleInfo
->ColsPerScreen
+ ConsoleInfo
->HistoryMode
.CursorColumn
;
528 for ( // no initializer needed
529 ; ConsoleInfo
->HistoryMode
.CursorColumn
< (INT32
) ConsoleInfo
->ColsPerScreen
530 ; ConsoleInfo
->HistoryMode
.CursorColumn
++
534 if (*Walker
== CHAR_NULL
535 ||*Walker
== CHAR_BACKSPACE
536 ||*Walker
== CHAR_LINEFEED
537 ||*Walker
== CHAR_CARRIAGE_RETURN
543 // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
546 ASSERT(PrintIndex
+ ConsoleInfo
->HistoryMode
.CursorRow
< ConsoleInfo
->BufferSize
);
547 ConsoleInfo
->Buffer
[PrintIndex
+ (2*ConsoleInfo
->HistoryMode
.CursorRow
)] = *Walker
;
548 ASSERT(PrintIndex
< ConsoleInfo
->AttribSize
);
549 ConsoleInfo
->Attributes
[PrintIndex
] = ConsoleInfo
->HistoryMode
.Attribute
;
553 // Add the carriage return and line feed at the end of the lines
555 if (ConsoleInfo
->HistoryMode
.CursorColumn
>= (INT32
)ConsoleInfo
->ColsPerScreen
) {
556 AppendStringToHistory(L
"\r\n", ConsoleInfo
);
561 } // switch for character
564 return (EFI_SUCCESS
);
568 Worker function to handle printing the output to the screen
569 and the history buffer
571 @param[in] String The string to output
572 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
574 @retval EFI_SUCCESS The string was printed
575 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
577 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
579 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
580 characters in the Unicode string could not be
581 rendered and were skipped.
585 ConsoleLoggerOutputStringSplit(
586 IN CONST CHAR16
*String
,
587 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
593 // Forward the request to the original ConOut
595 Status
= ConsoleInfo
->OldConOut
->OutputString (ConsoleInfo
->OldConOut
, (CHAR16
*)String
);
597 if (EFI_ERROR(Status
)) {
601 return (AppendStringToHistory(String
, ConsoleInfo
));
605 Function to handle page break mode.
607 This function will prompt for continue or break.
609 @retval EFI_SUCCESS Continue was choosen
610 @return other Break was choosen
614 ConsoleLoggerDoPageBreak(
618 SHELL_PROMPT_RESPONSE
*Resp
;
622 ASSERT(ShellInfoObject
.PageBreakEnabled
);
623 ShellInfoObject
.PageBreakEnabled
= FALSE
;
624 Status
= ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue
, STRING_TOKEN(STR_SHELL_QUIT_CONT
), ShellInfoObject
.HiiHandle
, (VOID
**)&Resp
);
625 ShellInfoObject
.PageBreakEnabled
= TRUE
;
626 ASSERT(Resp
!= NULL
);
628 return (EFI_NOT_FOUND
);
630 if (EFI_ERROR(Status
)) {
636 if (*Resp
== ShellPromptResponseContinue
) {
638 ShellInfoObject
.ConsoleInfo
->RowCounter
= 0;
639 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorRow = 0;
640 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
642 return (EFI_SUCCESS
);
643 } else if (*Resp
== ShellPromptResponseQuit
) {
645 ShellInfoObject
.ConsoleInfo
->Enabled
= FALSE
;
646 return (EFI_DEVICE_ERROR
);
650 return (EFI_SUCCESS
);
653 Worker function to handle printing the output with page breaks.
655 @param[in] String The string to output
656 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
658 @retval EFI_SUCCESS The string was printed
659 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
661 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
663 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
664 characters in the Unicode string could not be
665 rendered and were skipped.
669 ConsoleLoggerPrintWithPageBreak(
670 IN CONST CHAR16
*String
,
671 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
674 CONST CHAR16
*Walker
;
675 CONST CHAR16
*LineStart
;
680 StringCopy
= StrnCatGrow(&StringCopy
, NULL
, String
, 0);
681 if (StringCopy
== NULL
) {
682 return (EFI_OUT_OF_RESOURCES
);
685 for ( Walker
= StringCopy
686 , LineStart
= StringCopy
687 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
691 case (CHAR_BACKSPACE
):
692 if (ConsoleInfo
->OurConOut
.Mode
->CursorColumn
> 0) {
693 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
--;
696 case (CHAR_LINEFEED
):
698 // add a temp NULL terminator
700 TempChar
= *(Walker
+ 1);
701 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
706 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
709 // restore the temp NULL terminator to it's original character
711 *((CHAR16
*)(Walker
+1)) = TempChar
;
714 // Update LineStart Variable
716 LineStart
= Walker
+ 1;
719 // increment row count
721 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
722 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
725 case (CHAR_CARRIAGE_RETURN
):
727 // Move the cursor to the beginning of the current row.
729 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
733 // increment column count
735 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
++;
737 // check if that is the last column
739 if ((INTN
)ConsoleInfo
->ColsPerScreen
== ConsoleInfo
->OurConOut
.Mode
->CursorColumn
+ 1) {
741 // output a line similar to the linefeed character.
745 // add a temp NULL terminator
747 TempChar
= *(Walker
+ 1);
748 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
753 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
756 // restore the temp NULL terminator to it's original character
758 *((CHAR16
*)(Walker
+1)) = TempChar
;
761 // Update LineStart Variable
763 LineStart
= Walker
+ 1;
766 // increment row count and zero the column
768 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
769 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
770 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
771 } // last column on line
773 } // switch for character
776 // check if that was the last printable row. If yes handle PageBreak mode
778 if ((ConsoleInfo
->RowsPerScreen
) -1 == ShellInfoObject
.ConsoleInfo
->RowCounter
) {
779 if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
781 // We got an error which means 'break' and halt the printing
783 SHELL_FREE_NON_NULL(StringCopy
);
784 return (EFI_DEVICE_ERROR
);
789 if (LineStart
!= NULL
&& *LineStart
!= CHAR_NULL
) {
790 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
793 SHELL_FREE_NON_NULL(StringCopy
);
794 return (EFI_SUCCESS
);
798 Write a Unicode string to the output device.
800 @param[in] This Protocol instance pointer.
801 @param[in] WString The NULL-terminated Unicode string to be displayed on the output
802 device(s). All output devices must also support the Unicode
803 drawing defined in this file.
804 @retval EFI_SUCCESS The string was output to the device.
805 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
807 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
809 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
810 characters in the Unicode string could not be
811 rendered and were skipped.
815 ConsoleLoggerOutputString (
816 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
822 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
823 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
824 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
825 return (EFI_UNSUPPORTED
);
827 ASSERT(ShellInfoObject
.ConsoleInfo
== ConsoleInfo
);
828 if (ShellInfoObject
.HaltOutput
) {
832 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &EventIndex
);
833 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
834 ShellInfoObject
.HaltOutput
= FALSE
;
836 if (!ShellInfoObject
.ConsoleInfo
->Enabled
) {
837 return (EFI_DEVICE_ERROR
);
838 } else if (ShellInfoObject
.PageBreakEnabled
) {
839 return (ConsoleLoggerPrintWithPageBreak(WString
, ConsoleInfo
));
841 return (ConsoleLoggerOutputStringSplit(WString
, ConsoleInfo
));
846 Verifies that all characters in a Unicode string can be output to the
849 @param[in] This Protocol instance pointer.
850 @param[in] WString The NULL-terminated Unicode string to be examined for the output
853 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
854 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
855 rendered by one or more of the output devices mapped
861 ConsoleLoggerTestString (
862 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
866 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
867 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
869 // Forward the request to the original ConOut
871 return (ConsoleInfo
->OldConOut
->TestString (ConsoleInfo
->OldConOut
, WString
));
875 Returns information for an available text mode that the output device(s)
878 @param[in] This Protocol instance pointer.
879 @param[in] ModeNumber The mode number to return information on.
880 @param[out] Columns Upon return, the number of columns in the selected geometry
881 @param[out] Rows Upon return, the number of rows in the selected geometry
883 @retval EFI_SUCCESS The requested mode information was returned.
884 @retval EFI_DEVICE_ERROR The device had an error and could not
885 complete the request.
886 @retval EFI_UNSUPPORTED The mode number was not valid.
890 ConsoleLoggerQueryMode (
891 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
897 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
898 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
900 // Forward the request to the original ConOut
902 return (ConsoleInfo
->OldConOut
->QueryMode (
903 ConsoleInfo
->OldConOut
,
911 Sets the output device(s) to a specified mode.
913 @param[in] This Protocol instance pointer.
914 @param[in] ModeNumber The mode number to set.
917 @retval EFI_SUCCESS The requested text mode was set.
918 @retval EFI_DEVICE_ERROR The device had an error and
919 could not complete the request.
920 @retval EFI_UNSUPPORTED The mode number was not valid.
924 ConsoleLoggerSetMode (
925 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
931 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
932 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
935 // Forward the request to the original ConOut
937 Status
= ConsoleInfo
->OldConOut
->SetMode (ConsoleInfo
->OldConOut
, ModeNumber
);
940 // Check that the buffers are still correct for logging
942 if (!EFI_ERROR (Status
)) {
943 ConsoleInfo
->OurConOut
.Mode
= gST
->ConOut
->Mode
;
944 ConsoleLoggerResetBuffers(ConsoleInfo
);
951 Sets the background and foreground colors for the OutputString () and
952 ClearScreen () functions.
954 @param[in] This Protocol instance pointer.
955 @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
956 bits 4..6 are the background color. All other bits are undefined
957 and must be zero. The valid Attributes are defined in this file.
959 @retval EFI_SUCCESS The attribute was set.
960 @retval EFI_DEVICE_ERROR The device had an error and
961 could not complete the request.
962 @retval EFI_UNSUPPORTED The attribute requested is not defined.
967 ConsoleLoggerSetAttribute (
968 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
974 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
975 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
978 // Forward the request to the original ConOut
980 Status
= ConsoleInfo
->OldConOut
->SetAttribute (ConsoleInfo
->OldConOut
, Attribute
);
983 // Record console output history
985 if (!EFI_ERROR (Status
)) {
986 ConsoleInfo
->HistoryMode
.Attribute
= (INT32
) Attribute
;
993 Clears the output device(s) display to the currently selected background
996 @param[in] This Protocol instance pointer.
998 @retval EFI_SUCCESS The operation completed successfully.
999 @retval EFI_DEVICE_ERROR The device had an error and
1000 could not complete the request.
1001 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1005 ConsoleLoggerClearScreen (
1006 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
1014 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1016 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
1017 return (EFI_UNSUPPORTED
);
1020 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1023 // Forward the request to the original ConOut
1025 Status
= ConsoleInfo
->OldConOut
->ClearScreen (ConsoleInfo
->OldConOut
);
1028 // Record console output history
1030 if (!EFI_ERROR (Status
)) {
1031 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
1032 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
1033 for ( Row
= ConsoleInfo
->OriginalStartRow
1034 ; Row
< (ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)
1038 ; Column
< ConsoleInfo
->ColsPerScreen
1044 *Attributes
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
1047 // Skip the NULL on each column end in text buffer only
1051 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
1052 ConsoleInfo
->HistoryMode
.CursorRow
= 0;
1059 Sets the current coordinates of the cursor position
1061 @param[in] This Protocol instance pointer.
1062 @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
1063 @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
1065 @retval EFI_SUCCESS The operation completed successfully.
1066 @retval EFI_DEVICE_ERROR The device had an error and
1067 could not complete the request.
1068 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
1069 cursor position is invalid for the current mode.
1073 ConsoleLoggerSetCursorPosition (
1074 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1080 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1082 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
1083 return (EFI_UNSUPPORTED
);
1086 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1088 // Forward the request to the original ConOut
1090 Status
= ConsoleInfo
->OldConOut
->SetCursorPosition (
1091 ConsoleInfo
->OldConOut
,
1097 // Record console output history
1099 if (!EFI_ERROR (Status
)) {
1100 ConsoleInfo
->HistoryMode
.CursorColumn
= (INT32
)Column
;
1101 ConsoleInfo
->HistoryMode
.CursorRow
= (INT32
)(ConsoleInfo
->OriginalStartRow
+ Row
);
1108 Makes the cursor visible or invisible
1110 @param[in] This Protocol instance pointer.
1111 @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
1112 set to be invisible.
1114 @retval EFI_SUCCESS The operation completed successfully.
1115 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1116 request, or the device does not support changing
1118 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1122 ConsoleLoggerEnableCursor (
1123 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1129 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1130 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1132 // Forward the request to the original ConOut
1134 Status
= ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, Visible
);
1137 // Record console output history
1139 if (!EFI_ERROR (Status
)) {
1140 ConsoleInfo
->HistoryMode
.CursorVisible
= Visible
;
1147 Function to update and verify that the current buffers are correct.
1149 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
1151 This will be used when a mode has changed or a reset ocurred to verify all
1156 ConsoleLoggerResetBuffers(
1157 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
1162 if (ConsoleInfo
->Buffer
!= NULL
) {
1163 FreePool(ConsoleInfo
->Buffer
);
1164 ConsoleInfo
->Buffer
= NULL
;
1165 ConsoleInfo
->BufferSize
= 0;
1167 if (ConsoleInfo
->Attributes
!= NULL
) {
1168 FreePool(ConsoleInfo
->Attributes
);
1169 ConsoleInfo
->Attributes
= NULL
;
1170 ConsoleInfo
->AttribSize
= 0;
1173 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &ConsoleInfo
->ColsPerScreen
, &ConsoleInfo
->RowsPerScreen
);
1174 if (EFI_ERROR(Status
)){
1178 ConsoleInfo
->BufferSize
= (ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Buffer
[0]);
1179 ConsoleInfo
->AttribSize
= ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Attributes
[0]);
1181 ConsoleInfo
->Buffer
= (CHAR16
*)AllocateZeroPool(ConsoleInfo
->BufferSize
);
1183 if (ConsoleInfo
->Buffer
== NULL
) {
1184 return (EFI_OUT_OF_RESOURCES
);
1187 ConsoleInfo
->Attributes
= (INT32
*)AllocateZeroPool(ConsoleInfo
->AttribSize
);
1188 if (ConsoleInfo
->Attributes
== NULL
) {
1189 FreePool(ConsoleInfo
->Buffer
);
1190 ConsoleInfo
->Buffer
= NULL
;
1191 return (EFI_OUT_OF_RESOURCES
);
1194 CopyMem (&ConsoleInfo
->HistoryMode
, ConsoleInfo
->OldConOut
->Mode
, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE
));
1196 return (EFI_SUCCESS
);