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.
16 STATIC CONST CHAR16 mCrLfString
[3] = { CHAR_CARRIAGE_RETURN
, CHAR_LINEFEED
, CHAR_NULL
};
19 Install our intermediate ConOut into the system table to
20 keep a log of all the info that is displayed to the user.
22 @param[in] ScreensToSave Sets how many screen-worths of data to save.
23 @param[out] ConsoleInfo The object to pass into later functions.
25 @retval EFI_SUCCESS The operation was successful.
26 @return other The operation failed.
28 @sa ConsoleLoggerResetBuffers
29 @sa InstallProtocolInterface
34 IN CONST UINTN ScreensToSave
,
35 OUT CONSOLE_LOGGER_PRIVATE_DATA
**ConsoleInfo
39 ASSERT(ConsoleInfo
!= NULL
);
41 (*ConsoleInfo
) = AllocateZeroPool(sizeof(CONSOLE_LOGGER_PRIVATE_DATA
));
42 if ((*ConsoleInfo
) == NULL
) {
43 return (EFI_OUT_OF_RESOURCES
);
46 (*ConsoleInfo
)->Signature
= CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE
;
47 (*ConsoleInfo
)->OldConOut
= gST
->ConOut
;
48 (*ConsoleInfo
)->OldConHandle
= gST
->ConsoleOutHandle
;
49 (*ConsoleInfo
)->Buffer
= NULL
;
50 (*ConsoleInfo
)->BufferSize
= 0;
51 (*ConsoleInfo
)->OriginalStartRow
= 0;
52 (*ConsoleInfo
)->CurrentStartRow
= 0;
53 (*ConsoleInfo
)->RowsPerScreen
= 0;
54 (*ConsoleInfo
)->ColsPerScreen
= 0;
55 (*ConsoleInfo
)->Attributes
= NULL
;
56 (*ConsoleInfo
)->AttribSize
= 0;
57 (*ConsoleInfo
)->ScreenCount
= ScreensToSave
;
58 (*ConsoleInfo
)->HistoryMode
.MaxMode
= 1;
59 (*ConsoleInfo
)->HistoryMode
.Mode
= 0;
60 (*ConsoleInfo
)->HistoryMode
.Attribute
= 0;
61 (*ConsoleInfo
)->HistoryMode
.CursorColumn
= 0;
62 (*ConsoleInfo
)->HistoryMode
.CursorRow
= 0;
63 (*ConsoleInfo
)->HistoryMode
.CursorVisible
= FALSE
;
64 (*ConsoleInfo
)->OurConOut
.Reset
= ConsoleLoggerReset
;
65 (*ConsoleInfo
)->OurConOut
.OutputString
= ConsoleLoggerOutputString
;
66 (*ConsoleInfo
)->OurConOut
.TestString
= ConsoleLoggerTestString
;
67 (*ConsoleInfo
)->OurConOut
.QueryMode
= ConsoleLoggerQueryMode
;
68 (*ConsoleInfo
)->OurConOut
.SetMode
= ConsoleLoggerSetMode
;
69 (*ConsoleInfo
)->OurConOut
.SetAttribute
= ConsoleLoggerSetAttribute
;
70 (*ConsoleInfo
)->OurConOut
.ClearScreen
= ConsoleLoggerClearScreen
;
71 (*ConsoleInfo
)->OurConOut
.SetCursorPosition
= ConsoleLoggerSetCursorPosition
;
72 (*ConsoleInfo
)->OurConOut
.EnableCursor
= ConsoleLoggerEnableCursor
;
73 (*ConsoleInfo
)->OurConOut
.Mode
= gST
->ConOut
->Mode
;
74 (*ConsoleInfo
)->Enabled
= TRUE
;
76 Status
= ConsoleLoggerResetBuffers(*ConsoleInfo
);
77 if (EFI_ERROR(Status
)) {
78 SHELL_FREE_NON_NULL((*ConsoleInfo
));
83 Status
= gBS
->InstallProtocolInterface(&gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, EFI_NATIVE_INTERFACE
, (VOID
*)&((*ConsoleInfo
)->OurConOut
));
84 if (EFI_ERROR(Status
)) {
85 SHELL_FREE_NON_NULL((*ConsoleInfo
)->Buffer
);
86 SHELL_FREE_NON_NULL((*ConsoleInfo
)->Attributes
);
87 SHELL_FREE_NON_NULL((*ConsoleInfo
));
92 gST
->ConsoleOutHandle
= gImageHandle
;
93 gST
->ConOut
= &(*ConsoleInfo
)->OurConOut
;
99 Return the system to the state it was before InstallConsoleLogger
102 @param[in] ConsoleInfo The object from the install function.
104 @retval EFI_SUCCESS The operation was successful
105 @return other The operation failed. This was from UninstallProtocolInterface.
109 ConsoleLoggerUninstall(
110 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
113 ASSERT(ConsoleInfo
!= NULL
);
114 ASSERT(ConsoleInfo
->OldConOut
!= NULL
);
116 if (ConsoleInfo
->Buffer
!= NULL
) {
117 FreePool(ConsoleInfo
->Buffer
);
118 DEBUG_CODE(ConsoleInfo
->Buffer
= NULL
;);
119 DEBUG_CODE(ConsoleInfo
->BufferSize
= 0;);
121 if (ConsoleInfo
->Attributes
!= NULL
) {
122 FreePool(ConsoleInfo
->Attributes
);
123 DEBUG_CODE(ConsoleInfo
->Attributes
= NULL
;);
124 DEBUG_CODE(ConsoleInfo
->AttribSize
= 0;);
127 gST
->ConsoleOutHandle
= ConsoleInfo
->OldConHandle
;
128 gST
->ConOut
= ConsoleInfo
->OldConOut
;
130 return (gBS
->UninstallProtocolInterface(gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, (VOID
*)&ConsoleInfo
->OurConOut
));
134 Displays previously logged output back to the screen.
136 This will scroll the screen forwards and backwards through the log of previous
137 output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows
138 is (UINTN)(-1) then the size of the screen will be scrolled.
140 @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer).
141 If FALSE then the log will be displayed backwards (scroll to older).
142 @param[in] Rows Determines how many rows the log should scroll.
143 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
147 ConsoleLoggerDisplayHistory(
148 IN CONST BOOLEAN Forward
,
150 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
155 ASSERT(ConsoleInfo
!= NULL
);
158 // Calculate the row number change
162 RowChange
= ConsoleInfo
->RowsPerScreen
;
165 RowChange
= ConsoleInfo
->RowsPerScreen
/ 2;
173 // Do the math for direction
176 if ((ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
) < RowChange
) {
177 RowChange
= ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
;
180 if (ConsoleInfo
->CurrentStartRow
< RowChange
) {
181 RowChange
= ConsoleInfo
->CurrentStartRow
;
186 // If we are already at one end or the other
188 if (RowChange
== 0) {
189 return (EFI_SUCCESS
);
195 ConsoleInfo
->OldConOut
->ClearScreen(ConsoleInfo
->OldConOut
);
198 // Set the new start row
201 ConsoleInfo
->CurrentStartRow
+= RowChange
;
203 ConsoleInfo
->CurrentStartRow
-= RowChange
;
209 return (UpdateDisplayFromHistory(ConsoleInfo
));
213 Function to return to normal output whent he scrolling is complete.
214 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
216 @retval EFI_SUCCESS The operation was successful.
217 @return other The operation failed. See UpdateDisplayFromHistory.
219 @sa UpdateDisplayFromHistory
223 ConsoleLoggerStopHistory(
224 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
227 ASSERT(ConsoleInfo
!= NULL
);
228 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
229 return (EFI_SUCCESS
);
231 ConsoleInfo
->CurrentStartRow
= ConsoleInfo
->OriginalStartRow
;
232 return (UpdateDisplayFromHistory(ConsoleInfo
));
236 Updates the hidden ConOut to be displaying the correct stuff.
237 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
239 @retval EFI_SUCCESS The operation was successful.
240 @return other The operation failed.
244 UpdateDisplayFromHistory(
245 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
253 CHAR16 TempCharHolder
;
257 CHAR16
*StringSegment
;
258 CHAR16
*StringSegmentEnd
;
259 CHAR16 StringSegmentEndChar
;
262 ASSERT(ConsoleInfo
!= NULL
);
263 TempCharHolder
= CHAR_NULL
;
264 RetVal
= EFI_SUCCESS
;
265 OrigAttribute
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
268 // Disable cursor visibility and move it to the top left corner
270 ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, FALSE
);
271 ConsoleInfo
->OldConOut
->SetCursorPosition (ConsoleInfo
->OldConOut
, 0, 0);
273 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
274 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
276 ; CurrentRow
< ConsoleInfo
->RowsPerScreen
278 , Screen
+= (ConsoleInfo
->ColsPerScreen
+ 2)
279 , Attributes
+= ConsoleInfo
->ColsPerScreen
282 // dont use the last char - prevents screen scroll
284 if (CurrentRow
== (ConsoleInfo
->RowsPerScreen
-1)){
285 TempCharHolder
= Screen
[ConsoleInfo
->ColsPerScreen
- 1];
286 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = CHAR_NULL
;
290 ; Column
< ConsoleInfo
->ColsPerScreen
293 if (Screen
[Column
] != CHAR_NULL
) {
294 CurrentAttrib
= Attributes
[Column
];
295 CurrentColumn
= Column
;
296 StringSegment
= &Screen
[Column
];
299 // Find the first char with a different arrribute and make that temporarily NULL
300 // so we can do fewer printout statements. (later) restore that one and we will
301 // start at that collumn on the next loop.
303 StringSegmentEndChar
= CHAR_NULL
;
304 for ( StringSegmentEnd
= StringSegment
305 ; StringSegmentEnd
!= CHAR_NULL
309 if (Attributes
[Column
] != CurrentAttrib
) {
310 StringSegmentEndChar
= *StringSegmentEnd
;
311 *StringSegmentEnd
= CHAR_NULL
;
314 } // StringSegmentEnd loop
317 // Now write out as much as had the same Attributes
320 ConsoleInfo
->OldConOut
->SetAttribute(ConsoleInfo
->OldConOut
, CurrentAttrib
);
321 ConsoleInfo
->OldConOut
->SetCursorPosition(ConsoleInfo
->OldConOut
, CurrentColumn
, CurrentRow
);
322 Status
= ConsoleInfo
->OldConOut
->OutputString(ConsoleInfo
->OldConOut
, StringSegment
);
324 if (EFI_ERROR(Status
)) {
330 // If we found a change in attribute put the character back and decrement the column
331 // so when it increments it will point at that character and we will start printing
332 // a segment with that new attribute
334 if (StringSegmentEndChar
!= CHAR_NULL
) {
335 *StringSegmentEnd
= StringSegmentEndChar
;
336 StringSegmentEndChar
= CHAR_NULL
;
343 // If we removed the last char and this was the last row put it back
345 if (TempCharHolder
!= CHAR_NULL
) {
346 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = TempCharHolder
;
347 TempCharHolder
= CHAR_NULL
;
352 // If we are setting the screen back to original turn on the cursor and make it visible
353 // and set the attributes back to what they were
355 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
356 ConsoleInfo
->OldConOut
->SetAttribute (
357 ConsoleInfo
->OldConOut
,
358 ConsoleInfo
->HistoryMode
.Attribute
360 ConsoleInfo
->OldConOut
->SetCursorPosition (
361 ConsoleInfo
->OldConOut
,
362 ConsoleInfo
->HistoryMode
.CursorColumn
,
363 ConsoleInfo
->HistoryMode
.CursorRow
- ConsoleInfo
->OriginalStartRow
366 Status
= ConsoleInfo
->OldConOut
->EnableCursor (
367 ConsoleInfo
->OldConOut
,
368 ConsoleInfo
->HistoryMode
.CursorVisible
370 if (EFI_ERROR (Status
)) {
374 ConsoleInfo
->OldConOut
->SetAttribute (
375 ConsoleInfo
->OldConOut
,
384 Reset the text output device hardware and optionaly run diagnostics
386 @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
387 @param ExtendedVerification Indicates that a more extensive test may be performed
389 @retval EFI_SUCCESS The text output device was reset.
390 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
396 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
397 IN BOOLEAN ExtendedVerification
401 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
402 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
405 // Forward the request to the original ConOut
407 Status
= ConsoleInfo
->OldConOut
->Reset (ConsoleInfo
->OldConOut
, ExtendedVerification
);
410 // Check that the buffers are still correct for logging
412 if (!EFI_ERROR (Status
)) {
413 ConsoleLoggerResetBuffers(ConsoleInfo
);
420 Appends a string to the history buffer. If the buffer is full then the oldest
421 information in the buffer will be dropped. Information is added in a line by
422 line manner such that an empty line takes up just as much space as a full line.
424 @param[in] String String pointer to add.
425 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
429 AppendStringToHistory(
430 IN CONST CHAR16
*String
,
431 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
434 CONST CHAR16
*Walker
;
439 ASSERT(ConsoleInfo
!= NULL
);
441 for ( Walker
= String
442 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
446 case (CHAR_BACKSPACE
):
447 if (ConsoleInfo
->HistoryMode
.CursorColumn
> 0) {
448 ConsoleInfo
->HistoryMode
.CursorColumn
--;
451 case (CHAR_LINEFEED
):
452 if (ConsoleInfo
->HistoryMode
.CursorRow
>= (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1)) {
454 // Should never be bigger
456 ASSERT(ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1));
459 // scroll history attributes 'up' 1 row and set the last row to default attribute
461 CopySize
= ConsoleInfo
->ColsPerScreen
462 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
463 * sizeof(ConsoleInfo
->Attributes
[0]);
464 ASSERT(CopySize
< ConsoleInfo
->AttribSize
);
466 ConsoleInfo
->Attributes
,
467 ConsoleInfo
->Attributes
+ ConsoleInfo
->ColsPerScreen
,
472 ; Index
< ConsoleInfo
->ColsPerScreen
475 *(ConsoleInfo
->Attributes
+ (CopySize
/sizeof(ConsoleInfo
->Attributes
[0])) + Index
) = ConsoleInfo
->HistoryMode
.Attribute
;
479 // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
481 CopySize
= (ConsoleInfo
->ColsPerScreen
+ 2)
482 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
483 * sizeof(ConsoleInfo
->Buffer
[0]);
484 ASSERT(CopySize
< ConsoleInfo
->BufferSize
);
487 ConsoleInfo
->Buffer
+ (ConsoleInfo
->ColsPerScreen
+ 2),
492 // Set that last row of chars to spaces
494 SetMem16(((UINT8
*)ConsoleInfo
->Buffer
)+CopySize
, ConsoleInfo
->ColsPerScreen
*sizeof(CHAR16
), L
' ');
497 // we are not on the last row
501 // We should not be scrolling history
503 ASSERT (ConsoleInfo
->OriginalStartRow
== ConsoleInfo
->CurrentStartRow
);
505 // are we at the end of a row?
507 if (ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
) (ConsoleInfo
->OriginalStartRow
+ ConsoleInfo
->RowsPerScreen
- 1)) {
508 ConsoleInfo
->OriginalStartRow
++;
509 ConsoleInfo
->CurrentStartRow
++;
511 ConsoleInfo
->HistoryMode
.CursorRow
++;
514 case (CHAR_CARRIAGE_RETURN
):
516 // Move the cursor to the beginning of the current row.
518 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
522 // Acrtually print characters into the history buffer
525 PrintIndex
= ConsoleInfo
->HistoryMode
.CursorRow
* ConsoleInfo
->ColsPerScreen
+ ConsoleInfo
->HistoryMode
.CursorColumn
;
527 for ( // no initializer needed
528 ; ConsoleInfo
->HistoryMode
.CursorColumn
< (INT32
) ConsoleInfo
->ColsPerScreen
529 ; ConsoleInfo
->HistoryMode
.CursorColumn
++
533 if (*Walker
== CHAR_NULL
534 ||*Walker
== CHAR_BACKSPACE
535 ||*Walker
== CHAR_LINEFEED
536 ||*Walker
== CHAR_CARRIAGE_RETURN
542 // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
545 ASSERT(PrintIndex
+ ConsoleInfo
->HistoryMode
.CursorRow
< ConsoleInfo
->BufferSize
);
546 ConsoleInfo
->Buffer
[PrintIndex
+ (2*ConsoleInfo
->HistoryMode
.CursorRow
)] = *Walker
;
547 ASSERT(PrintIndex
< ConsoleInfo
->AttribSize
);
548 ConsoleInfo
->Attributes
[PrintIndex
] = ConsoleInfo
->HistoryMode
.Attribute
;
552 // Add the carriage return and line feed at the end of the lines
554 if (ConsoleInfo
->HistoryMode
.CursorColumn
>= (INT32
)ConsoleInfo
->ColsPerScreen
) {
555 AppendStringToHistory(L
"\r\n", ConsoleInfo
);
560 } // switch for character
563 return (EFI_SUCCESS
);
567 Worker function to handle printing the output to the screen
568 and the history buffer
570 @param[in] String The string to output
571 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
573 @retval EFI_SUCCESS The string was printed
574 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
576 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
578 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
579 characters in the Unicode string could not be
580 rendered and were skipped.
584 ConsoleLoggerOutputStringSplit(
585 IN CONST CHAR16
*String
,
586 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
592 // Forward the request to the original ConOut
594 Status
= ConsoleInfo
->OldConOut
->OutputString (ConsoleInfo
->OldConOut
, (CHAR16
*)String
);
596 if (EFI_ERROR(Status
)) {
600 return (AppendStringToHistory(String
, ConsoleInfo
));
604 Function to handle page break mode.
606 This function will prompt for continue or break.
608 @retval EFI_SUCCESS Continue was choosen
609 @return other Break was choosen
613 ConsoleLoggerDoPageBreak(
617 SHELL_PROMPT_RESPONSE
*Resp
;
621 ASSERT(ShellInfoObject
.PageBreakEnabled
);
622 ShellInfoObject
.PageBreakEnabled
= FALSE
;
623 Status
= ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue
, STRING_TOKEN(STR_SHELL_QUIT_CONT
), ShellInfoObject
.HiiHandle
, (VOID
**)&Resp
);
624 ShellInfoObject
.PageBreakEnabled
= TRUE
;
625 ASSERT(Resp
!= NULL
);
627 return (EFI_NOT_FOUND
);
629 if (EFI_ERROR(Status
)) {
635 if (*Resp
== ShellPromptResponseContinue
) {
637 ShellInfoObject
.ConsoleInfo
->RowCounter
= 0;
638 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorRow = 0;
639 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
641 return (EFI_SUCCESS
);
642 } else if (*Resp
== ShellPromptResponseQuit
) {
644 ShellInfoObject
.ConsoleInfo
->Enabled
= FALSE
;
645 return (EFI_DEVICE_ERROR
);
649 return (EFI_SUCCESS
);
652 Worker function to handle printing the output with page breaks.
654 @param[in] String The string to output
655 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
657 @retval EFI_SUCCESS The string was printed
658 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
660 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
662 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
663 characters in the Unicode string could not be
664 rendered and were skipped.
668 ConsoleLoggerPrintWithPageBreak(
669 IN CONST CHAR16
*String
,
670 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
673 CONST CHAR16
*Walker
;
674 CONST CHAR16
*LineStart
;
679 StringCopy
= StrnCatGrow(&StringCopy
, NULL
, String
, 0);
680 if (StringCopy
== NULL
) {
681 return (EFI_OUT_OF_RESOURCES
);
684 for ( Walker
= StringCopy
685 , LineStart
= StringCopy
686 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
690 case (CHAR_BACKSPACE
):
691 if (ConsoleInfo
->OurConOut
.Mode
->CursorColumn
> 0) {
692 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
--;
695 case (CHAR_LINEFEED
):
697 // add a temp NULL terminator
699 TempChar
= *(Walker
+ 1);
700 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
705 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
708 // restore the temp NULL terminator to it's original character
710 *((CHAR16
*)(Walker
+1)) = TempChar
;
713 // Update LineStart Variable
715 LineStart
= Walker
+ 1;
718 // increment row count
720 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
721 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
724 case (CHAR_CARRIAGE_RETURN
):
726 // Move the cursor to the beginning of the current row.
728 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
732 // increment column count
734 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
++;
736 // check if that is the last column
738 if ((INTN
)ConsoleInfo
->ColsPerScreen
== ConsoleInfo
->OurConOut
.Mode
->CursorColumn
+ 1) {
740 // output a line similar to the linefeed character.
744 // add a temp NULL terminator
746 TempChar
= *(Walker
+ 1);
747 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
752 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
755 // restore the temp NULL terminator to it's original character
757 *((CHAR16
*)(Walker
+1)) = TempChar
;
760 // Update LineStart Variable
762 LineStart
= Walker
+ 1;
765 // increment row count and zero the column
767 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
768 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
769 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
770 } // last column on line
772 } // switch for character
775 // check if that was the last printable row. If yes handle PageBreak mode
777 if ((ConsoleInfo
->RowsPerScreen
) -1 == ShellInfoObject
.ConsoleInfo
->RowCounter
) {
778 if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
780 // We got an error which means 'break' and halt the printing
782 SHELL_FREE_NON_NULL(StringCopy
);
783 return (EFI_DEVICE_ERROR
);
788 if (LineStart
!= NULL
&& *LineStart
!= CHAR_NULL
) {
789 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
792 SHELL_FREE_NON_NULL(StringCopy
);
793 return (EFI_SUCCESS
);
797 Write a Unicode string to the output device.
799 @param[in] This Protocol instance pointer.
800 @param[in] WString The NULL-terminated Unicode string to be displayed on the output
801 device(s). All output devices must also support the Unicode
802 drawing defined in this file.
803 @retval EFI_SUCCESS The string was output to the device.
804 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
806 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
808 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
809 characters in the Unicode string could not be
810 rendered and were skipped.
814 ConsoleLoggerOutputString (
815 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
821 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
822 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
823 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
824 return (EFI_UNSUPPORTED
);
826 ASSERT(ShellInfoObject
.ConsoleInfo
== ConsoleInfo
);
827 if (ShellInfoObject
.HaltOutput
) {
831 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &EventIndex
);
832 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
833 ShellInfoObject
.HaltOutput
= FALSE
;
835 if (!ShellInfoObject
.ConsoleInfo
->Enabled
) {
836 return (EFI_DEVICE_ERROR
);
837 } else if (ShellInfoObject
.PageBreakEnabled
) {
838 return (ConsoleLoggerPrintWithPageBreak(WString
, ConsoleInfo
));
840 return (ConsoleLoggerOutputStringSplit(WString
, ConsoleInfo
));
845 Verifies that all characters in a Unicode string can be output to the
848 @param[in] This Protocol instance pointer.
849 @param[in] WString The NULL-terminated Unicode string to be examined for the output
852 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
853 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
854 rendered by one or more of the output devices mapped
860 ConsoleLoggerTestString (
861 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
865 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
866 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
868 // Forward the request to the original ConOut
870 return (ConsoleInfo
->OldConOut
->TestString (ConsoleInfo
->OldConOut
, WString
));
874 Returns information for an available text mode that the output device(s)
877 @param[in] This Protocol instance pointer.
878 @param[in] ModeNumber The mode number to return information on.
879 @param[out] Columns Upon return, the number of columns in the selected geometry
880 @param[out] Rows Upon return, the number of rows in the selected geometry
882 @retval EFI_SUCCESS The requested mode information was returned.
883 @retval EFI_DEVICE_ERROR The device had an error and could not
884 complete the request.
885 @retval EFI_UNSUPPORTED The mode number was not valid.
889 ConsoleLoggerQueryMode (
890 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
896 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
897 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
899 // Forward the request to the original ConOut
901 return (ConsoleInfo
->OldConOut
->QueryMode (
902 ConsoleInfo
->OldConOut
,
910 Sets the output device(s) to a specified mode.
912 @param[in] This Protocol instance pointer.
913 @param[in] ModeNumber The mode number to set.
916 @retval EFI_SUCCESS The requested text mode was set.
917 @retval EFI_DEVICE_ERROR The device had an error and
918 could not complete the request.
919 @retval EFI_UNSUPPORTED The mode number was not valid.
923 ConsoleLoggerSetMode (
924 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
930 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
931 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
934 // Forward the request to the original ConOut
936 Status
= ConsoleInfo
->OldConOut
->SetMode (ConsoleInfo
->OldConOut
, ModeNumber
);
939 // Check that the buffers are still correct for logging
941 if (!EFI_ERROR (Status
)) {
942 ConsoleInfo
->OurConOut
.Mode
= gST
->ConOut
->Mode
;
943 ConsoleLoggerResetBuffers(ConsoleInfo
);
950 Sets the background and foreground colors for the OutputString () and
951 ClearScreen () functions.
953 @param[in] This Protocol instance pointer.
954 @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
955 bits 4..6 are the background color. All other bits are undefined
956 and must be zero. The valid Attributes are defined in this file.
958 @retval EFI_SUCCESS The attribute was set.
959 @retval EFI_DEVICE_ERROR The device had an error and
960 could not complete the request.
961 @retval EFI_UNSUPPORTED The attribute requested is not defined.
966 ConsoleLoggerSetAttribute (
967 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
973 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
974 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
977 // Forward the request to the original ConOut
979 Status
= ConsoleInfo
->OldConOut
->SetAttribute (ConsoleInfo
->OldConOut
, Attribute
);
982 // Record console output history
984 if (!EFI_ERROR (Status
)) {
985 ConsoleInfo
->HistoryMode
.Attribute
= (INT32
) Attribute
;
992 Clears the output device(s) display to the currently selected background
995 @param[in] This Protocol instance pointer.
997 @retval EFI_SUCCESS The operation completed successfully.
998 @retval EFI_DEVICE_ERROR The device had an error and
999 could not complete the request.
1000 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1004 ConsoleLoggerClearScreen (
1005 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
1013 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1015 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
1016 return (EFI_UNSUPPORTED
);
1019 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1022 // Forward the request to the original ConOut
1024 Status
= ConsoleInfo
->OldConOut
->ClearScreen (ConsoleInfo
->OldConOut
);
1027 // Record console output history
1029 if (!EFI_ERROR (Status
)) {
1030 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
1031 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
1032 for ( Row
= ConsoleInfo
->OriginalStartRow
1033 ; Row
< (ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)
1037 ; Column
< ConsoleInfo
->ColsPerScreen
1043 *Attributes
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
1046 // Skip the NULL on each column end in text buffer only
1050 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
1051 ConsoleInfo
->HistoryMode
.CursorRow
= 0;
1058 Sets the current coordinates of the cursor position
1060 @param[in] This Protocol instance pointer.
1061 @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
1062 @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
1064 @retval EFI_SUCCESS The operation completed successfully.
1065 @retval EFI_DEVICE_ERROR The device had an error and
1066 could not complete the request.
1067 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
1068 cursor position is invalid for the current mode.
1072 ConsoleLoggerSetCursorPosition (
1073 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1079 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1081 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
1082 return (EFI_UNSUPPORTED
);
1085 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1087 // Forward the request to the original ConOut
1089 Status
= ConsoleInfo
->OldConOut
->SetCursorPosition (
1090 ConsoleInfo
->OldConOut
,
1096 // Record console output history
1098 if (!EFI_ERROR (Status
)) {
1099 ConsoleInfo
->HistoryMode
.CursorColumn
= (INT32
)Column
;
1100 ConsoleInfo
->HistoryMode
.CursorRow
= (INT32
)(ConsoleInfo
->OriginalStartRow
+ Row
);
1107 Makes the cursor visible or invisible
1109 @param[in] This Protocol instance pointer.
1110 @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
1111 set to be invisible.
1113 @retval EFI_SUCCESS The operation completed successfully.
1114 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1115 request, or the device does not support changing
1117 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1121 ConsoleLoggerEnableCursor (
1122 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1128 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1129 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1131 // Forward the request to the original ConOut
1133 Status
= ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, Visible
);
1136 // Record console output history
1138 if (!EFI_ERROR (Status
)) {
1139 ConsoleInfo
->HistoryMode
.CursorVisible
= Visible
;
1146 Function to update and verify that the current buffers are correct.
1148 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
1150 This will be used when a mode has changed or a reset ocurred to verify all
1155 ConsoleLoggerResetBuffers(
1156 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
1161 if (ConsoleInfo
->Buffer
!= NULL
) {
1162 FreePool(ConsoleInfo
->Buffer
);
1163 ConsoleInfo
->Buffer
= NULL
;
1164 ConsoleInfo
->BufferSize
= 0;
1166 if (ConsoleInfo
->Attributes
!= NULL
) {
1167 FreePool(ConsoleInfo
->Attributes
);
1168 ConsoleInfo
->Attributes
= NULL
;
1169 ConsoleInfo
->AttribSize
= 0;
1172 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &ConsoleInfo
->ColsPerScreen
, &ConsoleInfo
->RowsPerScreen
);
1173 if (EFI_ERROR(Status
)){
1177 ConsoleInfo
->BufferSize
= (ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Buffer
[0]);
1178 ConsoleInfo
->AttribSize
= ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Attributes
[0]);
1180 ConsoleInfo
->Buffer
= (CHAR16
*)AllocateZeroPool(ConsoleInfo
->BufferSize
);
1182 if (ConsoleInfo
->Buffer
== NULL
) {
1183 return (EFI_OUT_OF_RESOURCES
);
1186 ConsoleInfo
->Attributes
= (INT32
*)AllocateZeroPool(ConsoleInfo
->AttribSize
);
1187 if (ConsoleInfo
->Attributes
== NULL
) {
1188 FreePool(ConsoleInfo
->Buffer
);
1189 ConsoleInfo
->Buffer
= NULL
;
1190 return (EFI_OUT_OF_RESOURCES
);
1193 CopyMem (&ConsoleInfo
->HistoryMode
, ConsoleInfo
->OldConOut
->Mode
, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE
));
1195 return (EFI_SUCCESS
);