Skip to content

Commit

Permalink
restruct history.efi
Browse files Browse the repository at this point in the history
  • Loading branch information
krishna116 committed Dec 2, 2021
1 parent 7f9fdb8 commit 4b8ef99
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 235 deletions.
277 changes: 133 additions & 144 deletions KrishnaTestPkg/Application/history/Historian.c
Original file line number Diff line number Diff line change
@@ -1,234 +1,223 @@
#include "history.h"
#include "Historian.h"

Historian gHistorian = {
NULL,
0,
0,
0,
NULL,
0,
NULL,
NULL,

HistorianConstructor,
HistorianDestructor,
TellStory,
};

UINTN HistorianConstructor(Historian *This)
#define WCHAR_LF 0x000A
#define WCHAR_CR 0x000D
#define WCHAR_F 0x0046
#define WCHAR_S 0x0053
#define WCHAR_SPACE 0x0020
#define WCHAR_BS 0x0008

EFI_STATUS HistorianInitParam(Historian *This)
{
EFI_STATUS status = 0;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *simpleTextProtocol = NULL;
CONSOLE_LOGGER_PRIVATE_DATA *consoleInfo = NULL;

/// Make sure do not construct this more than once;
ASSERT(This != NULL);
ASSERT(This->buffer == NULL);
ASSERT(This->handleBuffer == NULL);

status = gBS->LocateProtocol(&gEfiShellProtocolGuid, NULL, &(This->shell));
if (status != EFI_SUCCESS)
EFI_STATUS Status = EFI_ABORTED;

if(gBS->HandleProtocol(gImageHandle, &gEfiShellParametersProtocolGuid, &(This->Private_.Param)) == EFI_SUCCESS)
{
PrintError(L"[Cannot locate shell.\n");
return 0;
Status = EFI_SUCCESS;
}

status = gBS->HandleProtocol(gImageHandle, &gEfiShellParametersProtocolGuid, &(This->param));
if (status != EFI_SUCCESS)
else
{
PrintError(L"Cannot locate ParametersProtocol.\n");
return 0;
}

status = gBS->LocateHandleBuffer(ByProtocol, &gEfiShellProtocolGuid, NULL, &This->handleBufferLength, &(This->handleBuffer));
if (status == EFI_SUCCESS)
return Status;
}

EFI_STATUS HistorianInitScreenBuffer(Historian *This)
{
ASSERT(This != NULL);
ASSERT(This->Private_.ScreenBuffer == NULL);

EFI_STATUS Status = EFI_ABORTED;
EFI_HANDLE* ShellHandleBuffer=NULL;
UINTN ShellHandleBufferLength = 0;
CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo = NULL;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextProtocol = NULL;

if(gBS->LocateHandleBuffer(ByProtocol, &gEfiShellProtocolGuid, NULL, &ShellHandleBufferLength, &ShellHandleBuffer) == EFI_SUCCESS)
{
/// Assume there is only one shell instance in the system.
status = gBS->HandleProtocol(This->handleBuffer[0], &gEfiSimpleTextOutProtocolGuid, &simpleTextProtocol);
if (status == EFI_SUCCESS)
// Just try to get simple text protocol from first shell handle.
if(gBS->HandleProtocol(ShellHandleBuffer[0], &gEfiSimpleTextOutProtocolGuid, &SimpleTextProtocol) == EFI_SUCCESS)
{
consoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(simpleTextProtocol);
if (consoleInfo != NULL)
ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(SimpleTextProtocol);
This->Private_.ScreenBuffer = AllocateZeroPool(ConsoleInfo->BufferSize);
if (This->Private_.ScreenBuffer != NULL)
{
This->buffer = AllocateZeroPool(consoleInfo->BufferSize);
if (This->buffer != NULL)
{
CopyMem(This->buffer, consoleInfo->Buffer, consoleInfo->BufferSize);
This->bufferLength = consoleInfo->BufferSize / sizeof(CHAR16);

This->rowsPerScreen = consoleInfo->RowsPerScreen;
This->colsPerScreen = consoleInfo->ColsPerScreen;

return 1;
}
else
{
PrintError(L"Out of memory.\n");
}
CopyMem(This->Private_.ScreenBuffer, ConsoleInfo->Buffer, ConsoleInfo->BufferSize);
This->Private_.ScreenBufferLength = ConsoleInfo->BufferSize / sizeof(CHAR16);
This->Private_.RowsPerScreen = ConsoleInfo->RowsPerScreen;
This->Private_.ColsPerScreen = ConsoleInfo->ColsPerScreen;
Status = EFI_SUCCESS;
}
else
{
PrintError(L"Cannot locate consoleInfo.\n");
PrintError(L"Out of memory.\n");
}
}
else
{
PrintError(L"Cannot locate SimpleTextOutProtocol.\n");
}
FreePool(ShellHandleBuffer);
}
else
{
PrintError(L"Cannot get ShellHandleBuffer.\n");
PrintError(L"Cannot locate all shell handles.\n");
}

return 0;
return Status;
}

UINTN HistorianDestructor(Historian *This)
Historian* HistorianCreate()
{
ASSERT(This != NULL);
EFI_STATUS Status = EFI_ABORTED;
Historian* ThisHistorian = NULL;

if (This->buffer != NULL)
if((ThisHistorian = AllocateZeroPool(sizeof(Historian))) != NULL)
{
FreePool(This->buffer);
This->buffer = NULL;
}
ThisHistorian->Private_.Param = NULL;
if(HistorianInitParam(ThisHistorian) == EFI_SUCCESS)
{
ThisHistorian->Private_.ScreenBuffer = NULL;
if(HistorianInitScreenBuffer(ThisHistorian) == EFI_SUCCESS)
{
ThisHistorian->TellStory = HistorianTellStory;
ThisHistorian->Destroy = HistorianDestroy;

if (This->handleBuffer != NULL)
{
FreePool(This->handleBuffer);
This->handleBuffer = NULL;
Status = EFI_SUCCESS;
}
}
}

return 1;
if(Status != EFI_SUCCESS) HistorianDestroy(&ThisHistorian);

return ThisHistorian;
}

UINTN TellStory(Historian *This, UINTN DesiredRowCount, BOOLEAN IsOnlyGetLastLine)
EFI_STATUS HistorianTellStory(Historian *This, UINTN DesiredRowCount, BOOLEAN IsOnlyGetLastLine)
{
UINTN OneColumnSize = 0;
CHAR16 *outputPosition = NULL;
EFI_STATUS Status = EFI_ABORTED;

CHAR16 *outputBuffer = NULL;
UINTN outputBufferLength = 0;
UINTN byteSize = 0;
UINTN outputLineCount = 0;
UINTN OneColumnLineSize = 0;
CHAR16 *OutputPosition = NULL;

CHAR16 *start = NULL;
CHAR16 *final = NULL;
CHAR16 *dest = NULL;
CHAR16 *source = NULL;
CHAR16 *OutputBuffer = NULL;
UINTN OutputBufferLength = 0;
UINTN OutputBufferByteSize = 0;
UINTN OutputLineCount = 0;

CHAR16 *Start = NULL;
CHAR16 *Final = NULL;
CHAR16 *Dest = NULL;
CHAR16 *Source = NULL;

ASSERT(This != NULL);
ASSERT(This->buffer != NULL);
ASSERT(This->bufferLength != 0);

if(DesiredRowCount == 0) return 0;
if(This->Private_.ScreenBuffer == NULL ||
This->Private_.ScreenBufferLength == 0 ||
DesiredRowCount == 0
)
{
return Status;
}

/// Every line size is [ColsPerScreen + 2] used in uefi shell.
OneColumnSize = This->colsPerScreen + 2;
start = This->buffer;
while (start < (This->buffer + This->bufferLength))
// Every line size is [ColsPerScreen + 2] used in uefi shell.
OneColumnLineSize = This->Private_.ColsPerScreen + 2;
Start = This->Private_.ScreenBuffer;
while (Start < (This->Private_.ScreenBuffer +This->Private_.ScreenBufferLength))
{
if (*start == WCHAR_F && *(start + 1) == WCHAR_S)
// Try to locate current position.
if (*Start == WCHAR_F && *(Start + 1) == WCHAR_S)
{
final = start;
Final = Start;
}
start += OneColumnSize;
Start += OneColumnLineSize;
}

/// The final is the last line start with 'FS',it is the position where we execute this.efi.
if (final == NULL)
// Check current position.
if (Final == NULL)
{
PrintError(L"Cannot locate app's current position.\n");
return 0;
return Status;
}

/// This->buffer is the screen's first-line's begin.
/// final is the current line where we execute this.efi.
if ((This->buffer + (DesiredRowCount * OneColumnSize)) > final)
// This->buffer is the screen's first-line's begin.
// Final is the current line where we execute this.efi.
if ((This->Private_.ScreenBuffer + (DesiredRowCount * OneColumnLineSize)) > Final)
{
/// DesiredRowCount is out of range,just output This->buffer.
outputPosition = This->buffer;
outputLineCount = (final - This->buffer) / OneColumnSize;
/// DesiredRowCount is out of range,just output the present screen buffer.
OutputPosition = This->Private_.ScreenBuffer;
OutputLineCount = (Final - This->Private_.ScreenBuffer) / OneColumnLineSize;
}
else
{
/// Move up to desired line begin;
outputPosition = final - DesiredRowCount * OneColumnSize;
outputLineCount = DesiredRowCount;
// Move up to desired line begin;
OutputPosition = Final - DesiredRowCount * OneColumnLineSize;
OutputLineCount = DesiredRowCount;
}

if (IsOnlyGetLastLine)
{
outputLineCount = 1;
}
if (IsOnlyGetLastLine) OutputLineCount = 1;

outputBufferLength = outputLineCount * This->colsPerScreen;
/// Allocate one more CHAR16 is used for string-terminator,but do not count it.
outputBuffer = AllocateZeroPool((outputBufferLength + 1) * sizeof(CHAR16));
if (outputBuffer != NULL)
OutputBufferLength = OutputLineCount * This->Private_.ColsPerScreen;
// Allocate one more CHAR16 is used for string-terminator,but do not count it.
OutputBuffer = AllocateZeroPool((OutputBufferLength + 1) * sizeof(CHAR16));
if (OutputBuffer != NULL)
{
dest = outputBuffer;
source = outputPosition;
byteSize = outputBufferLength * sizeof(CHAR16);
Dest = OutputBuffer;
Source = OutputPosition;
OutputBufferByteSize = OutputBufferLength * sizeof(CHAR16);

/// Every line size is [ColsPerScreen + 2] used in uefi shell,but we exclude the last two char.
for (UINTN line = 0; line < outputLineCount; line++)
// Every line size is OneColumnLineSize(ColsPerScreen + 2) used in uefi shell,
// We should exclude the last two char.
for (UINTN line = 0; line < OutputLineCount; line++)
{
CopyMem(dest, source, This->colsPerScreen * sizeof(CHAR16));
dest += OneColumnSize - 2;
source += OneColumnSize;
CopyMem(Dest, Source, This->Private_.ColsPerScreen * sizeof(CHAR16));
Dest += This->Private_.ColsPerScreen;
Source += OneColumnLineSize;
}

/// In Emulator(QEMU) the buffer may contain zero-value chars,it is not valid for output,convert them to space.
for (UINTN i = 0; i < outputBufferLength; i++)
// In Emulator(QEMU) the buffer may contain zero-value chars,
// it is not valid for output, convert them to space.
for (UINTN i = 0; i < OutputBufferLength; i++)
{
if (outputBuffer[i] == 0)
{
outputBuffer[i] = WCHAR_SPACE;
}
if (OutputBuffer[i] == 0) OutputBuffer[i] = WCHAR_SPACE;
}

if (gEfiShellParametersProtocol != NULL && gEfiShellProtocol != NULL)
if (gEfiShellProtocol != NULL)
{
gEfiShellProtocol->WriteFile(gEfiShellParametersProtocol->StdOut, &byteSize, (VOID *)outputBuffer);
gEfiShellProtocol->FlushFile(gEfiShellParametersProtocol->StdOut);
gEfiShellProtocol->WriteFile(This->Private_.Param->StdOut, &OutputBufferByteSize, (VOID *)OutputBuffer);
gEfiShellProtocol->FlushFile(This->Private_.Param->StdOut);
Status = EFI_SUCCESS;
}
else
{
Print(L"%s", outputBuffer);
}

if (outputBuffer != NULL)
{
FreePool(outputBuffer);
outputBuffer = NULL;
PrintError(L"Need a shell instance to output.\n");
}

return 1;
FreePool(OutputBuffer);
}
else
{
PrintError(L"Out of memory\n");
}

return 0;
return Status;
}

VOID Dump(Historian *This)
VOID HistorianDestroy(Historian **This)
{
if (This == NULL || This->buffer == NULL)
if(This && *This)
{
return;
}

for (UINTN i = 0; i < This->bufferLength; i++)
{
Print(L"%02x-", This->buffer[i]);
if ((i + 1) % (This->colsPerScreen + 2) == 0)
if((*This)->Private_.ScreenBuffer)
{
Print(L"z\n");
FreePool((*This)->Private_.ScreenBuffer);
(*This)->Private_.ScreenBuffer = NULL;
}

FreePool(*This);
*This = NULL;
}
}
Loading

0 comments on commit 4b8ef99

Please sign in to comment.