2 Provides interface to shell console logger.
4 Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
5 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Install our intermediate ConOut into the system table to
19 keep a log of all the info that is displayed to the user.
21 @param[in] ScreensToSave Sets how many screen-worths of data to save.
22 @param[out] ConsoleInfo The object to pass into later functions.
24 @retval EFI_SUCCESS The operation was successful.
25 @return other The operation failed.
27 @sa ConsoleLoggerResetBuffers
28 @sa InstallProtocolInterface
33 IN CONST UINTN ScreensToSave
,
34 OUT CONSOLE_LOGGER_PRIVATE_DATA
**ConsoleInfo
38 ASSERT(ConsoleInfo
!= NULL
);
40 (*ConsoleInfo
) = AllocateZeroPool(sizeof(CONSOLE_LOGGER_PRIVATE_DATA
));
41 if ((*ConsoleInfo
) == NULL
) {
42 return (EFI_OUT_OF_RESOURCES
);
45 (*ConsoleInfo
)->Signature
= CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE
;
46 (*ConsoleInfo
)->OldConOut
= gST
->ConOut
;
47 (*ConsoleInfo
)->OldConHandle
= gST
->ConsoleOutHandle
;
48 (*ConsoleInfo
)->Buffer
= NULL
;
49 (*ConsoleInfo
)->BufferSize
= 0;
50 (*ConsoleInfo
)->OriginalStartRow
= 0;
51 (*ConsoleInfo
)->CurrentStartRow
= 0;
52 (*ConsoleInfo
)->RowsPerScreen
= 0;
53 (*ConsoleInfo
)->ColsPerScreen
= 0;
54 (*ConsoleInfo
)->Attributes
= NULL
;
55 (*ConsoleInfo
)->AttribSize
= 0;
56 (*ConsoleInfo
)->ScreenCount
= ScreensToSave
;
57 (*ConsoleInfo
)->HistoryMode
.MaxMode
= 1;
58 (*ConsoleInfo
)->HistoryMode
.Mode
= 0;
59 (*ConsoleInfo
)->HistoryMode
.Attribute
= 0;
60 (*ConsoleInfo
)->HistoryMode
.CursorColumn
= 0;
61 (*ConsoleInfo
)->HistoryMode
.CursorRow
= 0;
62 (*ConsoleInfo
)->HistoryMode
.CursorVisible
= FALSE
;
63 (*ConsoleInfo
)->OurConOut
.Reset
= ConsoleLoggerReset
;
64 (*ConsoleInfo
)->OurConOut
.OutputString
= ConsoleLoggerOutputString
;
65 (*ConsoleInfo
)->OurConOut
.TestString
= ConsoleLoggerTestString
;
66 (*ConsoleInfo
)->OurConOut
.QueryMode
= ConsoleLoggerQueryMode
;
67 (*ConsoleInfo
)->OurConOut
.SetMode
= ConsoleLoggerSetMode
;
68 (*ConsoleInfo
)->OurConOut
.SetAttribute
= ConsoleLoggerSetAttribute
;
69 (*ConsoleInfo
)->OurConOut
.ClearScreen
= ConsoleLoggerClearScreen
;
70 (*ConsoleInfo
)->OurConOut
.SetCursorPosition
= ConsoleLoggerSetCursorPosition
;
71 (*ConsoleInfo
)->OurConOut
.EnableCursor
= ConsoleLoggerEnableCursor
;
72 (*ConsoleInfo
)->OurConOut
.Mode
= gST
->ConOut
->Mode
;
73 (*ConsoleInfo
)->Enabled
= TRUE
;
75 Status
= ConsoleLoggerResetBuffers(*ConsoleInfo
);
76 if (EFI_ERROR(Status
)) {
77 SHELL_FREE_NON_NULL((*ConsoleInfo
));
82 Status
= gBS
->InstallProtocolInterface(&gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, EFI_NATIVE_INTERFACE
, (VOID
*)&((*ConsoleInfo
)->OurConOut
));
83 if (EFI_ERROR(Status
)) {
84 SHELL_FREE_NON_NULL((*ConsoleInfo
)->Buffer
);
85 SHELL_FREE_NON_NULL((*ConsoleInfo
)->Attributes
);
86 SHELL_FREE_NON_NULL((*ConsoleInfo
));
91 gST
->ConsoleOutHandle
= gImageHandle
;
92 gST
->ConOut
= &(*ConsoleInfo
)->OurConOut
;
98 Return the system to the state it was before InstallConsoleLogger
101 @param[in] ConsoleInfo The object from the install function.
103 @retval EFI_SUCCESS The operation was successful
104 @return other The operation failed. This was from UninstallProtocolInterface.
108 ConsoleLoggerUninstall(
109 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
112 ASSERT(ConsoleInfo
!= NULL
);
113 ASSERT(ConsoleInfo
->OldConOut
!= NULL
);
115 if (ConsoleInfo
->Buffer
!= NULL
) {
116 FreePool(ConsoleInfo
->Buffer
);
117 DEBUG_CODE(ConsoleInfo
->Buffer
= NULL
;);
118 DEBUG_CODE(ConsoleInfo
->BufferSize
= 0;);
120 if (ConsoleInfo
->Attributes
!= NULL
) {
121 FreePool(ConsoleInfo
->Attributes
);
122 DEBUG_CODE(ConsoleInfo
->Attributes
= NULL
;);
123 DEBUG_CODE(ConsoleInfo
->AttribSize
= 0;);
126 gST
->ConsoleOutHandle
= ConsoleInfo
->OldConHandle
;
127 gST
->ConOut
= ConsoleInfo
->OldConOut
;
129 return (gBS
->UninstallProtocolInterface(gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, (VOID
*)&ConsoleInfo
->OurConOut
));
133 Displays previously logged output back to the screen.
135 This will scroll the screen forwards and backwards through the log of previous
136 output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows
137 is (UINTN)(-1) then the size of the screen will be scrolled.
139 @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer).
140 If FALSE then the log will be displayed backwards (scroll to older).
141 @param[in] Rows Determines how many rows the log should scroll.
142 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
146 ConsoleLoggerDisplayHistory(
147 IN CONST BOOLEAN Forward
,
149 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
154 ASSERT(ConsoleInfo
!= NULL
);
157 // Calculate the row number change
161 RowChange
= ConsoleInfo
->RowsPerScreen
;
164 RowChange
= ConsoleInfo
->RowsPerScreen
/ 2;
172 // Do the math for direction
175 if ((ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
) < RowChange
) {
176 RowChange
= ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
;
179 if (ConsoleInfo
->CurrentStartRow
< RowChange
) {
180 RowChange
= ConsoleInfo
->CurrentStartRow
;
185 // If we are already at one end or the other
187 if (RowChange
== 0) {
188 return (EFI_SUCCESS
);
194 ConsoleInfo
->OldConOut
->ClearScreen(ConsoleInfo
->OldConOut
);
197 // Set the new start row
200 ConsoleInfo
->CurrentStartRow
+= RowChange
;
202 ConsoleInfo
->CurrentStartRow
-= RowChange
;
208 return (UpdateDisplayFromHistory(ConsoleInfo
));
212 Function to return to normal output whent he scrolling is complete.
213 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
215 @retval EFI_SUCCESS The operation was successful.
216 @return other The operation failed. See UpdateDisplayFromHistory.
218 @sa UpdateDisplayFromHistory
222 ConsoleLoggerStopHistory(
223 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
226 ASSERT(ConsoleInfo
!= NULL
);
227 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
228 return (EFI_SUCCESS
);
230 ConsoleInfo
->CurrentStartRow
= ConsoleInfo
->OriginalStartRow
;
231 return (UpdateDisplayFromHistory(ConsoleInfo
));
235 Updates the hidden ConOut to be displaying the correct stuff.
236 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
238 @retval EFI_SUCCESS The operation was successful.
239 @return other The operation failed.
243 UpdateDisplayFromHistory(
244 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
252 CHAR16 TempCharHolder
;
256 CHAR16
*StringSegment
;
257 CHAR16
*StringSegmentEnd
;
258 CHAR16 StringSegmentEndChar
;
261 ASSERT(ConsoleInfo
!= NULL
);
262 TempCharHolder
= CHAR_NULL
;
263 RetVal
= EFI_SUCCESS
;
264 OrigAttribute
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
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
)) {
373 ConsoleInfo
->OldConOut
->SetAttribute (
374 ConsoleInfo
->OldConOut
,
383 Reset the text output device hardware and optionaly run diagnostics
385 @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
386 @param ExtendedVerification Indicates that a more extensive test may be performed
388 @retval EFI_SUCCESS The text output device was reset.
389 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
395 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
396 IN BOOLEAN ExtendedVerification
400 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
401 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
404 // Forward the request to the original ConOut
406 Status
= ConsoleInfo
->OldConOut
->Reset (ConsoleInfo
->OldConOut
, ExtendedVerification
);
409 // Check that the buffers are still correct for logging
411 if (!EFI_ERROR (Status
)) {
412 ConsoleLoggerResetBuffers(ConsoleInfo
);
419 Appends a string to the history buffer. If the buffer is full then the oldest
420 information in the buffer will be dropped. Information is added in a line by
421 line manner such that an empty line takes up just as much space as a full line.
423 @param[in] String String pointer to add.
424 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
428 AppendStringToHistory(
429 IN CONST CHAR16
*String
,
430 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
433 CONST CHAR16
*Walker
;
438 ASSERT(ConsoleInfo
!= NULL
);
440 for ( Walker
= String
441 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
445 case (CHAR_BACKSPACE
):
446 if (ConsoleInfo
->HistoryMode
.CursorColumn
> 0) {
447 ConsoleInfo
->HistoryMode
.CursorColumn
--;
450 case (CHAR_LINEFEED
):
451 if (ConsoleInfo
->HistoryMode
.CursorRow
>= (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1)) {
453 // Should never be bigger
455 ASSERT(ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1));
458 // scroll history attributes 'up' 1 row and set the last row to default attribute
460 CopySize
= ConsoleInfo
->ColsPerScreen
461 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
462 * sizeof(ConsoleInfo
->Attributes
[0]);
463 ASSERT(CopySize
< ConsoleInfo
->AttribSize
);
465 ConsoleInfo
->Attributes
,
466 ConsoleInfo
->Attributes
+ ConsoleInfo
->ColsPerScreen
,
471 ; Index
< ConsoleInfo
->ColsPerScreen
474 *(ConsoleInfo
->Attributes
+ (CopySize
/sizeof(ConsoleInfo
->Attributes
[0])) + Index
) = ConsoleInfo
->HistoryMode
.Attribute
;
478 // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
480 CopySize
= (ConsoleInfo
->ColsPerScreen
+ 2)
481 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
482 * sizeof(ConsoleInfo
->Buffer
[0]);
483 ASSERT(CopySize
< ConsoleInfo
->BufferSize
);
486 ConsoleInfo
->Buffer
+ (ConsoleInfo
->ColsPerScreen
+ 2),
491 // Set that last row of chars to spaces
493 SetMem16(((UINT8
*)ConsoleInfo
->Buffer
)+CopySize
, ConsoleInfo
->ColsPerScreen
*sizeof(CHAR16
), L
' ');
496 // we are not on the last row
500 // We should not be scrolling history
502 ASSERT (ConsoleInfo
->OriginalStartRow
== ConsoleInfo
->CurrentStartRow
);
504 // are we at the end of a row?
506 if (ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
) (ConsoleInfo
->OriginalStartRow
+ ConsoleInfo
->RowsPerScreen
- 1)) {
507 ConsoleInfo
->OriginalStartRow
++;
508 ConsoleInfo
->CurrentStartRow
++;
510 ConsoleInfo
->HistoryMode
.CursorRow
++;
513 case (CHAR_CARRIAGE_RETURN
):
515 // Move the cursor to the beginning of the current row.
517 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
521 // Acrtually print characters into the history buffer
524 PrintIndex
= ConsoleInfo
->HistoryMode
.CursorRow
* ConsoleInfo
->ColsPerScreen
+ ConsoleInfo
->HistoryMode
.CursorColumn
;
526 for ( // no initializer needed
527 ; ConsoleInfo
->HistoryMode
.CursorColumn
< (INT32
) ConsoleInfo
->ColsPerScreen
528 ; ConsoleInfo
->HistoryMode
.CursorColumn
++
532 if (*Walker
== CHAR_NULL
533 ||*Walker
== CHAR_BACKSPACE
534 ||*Walker
== CHAR_LINEFEED
535 ||*Walker
== CHAR_CARRIAGE_RETURN
541 // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
544 ASSERT(PrintIndex
+ ConsoleInfo
->HistoryMode
.CursorRow
< ConsoleInfo
->BufferSize
);
545 ConsoleInfo
->Buffer
[PrintIndex
+ (2*ConsoleInfo
->HistoryMode
.CursorRow
)] = *Walker
;
546 ASSERT(PrintIndex
< ConsoleInfo
->AttribSize
);
547 ConsoleInfo
->Attributes
[PrintIndex
] = ConsoleInfo
->HistoryMode
.Attribute
;
551 // Add the carriage return and line feed at the end of the lines
553 if (ConsoleInfo
->HistoryMode
.CursorColumn
>= (INT32
)ConsoleInfo
->ColsPerScreen
) {
554 AppendStringToHistory(L
"\r\n", ConsoleInfo
);
559 } // switch for character
562 return (EFI_SUCCESS
);
566 Worker function to handle printing the output to the screen
567 and the history buffer
569 @param[in] String The string to output
570 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
572 @retval EFI_SUCCESS The string was printed
573 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
575 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
577 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
578 characters in the Unicode string could not be
579 rendered and were skipped.
583 ConsoleLoggerOutputStringSplit(
584 IN CONST CHAR16
*String
,
585 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
591 // Forward the request to the original ConOut
593 Status
= ConsoleInfo
->OldConOut
->OutputString (ConsoleInfo
->OldConOut
, (CHAR16
*)String
);
595 if (EFI_ERROR(Status
)) {
599 return (AppendStringToHistory(String
, ConsoleInfo
));
603 Function to handle page break mode.
605 This function will prompt for continue or break.
607 @retval EFI_SUCCESS Continue was choosen
608 @return other Break was choosen
612 ConsoleLoggerDoPageBreak(
616 SHELL_PROMPT_RESPONSE
*Resp
;
620 ASSERT(ShellInfoObject
.PageBreakEnabled
);
621 ShellInfoObject
.PageBreakEnabled
= FALSE
;
622 Status
= ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue
, STRING_TOKEN(STR_SHELL_QUIT_CONT
), ShellInfoObject
.HiiHandle
, (VOID
**)&Resp
);
623 ShellInfoObject
.PageBreakEnabled
= TRUE
;
624 ASSERT(Resp
!= NULL
);
626 return (EFI_NOT_FOUND
);
628 if (EFI_ERROR(Status
)) {
634 if (*Resp
== ShellPromptResponseContinue
) {
636 ShellInfoObject
.ConsoleInfo
->RowCounter
= 0;
637 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorRow = 0;
638 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
640 return (EFI_SUCCESS
);
641 } else if (*Resp
== ShellPromptResponseQuit
) {
643 ShellInfoObject
.ConsoleInfo
->Enabled
= FALSE
;
645 // When user wants to quit, the shell should stop running the command.
647 gBS
->SignalEvent (ShellInfoObject
.NewEfiShellProtocol
->ExecutionBreak
);
648 return (EFI_DEVICE_ERROR
);
652 return (EFI_SUCCESS
);
655 Worker function to handle printing the output with page breaks.
657 @param[in] String The string to output
658 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
660 @retval EFI_SUCCESS The string was printed
661 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
663 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
665 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
666 characters in the Unicode string could not be
667 rendered and were skipped.
671 ConsoleLoggerPrintWithPageBreak(
672 IN CONST CHAR16
*String
,
673 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
676 CONST CHAR16
*Walker
;
677 CONST CHAR16
*LineStart
;
682 StringCopy
= StrnCatGrow(&StringCopy
, NULL
, String
, 0);
683 if (StringCopy
== NULL
) {
684 return (EFI_OUT_OF_RESOURCES
);
687 for ( Walker
= StringCopy
688 , LineStart
= StringCopy
689 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
693 case (CHAR_BACKSPACE
):
694 if (ConsoleInfo
->OurConOut
.Mode
->CursorColumn
> 0) {
695 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
--;
698 case (CHAR_LINEFEED
):
700 // add a temp NULL terminator
702 TempChar
= *(Walker
+ 1);
703 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
708 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
711 // restore the temp NULL terminator to it's original character
713 *((CHAR16
*)(Walker
+1)) = TempChar
;
716 // Update LineStart Variable
718 LineStart
= Walker
+ 1;
721 // increment row count
723 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
724 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
727 case (CHAR_CARRIAGE_RETURN
):
729 // Move the cursor to the beginning of the current row.
731 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
735 // increment column count
737 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
++;
739 // check if that is the last column
741 if ((INTN
)ConsoleInfo
->ColsPerScreen
== ConsoleInfo
->OurConOut
.Mode
->CursorColumn
+ 1) {
743 // output a line similar to the linefeed character.
747 // add a temp NULL terminator
749 TempChar
= *(Walker
+ 1);
750 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
755 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
758 // restore the temp NULL terminator to it's original character
760 *((CHAR16
*)(Walker
+1)) = TempChar
;
763 // Update LineStart Variable
765 LineStart
= Walker
+ 1;
768 // increment row count and zero the column
770 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
771 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
772 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
773 } // last column on line
775 } // switch for character
778 // check if that was the last printable row. If yes handle PageBreak mode
780 if ((ConsoleInfo
->RowsPerScreen
) -1 == ShellInfoObject
.ConsoleInfo
->RowCounter
) {
781 if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
783 // We got an error which means 'break' and halt the printing
785 SHELL_FREE_NON_NULL(StringCopy
);
786 return (EFI_DEVICE_ERROR
);
791 if (LineStart
!= NULL
&& *LineStart
!= CHAR_NULL
) {
792 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
795 SHELL_FREE_NON_NULL(StringCopy
);
796 return (EFI_SUCCESS
);
800 Write a Unicode string to the output device.
802 @param[in] This Protocol instance pointer.
803 @param[in] WString The NULL-terminated Unicode string to be displayed on the output
804 device(s). All output devices must also support the Unicode
805 drawing defined in this file.
806 @retval EFI_SUCCESS The string was output to the device.
807 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
809 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
811 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
812 characters in the Unicode string could not be
813 rendered and were skipped.
817 ConsoleLoggerOutputString (
818 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
824 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
825 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
826 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
827 return (EFI_UNSUPPORTED
);
829 ASSERT(ShellInfoObject
.ConsoleInfo
== ConsoleInfo
);
830 if (ShellInfoObject
.HaltOutput
) {
834 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &EventIndex
);
835 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
836 ShellInfoObject
.HaltOutput
= FALSE
;
838 if (!ShellInfoObject
.ConsoleInfo
->Enabled
) {
839 return (EFI_DEVICE_ERROR
);
840 } else if (ShellInfoObject
.PageBreakEnabled
) {
841 return (ConsoleLoggerPrintWithPageBreak(WString
, ConsoleInfo
));
843 return (ConsoleLoggerOutputStringSplit(WString
, ConsoleInfo
));
848 Verifies that all characters in a Unicode string can be output to the
851 @param[in] This Protocol instance pointer.
852 @param[in] WString The NULL-terminated Unicode string to be examined for the output
855 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
856 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
857 rendered by one or more of the output devices mapped
863 ConsoleLoggerTestString (
864 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
868 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
869 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
871 // Forward the request to the original ConOut
873 return (ConsoleInfo
->OldConOut
->TestString (ConsoleInfo
->OldConOut
, WString
));
877 Returns information for an available text mode that the output device(s)
880 @param[in] This Protocol instance pointer.
881 @param[in] ModeNumber The mode number to return information on.
882 @param[out] Columns Upon return, the number of columns in the selected geometry
883 @param[out] Rows Upon return, the number of rows in the selected geometry
885 @retval EFI_SUCCESS The requested mode information was returned.
886 @retval EFI_DEVICE_ERROR The device had an error and could not
887 complete the request.
888 @retval EFI_UNSUPPORTED The mode number was not valid.
892 ConsoleLoggerQueryMode (
893 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
899 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
900 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
902 // Forward the request to the original ConOut
904 return (ConsoleInfo
->OldConOut
->QueryMode (
905 ConsoleInfo
->OldConOut
,
913 Sets the output device(s) to a specified mode.
915 @param[in] This Protocol instance pointer.
916 @param[in] ModeNumber The mode number to set.
919 @retval EFI_SUCCESS The requested text mode was set.
920 @retval EFI_DEVICE_ERROR The device had an error and
921 could not complete the request.
922 @retval EFI_UNSUPPORTED The mode number was not valid.
926 ConsoleLoggerSetMode (
927 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
933 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
934 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
937 // Forward the request to the original ConOut
939 Status
= ConsoleInfo
->OldConOut
->SetMode (ConsoleInfo
->OldConOut
, ModeNumber
);
942 // Check that the buffers are still correct for logging
944 if (!EFI_ERROR (Status
)) {
945 ConsoleInfo
->OurConOut
.Mode
= gST
->ConOut
->Mode
;
946 ConsoleLoggerResetBuffers(ConsoleInfo
);
953 Sets the background and foreground colors for the OutputString () and
954 ClearScreen () functions.
956 @param[in] This Protocol instance pointer.
957 @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
958 bits 4..6 are the background color. All other bits are undefined
959 and must be zero. The valid Attributes are defined in this file.
961 @retval EFI_SUCCESS The attribute was set.
962 @retval EFI_DEVICE_ERROR The device had an error and
963 could not complete the request.
964 @retval EFI_UNSUPPORTED The attribute requested is not defined.
969 ConsoleLoggerSetAttribute (
970 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
976 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
977 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
980 // Forward the request to the original ConOut
982 Status
= ConsoleInfo
->OldConOut
->SetAttribute (ConsoleInfo
->OldConOut
, Attribute
);
985 // Record console output history
987 if (!EFI_ERROR (Status
)) {
988 ConsoleInfo
->HistoryMode
.Attribute
= (INT32
) Attribute
;
995 Clears the output device(s) display to the currently selected background
998 @param[in] This Protocol instance pointer.
1000 @retval EFI_SUCCESS The operation completed successfully.
1001 @retval EFI_DEVICE_ERROR The device had an error and
1002 could not complete the request.
1003 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1007 ConsoleLoggerClearScreen (
1008 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
1016 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1018 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
1019 return (EFI_UNSUPPORTED
);
1022 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1025 // Forward the request to the original ConOut
1027 Status
= ConsoleInfo
->OldConOut
->ClearScreen (ConsoleInfo
->OldConOut
);
1030 // Record console output history
1032 if (!EFI_ERROR (Status
)) {
1033 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
1034 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
1035 for ( Row
= ConsoleInfo
->OriginalStartRow
1036 ; Row
< (ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)
1040 ; Column
< ConsoleInfo
->ColsPerScreen
1046 *Attributes
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
1049 // Skip the NULL on each column end in text buffer only
1053 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
1054 ConsoleInfo
->HistoryMode
.CursorRow
= 0;
1061 Sets the current coordinates of the cursor position
1063 @param[in] This Protocol instance pointer.
1064 @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
1065 @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
1067 @retval EFI_SUCCESS The operation completed successfully.
1068 @retval EFI_DEVICE_ERROR The device had an error and
1069 could not complete the request.
1070 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
1071 cursor position is invalid for the current mode.
1075 ConsoleLoggerSetCursorPosition (
1076 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1082 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1084 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
1085 return (EFI_UNSUPPORTED
);
1088 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1090 // Forward the request to the original ConOut
1092 Status
= ConsoleInfo
->OldConOut
->SetCursorPosition (
1093 ConsoleInfo
->OldConOut
,
1099 // Record console output history
1101 if (!EFI_ERROR (Status
)) {
1102 ConsoleInfo
->HistoryMode
.CursorColumn
= (INT32
)Column
;
1103 ConsoleInfo
->HistoryMode
.CursorRow
= (INT32
)(ConsoleInfo
->OriginalStartRow
+ Row
);
1110 Makes the cursor visible or invisible
1112 @param[in] This Protocol instance pointer.
1113 @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
1114 set to be invisible.
1116 @retval EFI_SUCCESS The operation completed successfully.
1117 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1118 request, or the device does not support changing
1120 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1124 ConsoleLoggerEnableCursor (
1125 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1131 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1132 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1134 // Forward the request to the original ConOut
1136 Status
= ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, Visible
);
1139 // Record console output history
1141 if (!EFI_ERROR (Status
)) {
1142 ConsoleInfo
->HistoryMode
.CursorVisible
= Visible
;
1149 Function to update and verify that the current buffers are correct.
1151 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
1153 This will be used when a mode has changed or a reset ocurred to verify all
1158 ConsoleLoggerResetBuffers(
1159 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
1164 if (ConsoleInfo
->Buffer
!= NULL
) {
1165 FreePool(ConsoleInfo
->Buffer
);
1166 ConsoleInfo
->Buffer
= NULL
;
1167 ConsoleInfo
->BufferSize
= 0;
1169 if (ConsoleInfo
->Attributes
!= NULL
) {
1170 FreePool(ConsoleInfo
->Attributes
);
1171 ConsoleInfo
->Attributes
= NULL
;
1172 ConsoleInfo
->AttribSize
= 0;
1175 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &ConsoleInfo
->ColsPerScreen
, &ConsoleInfo
->RowsPerScreen
);
1176 if (EFI_ERROR(Status
)){
1180 ConsoleInfo
->BufferSize
= (ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Buffer
[0]);
1181 ConsoleInfo
->AttribSize
= ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Attributes
[0]);
1183 ConsoleInfo
->Buffer
= (CHAR16
*)AllocateZeroPool(ConsoleInfo
->BufferSize
);
1185 if (ConsoleInfo
->Buffer
== NULL
) {
1186 return (EFI_OUT_OF_RESOURCES
);
1189 ConsoleInfo
->Attributes
= (INT32
*)AllocateZeroPool(ConsoleInfo
->AttribSize
);
1190 if (ConsoleInfo
->Attributes
== NULL
) {
1191 FreePool(ConsoleInfo
->Buffer
);
1192 ConsoleInfo
->Buffer
= NULL
;
1193 return (EFI_OUT_OF_RESOURCES
);
1196 CopyMem (&ConsoleInfo
->HistoryMode
, ConsoleInfo
->OldConOut
->Mode
, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE
));
1198 return (EFI_SUCCESS
);