From 4b8ef995345ffb694f97a204aa75eca18fcf5f46 Mon Sep 17 00:00:00 2001 From: krishna Date: Thu, 2 Dec 2021 10:33:35 +0800 Subject: [PATCH] restruct history.efi --- .../Application/history/Historian.c | 277 +++++++++--------- .../Application/history/Historian.h | 81 ++--- KrishnaTestPkg/Application/history/history.c | 34 ++- KrishnaTestPkg/Application/history/history.h | 37 +-- 4 files changed, 194 insertions(+), 235 deletions(-) diff --git a/KrishnaTestPkg/Application/history/Historian.c b/KrishnaTestPkg/Application/history/Historian.c index 0570e2e..c6bf3ea 100644 --- a/KrishnaTestPkg/Application/history/Historian.c +++ b/KrishnaTestPkg/Application/history/Historian.c @@ -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; } } diff --git a/KrishnaTestPkg/Application/history/Historian.h b/KrishnaTestPkg/Application/history/Historian.h index 8646164..756544b 100644 --- a/KrishnaTestPkg/Application/history/Historian.h +++ b/KrishnaTestPkg/Application/history/Historian.h @@ -1,73 +1,54 @@ #ifndef __HISTORIAN__H__ #define __HISTORIAN__H__ -#define WCHAR_LF 0x000A -#define WCHAR_CR 0x000D -#define WCHAR_F 0x0046 -#define WCHAR_S 0x0053 -#define WCHAR_SPACE 0x0020 -#define WCHAR_BS 0x0008 - typedef struct historian_ Historian; -typedef UINTN (*HISTORIAN_CONSTRUCTOR)(Historian *This); -typedef UINTN (*HISTORIAN_DESTRUCTOR)(Historian *This); -typedef UINTN (*TELL_HISTORY)(Historian *This, UINTN DesiredRowCount, BOOLEAN IsOnlyGetLastLine); -typedef UINTN (*PREPARE_OUTPUT_BUFFER)(Historian *This, CHAR16 *SourceBuffer, UINTN SourceRowCount, UINTN SourceColumnLength, CHAR16 **OutputBuffer, UINTN *OutputBufferLength); +typedef Historian* (*HISTORIAN_CREATE)(); +typedef EFI_STATUS (*HISTORIAN_TELL_HISTORY)(Historian *This, UINTN DesiredRowCount, BOOLEAN IsOnlyGetLastLine); +typedef VOID (*HISTORIAN_DESTROY)(Historian **This); + +typedef struct { + EFI_SHELL_PARAMETERS_PROTOCOL *Param; + CHAR16 *ScreenBuffer; + UINTN ScreenBufferLength; + UINTN RowsPerScreen; + UINTN ColsPerScreen; +}HistorianPrivateInfo; struct historian_{ - CHAR16 *buffer; ///< Make a copy from UEFI Shell's internal screen buffer. - UINTN bufferLength; ///< Buffer item size,unit is CHAR16 not byte. - UINTN rowsPerScreen; ///< Record UEFI Shell's internal console's height. - UINTN colsPerScreen; ///< Record UEFI Shell's internal console's width. - EFI_HANDLE *handleBuffer; ///< Store temp Handle buffer. - UINTN handleBufferLength; ///< Temp Handle buffer length. - EFI_SHELL_PARAMETERS_PROTOCOL *param; ///< The param binded on this imageHandle. - EFI_SHELL_PROTOCOL *shell; ///< A shell reference. + //public: + HISTORIAN_TELL_HISTORY TellStory; + HISTORIAN_DESTROY Destroy; - /* public functions */ - HISTORIAN_CONSTRUCTOR constructor; ///< Construct this. - HISTORIAN_DESTRUCTOR destructor; ///< Destruct this. - TELL_HISTORY tellStory; ///< Tell recent lines of screen. + //private: + HistorianPrivateInfo Private_; }; -extern Historian gHistorian; - -/** - * Construct a Historian. - * @param[IN] This The instance of Historian. - * - * @retval 1 Operation pass. - * @retval 0 Operation failed. - */ -UINTN HistorianConstructor(Historian *This); - /** - * Destruct a Historian. - * @param[IN] This The instance of Historian. + * @brief Create a new historian. * - * @retval 1 Operation pass. - * @retval 0 Operation failed. + * @return NOT NULL A new historian instance. + * @return NULL Operation fail. */ -UINTN HistorianDestructor(Historian *This); +Historian* HistorianCreate(); /** - * Tell recent lines of history messages. + * @brief Read console text-lines and output them. * - * @param[IN] This The instance of Historian. - * @parma[IN] DesiredRowCount How many recent history-message-lines to output,DesiredRowCount > 0. - * @param[IN] IsOnlyGetLastLine It is the last one line(counting from down to top)we will output.(It is our first line in screen-buffer's view.) + * @param[in] This A historian instance + * @param[in] DesiredRowCount Max desired row count. + * @param[in] IsOnlyGetLastLine Only output last line. * - * @retval 1 Operation pass. - * @retval 0 Operation failed. + * @return EFI_SUCCESS Operation success. + * @return Others Operation fail. */ -UINTN TellStory(Historian *This, UINTN DesiredRowCount, BOOLEAN IsOnlyGetLastLine); +EFI_STATUS HistorianTellStory(Historian *This, UINTN DesiredRowCount, BOOLEAN IsOnlyGetLastLine); /** - * Debug function,used to dump the screen-buffer-raw-data. + * @brief Historian destructor. * - * @param[IN] This The instance of Historian. + * @param[in] This Historian instance address. */ -VOID Dump(Historian *This); +VOID HistorianDestroy(Historian **This); -#endif //__HISTORIAN__H__ \ No newline at end of file +#endif //__HISTORIAN__H__ diff --git a/KrishnaTestPkg/Application/history/history.c b/KrishnaTestPkg/Application/history/history.c index 50ebcf1..32408c4 100644 --- a/KrishnaTestPkg/Application/history/history.c +++ b/KrishnaTestPkg/Application/history/history.c @@ -1,13 +1,24 @@ #include "history.h" #include "Historian.h" +EFI_STATUS DoWork(Historian* This); + EFI_STATUS EFIAPI UefiMain( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { - return ReadHistory(); + EFI_STATUS Status = EFI_ABORTED; + Historian* ThisHistorian = NULL; + + if((ThisHistorian = HistorianCreate()) != NULL) + { + Status = DoWork(ThisHistorian); + ThisHistorian->Destroy(&ThisHistorian); + } + + return Status; } EFI_STATUS PrintHelp() @@ -31,18 +42,18 @@ EFI_STATUS PrintVersion() return EFI_SUCCESS; } -EFI_STATUS ReadHistory() +EFI_STATUS DoWork(Historian* This) { + ASSERT(This != NULL); + UINTN Argc = 0; CHAR16** Argv = NULL; UINTN Number = 0; UINTN i = 1; EFI_STATUS Status = EFI_ABORTED; - if (gHistorian.constructor(&gHistorian) != 1) return Status; - - Argc = gHistorian.param->Argc; - Argv = gHistorian.param->Argv; + Argc = This->Private_.Param->Argc; + Argv = This->Private_.Param->Argv; if(Argc <= 1) return PrintHelp(); @@ -50,19 +61,17 @@ EFI_STATUS ReadHistory() { if(StrCmp(Argv[i], L"-h") == 0 || StrCmp(Argv[i], L"--help") == 0) { - Status = PrintHelp(); - break; + return PrintHelp(); } else if(StrCmp(Argv[i], L"-v") == 0 || StrCmp(Argv[i], L"--version") == 0) { - Status = PrintVersion(); - break; + return PrintVersion(); } else if((StrCmp(Argv[i], L"-b") == 0 || StrCmp(Argv[i], L"--block") == 0) && (i+1)TellStory(This, Number, 0); } else { @@ -74,7 +83,7 @@ EFI_STATUS ReadHistory() { if (StrDecimalToUintnS(Argv[i+1], NULL, &Number) == RETURN_SUCCESS) { - Status = gHistorian.tellStory(&gHistorian, Number, 1); + return This->TellStory(This, Number, 1); } else { @@ -89,6 +98,5 @@ EFI_STATUS ReadHistory() } } - gHistorian.destructor(&gHistorian); return Status; } diff --git a/KrishnaTestPkg/Application/history/history.h b/KrishnaTestPkg/Application/history/history.h index 16606dd..2b78160 100644 --- a/KrishnaTestPkg/Application/history/history.h +++ b/KrishnaTestPkg/Application/history/history.h @@ -1,5 +1,5 @@ -#ifndef __READ_HISTORY__H__ -#define __READ_HISTORY__H__ +#ifndef _HISTORY_H_ +#define _HISTORY_H_ #include #include @@ -14,10 +14,13 @@ #include #include -/// Reference from Shell->ConsoleLogger.h +#define APP_NAME "history" +#define HISTORY_APP_VERSION_STR L"history.efi version 0.1.0" + +// Reference from Shell->ConsoleLogger.h #define CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE SIGNATURE_32('c', 'o', 'P', 'D') -/// Reference from Shell->ConsoleLogger.h +// Reference from Shell->ConsoleLogger.h #pragma pack(1) typedef struct _CONSOLE_LOGGER_PRIVATE_DATA { @@ -44,35 +47,13 @@ typedef struct _CONSOLE_LOGGER_PRIVATE_DATA } CONSOLE_LOGGER_PRIVATE_DATA; #pragma pack() -/// Reference from Shell->ConsoleLogger.h +// Reference from Shell->ConsoleLogger.h #define CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(a) CR(a, CONSOLE_LOGGER_PRIVATE_DATA, OurConOut, CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE) -/** - * This application's name. - */ -#define APP_NAME "history" -#define HISTORY_APP_VERSION_STR L"history.efi version 0.1.0" - -/** - * Using it to print verbose informations. - */ #ifndef NO_VERBOSE #define PrintError(message, ...) Print(L"[%a][%d][%a]:" message, APP_NAME, __LINE__, __FUNCTION__, ##__VA_ARGS__) #else #define PrintError(message, ...) #endif -/** - * This application's help message. - */ -VOID PrintUsageMsg(); - -/** - * Read some history messages from console. - * - * @retval 1 Operation pass. - * @retval 0 Operation failed. - */ -UINTN ReadHistory(); - -#endif //__READ_HISTORY__H__ +#endif //_HISTORY_H_