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.
17 Install our intermediate ConOut into the system table to
18 keep a log of all the info that is displayed to the user.
20 @param[in] ScreensToSave Sets how many screen-worths of data to save.
21 @param[out] ConsoleInfo The object to pass into later functions.
23 @retval EFI_SUCCESS The operation was successful.
24 @return other The operation failed.
26 @sa ConsoleLoggerResetBuffers
27 @sa InstallProtocolInterface
32 IN CONST UINTN ScreensToSave
,
33 OUT CONSOLE_LOGGER_PRIVATE_DATA
**ConsoleInfo
37 ASSERT(ConsoleInfo
!= NULL
);
39 (*ConsoleInfo
) = AllocateZeroPool(sizeof(CONSOLE_LOGGER_PRIVATE_DATA
));
40 if ((*ConsoleInfo
) == NULL
) {
41 return (EFI_OUT_OF_RESOURCES
);
44 (*ConsoleInfo
)->Signature
= CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE
;
45 (*ConsoleInfo
)->OldConOut
= gST
->ConOut
;
46 (*ConsoleInfo
)->OldConHandle
= gST
->ConsoleOutHandle
;
47 (*ConsoleInfo
)->Buffer
= NULL
;
48 (*ConsoleInfo
)->BufferSize
= 0;
49 (*ConsoleInfo
)->OriginalStartRow
= 0;
50 (*ConsoleInfo
)->CurrentStartRow
= 0;
51 (*ConsoleInfo
)->RowsPerScreen
= 0;
52 (*ConsoleInfo
)->ColsPerScreen
= 0;
53 (*ConsoleInfo
)->Attributes
= NULL
;
54 (*ConsoleInfo
)->AttribSize
= 0;
55 (*ConsoleInfo
)->ScreenCount
= ScreensToSave
;
56 (*ConsoleInfo
)->HistoryMode
.MaxMode
= 1;
57 (*ConsoleInfo
)->HistoryMode
.Mode
= 0;
58 (*ConsoleInfo
)->HistoryMode
.Attribute
= 0;
59 (*ConsoleInfo
)->HistoryMode
.CursorColumn
= 0;
60 (*ConsoleInfo
)->HistoryMode
.CursorRow
= 0;
61 (*ConsoleInfo
)->HistoryMode
.CursorVisible
= FALSE
;
62 (*ConsoleInfo
)->OurConOut
.Reset
= ConsoleLoggerReset
;
63 (*ConsoleInfo
)->OurConOut
.OutputString
= ConsoleLoggerOutputString
;
64 (*ConsoleInfo
)->OurConOut
.TestString
= ConsoleLoggerTestString
;
65 (*ConsoleInfo
)->OurConOut
.QueryMode
= ConsoleLoggerQueryMode
;
66 (*ConsoleInfo
)->OurConOut
.SetMode
= ConsoleLoggerSetMode
;
67 (*ConsoleInfo
)->OurConOut
.SetAttribute
= ConsoleLoggerSetAttribute
;
68 (*ConsoleInfo
)->OurConOut
.ClearScreen
= ConsoleLoggerClearScreen
;
69 (*ConsoleInfo
)->OurConOut
.SetCursorPosition
= ConsoleLoggerSetCursorPosition
;
70 (*ConsoleInfo
)->OurConOut
.EnableCursor
= ConsoleLoggerEnableCursor
;
71 (*ConsoleInfo
)->OurConOut
.Mode
= gST
->ConOut
->Mode
;
72 (*ConsoleInfo
)->Enabled
= TRUE
;
74 Status
= ConsoleLoggerResetBuffers(*ConsoleInfo
);
75 if (EFI_ERROR(Status
)) {
76 SHELL_FREE_NON_NULL((*ConsoleInfo
));
81 Status
= gBS
->InstallProtocolInterface(&gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, EFI_NATIVE_INTERFACE
, (VOID
*)&((*ConsoleInfo
)->OurConOut
));
82 if (EFI_ERROR(Status
)) {
83 SHELL_FREE_NON_NULL((*ConsoleInfo
)->Buffer
);
84 SHELL_FREE_NON_NULL((*ConsoleInfo
)->Attributes
);
85 SHELL_FREE_NON_NULL((*ConsoleInfo
));
90 gST
->ConsoleOutHandle
= gImageHandle
;
91 gST
->ConOut
= &(*ConsoleInfo
)->OurConOut
;
97 Return the system to the state it was before InstallConsoleLogger
100 @param[in] ConsoleInfo The object from the install function.
102 @retval EFI_SUCCESS The operation was successful
103 @return other The operation failed. This was from UninstallProtocolInterface.
107 ConsoleLoggerUninstall(
108 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
111 ASSERT(ConsoleInfo
!= NULL
);
112 ASSERT(ConsoleInfo
->OldConOut
!= NULL
);
114 if (ConsoleInfo
->Buffer
!= NULL
) {
115 FreePool(ConsoleInfo
->Buffer
);
116 DEBUG_CODE(ConsoleInfo
->Buffer
= NULL
;);
117 DEBUG_CODE(ConsoleInfo
->BufferSize
= 0;);
119 if (ConsoleInfo
->Attributes
!= NULL
) {
120 FreePool(ConsoleInfo
->Attributes
);
121 DEBUG_CODE(ConsoleInfo
->Attributes
= NULL
;);
122 DEBUG_CODE(ConsoleInfo
->AttribSize
= 0;);
125 gST
->ConsoleOutHandle
= ConsoleInfo
->OldConHandle
;
126 gST
->ConOut
= ConsoleInfo
->OldConOut
;
128 return (gBS
->UninstallProtocolInterface(gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, (VOID
*)&ConsoleInfo
->OurConOut
));
132 Displays previously logged output back to the screen.
134 This will scroll the screen forwards and backwards through the log of previous
135 output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows
136 is (UINTN)(-1) then the size of the screen will be scrolled.
138 @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer).
139 If FALSE then the log will be displayed backwards (scroll to older).
140 @param[in] Rows Determines how many rows the log should scroll.
141 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
145 ConsoleLoggerDisplayHistory(
146 IN CONST BOOLEAN Forward
,
148 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
153 ASSERT(ConsoleInfo
!= NULL
);
156 // Calculate the row number change
160 RowChange
= ConsoleInfo
->RowsPerScreen
;
163 RowChange
= ConsoleInfo
->RowsPerScreen
/ 2;
171 // Do the math for direction
174 if ((ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
) < RowChange
) {
175 RowChange
= ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
;
178 if (ConsoleInfo
->CurrentStartRow
< RowChange
) {
179 RowChange
= ConsoleInfo
->CurrentStartRow
;
184 // If we are already at one end or the other
186 if (RowChange
== 0) {
187 return (EFI_SUCCESS
);
193 ConsoleInfo
->OldConOut
->ClearScreen(ConsoleInfo
->OldConOut
);
196 // Set the new start row
199 ConsoleInfo
->CurrentStartRow
+= RowChange
;
201 ConsoleInfo
->CurrentStartRow
-= RowChange
;
207 return (UpdateDisplayFromHistory(ConsoleInfo
));
211 Function to return to normal output whent he scrolling is complete.
212 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
214 @retval EFI_SUCCESS The operation was successful.
215 @return other The operation failed. See UpdateDisplayFromHistory.
217 @sa UpdateDisplayFromHistory
221 ConsoleLoggerStopHistory(
222 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
225 ASSERT(ConsoleInfo
!= NULL
);
226 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
227 return (EFI_SUCCESS
);
229 ConsoleInfo
->CurrentStartRow
= ConsoleInfo
->OriginalStartRow
;
230 return (UpdateDisplayFromHistory(ConsoleInfo
));
234 Updates the hidden ConOut to be displaying the correct stuff.
235 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
237 @retval EFI_SUCCESS The operation was successful.
238 @return other The operation failed.
242 UpdateDisplayFromHistory(
243 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
251 CHAR16 TempCharHolder
;
255 CHAR16
*StringSegment
;
256 CHAR16
*StringSegmentEnd
;
257 CHAR16 StringSegmentEndChar
;
260 ASSERT(ConsoleInfo
!= NULL
);
261 TempCharHolder
= CHAR_NULL
;
262 RetVal
= EFI_SUCCESS
;
263 OrigAttribute
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
266 // Disable cursor visibility and move it to the top left corner
268 ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, FALSE
);
269 ConsoleInfo
->OldConOut
->SetCursorPosition (ConsoleInfo
->OldConOut
, 0, 0);
271 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
272 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
274 ; CurrentRow
< ConsoleInfo
->RowsPerScreen
276 , Screen
+= (ConsoleInfo
->ColsPerScreen
+ 2)
277 , Attributes
+= ConsoleInfo
->ColsPerScreen
280 // dont use the last char - prevents screen scroll
282 if (CurrentRow
== (ConsoleInfo
->RowsPerScreen
-1)){
283 TempCharHolder
= Screen
[ConsoleInfo
->ColsPerScreen
- 1];
284 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = CHAR_NULL
;
288 ; Column
< ConsoleInfo
->ColsPerScreen
291 if (Screen
[Column
] != CHAR_NULL
) {
292 CurrentAttrib
= Attributes
[Column
];
293 CurrentColumn
= Column
;
294 StringSegment
= &Screen
[Column
];
297 // Find the first char with a different arrribute and make that temporarily NULL
298 // so we can do fewer printout statements. (later) restore that one and we will
299 // start at that collumn on the next loop.
301 StringSegmentEndChar
= CHAR_NULL
;
302 for ( StringSegmentEnd
= StringSegment
303 ; StringSegmentEnd
!= CHAR_NULL
307 if (Attributes
[Column
] != CurrentAttrib
) {
308 StringSegmentEndChar
= *StringSegmentEnd
;
309 *StringSegmentEnd
= CHAR_NULL
;
312 } // StringSegmentEnd loop
315 // Now write out as much as had the same Attributes
318 ConsoleInfo
->OldConOut
->SetAttribute(ConsoleInfo
->OldConOut
, CurrentAttrib
);
319 ConsoleInfo
->OldConOut
->SetCursorPosition(ConsoleInfo
->OldConOut
, CurrentColumn
, CurrentRow
);
320 Status
= ConsoleInfo
->OldConOut
->OutputString(ConsoleInfo
->OldConOut
, StringSegment
);
322 if (EFI_ERROR(Status
)) {
328 // If we found a change in attribute put the character back and decrement the column
329 // so when it increments it will point at that character and we will start printing
330 // a segment with that new attribute
332 if (StringSegmentEndChar
!= CHAR_NULL
) {
333 *StringSegmentEnd
= StringSegmentEndChar
;
334 StringSegmentEndChar
= CHAR_NULL
;
341 // If we removed the last char and this was the last row put it back
343 if (TempCharHolder
!= CHAR_NULL
) {
344 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = TempCharHolder
;
345 TempCharHolder
= CHAR_NULL
;
350 // If we are setting the screen back to original turn on the cursor and make it visible
351 // and set the attributes back to what they were
353 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
354 ConsoleInfo
->OldConOut
->SetAttribute (
355 ConsoleInfo
->OldConOut
,
356 ConsoleInfo
->HistoryMode
.Attribute
358 ConsoleInfo
->OldConOut
->SetCursorPosition (
359 ConsoleInfo
->OldConOut
,
360 ConsoleInfo
->HistoryMode
.CursorColumn
,
361 ConsoleInfo
->HistoryMode
.CursorRow
- ConsoleInfo
->OriginalStartRow
364 Status
= ConsoleInfo
->OldConOut
->EnableCursor (
365 ConsoleInfo
->OldConOut
,
366 ConsoleInfo
->HistoryMode
.CursorVisible
368 if (EFI_ERROR (Status
)) {
372 ConsoleInfo
->OldConOut
->SetAttribute (
373 ConsoleInfo
->OldConOut
,
382 Reset the text output device hardware and optionaly run diagnostics
384 @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
385 @param ExtendedVerification Indicates that a more extensive test may be performed
387 @retval EFI_SUCCESS The text output device was reset.
388 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
394 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
395 IN BOOLEAN ExtendedVerification
399 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
400 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
403 // Forward the request to the original ConOut
405 Status
= ConsoleInfo
->OldConOut
->Reset (ConsoleInfo
->OldConOut
, ExtendedVerification
);
408 // Check that the buffers are still correct for logging
410 if (!EFI_ERROR (Status
)) {
411 ConsoleLoggerResetBuffers(ConsoleInfo
);
418 Appends a string to the history buffer. If the buffer is full then the oldest
419 information in the buffer will be dropped. Information is added in a line by
420 line manner such that an empty line takes up just as much space as a full line.
422 @param[in] String String pointer to add.
423 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
427 AppendStringToHistory(
428 IN CONST CHAR16
*String
,
429 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
432 CONST CHAR16
*Walker
;
437 ASSERT(ConsoleInfo
!= NULL
);
439 for ( Walker
= String
440 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
444 case (CHAR_BACKSPACE
):
445 if (ConsoleInfo
->HistoryMode
.CursorColumn
> 0) {
446 ConsoleInfo
->HistoryMode
.CursorColumn
--;
449 case (CHAR_LINEFEED
):
450 if (ConsoleInfo
->HistoryMode
.CursorRow
>= (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1)) {
452 // Should never be bigger
454 ASSERT(ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1));
457 // scroll history attributes 'up' 1 row and set the last row to default attribute
459 CopySize
= ConsoleInfo
->ColsPerScreen
460 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
461 * sizeof(ConsoleInfo
->Attributes
[0]);
462 ASSERT(CopySize
< ConsoleInfo
->AttribSize
);
464 ConsoleInfo
->Attributes
,
465 ConsoleInfo
->Attributes
+ ConsoleInfo
->ColsPerScreen
,
470 ; Index
< ConsoleInfo
->ColsPerScreen
473 *(ConsoleInfo
->Attributes
+ (CopySize
/sizeof(ConsoleInfo
->Attributes
[0])) + Index
) = ConsoleInfo
->HistoryMode
.Attribute
;
477 // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
479 CopySize
= (ConsoleInfo
->ColsPerScreen
+ 2)
480 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
481 * sizeof(ConsoleInfo
->Buffer
[0]);
482 ASSERT(CopySize
< ConsoleInfo
->BufferSize
);
485 ConsoleInfo
->Buffer
+ (ConsoleInfo
->ColsPerScreen
+ 2),
490 // Set that last row of chars to spaces
492 SetMem16(((UINT8
*)ConsoleInfo
->Buffer
)+CopySize
, ConsoleInfo
->ColsPerScreen
*sizeof(CHAR16
), L
' ');
495 // we are not on the last row
499 // We should not be scrolling history
501 ASSERT (ConsoleInfo
->OriginalStartRow
== ConsoleInfo
->CurrentStartRow
);
503 // are we at the end of a row?
505 if (ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
) (ConsoleInfo
->OriginalStartRow
+ ConsoleInfo
->RowsPerScreen
- 1)) {
506 ConsoleInfo
->OriginalStartRow
++;
507 ConsoleInfo
->CurrentStartRow
++;
509 ConsoleInfo
->HistoryMode
.CursorRow
++;
512 case (CHAR_CARRIAGE_RETURN
):
514 // Move the cursor to the beginning of the current row.
516 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
520 // Acrtually print characters into the history buffer
523 PrintIndex
= ConsoleInfo
->HistoryMode
.CursorRow
* ConsoleInfo
->ColsPerScreen
+ ConsoleInfo
->HistoryMode
.CursorColumn
;
525 for ( // no initializer needed
526 ; ConsoleInfo
->HistoryMode
.CursorColumn
< (INT32
) ConsoleInfo
->ColsPerScreen
527 ; ConsoleInfo
->HistoryMode
.CursorColumn
++
531 if (*Walker
== CHAR_NULL
532 ||*Walker
== CHAR_BACKSPACE
533 ||*Walker
== CHAR_LINEFEED
534 ||*Walker
== CHAR_CARRIAGE_RETURN
540 // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
543 ASSERT(PrintIndex
+ ConsoleInfo
->HistoryMode
.CursorRow
< ConsoleInfo
->BufferSize
);
544 ConsoleInfo
->Buffer
[PrintIndex
+ (2*ConsoleInfo
->HistoryMode
.CursorRow
)] = *Walker
;
545 ASSERT(PrintIndex
< ConsoleInfo
->AttribSize
);
546 ConsoleInfo
->Attributes
[PrintIndex
] = ConsoleInfo
->HistoryMode
.Attribute
;
550 // Add the carriage return and line feed at the end of the lines
552 if (ConsoleInfo
->HistoryMode
.CursorColumn
>= (INT32
)ConsoleInfo
->ColsPerScreen
) {
553 AppendStringToHistory(L
"\r\n", ConsoleInfo
);
558 } // switch for character
561 return (EFI_SUCCESS
);
565 Worker function to handle printing the output to the screen
566 and the history buffer
568 @param[in] String The string to output
569 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
571 @retval EFI_SUCCESS The string was printed
572 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
574 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
576 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
577 characters in the Unicode string could not be
578 rendered and were skipped.
582 ConsoleLoggerOutputStringSplit(
583 IN CONST CHAR16
*String
,
584 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
590 // Forward the request to the original ConOut
592 Status
= ConsoleInfo
->OldConOut
->OutputString (ConsoleInfo
->OldConOut
, (CHAR16
*)String
);
594 if (EFI_ERROR(Status
)) {
598 return (AppendStringToHistory(String
, ConsoleInfo
));
602 Function to handle page break mode.
604 This function will prompt for continue or break.
606 @retval EFI_SUCCESS Continue was choosen
607 @return other Break was choosen
611 ConsoleLoggerDoPageBreak(
615 SHELL_PROMPT_RESPONSE
*Resp
;
619 ASSERT(ShellInfoObject
.PageBreakEnabled
);
620 ShellInfoObject
.PageBreakEnabled
= FALSE
;
621 Status
= ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue
, STRING_TOKEN(STR_SHELL_QUIT_CONT
), ShellInfoObject
.HiiHandle
, (VOID
**)&Resp
);
622 ShellInfoObject
.PageBreakEnabled
= TRUE
;
623 ASSERT(Resp
!= NULL
);
625 return (EFI_NOT_FOUND
);
627 if (EFI_ERROR(Status
)) {
633 if (*Resp
== ShellPromptResponseContinue
) {
635 ShellInfoObject
.ConsoleInfo
->RowCounter
= 0;
636 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorRow = 0;
637 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
639 return (EFI_SUCCESS
);
640 } else if (*Resp
== ShellPromptResponseQuit
) {
642 ShellInfoObject
.ConsoleInfo
->Enabled
= FALSE
;
643 return (EFI_DEVICE_ERROR
);
647 return (EFI_SUCCESS
);
650 Worker function to handle printing the output with page breaks.
652 @param[in] String The string to output
653 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
655 @retval EFI_SUCCESS The string was printed
656 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
658 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
660 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
661 characters in the Unicode string could not be
662 rendered and were skipped.
666 ConsoleLoggerPrintWithPageBreak(
667 IN CONST CHAR16
*String
,
668 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
671 CONST CHAR16
*Walker
;
672 CONST CHAR16
*LineStart
;
677 StringCopy
= StrnCatGrow(&StringCopy
, NULL
, String
, 0);
678 if (StringCopy
== NULL
) {
679 return (EFI_OUT_OF_RESOURCES
);
682 for ( Walker
= StringCopy
683 , LineStart
= StringCopy
684 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
688 case (CHAR_BACKSPACE
):
689 if (ConsoleInfo
->OurConOut
.Mode
->CursorColumn
> 0) {
690 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
--;
693 case (CHAR_LINEFEED
):
695 // add a temp NULL terminator
697 TempChar
= *(Walker
+ 1);
698 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
703 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
706 // restore the temp NULL terminator to it's original character
708 *((CHAR16
*)(Walker
+1)) = TempChar
;
711 // Update LineStart Variable
713 LineStart
= Walker
+ 1;
716 // increment row count
718 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
719 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
722 case (CHAR_CARRIAGE_RETURN
):
724 // Move the cursor to the beginning of the current row.
726 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
730 // increment column count
732 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
++;
734 // check if that is the last column
736 if ((INTN
)ConsoleInfo
->ColsPerScreen
== ConsoleInfo
->OurConOut
.Mode
->CursorColumn
+ 1) {
738 // output a line similar to the linefeed character.
742 // add a temp NULL terminator
744 TempChar
= *(Walker
+ 1);
745 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
750 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
753 // restore the temp NULL terminator to it's original character
755 *((CHAR16
*)(Walker
+1)) = TempChar
;
758 // Update LineStart Variable
760 LineStart
= Walker
+ 1;
763 // increment row count and zero the column
765 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
766 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
767 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
768 } // last column on line
770 } // switch for character
773 // check if that was the last printable row. If yes handle PageBreak mode
775 if ((ConsoleInfo
->RowsPerScreen
) -1 == ShellInfoObject
.ConsoleInfo
->RowCounter
) {
776 if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
778 // We got an error which means 'break' and halt the printing
780 SHELL_FREE_NON_NULL(StringCopy
);
781 return (EFI_DEVICE_ERROR
);
786 if (LineStart
!= NULL
&& *LineStart
!= CHAR_NULL
) {
787 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
790 SHELL_FREE_NON_NULL(StringCopy
);
791 return (EFI_SUCCESS
);
795 Write a Unicode string to the output device.
797 @param[in] This Protocol instance pointer.
798 @param[in] WString The NULL-terminated Unicode string to be displayed on the output
799 device(s). All output devices must also support the Unicode
800 drawing defined in this file.
801 @retval EFI_SUCCESS The string was output to the device.
802 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
804 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
806 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
807 characters in the Unicode string could not be
808 rendered and were skipped.
812 ConsoleLoggerOutputString (
813 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
819 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
820 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
821 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
822 return (EFI_UNSUPPORTED
);
824 ASSERT(ShellInfoObject
.ConsoleInfo
== ConsoleInfo
);
825 if (ShellInfoObject
.HaltOutput
) {
829 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &EventIndex
);
830 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
831 ShellInfoObject
.HaltOutput
= FALSE
;
833 if (!ShellInfoObject
.ConsoleInfo
->Enabled
) {
834 return (EFI_DEVICE_ERROR
);
835 } else if (ShellInfoObject
.PageBreakEnabled
) {
836 return (ConsoleLoggerPrintWithPageBreak(WString
, ConsoleInfo
));
838 return (ConsoleLoggerOutputStringSplit(WString
, ConsoleInfo
));
843 Verifies that all characters in a Unicode string can be output to the
846 @param[in] This Protocol instance pointer.
847 @param[in] WString The NULL-terminated Unicode string to be examined for the output
850 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
851 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
852 rendered by one or more of the output devices mapped
858 ConsoleLoggerTestString (
859 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
863 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
864 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
866 // Forward the request to the original ConOut
868 return (ConsoleInfo
->OldConOut
->TestString (ConsoleInfo
->OldConOut
, WString
));
872 Returns information for an available text mode that the output device(s)
875 @param[in] This Protocol instance pointer.
876 @param[in] ModeNumber The mode number to return information on.
877 @param[out] Columns Upon return, the number of columns in the selected geometry
878 @param[out] Rows Upon return, the number of rows in the selected geometry
880 @retval EFI_SUCCESS The requested mode information was returned.
881 @retval EFI_DEVICE_ERROR The device had an error and could not
882 complete the request.
883 @retval EFI_UNSUPPORTED The mode number was not valid.
887 ConsoleLoggerQueryMode (
888 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
894 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
895 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
897 // Forward the request to the original ConOut
899 return (ConsoleInfo
->OldConOut
->QueryMode (
900 ConsoleInfo
->OldConOut
,
908 Sets the output device(s) to a specified mode.
910 @param[in] This Protocol instance pointer.
911 @param[in] ModeNumber The mode number to set.
914 @retval EFI_SUCCESS The requested text mode was set.
915 @retval EFI_DEVICE_ERROR The device had an error and
916 could not complete the request.
917 @retval EFI_UNSUPPORTED The mode number was not valid.
921 ConsoleLoggerSetMode (
922 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
928 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
929 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
932 // Forward the request to the original ConOut
934 Status
= ConsoleInfo
->OldConOut
->SetMode (ConsoleInfo
->OldConOut
, ModeNumber
);
937 // Check that the buffers are still correct for logging
939 if (!EFI_ERROR (Status
)) {
940 ConsoleInfo
->OurConOut
.Mode
= gST
->ConOut
->Mode
;
941 ConsoleLoggerResetBuffers(ConsoleInfo
);
948 Sets the background and foreground colors for the OutputString () and
949 ClearScreen () functions.
951 @param[in] This Protocol instance pointer.
952 @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
953 bits 4..6 are the background color. All other bits are undefined
954 and must be zero. The valid Attributes are defined in this file.
956 @retval EFI_SUCCESS The attribute was set.
957 @retval EFI_DEVICE_ERROR The device had an error and
958 could not complete the request.
959 @retval EFI_UNSUPPORTED The attribute requested is not defined.
964 ConsoleLoggerSetAttribute (
965 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
971 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
972 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
975 // Forward the request to the original ConOut
977 Status
= ConsoleInfo
->OldConOut
->SetAttribute (ConsoleInfo
->OldConOut
, Attribute
);
980 // Record console output history
982 if (!EFI_ERROR (Status
)) {
983 ConsoleInfo
->HistoryMode
.Attribute
= (INT32
) Attribute
;
990 Clears the output device(s) display to the currently selected background
993 @param[in] This Protocol instance pointer.
995 @retval EFI_SUCCESS The operation completed successfully.
996 @retval EFI_DEVICE_ERROR The device had an error and
997 could not complete the request.
998 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1002 ConsoleLoggerClearScreen (
1003 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
1011 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1013 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
1014 return (EFI_UNSUPPORTED
);
1017 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1020 // Forward the request to the original ConOut
1022 Status
= ConsoleInfo
->OldConOut
->ClearScreen (ConsoleInfo
->OldConOut
);
1025 // Record console output history
1027 if (!EFI_ERROR (Status
)) {
1028 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
1029 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
1030 for ( Row
= ConsoleInfo
->OriginalStartRow
1031 ; Row
< (ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)
1035 ; Column
< ConsoleInfo
->ColsPerScreen
1041 *Attributes
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
1044 // Skip the NULL on each column end in text buffer only
1048 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
1049 ConsoleInfo
->HistoryMode
.CursorRow
= 0;
1056 Sets the current coordinates of the cursor position
1058 @param[in] This Protocol instance pointer.
1059 @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
1060 @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
1062 @retval EFI_SUCCESS The operation completed successfully.
1063 @retval EFI_DEVICE_ERROR The device had an error and
1064 could not complete the request.
1065 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
1066 cursor position is invalid for the current mode.
1070 ConsoleLoggerSetCursorPosition (
1071 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1077 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1079 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
1080 return (EFI_UNSUPPORTED
);
1083 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1085 // Forward the request to the original ConOut
1087 Status
= ConsoleInfo
->OldConOut
->SetCursorPosition (
1088 ConsoleInfo
->OldConOut
,
1094 // Record console output history
1096 if (!EFI_ERROR (Status
)) {
1097 ConsoleInfo
->HistoryMode
.CursorColumn
= (INT32
)Column
;
1098 ConsoleInfo
->HistoryMode
.CursorRow
= (INT32
)(ConsoleInfo
->OriginalStartRow
+ Row
);
1105 Makes the cursor visible or invisible
1107 @param[in] This Protocol instance pointer.
1108 @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
1109 set to be invisible.
1111 @retval EFI_SUCCESS The operation completed successfully.
1112 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1113 request, or the device does not support changing
1115 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1119 ConsoleLoggerEnableCursor (
1120 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1126 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1127 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1129 // Forward the request to the original ConOut
1131 Status
= ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, Visible
);
1134 // Record console output history
1136 if (!EFI_ERROR (Status
)) {
1137 ConsoleInfo
->HistoryMode
.CursorVisible
= Visible
;
1144 Function to update and verify that the current buffers are correct.
1146 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
1148 This will be used when a mode has changed or a reset ocurred to verify all
1153 ConsoleLoggerResetBuffers(
1154 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
1159 if (ConsoleInfo
->Buffer
!= NULL
) {
1160 FreePool(ConsoleInfo
->Buffer
);
1161 ConsoleInfo
->Buffer
= NULL
;
1162 ConsoleInfo
->BufferSize
= 0;
1164 if (ConsoleInfo
->Attributes
!= NULL
) {
1165 FreePool(ConsoleInfo
->Attributes
);
1166 ConsoleInfo
->Attributes
= NULL
;
1167 ConsoleInfo
->AttribSize
= 0;
1170 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &ConsoleInfo
->ColsPerScreen
, &ConsoleInfo
->RowsPerScreen
);
1171 if (EFI_ERROR(Status
)){
1175 ConsoleInfo
->BufferSize
= (ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Buffer
[0]);
1176 ConsoleInfo
->AttribSize
= ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Attributes
[0]);
1178 ConsoleInfo
->Buffer
= (CHAR16
*)AllocateZeroPool(ConsoleInfo
->BufferSize
);
1180 if (ConsoleInfo
->Buffer
== NULL
) {
1181 return (EFI_OUT_OF_RESOURCES
);
1184 ConsoleInfo
->Attributes
= (INT32
*)AllocateZeroPool(ConsoleInfo
->AttribSize
);
1185 if (ConsoleInfo
->Attributes
== NULL
) {
1186 FreePool(ConsoleInfo
->Buffer
);
1187 ConsoleInfo
->Buffer
= NULL
;
1188 return (EFI_OUT_OF_RESOURCES
);
1191 CopyMem (&ConsoleInfo
->HistoryMode
, ConsoleInfo
->OldConOut
->Mode
, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE
));
1193 return (EFI_SUCCESS
);