mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-27 16:58:09 +01:00
1289 lines
41 KiB
C
1289 lines
41 KiB
C
|
/** @file
|
||
|
Provides interface to shell console logger.
|
||
|
|
||
|
(C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
|
||
|
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
|
||
|
(C) Copyright 2016 Hewlett-Packard Development Company, L.P.<BR>
|
||
|
This program and the accompanying materials
|
||
|
are licensed and made available under the terms and conditions of the BSD License
|
||
|
which accompanies this distribution. The full text of the license may be found at
|
||
|
http://opensource.org/licenses/bsd-license.php
|
||
|
|
||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||
|
**/
|
||
|
|
||
|
#include "Shell.h"
|
||
|
|
||
|
/**
|
||
|
Install our intermediate ConOut into the system table to
|
||
|
keep a log of all the info that is displayed to the user.
|
||
|
|
||
|
@param[in] ScreensToSave Sets how many screen-worths of data to save.
|
||
|
@param[out] ConsoleInfo The object to pass into later functions.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
@return other The operation failed.
|
||
|
|
||
|
@sa ConsoleLoggerResetBuffers
|
||
|
@sa InstallProtocolInterface
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
ConsoleLoggerInstall(
|
||
|
IN CONST UINTN ScreensToSave,
|
||
|
OUT CONSOLE_LOGGER_PRIVATE_DATA **ConsoleInfo
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
// ASSERT(ConsoleInfo != NULL);
|
||
|
if (ConsoleInfo == NULL) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
|
||
|
(*ConsoleInfo) = AllocateZeroPool(sizeof(CONSOLE_LOGGER_PRIVATE_DATA));
|
||
|
if ((*ConsoleInfo) == NULL) {
|
||
|
return (EFI_OUT_OF_RESOURCES);
|
||
|
}
|
||
|
|
||
|
(*ConsoleInfo)->Signature = CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE;
|
||
|
(*ConsoleInfo)->OldConOut = gST->ConOut;
|
||
|
(*ConsoleInfo)->OldConHandle = gST->ConsoleOutHandle;
|
||
|
(*ConsoleInfo)->Buffer = NULL;
|
||
|
(*ConsoleInfo)->BufferSize = 0;
|
||
|
(*ConsoleInfo)->OriginalStartRow = 0;
|
||
|
(*ConsoleInfo)->CurrentStartRow = 0;
|
||
|
(*ConsoleInfo)->RowsPerScreen = 0;
|
||
|
(*ConsoleInfo)->ColsPerScreen = 0;
|
||
|
(*ConsoleInfo)->Attributes = NULL;
|
||
|
(*ConsoleInfo)->AttribSize = 0;
|
||
|
(*ConsoleInfo)->ScreenCount = ScreensToSave;
|
||
|
(*ConsoleInfo)->HistoryMode.MaxMode = 1;
|
||
|
(*ConsoleInfo)->HistoryMode.Mode = 0;
|
||
|
(*ConsoleInfo)->HistoryMode.Attribute = 0;
|
||
|
(*ConsoleInfo)->HistoryMode.CursorColumn = 0;
|
||
|
(*ConsoleInfo)->HistoryMode.CursorRow = 0;
|
||
|
(*ConsoleInfo)->HistoryMode.CursorVisible = FALSE;
|
||
|
(*ConsoleInfo)->OurConOut.Reset = ConsoleLoggerReset;
|
||
|
(*ConsoleInfo)->OurConOut.OutputString = ConsoleLoggerOutputString;
|
||
|
(*ConsoleInfo)->OurConOut.TestString = ConsoleLoggerTestString;
|
||
|
(*ConsoleInfo)->OurConOut.QueryMode = ConsoleLoggerQueryMode;
|
||
|
(*ConsoleInfo)->OurConOut.SetMode = ConsoleLoggerSetMode;
|
||
|
(*ConsoleInfo)->OurConOut.SetAttribute = ConsoleLoggerSetAttribute;
|
||
|
(*ConsoleInfo)->OurConOut.ClearScreen = ConsoleLoggerClearScreen;
|
||
|
(*ConsoleInfo)->OurConOut.SetCursorPosition = ConsoleLoggerSetCursorPosition;
|
||
|
(*ConsoleInfo)->OurConOut.EnableCursor = ConsoleLoggerEnableCursor;
|
||
|
(*ConsoleInfo)->OurConOut.Mode = gST->ConOut->Mode;
|
||
|
(*ConsoleInfo)->Enabled = TRUE;
|
||
|
|
||
|
Status = ConsoleLoggerResetBuffers(*ConsoleInfo);
|
||
|
if (EFI_ERROR(Status)) {
|
||
|
SHELL_FREE_NON_NULL((*ConsoleInfo));
|
||
|
*ConsoleInfo = NULL;
|
||
|
return (Status);
|
||
|
}
|
||
|
|
||
|
Status = gBS->InstallProtocolInterface(&gImageHandle, &gEfiSimpleTextOutProtocolGuid, EFI_NATIVE_INTERFACE, (VOID*)&((*ConsoleInfo)->OurConOut));
|
||
|
if (EFI_ERROR(Status)) {
|
||
|
SHELL_FREE_NON_NULL((*ConsoleInfo)->Buffer);
|
||
|
SHELL_FREE_NON_NULL((*ConsoleInfo)->Attributes);
|
||
|
SHELL_FREE_NON_NULL((*ConsoleInfo));
|
||
|
*ConsoleInfo = NULL;
|
||
|
return (Status);
|
||
|
}
|
||
|
|
||
|
gST->ConsoleOutHandle = gImageHandle;
|
||
|
gST->ConOut = &(*ConsoleInfo)->OurConOut;
|
||
|
|
||
|
//
|
||
|
// Update the CRC32 in the EFI System Table header
|
||
|
//
|
||
|
gST->Hdr.CRC32 = 0;
|
||
|
gBS->CalculateCrc32 (
|
||
|
(UINT8 *)&gST->Hdr,
|
||
|
gST->Hdr.HeaderSize,
|
||
|
&gST->Hdr.CRC32
|
||
|
);
|
||
|
return (Status);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Return the system to the state it was before InstallConsoleLogger
|
||
|
was installed.
|
||
|
|
||
|
@param[in] ConsoleInfo The object from the install function.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful
|
||
|
@return other The operation failed. This was from UninstallProtocolInterface.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
ConsoleLoggerUninstall(
|
||
|
IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
|
||
|
)
|
||
|
{
|
||
|
// ASSERT(ConsoleInfo != NULL);
|
||
|
if (ConsoleInfo == NULL) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
// ASSERT(ConsoleInfo->OldConOut != NULL);
|
||
|
if (ConsoleInfo->OldConOut == NULL) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
|
||
|
if (ConsoleInfo->Buffer != NULL) {
|
||
|
FreePool(ConsoleInfo->Buffer);
|
||
|
DEBUG_CODE(ConsoleInfo->Buffer = NULL;);
|
||
|
DEBUG_CODE(ConsoleInfo->BufferSize = 0;);
|
||
|
}
|
||
|
if (ConsoleInfo->Attributes != NULL) {
|
||
|
FreePool(ConsoleInfo->Attributes);
|
||
|
DEBUG_CODE(ConsoleInfo->Attributes = NULL;);
|
||
|
DEBUG_CODE(ConsoleInfo->AttribSize = 0;);
|
||
|
}
|
||
|
|
||
|
gST->ConsoleOutHandle = ConsoleInfo->OldConHandle;
|
||
|
gST->ConOut = ConsoleInfo->OldConOut;
|
||
|
|
||
|
//
|
||
|
// Update the CRC32 in the EFI System Table header
|
||
|
//
|
||
|
gST->Hdr.CRC32 = 0;
|
||
|
gBS->CalculateCrc32 (
|
||
|
(UINT8 *)&gST->Hdr,
|
||
|
gST->Hdr.HeaderSize,
|
||
|
&gST->Hdr.CRC32
|
||
|
);
|
||
|
|
||
|
return (gBS->UninstallProtocolInterface(gImageHandle, &gEfiSimpleTextOutProtocolGuid, (VOID*)&ConsoleInfo->OurConOut));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Displays previously logged output back to the screen.
|
||
|
|
||
|
This will scroll the screen forwards and backwards through the log of previous
|
||
|
output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows
|
||
|
is (UINTN)(-1) then the size of the screen will be scrolled.
|
||
|
|
||
|
@param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer).
|
||
|
If FALSE then the log will be displayed backwards (scroll to older).
|
||
|
@param[in] Rows Determines how many rows the log should scroll.
|
||
|
@param[in] ConsoleInfo The pointer to the instance of the console logger information.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
ConsoleLoggerDisplayHistory(
|
||
|
IN CONST BOOLEAN Forward,
|
||
|
IN CONST UINTN Rows,
|
||
|
IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
|
||
|
)
|
||
|
{
|
||
|
UINTN RowChange;
|
||
|
|
||
|
// ASSERT(ConsoleInfo != NULL);
|
||
|
if (ConsoleInfo == NULL) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Calculate the row number change
|
||
|
//
|
||
|
switch (Rows) {
|
||
|
case ((UINTN)(-1)):
|
||
|
RowChange = ConsoleInfo->RowsPerScreen;
|
||
|
break;
|
||
|
case (0):
|
||
|
RowChange = ConsoleInfo->RowsPerScreen / 2;
|
||
|
break;
|
||
|
default:
|
||
|
RowChange = Rows;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Do the math for direction
|
||
|
//
|
||
|
if (Forward) {
|
||
|
if ((ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow) < RowChange) {
|
||
|
RowChange = ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow;
|
||
|
}
|
||
|
} else {
|
||
|
if (ConsoleInfo->CurrentStartRow < RowChange) {
|
||
|
RowChange = ConsoleInfo->CurrentStartRow;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If we are already at one end or the other
|
||
|
//
|
||
|
if (RowChange == 0) {
|
||
|
return (EFI_SUCCESS);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Clear the screen
|
||
|
//
|
||
|
ConsoleInfo->OldConOut->ClearScreen(ConsoleInfo->OldConOut);
|
||
|
|
||
|
//
|
||
|
// Set the new start row
|
||
|
//
|
||
|
if (Forward) {
|
||
|
ConsoleInfo->CurrentStartRow += RowChange;
|
||
|
} else {
|
||
|
ConsoleInfo->CurrentStartRow -= RowChange;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Change the screen
|
||
|
//
|
||
|
return (UpdateDisplayFromHistory(ConsoleInfo));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Function to return to normal output whent he scrolling is complete.
|
||
|
@param[in] ConsoleInfo The pointer to the instance of the console logger information.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
@return other The operation failed. See UpdateDisplayFromHistory.
|
||
|
|
||
|
@sa UpdateDisplayFromHistory
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
ConsoleLoggerStopHistory(
|
||
|
IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
|
||
|
)
|
||
|
{
|
||
|
// ASSERT(ConsoleInfo != NULL);
|
||
|
if (ConsoleInfo == NULL) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) {
|
||
|
return (EFI_SUCCESS);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Clear the screen
|
||
|
//
|
||
|
ConsoleInfo->OldConOut->ClearScreen(ConsoleInfo->OldConOut);
|
||
|
|
||
|
ConsoleInfo->CurrentStartRow = ConsoleInfo->OriginalStartRow;
|
||
|
return (UpdateDisplayFromHistory(ConsoleInfo));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Updates the hidden ConOut to be displaying the correct stuff.
|
||
|
@param[in] ConsoleInfo The pointer to the instance of the console logger information.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
@return other The operation failed.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
UpdateDisplayFromHistory(
|
||
|
IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EFI_STATUS RetVal;
|
||
|
CHAR16 *Screen;
|
||
|
INT32 *Attributes;
|
||
|
UINTN CurrentRow;
|
||
|
CHAR16 TempCharHolder;
|
||
|
UINTN Column;
|
||
|
INT32 CurrentAttrib;
|
||
|
UINTN CurrentColumn;
|
||
|
CHAR16 *StringSegment;
|
||
|
CHAR16 *StringSegmentEnd;
|
||
|
CHAR16 StringSegmentEndChar;
|
||
|
INT32 OrigAttribute;
|
||
|
|
||
|
// ASSERT(ConsoleInfo != NULL);
|
||
|
if (ConsoleInfo == NULL) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
TempCharHolder = CHAR_NULL;
|
||
|
RetVal = EFI_SUCCESS;
|
||
|
OrigAttribute = ConsoleInfo->OldConOut->Mode->Attribute;
|
||
|
|
||
|
//
|
||
|
// Disable cursor visibility and move it to the top left corner
|
||
|
//
|
||
|
ConsoleInfo->OldConOut->EnableCursor (ConsoleInfo->OldConOut, FALSE);
|
||
|
ConsoleInfo->OldConOut->SetCursorPosition (ConsoleInfo->OldConOut, 0, 0);
|
||
|
|
||
|
Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow];
|
||
|
Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow];
|
||
|
for ( CurrentRow = 0
|
||
|
; CurrentRow < ConsoleInfo->RowsPerScreen
|
||
|
; CurrentRow++
|
||
|
, Screen += (ConsoleInfo->ColsPerScreen + 2)
|
||
|
, Attributes += ConsoleInfo->ColsPerScreen
|
||
|
){
|
||
|
//
|
||
|
// dont use the last char - prevents screen scroll
|
||
|
//
|
||
|
if (CurrentRow == (ConsoleInfo->RowsPerScreen-1)){
|
||
|
TempCharHolder = Screen[ConsoleInfo->ColsPerScreen - 1];
|
||
|
Screen[ConsoleInfo->ColsPerScreen - 1] = CHAR_NULL;
|
||
|
}
|
||
|
|
||
|
for ( Column = 0
|
||
|
; Column < ConsoleInfo->ColsPerScreen
|
||
|
; Column++
|
||
|
){
|
||
|
if (Screen[Column] != CHAR_NULL) {
|
||
|
CurrentAttrib = Attributes[Column];
|
||
|
CurrentColumn = Column;
|
||
|
StringSegment = &Screen[Column];
|
||
|
|
||
|
//
|
||
|
// Find the first char with a different arrribute and make that temporarily NULL
|
||
|
// so we can do fewer printout statements. (later) restore that one and we will
|
||
|
// start at that collumn on the next loop.
|
||
|
//
|
||
|
StringSegmentEndChar = CHAR_NULL;
|
||
|
for ( StringSegmentEnd = StringSegment
|
||
|
; *StringSegmentEnd != CHAR_NULL
|
||
|
; StringSegmentEnd++
|
||
|
, Column++
|
||
|
){
|
||
|
if (Attributes[Column] != CurrentAttrib) {
|
||
|
StringSegmentEndChar = *StringSegmentEnd;
|
||
|
*StringSegmentEnd = CHAR_NULL;
|
||
|
break;
|
||
|
}
|
||
|
} // StringSegmentEnd loop
|
||
|
|
||
|
//
|
||
|
// Now write out as much as had the same Attributes
|
||
|
//
|
||
|
|
||
|
ConsoleInfo->OldConOut->SetAttribute(ConsoleInfo->OldConOut, CurrentAttrib);
|
||
|
ConsoleInfo->OldConOut->SetCursorPosition(ConsoleInfo->OldConOut, CurrentColumn, CurrentRow);
|
||
|
Status = ConsoleInfo->OldConOut->OutputString(ConsoleInfo->OldConOut, StringSegment);
|
||
|
|
||
|
if (EFI_ERROR(Status)) {
|
||
|
// ASSERT(FALSE);
|
||
|
RetVal = Status;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If we found a change in attribute put the character back and decrement the column
|
||
|
// so when it increments it will point at that character and we will start printing
|
||
|
// a segment with that new attribute
|
||
|
//
|
||
|
if (StringSegmentEndChar != CHAR_NULL) {
|
||
|
*StringSegmentEnd = StringSegmentEndChar;
|
||
|
StringSegmentEndChar = CHAR_NULL;
|
||
|
Column--;
|
||
|
}
|
||
|
}
|
||
|
} // column for loop
|
||
|
|
||
|
//
|
||
|
// If we removed the last char and this was the last row put it back
|
||
|
//
|
||
|
if (TempCharHolder != CHAR_NULL) {
|
||
|
Screen[ConsoleInfo->ColsPerScreen - 1] = TempCharHolder;
|
||
|
TempCharHolder = CHAR_NULL;
|
||
|
}
|
||
|
} // row for loop
|
||
|
|
||
|
//
|
||
|
// If we are setting the screen back to original turn on the cursor and make it visible
|
||
|
// and set the attributes back to what they were
|
||
|
//
|
||
|
if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) {
|
||
|
ConsoleInfo->OldConOut->SetAttribute (
|
||
|
ConsoleInfo->OldConOut,
|
||
|
ConsoleInfo->HistoryMode.Attribute
|
||
|
);
|
||
|
ConsoleInfo->OldConOut->SetCursorPosition (
|
||
|
ConsoleInfo->OldConOut,
|
||
|
ConsoleInfo->HistoryMode.CursorColumn,
|
||
|
ConsoleInfo->HistoryMode.CursorRow - ConsoleInfo->OriginalStartRow
|
||
|
);
|
||
|
|
||
|
Status = ConsoleInfo->OldConOut->EnableCursor (
|
||
|
ConsoleInfo->OldConOut,
|
||
|
ConsoleInfo->HistoryMode.CursorVisible
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
RetVal = Status;
|
||
|
}
|
||
|
} else {
|
||
|
ConsoleInfo->OldConOut->SetAttribute (
|
||
|
ConsoleInfo->OldConOut,
|
||
|
OrigAttribute
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return (RetVal);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Reset the text output device hardware and optionaly run diagnostics
|
||
|
|
||
|
@param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
|
||
|
@param ExtendedVerification Indicates that a more extensive test may be performed
|
||
|
|
||
|
@retval EFI_SUCCESS The text output device was reset.
|
||
|
@retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
|
||
|
could not be reset.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
ConsoleLoggerReset (
|
||
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||
|
IN BOOLEAN ExtendedVerification
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
|
||
|
ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
|
||
|
|
||
|
//
|
||
|
// Forward the request to the original ConOut
|
||
|
//
|
||
|
Status = ConsoleInfo->OldConOut->Reset (ConsoleInfo->OldConOut, ExtendedVerification);
|
||
|
|
||
|
//
|
||
|
// Check that the buffers are still correct for logging
|
||
|
//
|
||
|
if (!EFI_ERROR (Status)) {
|
||
|
ConsoleLoggerResetBuffers(ConsoleInfo);
|
||
|
if (ExtendedVerification) {
|
||
|
ConsoleInfo->OriginalStartRow = 0;
|
||
|
ConsoleInfo->CurrentStartRow = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Appends a string to the history buffer. If the buffer is full then the oldest
|
||
|
information in the buffer will be dropped. Information is added in a line by
|
||
|
line manner such that an empty line takes up just as much space as a full line.
|
||
|
|
||
|
@param[in] String String pointer to add.
|
||
|
@param[in] ConsoleInfo The pointer to the instance of the console logger information.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
AppendStringToHistory(
|
||
|
IN CONST CHAR16 *String,
|
||
|
IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
|
||
|
)
|
||
|
{
|
||
|
CONST CHAR16 *Walker;
|
||
|
UINTN CopySize;
|
||
|
UINTN PrintIndex;
|
||
|
UINTN Index;
|
||
|
|
||
|
// ASSERT(ConsoleInfo != NULL);
|
||
|
if (ConsoleInfo == NULL) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
|
||
|
for ( Walker = String
|
||
|
; Walker != NULL && *Walker != CHAR_NULL
|
||
|
; Walker++
|
||
|
){
|
||
|
switch (*Walker) {
|
||
|
case (CHAR_BACKSPACE):
|
||
|
if (ConsoleInfo->HistoryMode.CursorColumn > 0) {
|
||
|
ConsoleInfo->HistoryMode.CursorColumn--;
|
||
|
}
|
||
|
break;
|
||
|
case (CHAR_LINEFEED):
|
||
|
if (ConsoleInfo->HistoryMode.CursorRow >= (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1)) {
|
||
|
//
|
||
|
// Should never be bigger
|
||
|
//
|
||
|
// ASSERT(ConsoleInfo->HistoryMode.CursorRow == (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1));
|
||
|
if (ConsoleInfo->HistoryMode.CursorRow > (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1)) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// scroll history attributes 'up' 1 row and set the last row to default attribute
|
||
|
//
|
||
|
CopySize = ConsoleInfo->ColsPerScreen
|
||
|
* ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1)
|
||
|
* sizeof(ConsoleInfo->Attributes[0]);
|
||
|
// ASSERT(CopySize < ConsoleInfo->AttribSize);
|
||
|
if (CopySize >= ConsoleInfo->AttribSize) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
CopyMem(
|
||
|
ConsoleInfo->Attributes,
|
||
|
ConsoleInfo->Attributes + ConsoleInfo->ColsPerScreen,
|
||
|
CopySize
|
||
|
);
|
||
|
|
||
|
for ( Index = 0
|
||
|
; Index < ConsoleInfo->ColsPerScreen
|
||
|
; Index++
|
||
|
){
|
||
|
*(ConsoleInfo->Attributes + (CopySize/sizeof(ConsoleInfo->Attributes[0])) + Index) = ConsoleInfo->HistoryMode.Attribute;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
|
||
|
//
|
||
|
CopySize = (ConsoleInfo->ColsPerScreen + 2)
|
||
|
* ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1)
|
||
|
* sizeof(ConsoleInfo->Buffer[0]);
|
||
|
// ASSERT(CopySize < ConsoleInfo->BufferSize);
|
||
|
if (CopySize >= ConsoleInfo->BufferSize) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
CopyMem(
|
||
|
ConsoleInfo->Buffer,
|
||
|
ConsoleInfo->Buffer + (ConsoleInfo->ColsPerScreen + 2),
|
||
|
CopySize
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Set that last row of chars to spaces
|
||
|
//
|
||
|
SetMem16(((UINT8*)ConsoleInfo->Buffer)+CopySize, ConsoleInfo->ColsPerScreen*sizeof(CHAR16), L' ');
|
||
|
} else {
|
||
|
//
|
||
|
// we are not on the last row
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// We should not be scrolling history
|
||
|
//
|
||
|
// ASSERT (ConsoleInfo->OriginalStartRow == ConsoleInfo->CurrentStartRow);
|
||
|
if (ConsoleInfo->OriginalStartRow != ConsoleInfo->CurrentStartRow) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
//
|
||
|
// are we at the end of a row?
|
||
|
//
|
||
|
if (ConsoleInfo->HistoryMode.CursorRow == (INT32) (ConsoleInfo->OriginalStartRow + ConsoleInfo->RowsPerScreen - 1)) {
|
||
|
ConsoleInfo->OriginalStartRow++;
|
||
|
ConsoleInfo->CurrentStartRow++;
|
||
|
}
|
||
|
ConsoleInfo->HistoryMode.CursorRow++;
|
||
|
}
|
||
|
break;
|
||
|
case (CHAR_CARRIAGE_RETURN):
|
||
|
//
|
||
|
// Move the cursor to the beginning of the current row.
|
||
|
//
|
||
|
ConsoleInfo->HistoryMode.CursorColumn = 0;
|
||
|
break;
|
||
|
default:
|
||
|
//
|
||
|
// Actually print characters into the history buffer
|
||
|
//
|
||
|
|
||
|
PrintIndex = ConsoleInfo->HistoryMode.CursorRow * ConsoleInfo->ColsPerScreen + ConsoleInfo->HistoryMode.CursorColumn;
|
||
|
|
||
|
for ( // no initializer needed
|
||
|
; ConsoleInfo->HistoryMode.CursorColumn < (INT32) ConsoleInfo->ColsPerScreen
|
||
|
; ConsoleInfo->HistoryMode.CursorColumn++
|
||
|
, PrintIndex++
|
||
|
, Walker++
|
||
|
){
|
||
|
if (*Walker == CHAR_NULL
|
||
|
||*Walker == CHAR_BACKSPACE
|
||
|
||*Walker == CHAR_LINEFEED
|
||
|
||*Walker == CHAR_CARRIAGE_RETURN
|
||
|
){
|
||
|
Walker--;
|
||
|
break;
|
||
|
}
|
||
|
//
|
||
|
// The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
|
||
|
//
|
||
|
|
||
|
// ASSERT(PrintIndex + ConsoleInfo->HistoryMode.CursorRow < ConsoleInfo->BufferSize);
|
||
|
if (PrintIndex + ConsoleInfo->HistoryMode.CursorRow >= ConsoleInfo->BufferSize) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
ConsoleInfo->Buffer[PrintIndex + (2*ConsoleInfo->HistoryMode.CursorRow)] = *Walker;
|
||
|
// ASSERT(PrintIndex < ConsoleInfo->AttribSize);
|
||
|
if (PrintIndex >= ConsoleInfo->AttribSize) {
|
||
|
return (EFI_INVALID_PARAMETER);
|
||
|
}
|
||
|
ConsoleInfo->Attributes[PrintIndex] = ConsoleInfo->HistoryMode.Attribute;
|
||
|
} // for loop
|
||
|
|
||
|
//
|
||
|
// Add the carriage return and line feed at the end of the lines
|
||
|
//
|
||
|
if (ConsoleInfo->HistoryMode.CursorColumn >= (INT32)ConsoleInfo->ColsPerScreen) {
|
||
|
AppendStringToHistory(L"\r\n", ConsoleInfo);
|
||
|
Walker--;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
} // switch for character
|
||
|
} // for loop
|
||
|
|
||
|
return (EFI_SUCCESS);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Worker function to handle printing the output to the screen
|
||
|
and the history buffer
|
||
|
|
||
|
@param[in] String The string to output
|
||
|
@param[in] ConsoleInfo The pointer to the instance of the console logger information.
|
||
|
|
||
|
@retval EFI_SUCCESS The string was printed
|
||
|
@retval EFI_DEVICE_ERROR The device reported an error while attempting to output
|
||
|
the text.
|
||
|
@retval EFI_UNSUPPORTED The output device's mode is not currently in a
|
||
|
defined text mode.
|
||
|
@retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
|
||
|
characters in the Unicode string could not be
|
||
|
rendered and were skipped.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
ConsoleLoggerOutputStringSplit(
|
||
|
IN CONST CHAR16 *String,
|
||
|
IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
//
|
||
|
// Forward the request to the original ConOut
|
||
|
//
|
||
|
Status = ConsoleInfo->OldConOut->OutputString (ConsoleInfo->OldConOut, (CHAR16*)String);
|
||
|
|
||
|
if (EFI_ERROR(Status)) {
|
||
|
return (Status);
|
||
|
}
|
||
|
|
||
|
return (AppendStringToHistory(String, ConsoleInfo));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Function to handle page break mode.
|
||
|
|
||
|
This function will prompt for continue or break.
|
||
|
|
||
|
@retval EFI_SUCCESS Continue was choosen
|
||
|
@return other Break was choosen
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
ConsoleLoggerDoPageBreak(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
SHELL_PROMPT_RESPONSE *Resp;
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
Resp = NULL;
|
||
|
// ASSERT(ShellInfoObject.PageBreakEnabled);
|
||
|
if (!ShellInfoObject.PageBreakEnabled) {
|
||
|
return (EFI_NOT_FOUND);
|
||
|
}
|
||
|
ShellInfoObject.PageBreakEnabled = FALSE;
|
||
|
Status = ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue, STRING_TOKEN(STR_SHELL_QUIT_CONT), ShellInfoObject.HiiHandle, (VOID**)&Resp);
|
||
|
ShellInfoObject.PageBreakEnabled = TRUE;
|
||
|
// ASSERT(Resp != NULL);
|
||
|
if (Resp == NULL) {
|
||
|
return (EFI_NOT_FOUND);
|
||
|
}
|
||
|
if (EFI_ERROR(Status)) {
|
||
|
if (Resp != NULL) {
|
||
|
FreePool(Resp);
|
||
|
}
|
||
|
return (Status);
|
||
|
}
|
||
|
if (*Resp == ShellPromptResponseContinue) {
|
||
|
FreePool(Resp);
|
||
|
ShellInfoObject.ConsoleInfo->RowCounter = 0;
|
||
|
// ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorRow = 0;
|
||
|
// ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
|
||
|
|
||
|
return (EFI_SUCCESS);
|
||
|
} else if (*Resp == ShellPromptResponseQuit) {
|
||
|
FreePool(Resp);
|
||
|
ShellInfoObject.ConsoleInfo->Enabled = FALSE;
|
||
|
//
|
||
|
// When user wants to quit, the shell should stop running the command.
|
||
|
//
|
||
|
gBS->SignalEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak);
|
||
|
return (EFI_DEVICE_ERROR);
|
||
|
}/* else {
|
||
|
ASSERT(FALSE);
|
||
|
}*/
|
||
|
return (EFI_SUCCESS);
|
||
|
}
|
||
|
/**
|
||
|
Worker function to handle printing the output with page breaks.
|
||
|
|
||
|
@param[in] String The string to output
|
||
|
@param[in] ConsoleInfo The pointer to the instance of the console logger information.
|
||
|
|
||
|
@retval EFI_SUCCESS The string was printed
|
||
|
@retval EFI_DEVICE_ERROR The device reported an error while attempting to output
|
||
|
the text.
|
||
|
@retval EFI_UNSUPPORTED The output device's mode is not currently in a
|
||
|
defined text mode.
|
||
|
@retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
|
||
|
characters in the Unicode string could not be
|
||
|
rendered and were skipped.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
ConsoleLoggerPrintWithPageBreak(
|
||
|
IN CONST CHAR16 *String,
|
||
|
IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
|
||
|
)
|
||
|
{
|
||
|
CONST CHAR16 *Walker;
|
||
|
CONST CHAR16 *LineStart;
|
||
|
CHAR16 *StringCopy;
|
||
|
CHAR16 TempChar;
|
||
|
|
||
|
StringCopy = NULL;
|
||
|
StringCopy = StrnCatGrow(&StringCopy, NULL, String, 0);
|
||
|
if (StringCopy == NULL) {
|
||
|
return (EFI_OUT_OF_RESOURCES);
|
||
|
}
|
||
|
|
||
|
for ( Walker = StringCopy
|
||
|
, LineStart = StringCopy
|
||
|
; Walker != NULL && *Walker != CHAR_NULL
|
||
|
; Walker++
|
||
|
){
|
||
|
switch (*Walker) {
|
||
|
case (CHAR_BACKSPACE):
|
||
|
if (ConsoleInfo->OurConOut.Mode->CursorColumn > 0) {
|
||
|
ConsoleInfo->OurConOut.Mode->CursorColumn--;
|
||
|
}
|
||
|
break;
|
||
|
case (CHAR_LINEFEED):
|
||
|
//
|
||
|
// add a temp NULL terminator
|
||
|
//
|
||
|
TempChar = *(Walker + 1);
|
||
|
*((CHAR16*)(Walker+1)) = CHAR_NULL;
|
||
|
|
||
|
//
|
||
|
// output the string
|
||
|
//
|
||
|
ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);
|
||
|
|
||
|
//
|
||
|
// restore the temp NULL terminator to it's original character
|
||
|
//
|
||
|
*((CHAR16*)(Walker+1)) = TempChar;
|
||
|
|
||
|
//
|
||
|
// Update LineStart Variable
|
||
|
//
|
||
|
LineStart = Walker + 1;
|
||
|
|
||
|
//
|
||
|
// increment row count
|
||
|
//
|
||
|
ShellInfoObject.ConsoleInfo->RowCounter++;
|
||
|
ConsoleInfo->OurConOut.Mode->CursorRow++;
|
||
|
|
||
|
break;
|
||
|
case (CHAR_CARRIAGE_RETURN):
|
||
|
//
|
||
|
// Move the cursor to the beginning of the current row.
|
||
|
//
|
||
|
ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
|
||
|
break;
|
||
|
default:
|
||
|
//
|
||
|
// increment column count
|
||
|
//
|
||
|
ConsoleInfo->OurConOut.Mode->CursorColumn++;
|
||
|
//
|
||
|
// check if that is the last column
|
||
|
//
|
||
|
if ((INTN)ConsoleInfo->ColsPerScreen == ConsoleInfo->OurConOut.Mode->CursorColumn + 1) {
|
||
|
//
|
||
|
// output a line similar to the linefeed character.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// add a temp NULL terminator
|
||
|
//
|
||
|
TempChar = *(Walker + 1);
|
||
|
*((CHAR16*)(Walker+1)) = CHAR_NULL;
|
||
|
|
||
|
//
|
||
|
// output the string
|
||
|
//
|
||
|
ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);
|
||
|
|
||
|
//
|
||
|
// restore the temp NULL terminator to it's original character
|
||
|
//
|
||
|
*((CHAR16*)(Walker+1)) = TempChar;
|
||
|
|
||
|
//
|
||
|
// Update LineStart Variable
|
||
|
//
|
||
|
LineStart = Walker + 1;
|
||
|
|
||
|
//
|
||
|
// increment row count and zero the column
|
||
|
//
|
||
|
ShellInfoObject.ConsoleInfo->RowCounter++;
|
||
|
ConsoleInfo->OurConOut.Mode->CursorRow++;
|
||
|
ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
|
||
|
} // last column on line
|
||
|
break;
|
||
|
} // switch for character
|
||
|
|
||
|
//
|
||
|
// check if that was the last printable row. If yes handle PageBreak mode
|
||
|
//
|
||
|
if ((ConsoleInfo->RowsPerScreen) -1 == ShellInfoObject.ConsoleInfo->RowCounter) {
|
||
|
if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
|
||
|
//
|
||
|
// We got an error which means 'break' and halt the printing
|
||
|
//
|
||
|
SHELL_FREE_NON_NULL(StringCopy);
|
||
|
return (EFI_DEVICE_ERROR);
|
||
|
}
|
||
|
}
|
||
|
} // for loop
|
||
|
|
||
|
if (LineStart != NULL && *LineStart != CHAR_NULL) {
|
||
|
ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);
|
||
|
}
|
||
|
|
||
|
SHELL_FREE_NON_NULL(StringCopy);
|
||
|
return (EFI_SUCCESS);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Write a Unicode string to the output device.
|
||
|
|
||
|
@param[in] This Protocol instance pointer.
|
||
|
@param[in] WString The NULL-terminated Unicode string to be displayed on the output
|
||
|
device(s). All output devices must also support the Unicode
|
||
|
drawing defined in this file.
|
||
|
@retval EFI_SUCCESS The string was output to the device.
|
||
|
@retval EFI_DEVICE_ERROR The device reported an error while attempting to output
|
||
|
the text.
|
||
|
@retval EFI_UNSUPPORTED The output device's mode is not currently in a
|
||
|
defined text mode.
|
||
|
@retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
|
||
|
characters in the Unicode string could not be
|
||
|
rendered and were skipped.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
ConsoleLoggerOutputString (
|
||
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||
|
IN CHAR16 *WString
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;
|
||
|
EFI_KEY_DATA KeyData;
|
||
|
UINTN EventIndex;
|
||
|
CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
|
||
|
|
||
|
ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
|
||
|
if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
|
||
|
return (EFI_UNSUPPORTED);
|
||
|
}
|
||
|
// ASSERT(ShellInfoObject.ConsoleInfo == ConsoleInfo);
|
||
|
if (ShellInfoObject.ConsoleInfo != ConsoleInfo) {
|
||
|
return (EFI_UNSUPPORTED);
|
||
|
}
|
||
|
|
||
|
Status = gBS->HandleProtocol (gST->ConsoleInHandle, &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);
|
||
|
if (!EFI_ERROR (Status)) {
|
||
|
while (ShellInfoObject.HaltOutput) {
|
||
|
|
||
|
ShellInfoObject.HaltOutput = FALSE;
|
||
|
//
|
||
|
// just get some key
|
||
|
//
|
||
|
Status = gBS->WaitForEvent (1, &TxtInEx->WaitForKeyEx, &EventIndex);
|
||
|
ASSERT_EFI_ERROR (Status);
|
||
|
Status = TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData);
|
||
|
if (EFI_ERROR(Status)) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ((KeyData.Key.UnicodeChar == L's') && (KeyData.Key.ScanCode == SCAN_NULL) &&
|
||
|
((KeyData.KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED)) ||
|
||
|
(KeyData.KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID | EFI_RIGHT_CONTROL_PRESSED))
|
||
|
)
|
||
|
) {
|
||
|
ShellInfoObject.HaltOutput = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!ShellInfoObject.ConsoleInfo->Enabled) {
|
||
|
return (EFI_DEVICE_ERROR);
|
||
|
} else if (ShellInfoObject.PageBreakEnabled) {
|
||
|
return (ConsoleLoggerPrintWithPageBreak(WString, ConsoleInfo));
|
||
|
} else {
|
||
|
return (ConsoleLoggerOutputStringSplit(WString, ConsoleInfo));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Verifies that all characters in a Unicode string can be output to the
|
||
|
target device.
|
||
|
|
||
|
@param[in] This Protocol instance pointer.
|
||
|
@param[in] WString The NULL-terminated Unicode string to be examined for the output
|
||
|
device(s).
|
||
|
|
||
|
@retval EFI_SUCCESS The device(s) are capable of rendering the output string.
|
||
|
@retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
|
||
|
rendered by one or more of the output devices mapped
|
||
|
by the EFI handle.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
ConsoleLoggerTestString (
|
||
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||
|
IN CHAR16 *WString
|
||
|
)
|
||
|
{
|
||
|
CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
|
||
|
ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
|
||
|
//
|
||
|
// Forward the request to the original ConOut
|
||
|
//
|
||
|
return (ConsoleInfo->OldConOut->TestString (ConsoleInfo->OldConOut, WString));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Returns information for an available text mode that the output device(s)
|
||
|
supports.
|
||
|
|
||
|
@param[in] This Protocol instance pointer.
|
||
|
@param[in] ModeNumber The mode number to return information on.
|
||
|
@param[out] Columns Upon return, the number of columns in the selected geometry
|
||
|
@param[out] Rows Upon return, the number of rows in the selected geometry
|
||
|
|
||
|
@retval EFI_SUCCESS The requested mode information was returned.
|
||
|
@retval EFI_DEVICE_ERROR The device had an error and could not
|
||
|
complete the request.
|
||
|
@retval EFI_UNSUPPORTED The mode number was not valid.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
ConsoleLoggerQueryMode (
|
||
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||
|
IN UINTN ModeNumber,
|
||
|
OUT UINTN *Columns,
|
||
|
OUT UINTN *Rows
|
||
|
)
|
||
|
{
|
||
|
CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
|
||
|
ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
|
||
|
//
|
||
|
// Forward the request to the original ConOut
|
||
|
//
|
||
|
return (ConsoleInfo->OldConOut->QueryMode (
|
||
|
ConsoleInfo->OldConOut,
|
||
|
ModeNumber,
|
||
|
Columns,
|
||
|
Rows
|
||
|
));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Sets the output device(s) to a specified mode.
|
||
|
|
||
|
@param[in] This Protocol instance pointer.
|
||
|
@param[in] ModeNumber The mode number to set.
|
||
|
|
||
|
|
||
|
@retval EFI_SUCCESS The requested text mode was set.
|
||
|
@retval EFI_DEVICE_ERROR The device had an error and
|
||
|
could not complete the request.
|
||
|
@retval EFI_UNSUPPORTED The mode number was not valid.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
ConsoleLoggerSetMode (
|
||
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||
|
IN UINTN ModeNumber
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
|
||
|
ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
|
||
|
|
||
|
//
|
||
|
// Forward the request to the original ConOut
|
||
|
//
|
||
|
Status = ConsoleInfo->OldConOut->SetMode (ConsoleInfo->OldConOut, ModeNumber);
|
||
|
|
||
|
//
|
||
|
// Check that the buffers are still correct for logging
|
||
|
//
|
||
|
if (!EFI_ERROR (Status)) {
|
||
|
ConsoleInfo->OurConOut.Mode = ConsoleInfo->OldConOut->Mode;
|
||
|
ConsoleLoggerResetBuffers(ConsoleInfo);
|
||
|
ConsoleInfo->OriginalStartRow = 0;
|
||
|
ConsoleInfo->CurrentStartRow = 0;
|
||
|
ConsoleInfo->OurConOut.ClearScreen (&ConsoleInfo->OurConOut);
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Sets the background and foreground colors for the OutputString () and
|
||
|
ClearScreen () functions.
|
||
|
|
||
|
@param[in] This Protocol instance pointer.
|
||
|
@param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
|
||
|
bits 4..6 are the background color. All other bits are undefined
|
||
|
and must be zero. The valid Attributes are defined in this file.
|
||
|
|
||
|
@retval EFI_SUCCESS The attribute was set.
|
||
|
@retval EFI_DEVICE_ERROR The device had an error and
|
||
|
could not complete the request.
|
||
|
@retval EFI_UNSUPPORTED The attribute requested is not defined.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
ConsoleLoggerSetAttribute (
|
||
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||
|
IN UINTN Attribute
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
|
||
|
ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
|
||
|
|
||
|
//
|
||
|
// Forward the request to the original ConOut
|
||
|
//
|
||
|
Status = ConsoleInfo->OldConOut->SetAttribute (ConsoleInfo->OldConOut, Attribute);
|
||
|
|
||
|
//
|
||
|
// Record console output history
|
||
|
//
|
||
|
if (!EFI_ERROR (Status)) {
|
||
|
ConsoleInfo->HistoryMode.Attribute = (INT32) Attribute;
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Clears the output device(s) display to the currently selected background
|
||
|
color.
|
||
|
|
||
|
@param[in] This Protocol instance pointer.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation completed successfully.
|
||
|
@retval EFI_DEVICE_ERROR The device had an error and
|
||
|
could not complete the request.
|
||
|
@retval EFI_UNSUPPORTED The output device is not in a valid text mode.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
ConsoleLoggerClearScreen (
|
||
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
CHAR16 *Screen;
|
||
|
INT32 *Attributes;
|
||
|
UINTN Row;
|
||
|
UINTN Column;
|
||
|
CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
|
||
|
|
||
|
if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
|
||
|
return (EFI_UNSUPPORTED);
|
||
|
}
|
||
|
|
||
|
ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
|
||
|
|
||
|
//
|
||
|
// Forward the request to the original ConOut
|
||
|
//
|
||
|
Status = ConsoleInfo->OldConOut->ClearScreen (ConsoleInfo->OldConOut);
|
||
|
|
||
|
//
|
||
|
// Record console output history
|
||
|
//
|
||
|
if (!EFI_ERROR (Status)) {
|
||
|
Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow];
|
||
|
Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow];
|
||
|
for ( Row = ConsoleInfo->OriginalStartRow
|
||
|
; Row < (ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)
|
||
|
; Row++
|
||
|
){
|
||
|
for ( Column = 0
|
||
|
; Column < ConsoleInfo->ColsPerScreen
|
||
|
; Column++
|
||
|
, Screen++
|
||
|
, Attributes++
|
||
|
){
|
||
|
*Screen = L' ';
|
||
|
*Attributes = ConsoleInfo->OldConOut->Mode->Attribute;
|
||
|
}
|
||
|
//
|
||
|
// Skip the NULL on each column end in text buffer only
|
||
|
//
|
||
|
Screen += 2;
|
||
|
}
|
||
|
ConsoleInfo->HistoryMode.CursorColumn = 0;
|
||
|
ConsoleInfo->HistoryMode.CursorRow = 0;
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Sets the current coordinates of the cursor position
|
||
|
|
||
|
@param[in] This Protocol instance pointer.
|
||
|
@param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
|
||
|
@param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
|
||
|
|
||
|
@retval EFI_SUCCESS The operation completed successfully.
|
||
|
@retval EFI_DEVICE_ERROR The device had an error and
|
||
|
could not complete the request.
|
||
|
@retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
|
||
|
cursor position is invalid for the current mode.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
ConsoleLoggerSetCursorPosition (
|
||
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||
|
IN UINTN Column,
|
||
|
IN UINTN Row
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
|
||
|
|
||
|
if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
|
||
|
return (EFI_UNSUPPORTED);
|
||
|
}
|
||
|
|
||
|
ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
|
||
|
//
|
||
|
// Forward the request to the original ConOut
|
||
|
//
|
||
|
Status = ConsoleInfo->OldConOut->SetCursorPosition (
|
||
|
ConsoleInfo->OldConOut,
|
||
|
Column,
|
||
|
Row
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Record console output history
|
||
|
//
|
||
|
if (!EFI_ERROR (Status)) {
|
||
|
ConsoleInfo->HistoryMode.CursorColumn = (INT32)Column;
|
||
|
ConsoleInfo->HistoryMode.CursorRow = (INT32)(ConsoleInfo->OriginalStartRow + Row);
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Makes the cursor visible or invisible
|
||
|
|
||
|
@param[in] This Protocol instance pointer.
|
||
|
@param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
|
||
|
set to be invisible.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation completed successfully.
|
||
|
@retval EFI_DEVICE_ERROR The device had an error and could not complete the
|
||
|
request, or the device does not support changing
|
||
|
the cursor mode.
|
||
|
@retval EFI_UNSUPPORTED The output device is not in a valid text mode.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
ConsoleLoggerEnableCursor (
|
||
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
|
||
|
IN BOOLEAN Visible
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
|
||
|
ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
|
||
|
//
|
||
|
// Forward the request to the original ConOut
|
||
|
//
|
||
|
Status = ConsoleInfo->OldConOut->EnableCursor (ConsoleInfo->OldConOut, Visible);
|
||
|
|
||
|
//
|
||
|
// Record console output history
|
||
|
//
|
||
|
if (!EFI_ERROR (Status)) {
|
||
|
ConsoleInfo->HistoryMode.CursorVisible = Visible;
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Function to update and verify that the current buffers are correct.
|
||
|
|
||
|
@param[in] ConsoleInfo The pointer to the instance of the console logger information.
|
||
|
|
||
|
This will be used when a mode has changed or a reset ocurred to verify all
|
||
|
history buffers.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
ConsoleLoggerResetBuffers(
|
||
|
IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
if (ConsoleInfo->Buffer != NULL) {
|
||
|
FreePool(ConsoleInfo->Buffer);
|
||
|
ConsoleInfo->Buffer = NULL;
|
||
|
ConsoleInfo->BufferSize = 0;
|
||
|
}
|
||
|
if (ConsoleInfo->Attributes != NULL) {
|
||
|
FreePool(ConsoleInfo->Attributes);
|
||
|
ConsoleInfo->Attributes = NULL;
|
||
|
ConsoleInfo->AttribSize = 0;
|
||
|
}
|
||
|
|
||
|
Status = gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &ConsoleInfo->ColsPerScreen, &ConsoleInfo->RowsPerScreen);
|
||
|
if (EFI_ERROR(Status)){
|
||
|
return (Status);
|
||
|
}
|
||
|
|
||
|
ConsoleInfo->BufferSize = (ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof(ConsoleInfo->Buffer[0]);
|
||
|
ConsoleInfo->AttribSize = ConsoleInfo->ColsPerScreen * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof(ConsoleInfo->Attributes[0]);
|
||
|
|
||
|
ConsoleInfo->Buffer = (CHAR16*)AllocateZeroPool(ConsoleInfo->BufferSize);
|
||
|
|
||
|
if (ConsoleInfo->Buffer == NULL) {
|
||
|
return (EFI_OUT_OF_RESOURCES);
|
||
|
}
|
||
|
|
||
|
ConsoleInfo->Attributes = (INT32*)AllocateZeroPool(ConsoleInfo->AttribSize);
|
||
|
if (ConsoleInfo->Attributes == NULL) {
|
||
|
FreePool(ConsoleInfo->Buffer);
|
||
|
ConsoleInfo->Buffer = NULL;
|
||
|
return (EFI_OUT_OF_RESOURCES);
|
||
|
}
|
||
|
|
||
|
CopyMem (&ConsoleInfo->HistoryMode, ConsoleInfo->OldConOut->Mode, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE));
|
||
|
|
||
|
return (EFI_SUCCESS);
|
||
|
}
|