| /** @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> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #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); | |
| (*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); | |
| ASSERT (ConsoleInfo->OldConOut != NULL); | |
| 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); | |
| // | |
| // 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->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); | |
| 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 attribute and make that temporarily NULL | |
| // so we can do fewer printout statements. (later) restore that one and we will | |
| // start at that column 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 optionally 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); | |
| 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)); | |
| // | |
| // 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); | |
| 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); | |
| 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); | |
| // | |
| // 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: | |
| // | |
| // Acrtually 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); | |
| ConsoleInfo->Buffer[PrintIndex + (2*ConsoleInfo->HistoryMode.CursorRow)] = *Walker; | |
| ASSERT (PrintIndex < ConsoleInfo->AttribSize); | |
| 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); | |
| 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 its 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 its 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); | |
| 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 occurred 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); | |
| } |