2 Provides interface to shell console logger.
4 (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
6 (C) Copyright 2016 Hewlett-Packard Development Company, L.P.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
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
;
96 // Update the CRC32 in the EFI System Table header
108 Return the system to the state it was before InstallConsoleLogger
111 @param[in] ConsoleInfo The object from the install function.
113 @retval EFI_SUCCESS The operation was successful
114 @return other The operation failed. This was from UninstallProtocolInterface.
118 ConsoleLoggerUninstall(
119 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
122 ASSERT(ConsoleInfo
!= NULL
);
123 ASSERT(ConsoleInfo
->OldConOut
!= NULL
);
125 if (ConsoleInfo
->Buffer
!= NULL
) {
126 FreePool(ConsoleInfo
->Buffer
);
127 DEBUG_CODE(ConsoleInfo
->Buffer
= NULL
;);
128 DEBUG_CODE(ConsoleInfo
->BufferSize
= 0;);
130 if (ConsoleInfo
->Attributes
!= NULL
) {
131 FreePool(ConsoleInfo
->Attributes
);
132 DEBUG_CODE(ConsoleInfo
->Attributes
= NULL
;);
133 DEBUG_CODE(ConsoleInfo
->AttribSize
= 0;);
136 gST
->ConsoleOutHandle
= ConsoleInfo
->OldConHandle
;
137 gST
->ConOut
= ConsoleInfo
->OldConOut
;
140 // Update the CRC32 in the EFI System Table header
143 gBS
->CalculateCrc32 (
149 return (gBS
->UninstallProtocolInterface(gImageHandle
, &gEfiSimpleTextOutProtocolGuid
, (VOID
*)&ConsoleInfo
->OurConOut
));
153 Displays previously logged output back to the screen.
155 This will scroll the screen forwards and backwards through the log of previous
156 output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows
157 is (UINTN)(-1) then the size of the screen will be scrolled.
159 @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer).
160 If FALSE then the log will be displayed backwards (scroll to older).
161 @param[in] Rows Determines how many rows the log should scroll.
162 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
166 ConsoleLoggerDisplayHistory(
167 IN CONST BOOLEAN Forward
,
169 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
174 ASSERT(ConsoleInfo
!= NULL
);
177 // Calculate the row number change
181 RowChange
= ConsoleInfo
->RowsPerScreen
;
184 RowChange
= ConsoleInfo
->RowsPerScreen
/ 2;
192 // Do the math for direction
195 if ((ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
) < RowChange
) {
196 RowChange
= ConsoleInfo
->OriginalStartRow
- ConsoleInfo
->CurrentStartRow
;
199 if (ConsoleInfo
->CurrentStartRow
< RowChange
) {
200 RowChange
= ConsoleInfo
->CurrentStartRow
;
205 // If we are already at one end or the other
207 if (RowChange
== 0) {
208 return (EFI_SUCCESS
);
214 ConsoleInfo
->OldConOut
->ClearScreen(ConsoleInfo
->OldConOut
);
217 // Set the new start row
220 ConsoleInfo
->CurrentStartRow
+= RowChange
;
222 ConsoleInfo
->CurrentStartRow
-= RowChange
;
228 return (UpdateDisplayFromHistory(ConsoleInfo
));
232 Function to return to normal output whent he scrolling is complete.
233 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
235 @retval EFI_SUCCESS The operation was successful.
236 @return other The operation failed. See UpdateDisplayFromHistory.
238 @sa UpdateDisplayFromHistory
242 ConsoleLoggerStopHistory(
243 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
246 ASSERT(ConsoleInfo
!= NULL
);
247 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
248 return (EFI_SUCCESS
);
254 ConsoleInfo
->OldConOut
->ClearScreen(ConsoleInfo
->OldConOut
);
256 ConsoleInfo
->CurrentStartRow
= ConsoleInfo
->OriginalStartRow
;
257 return (UpdateDisplayFromHistory(ConsoleInfo
));
261 Updates the hidden ConOut to be displaying the correct stuff.
262 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
264 @retval EFI_SUCCESS The operation was successful.
265 @return other The operation failed.
269 UpdateDisplayFromHistory(
270 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
278 CHAR16 TempCharHolder
;
282 CHAR16
*StringSegment
;
283 CHAR16
*StringSegmentEnd
;
284 CHAR16 StringSegmentEndChar
;
287 ASSERT(ConsoleInfo
!= NULL
);
288 TempCharHolder
= CHAR_NULL
;
289 RetVal
= EFI_SUCCESS
;
290 OrigAttribute
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
293 // Disable cursor visibility and move it to the top left corner
295 ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, FALSE
);
296 ConsoleInfo
->OldConOut
->SetCursorPosition (ConsoleInfo
->OldConOut
, 0, 0);
298 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
299 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
301 ; CurrentRow
< ConsoleInfo
->RowsPerScreen
303 , Screen
+= (ConsoleInfo
->ColsPerScreen
+ 2)
304 , Attributes
+= ConsoleInfo
->ColsPerScreen
307 // dont use the last char - prevents screen scroll
309 if (CurrentRow
== (ConsoleInfo
->RowsPerScreen
-1)){
310 TempCharHolder
= Screen
[ConsoleInfo
->ColsPerScreen
- 1];
311 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = CHAR_NULL
;
315 ; Column
< ConsoleInfo
->ColsPerScreen
318 if (Screen
[Column
] != CHAR_NULL
) {
319 CurrentAttrib
= Attributes
[Column
];
320 CurrentColumn
= Column
;
321 StringSegment
= &Screen
[Column
];
324 // Find the first char with a different arrribute and make that temporarily NULL
325 // so we can do fewer printout statements. (later) restore that one and we will
326 // start at that collumn on the next loop.
328 StringSegmentEndChar
= CHAR_NULL
;
329 for ( StringSegmentEnd
= StringSegment
330 ; StringSegmentEnd
!= CHAR_NULL
334 if (Attributes
[Column
] != CurrentAttrib
) {
335 StringSegmentEndChar
= *StringSegmentEnd
;
336 *StringSegmentEnd
= CHAR_NULL
;
339 } // StringSegmentEnd loop
342 // Now write out as much as had the same Attributes
345 ConsoleInfo
->OldConOut
->SetAttribute(ConsoleInfo
->OldConOut
, CurrentAttrib
);
346 ConsoleInfo
->OldConOut
->SetCursorPosition(ConsoleInfo
->OldConOut
, CurrentColumn
, CurrentRow
);
347 Status
= ConsoleInfo
->OldConOut
->OutputString(ConsoleInfo
->OldConOut
, StringSegment
);
349 if (EFI_ERROR(Status
)) {
355 // If we found a change in attribute put the character back and decrement the column
356 // so when it increments it will point at that character and we will start printing
357 // a segment with that new attribute
359 if (StringSegmentEndChar
!= CHAR_NULL
) {
360 *StringSegmentEnd
= StringSegmentEndChar
;
361 StringSegmentEndChar
= CHAR_NULL
;
368 // If we removed the last char and this was the last row put it back
370 if (TempCharHolder
!= CHAR_NULL
) {
371 Screen
[ConsoleInfo
->ColsPerScreen
- 1] = TempCharHolder
;
372 TempCharHolder
= CHAR_NULL
;
377 // If we are setting the screen back to original turn on the cursor and make it visible
378 // and set the attributes back to what they were
380 if (ConsoleInfo
->CurrentStartRow
== ConsoleInfo
->OriginalStartRow
) {
381 ConsoleInfo
->OldConOut
->SetAttribute (
382 ConsoleInfo
->OldConOut
,
383 ConsoleInfo
->HistoryMode
.Attribute
385 ConsoleInfo
->OldConOut
->SetCursorPosition (
386 ConsoleInfo
->OldConOut
,
387 ConsoleInfo
->HistoryMode
.CursorColumn
,
388 ConsoleInfo
->HistoryMode
.CursorRow
- ConsoleInfo
->OriginalStartRow
391 Status
= ConsoleInfo
->OldConOut
->EnableCursor (
392 ConsoleInfo
->OldConOut
,
393 ConsoleInfo
->HistoryMode
.CursorVisible
395 if (EFI_ERROR (Status
)) {
399 ConsoleInfo
->OldConOut
->SetAttribute (
400 ConsoleInfo
->OldConOut
,
409 Reset the text output device hardware and optionaly run diagnostics
411 @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
412 @param ExtendedVerification Indicates that a more extensive test may be performed
414 @retval EFI_SUCCESS The text output device was reset.
415 @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
421 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
422 IN BOOLEAN ExtendedVerification
426 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
427 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
430 // Forward the request to the original ConOut
432 Status
= ConsoleInfo
->OldConOut
->Reset (ConsoleInfo
->OldConOut
, ExtendedVerification
);
435 // Check that the buffers are still correct for logging
437 if (!EFI_ERROR (Status
)) {
438 ConsoleLoggerResetBuffers(ConsoleInfo
);
439 if (ExtendedVerification
) {
440 ConsoleInfo
->OriginalStartRow
= 0;
441 ConsoleInfo
->CurrentStartRow
= 0;
449 Appends a string to the history buffer. If the buffer is full then the oldest
450 information in the buffer will be dropped. Information is added in a line by
451 line manner such that an empty line takes up just as much space as a full line.
453 @param[in] String String pointer to add.
454 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
458 AppendStringToHistory(
459 IN CONST CHAR16
*String
,
460 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
463 CONST CHAR16
*Walker
;
468 ASSERT(ConsoleInfo
!= NULL
);
470 for ( Walker
= String
471 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
475 case (CHAR_BACKSPACE
):
476 if (ConsoleInfo
->HistoryMode
.CursorColumn
> 0) {
477 ConsoleInfo
->HistoryMode
.CursorColumn
--;
480 case (CHAR_LINEFEED
):
481 if (ConsoleInfo
->HistoryMode
.CursorRow
>= (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1)) {
483 // Should never be bigger
485 ASSERT(ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
)((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)-1));
488 // scroll history attributes 'up' 1 row and set the last row to default attribute
490 CopySize
= ConsoleInfo
->ColsPerScreen
491 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
492 * sizeof(ConsoleInfo
->Attributes
[0]);
493 ASSERT(CopySize
< ConsoleInfo
->AttribSize
);
495 ConsoleInfo
->Attributes
,
496 ConsoleInfo
->Attributes
+ ConsoleInfo
->ColsPerScreen
,
501 ; Index
< ConsoleInfo
->ColsPerScreen
504 *(ConsoleInfo
->Attributes
+ (CopySize
/sizeof(ConsoleInfo
->Attributes
[0])) + Index
) = ConsoleInfo
->HistoryMode
.Attribute
;
508 // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
510 CopySize
= (ConsoleInfo
->ColsPerScreen
+ 2)
511 * ((ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
) - 1)
512 * sizeof(ConsoleInfo
->Buffer
[0]);
513 ASSERT(CopySize
< ConsoleInfo
->BufferSize
);
516 ConsoleInfo
->Buffer
+ (ConsoleInfo
->ColsPerScreen
+ 2),
521 // Set that last row of chars to spaces
523 SetMem16(((UINT8
*)ConsoleInfo
->Buffer
)+CopySize
, ConsoleInfo
->ColsPerScreen
*sizeof(CHAR16
), L
' ');
526 // we are not on the last row
530 // We should not be scrolling history
532 ASSERT (ConsoleInfo
->OriginalStartRow
== ConsoleInfo
->CurrentStartRow
);
534 // are we at the end of a row?
536 if (ConsoleInfo
->HistoryMode
.CursorRow
== (INT32
) (ConsoleInfo
->OriginalStartRow
+ ConsoleInfo
->RowsPerScreen
- 1)) {
537 ConsoleInfo
->OriginalStartRow
++;
538 ConsoleInfo
->CurrentStartRow
++;
540 ConsoleInfo
->HistoryMode
.CursorRow
++;
543 case (CHAR_CARRIAGE_RETURN
):
545 // Move the cursor to the beginning of the current row.
547 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
551 // Acrtually print characters into the history buffer
554 PrintIndex
= ConsoleInfo
->HistoryMode
.CursorRow
* ConsoleInfo
->ColsPerScreen
+ ConsoleInfo
->HistoryMode
.CursorColumn
;
556 for ( // no initializer needed
557 ; ConsoleInfo
->HistoryMode
.CursorColumn
< (INT32
) ConsoleInfo
->ColsPerScreen
558 ; ConsoleInfo
->HistoryMode
.CursorColumn
++
562 if (*Walker
== CHAR_NULL
563 ||*Walker
== CHAR_BACKSPACE
564 ||*Walker
== CHAR_LINEFEED
565 ||*Walker
== CHAR_CARRIAGE_RETURN
571 // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
574 ASSERT(PrintIndex
+ ConsoleInfo
->HistoryMode
.CursorRow
< ConsoleInfo
->BufferSize
);
575 ConsoleInfo
->Buffer
[PrintIndex
+ (2*ConsoleInfo
->HistoryMode
.CursorRow
)] = *Walker
;
576 ASSERT(PrintIndex
< ConsoleInfo
->AttribSize
);
577 ConsoleInfo
->Attributes
[PrintIndex
] = ConsoleInfo
->HistoryMode
.Attribute
;
581 // Add the carriage return and line feed at the end of the lines
583 if (ConsoleInfo
->HistoryMode
.CursorColumn
>= (INT32
)ConsoleInfo
->ColsPerScreen
) {
584 AppendStringToHistory(L
"\r\n", ConsoleInfo
);
589 } // switch for character
592 return (EFI_SUCCESS
);
596 Worker function to handle printing the output to the screen
597 and the history buffer
599 @param[in] String The string to output
600 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
602 @retval EFI_SUCCESS The string was printed
603 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
605 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
607 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
608 characters in the Unicode string could not be
609 rendered and were skipped.
613 ConsoleLoggerOutputStringSplit(
614 IN CONST CHAR16
*String
,
615 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
621 // Forward the request to the original ConOut
623 Status
= ConsoleInfo
->OldConOut
->OutputString (ConsoleInfo
->OldConOut
, (CHAR16
*)String
);
625 if (EFI_ERROR(Status
)) {
629 return (AppendStringToHistory(String
, ConsoleInfo
));
633 Function to handle page break mode.
635 This function will prompt for continue or break.
637 @retval EFI_SUCCESS Continue was choosen
638 @return other Break was choosen
642 ConsoleLoggerDoPageBreak(
646 SHELL_PROMPT_RESPONSE
*Resp
;
650 ASSERT(ShellInfoObject
.PageBreakEnabled
);
651 ShellInfoObject
.PageBreakEnabled
= FALSE
;
652 Status
= ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue
, STRING_TOKEN(STR_SHELL_QUIT_CONT
), ShellInfoObject
.HiiHandle
, (VOID
**)&Resp
);
653 ShellInfoObject
.PageBreakEnabled
= TRUE
;
654 ASSERT(Resp
!= NULL
);
656 return (EFI_NOT_FOUND
);
658 if (EFI_ERROR(Status
)) {
664 if (*Resp
== ShellPromptResponseContinue
) {
666 ShellInfoObject
.ConsoleInfo
->RowCounter
= 0;
667 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorRow = 0;
668 // ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
670 return (EFI_SUCCESS
);
671 } else if (*Resp
== ShellPromptResponseQuit
) {
673 ShellInfoObject
.ConsoleInfo
->Enabled
= FALSE
;
675 // When user wants to quit, the shell should stop running the command.
677 gBS
->SignalEvent (ShellInfoObject
.NewEfiShellProtocol
->ExecutionBreak
);
678 return (EFI_DEVICE_ERROR
);
682 return (EFI_SUCCESS
);
685 Worker function to handle printing the output with page breaks.
687 @param[in] String The string to output
688 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
690 @retval EFI_SUCCESS The string was printed
691 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
693 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
695 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
696 characters in the Unicode string could not be
697 rendered and were skipped.
701 ConsoleLoggerPrintWithPageBreak(
702 IN CONST CHAR16
*String
,
703 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
706 CONST CHAR16
*Walker
;
707 CONST CHAR16
*LineStart
;
712 StringCopy
= StrnCatGrow(&StringCopy
, NULL
, String
, 0);
713 if (StringCopy
== NULL
) {
714 return (EFI_OUT_OF_RESOURCES
);
717 for ( Walker
= StringCopy
718 , LineStart
= StringCopy
719 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
723 case (CHAR_BACKSPACE
):
724 if (ConsoleInfo
->OurConOut
.Mode
->CursorColumn
> 0) {
725 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
--;
728 case (CHAR_LINEFEED
):
730 // add a temp NULL terminator
732 TempChar
= *(Walker
+ 1);
733 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
738 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
741 // restore the temp NULL terminator to it's original character
743 *((CHAR16
*)(Walker
+1)) = TempChar
;
746 // Update LineStart Variable
748 LineStart
= Walker
+ 1;
751 // increment row count
753 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
754 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
757 case (CHAR_CARRIAGE_RETURN
):
759 // Move the cursor to the beginning of the current row.
761 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
765 // increment column count
767 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
++;
769 // check if that is the last column
771 if ((INTN
)ConsoleInfo
->ColsPerScreen
== ConsoleInfo
->OurConOut
.Mode
->CursorColumn
+ 1) {
773 // output a line similar to the linefeed character.
777 // add a temp NULL terminator
779 TempChar
= *(Walker
+ 1);
780 *((CHAR16
*)(Walker
+1)) = CHAR_NULL
;
785 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
788 // restore the temp NULL terminator to it's original character
790 *((CHAR16
*)(Walker
+1)) = TempChar
;
793 // Update LineStart Variable
795 LineStart
= Walker
+ 1;
798 // increment row count and zero the column
800 ShellInfoObject
.ConsoleInfo
->RowCounter
++;
801 ConsoleInfo
->OurConOut
.Mode
->CursorRow
++;
802 ConsoleInfo
->OurConOut
.Mode
->CursorColumn
= 0;
803 } // last column on line
805 } // switch for character
808 // check if that was the last printable row. If yes handle PageBreak mode
810 if ((ConsoleInfo
->RowsPerScreen
) -1 == ShellInfoObject
.ConsoleInfo
->RowCounter
) {
811 if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
813 // We got an error which means 'break' and halt the printing
815 SHELL_FREE_NON_NULL(StringCopy
);
816 return (EFI_DEVICE_ERROR
);
821 if (LineStart
!= NULL
&& *LineStart
!= CHAR_NULL
) {
822 ConsoleLoggerOutputStringSplit (LineStart
, ConsoleInfo
);
825 SHELL_FREE_NON_NULL(StringCopy
);
826 return (EFI_SUCCESS
);
830 Write a Unicode string to the output device.
832 @param[in] This Protocol instance pointer.
833 @param[in] WString The NULL-terminated Unicode string to be displayed on the output
834 device(s). All output devices must also support the Unicode
835 drawing defined in this file.
836 @retval EFI_SUCCESS The string was output to the device.
837 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
839 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
841 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
842 characters in the Unicode string could not be
843 rendered and were skipped.
847 ConsoleLoggerOutputString (
848 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
853 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TxtInEx
;
854 EFI_KEY_DATA KeyData
;
856 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
858 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
859 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
860 return (EFI_UNSUPPORTED
);
862 ASSERT(ShellInfoObject
.ConsoleInfo
== ConsoleInfo
);
864 Status
= gBS
->HandleProtocol (gST
->ConsoleInHandle
, &gEfiSimpleTextInputExProtocolGuid
, (VOID
**) &TxtInEx
);
865 if (!EFI_ERROR (Status
)) {
866 while (ShellInfoObject
.HaltOutput
) {
868 ShellInfoObject
.HaltOutput
= FALSE
;
872 Status
= gBS
->WaitForEvent (1, &TxtInEx
->WaitForKeyEx
, &EventIndex
);
873 ASSERT_EFI_ERROR (Status
);
874 Status
= TxtInEx
->ReadKeyStrokeEx (TxtInEx
, &KeyData
);
875 if (EFI_ERROR(Status
)) {
879 if ((KeyData
.Key
.UnicodeChar
== L
's') && (KeyData
.Key
.ScanCode
== SCAN_NULL
) &&
880 ((KeyData
.KeyState
.KeyShiftState
== (EFI_SHIFT_STATE_VALID
| EFI_LEFT_CONTROL_PRESSED
)) ||
881 (KeyData
.KeyState
.KeyShiftState
== (EFI_SHIFT_STATE_VALID
| EFI_RIGHT_CONTROL_PRESSED
))
884 ShellInfoObject
.HaltOutput
= TRUE
;
889 if (!ShellInfoObject
.ConsoleInfo
->Enabled
) {
890 return (EFI_DEVICE_ERROR
);
891 } else if (ShellInfoObject
.PageBreakEnabled
) {
892 return (ConsoleLoggerPrintWithPageBreak(WString
, ConsoleInfo
));
894 return (ConsoleLoggerOutputStringSplit(WString
, ConsoleInfo
));
899 Verifies that all characters in a Unicode string can be output to the
902 @param[in] This Protocol instance pointer.
903 @param[in] WString The NULL-terminated Unicode string to be examined for the output
906 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
907 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
908 rendered by one or more of the output devices mapped
914 ConsoleLoggerTestString (
915 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
919 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
920 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
922 // Forward the request to the original ConOut
924 return (ConsoleInfo
->OldConOut
->TestString (ConsoleInfo
->OldConOut
, WString
));
928 Returns information for an available text mode that the output device(s)
931 @param[in] This Protocol instance pointer.
932 @param[in] ModeNumber The mode number to return information on.
933 @param[out] Columns Upon return, the number of columns in the selected geometry
934 @param[out] Rows Upon return, the number of rows in the selected geometry
936 @retval EFI_SUCCESS The requested mode information was returned.
937 @retval EFI_DEVICE_ERROR The device had an error and could not
938 complete the request.
939 @retval EFI_UNSUPPORTED The mode number was not valid.
943 ConsoleLoggerQueryMode (
944 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
950 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
951 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
953 // Forward the request to the original ConOut
955 return (ConsoleInfo
->OldConOut
->QueryMode (
956 ConsoleInfo
->OldConOut
,
964 Sets the output device(s) to a specified mode.
966 @param[in] This Protocol instance pointer.
967 @param[in] ModeNumber The mode number to set.
970 @retval EFI_SUCCESS The requested text mode was set.
971 @retval EFI_DEVICE_ERROR The device had an error and
972 could not complete the request.
973 @retval EFI_UNSUPPORTED The mode number was not valid.
977 ConsoleLoggerSetMode (
978 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
984 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
985 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
988 // Forward the request to the original ConOut
990 Status
= ConsoleInfo
->OldConOut
->SetMode (ConsoleInfo
->OldConOut
, ModeNumber
);
993 // Check that the buffers are still correct for logging
995 if (!EFI_ERROR (Status
)) {
996 ConsoleInfo
->OurConOut
.Mode
= ConsoleInfo
->OldConOut
->Mode
;
997 ConsoleLoggerResetBuffers(ConsoleInfo
);
998 ConsoleInfo
->OriginalStartRow
= 0;
999 ConsoleInfo
->CurrentStartRow
= 0;
1000 ConsoleInfo
->OurConOut
.ClearScreen (&ConsoleInfo
->OurConOut
);
1007 Sets the background and foreground colors for the OutputString () and
1008 ClearScreen () functions.
1010 @param[in] This Protocol instance pointer.
1011 @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
1012 bits 4..6 are the background color. All other bits are undefined
1013 and must be zero. The valid Attributes are defined in this file.
1015 @retval EFI_SUCCESS The attribute was set.
1016 @retval EFI_DEVICE_ERROR The device had an error and
1017 could not complete the request.
1018 @retval EFI_UNSUPPORTED The attribute requested is not defined.
1023 ConsoleLoggerSetAttribute (
1024 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1030 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1031 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1034 // Forward the request to the original ConOut
1036 Status
= ConsoleInfo
->OldConOut
->SetAttribute (ConsoleInfo
->OldConOut
, Attribute
);
1039 // Record console output history
1041 if (!EFI_ERROR (Status
)) {
1042 ConsoleInfo
->HistoryMode
.Attribute
= (INT32
) Attribute
;
1049 Clears the output device(s) display to the currently selected background
1052 @param[in] This Protocol instance pointer.
1054 @retval EFI_SUCCESS The operation completed successfully.
1055 @retval EFI_DEVICE_ERROR The device had an error and
1056 could not complete the request.
1057 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1061 ConsoleLoggerClearScreen (
1062 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
1070 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1072 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
1073 return (EFI_UNSUPPORTED
);
1076 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1079 // Forward the request to the original ConOut
1081 Status
= ConsoleInfo
->OldConOut
->ClearScreen (ConsoleInfo
->OldConOut
);
1084 // Record console output history
1086 if (!EFI_ERROR (Status
)) {
1087 Screen
= &ConsoleInfo
->Buffer
[(ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->CurrentStartRow
];
1088 Attributes
= &ConsoleInfo
->Attributes
[ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->CurrentStartRow
];
1089 for ( Row
= ConsoleInfo
->OriginalStartRow
1090 ; Row
< (ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
)
1094 ; Column
< ConsoleInfo
->ColsPerScreen
1100 *Attributes
= ConsoleInfo
->OldConOut
->Mode
->Attribute
;
1103 // Skip the NULL on each column end in text buffer only
1107 ConsoleInfo
->HistoryMode
.CursorColumn
= 0;
1108 ConsoleInfo
->HistoryMode
.CursorRow
= 0;
1115 Sets the current coordinates of the cursor position
1117 @param[in] This Protocol instance pointer.
1118 @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
1119 @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
1121 @retval EFI_SUCCESS The operation completed successfully.
1122 @retval EFI_DEVICE_ERROR The device had an error and
1123 could not complete the request.
1124 @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
1125 cursor position is invalid for the current mode.
1129 ConsoleLoggerSetCursorPosition (
1130 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1136 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1138 if (ShellInfoObject
.ShellInitSettings
.BitUnion
.Bits
.NoConsoleOut
) {
1139 return (EFI_UNSUPPORTED
);
1142 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1144 // Forward the request to the original ConOut
1146 Status
= ConsoleInfo
->OldConOut
->SetCursorPosition (
1147 ConsoleInfo
->OldConOut
,
1153 // Record console output history
1155 if (!EFI_ERROR (Status
)) {
1156 ConsoleInfo
->HistoryMode
.CursorColumn
= (INT32
)Column
;
1157 ConsoleInfo
->HistoryMode
.CursorRow
= (INT32
)(ConsoleInfo
->OriginalStartRow
+ Row
);
1164 Makes the cursor visible or invisible
1166 @param[in] This Protocol instance pointer.
1167 @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
1168 set to be invisible.
1170 @retval EFI_SUCCESS The operation completed successfully.
1171 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1172 request, or the device does not support changing
1174 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
1178 ConsoleLoggerEnableCursor (
1179 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
1185 CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
;
1186 ConsoleInfo
= CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This
);
1188 // Forward the request to the original ConOut
1190 Status
= ConsoleInfo
->OldConOut
->EnableCursor (ConsoleInfo
->OldConOut
, Visible
);
1193 // Record console output history
1195 if (!EFI_ERROR (Status
)) {
1196 ConsoleInfo
->HistoryMode
.CursorVisible
= Visible
;
1203 Function to update and verify that the current buffers are correct.
1205 @param[in] ConsoleInfo The pointer to the instance of the console logger information.
1207 This will be used when a mode has changed or a reset ocurred to verify all
1212 ConsoleLoggerResetBuffers(
1213 IN CONSOLE_LOGGER_PRIVATE_DATA
*ConsoleInfo
1218 if (ConsoleInfo
->Buffer
!= NULL
) {
1219 FreePool(ConsoleInfo
->Buffer
);
1220 ConsoleInfo
->Buffer
= NULL
;
1221 ConsoleInfo
->BufferSize
= 0;
1223 if (ConsoleInfo
->Attributes
!= NULL
) {
1224 FreePool(ConsoleInfo
->Attributes
);
1225 ConsoleInfo
->Attributes
= NULL
;
1226 ConsoleInfo
->AttribSize
= 0;
1229 Status
= gST
->ConOut
->QueryMode (gST
->ConOut
, gST
->ConOut
->Mode
->Mode
, &ConsoleInfo
->ColsPerScreen
, &ConsoleInfo
->RowsPerScreen
);
1230 if (EFI_ERROR(Status
)){
1234 ConsoleInfo
->BufferSize
= (ConsoleInfo
->ColsPerScreen
+ 2) * ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Buffer
[0]);
1235 ConsoleInfo
->AttribSize
= ConsoleInfo
->ColsPerScreen
* ConsoleInfo
->RowsPerScreen
* ConsoleInfo
->ScreenCount
* sizeof(ConsoleInfo
->Attributes
[0]);
1237 ConsoleInfo
->Buffer
= (CHAR16
*)AllocateZeroPool(ConsoleInfo
->BufferSize
);
1239 if (ConsoleInfo
->Buffer
== NULL
) {
1240 return (EFI_OUT_OF_RESOURCES
);
1243 ConsoleInfo
->Attributes
= (INT32
*)AllocateZeroPool(ConsoleInfo
->AttribSize
);
1244 if (ConsoleInfo
->Attributes
== NULL
) {
1245 FreePool(ConsoleInfo
->Buffer
);
1246 ConsoleInfo
->Buffer
= NULL
;
1247 return (EFI_OUT_OF_RESOURCES
);
1250 CopyMem (&ConsoleInfo
->HistoryMode
, ConsoleInfo
->OldConOut
->Mode
, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE
));
1252 return (EFI_SUCCESS
);