Home | History | Annotate | Download | only in Shell
      1 /** @file
      2   Provides interface to shell console logger.
      3 
      4   (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
      5   Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 **/
     14 
     15 #include "Shell.h"
     16 
     17 /**
     18   Install our intermediate ConOut into the system table to
     19   keep a log of all the info that is displayed to the user.
     20 
     21   @param[in] ScreensToSave  Sets how many screen-worths of data to save.
     22   @param[out] ConsoleInfo   The object to pass into later functions.
     23 
     24   @retval EFI_SUCCESS       The operation was successful.
     25   @return other             The operation failed.
     26 
     27   @sa ConsoleLoggerResetBuffers
     28   @sa InstallProtocolInterface
     29 **/
     30 EFI_STATUS
     31 EFIAPI
     32 ConsoleLoggerInstall(
     33   IN CONST UINTN ScreensToSave,
     34   OUT CONSOLE_LOGGER_PRIVATE_DATA **ConsoleInfo
     35   )
     36 {
     37   EFI_STATUS Status;
     38   ASSERT(ConsoleInfo != NULL);
     39 
     40   (*ConsoleInfo) = AllocateZeroPool(sizeof(CONSOLE_LOGGER_PRIVATE_DATA));
     41   if ((*ConsoleInfo) == NULL) {
     42     return (EFI_OUT_OF_RESOURCES);
     43   }
     44 
     45   (*ConsoleInfo)->Signature                   = CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE;
     46   (*ConsoleInfo)->OldConOut                   = gST->ConOut;
     47   (*ConsoleInfo)->OldConHandle                = gST->ConsoleOutHandle;
     48   (*ConsoleInfo)->Buffer                      = NULL;
     49   (*ConsoleInfo)->BufferSize                  = 0;
     50   (*ConsoleInfo)->OriginalStartRow            = 0;
     51   (*ConsoleInfo)->CurrentStartRow             = 0;
     52   (*ConsoleInfo)->RowsPerScreen               = 0;
     53   (*ConsoleInfo)->ColsPerScreen               = 0;
     54   (*ConsoleInfo)->Attributes                  = NULL;
     55   (*ConsoleInfo)->AttribSize                  = 0;
     56   (*ConsoleInfo)->ScreenCount                 = ScreensToSave;
     57   (*ConsoleInfo)->HistoryMode.MaxMode         = 1;
     58   (*ConsoleInfo)->HistoryMode.Mode            = 0;
     59   (*ConsoleInfo)->HistoryMode.Attribute       = 0;
     60   (*ConsoleInfo)->HistoryMode.CursorColumn    = 0;
     61   (*ConsoleInfo)->HistoryMode.CursorRow       = 0;
     62   (*ConsoleInfo)->HistoryMode.CursorVisible   = FALSE;
     63   (*ConsoleInfo)->OurConOut.Reset             = ConsoleLoggerReset;
     64   (*ConsoleInfo)->OurConOut.OutputString      = ConsoleLoggerOutputString;
     65   (*ConsoleInfo)->OurConOut.TestString        = ConsoleLoggerTestString;
     66   (*ConsoleInfo)->OurConOut.QueryMode         = ConsoleLoggerQueryMode;
     67   (*ConsoleInfo)->OurConOut.SetMode           = ConsoleLoggerSetMode;
     68   (*ConsoleInfo)->OurConOut.SetAttribute      = ConsoleLoggerSetAttribute;
     69   (*ConsoleInfo)->OurConOut.ClearScreen       = ConsoleLoggerClearScreen;
     70   (*ConsoleInfo)->OurConOut.SetCursorPosition = ConsoleLoggerSetCursorPosition;
     71   (*ConsoleInfo)->OurConOut.EnableCursor      = ConsoleLoggerEnableCursor;
     72   (*ConsoleInfo)->OurConOut.Mode              = gST->ConOut->Mode;
     73   (*ConsoleInfo)->Enabled                     = TRUE;
     74 
     75   Status = ConsoleLoggerResetBuffers(*ConsoleInfo);
     76   if (EFI_ERROR(Status)) {
     77     SHELL_FREE_NON_NULL((*ConsoleInfo));
     78     *ConsoleInfo = NULL;
     79     return (Status);
     80   }
     81 
     82   Status = gBS->InstallProtocolInterface(&gImageHandle, &gEfiSimpleTextOutProtocolGuid, EFI_NATIVE_INTERFACE, (VOID*)&((*ConsoleInfo)->OurConOut));
     83   if (EFI_ERROR(Status)) {
     84     SHELL_FREE_NON_NULL((*ConsoleInfo)->Buffer);
     85     SHELL_FREE_NON_NULL((*ConsoleInfo)->Attributes);
     86     SHELL_FREE_NON_NULL((*ConsoleInfo));
     87     *ConsoleInfo = NULL;
     88     return (Status);
     89   }
     90 
     91   gST->ConsoleOutHandle = gImageHandle;
     92   gST->ConOut           = &(*ConsoleInfo)->OurConOut;
     93 
     94   return (Status);
     95 }
     96 
     97 /**
     98   Return the system to the state it was before InstallConsoleLogger
     99   was installed.
    100 
    101   @param[in] ConsoleInfo  The object from the install function.
    102 
    103   @retval EFI_SUCCESS     The operation was successful
    104   @return other           The operation failed.  This was from UninstallProtocolInterface.
    105 **/
    106 EFI_STATUS
    107 EFIAPI
    108 ConsoleLoggerUninstall(
    109   IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
    110   )
    111 {
    112   ASSERT(ConsoleInfo != NULL);
    113   ASSERT(ConsoleInfo->OldConOut != NULL);
    114 
    115   if (ConsoleInfo->Buffer != NULL) {
    116     FreePool(ConsoleInfo->Buffer);
    117     DEBUG_CODE(ConsoleInfo->Buffer     = NULL;);
    118     DEBUG_CODE(ConsoleInfo->BufferSize = 0;);
    119   }
    120   if (ConsoleInfo->Attributes != NULL) {
    121     FreePool(ConsoleInfo->Attributes);
    122     DEBUG_CODE(ConsoleInfo->Attributes = NULL;);
    123     DEBUG_CODE(ConsoleInfo->AttribSize = 0;);
    124   }
    125 
    126   gST->ConsoleOutHandle = ConsoleInfo->OldConHandle;
    127   gST->ConOut = ConsoleInfo->OldConOut;
    128 
    129   return (gBS->UninstallProtocolInterface(gImageHandle, &gEfiSimpleTextOutProtocolGuid, (VOID*)&ConsoleInfo->OurConOut));
    130 }
    131 
    132 /**
    133   Displays previously logged output back to the screen.
    134 
    135   This will scroll the screen forwards and backwards through the log of previous
    136   output.  If Rows is 0 then the size of 1/2 the screen will be scrolled.  If Rows
    137   is (UINTN)(-1) then the size of the screen will be scrolled.
    138 
    139   @param[in] Forward      If TRUE then the log will be displayed forwards (scroll to newer).
    140                           If FALSE then the log will be displayed backwards (scroll to older).
    141   @param[in] Rows         Determines how many rows the log should scroll.
    142   @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
    143 **/
    144 EFI_STATUS
    145 EFIAPI
    146 ConsoleLoggerDisplayHistory(
    147   IN CONST BOOLEAN  Forward,
    148   IN CONST UINTN    Rows,
    149   IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
    150   )
    151 {
    152   UINTN   RowChange;
    153 
    154   ASSERT(ConsoleInfo != NULL);
    155 
    156   //
    157   // Calculate the row number change
    158   //
    159   switch (Rows) {
    160   case ((UINTN)(-1)):
    161     RowChange = ConsoleInfo->RowsPerScreen;
    162     break;
    163   case (0):
    164     RowChange = ConsoleInfo->RowsPerScreen / 2;
    165     break;
    166   default:
    167     RowChange = Rows;
    168     break;
    169   }
    170 
    171   //
    172   // Do the math for direction
    173   //
    174   if (Forward) {
    175     if ((ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow) < RowChange) {
    176       RowChange = ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow;
    177     }
    178   } else {
    179     if (ConsoleInfo->CurrentStartRow < RowChange) {
    180       RowChange = ConsoleInfo->CurrentStartRow;
    181     }
    182   }
    183 
    184   //
    185   // If we are already at one end or the other
    186   //
    187   if (RowChange == 0) {
    188     return (EFI_SUCCESS);
    189   }
    190 
    191   //
    192   // Clear the screen
    193   //
    194   ConsoleInfo->OldConOut->ClearScreen(ConsoleInfo->OldConOut);
    195 
    196   //
    197   // Set the new start row
    198   //
    199   if (Forward) {
    200     ConsoleInfo->CurrentStartRow += RowChange;
    201   } else {
    202     ConsoleInfo->CurrentStartRow -= RowChange;
    203   }
    204 
    205   //
    206   // Change the screen
    207   //
    208   return (UpdateDisplayFromHistory(ConsoleInfo));
    209 }
    210 
    211 /**
    212   Function to return to normal output whent he scrolling is complete.
    213   @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
    214 
    215   @retval EFI_SUCCESS   The operation was successful.
    216   @return other         The operation failed.  See UpdateDisplayFromHistory.
    217 
    218   @sa UpdateDisplayFromHistory
    219 **/
    220 EFI_STATUS
    221 EFIAPI
    222 ConsoleLoggerStopHistory(
    223   IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
    224   )
    225 {
    226   ASSERT(ConsoleInfo != NULL);
    227   if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) {
    228     return (EFI_SUCCESS);
    229   }
    230 
    231   //
    232   // Clear the screen
    233   //
    234   ConsoleInfo->OldConOut->ClearScreen(ConsoleInfo->OldConOut);
    235 
    236   ConsoleInfo->CurrentStartRow = ConsoleInfo->OriginalStartRow;
    237   return (UpdateDisplayFromHistory(ConsoleInfo));
    238 }
    239 
    240 /**
    241   Updates the hidden ConOut to be displaying the correct stuff.
    242   @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
    243 
    244   @retval EFI_SUCCESS     The operation was successful.
    245   @return other           The operation failed.
    246 **/
    247 EFI_STATUS
    248 EFIAPI
    249 UpdateDisplayFromHistory(
    250   IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
    251   )
    252 {
    253   EFI_STATUS      Status;
    254   EFI_STATUS      RetVal;
    255   CHAR16          *Screen;
    256   INT32           *Attributes;
    257   UINTN           CurrentRow;
    258   CHAR16          TempCharHolder;
    259   UINTN           Column;
    260   INT32           CurrentAttrib;
    261   UINTN           CurrentColumn;
    262   CHAR16          *StringSegment;
    263   CHAR16          *StringSegmentEnd;
    264   CHAR16          StringSegmentEndChar;
    265   INT32           OrigAttribute;
    266 
    267   ASSERT(ConsoleInfo != NULL);
    268   TempCharHolder = CHAR_NULL;
    269   RetVal = EFI_SUCCESS;
    270   OrigAttribute = ConsoleInfo->OldConOut->Mode->Attribute;
    271 
    272   //
    273   // Disable cursor visibility and move it to the top left corner
    274   //
    275   ConsoleInfo->OldConOut->EnableCursor       (ConsoleInfo->OldConOut, FALSE);
    276   ConsoleInfo->OldConOut->SetCursorPosition  (ConsoleInfo->OldConOut, 0, 0);
    277 
    278   Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow];
    279   Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow];
    280   for ( CurrentRow = 0
    281       ; CurrentRow < ConsoleInfo->RowsPerScreen
    282       ; CurrentRow++
    283       , Screen += (ConsoleInfo->ColsPerScreen + 2)
    284       , Attributes += ConsoleInfo->ColsPerScreen
    285      ){
    286     //
    287     // dont use the last char - prevents screen scroll
    288     //
    289     if (CurrentRow == (ConsoleInfo->RowsPerScreen-1)){
    290       TempCharHolder = Screen[ConsoleInfo->ColsPerScreen - 1];
    291       Screen[ConsoleInfo->ColsPerScreen - 1] = CHAR_NULL;
    292     }
    293 
    294     for ( Column = 0
    295         ; Column < ConsoleInfo->ColsPerScreen
    296         ; Column++
    297        ){
    298       if (Screen[Column] != CHAR_NULL) {
    299         CurrentAttrib = Attributes[Column];
    300         CurrentColumn = Column;
    301         StringSegment = &Screen[Column];
    302 
    303         //
    304         // Find the first char with a different arrribute and make that temporarily NULL
    305         // so we can do fewer printout statements.  (later) restore that one and we will
    306         // start at that collumn on the next loop.
    307         //
    308         StringSegmentEndChar = CHAR_NULL;
    309         for ( StringSegmentEnd = StringSegment
    310             ; StringSegmentEnd != CHAR_NULL
    311             ; StringSegmentEnd++
    312             , Column++
    313            ){
    314           if (Attributes[Column] != CurrentAttrib) {
    315             StringSegmentEndChar = *StringSegmentEnd;
    316             *StringSegmentEnd    = CHAR_NULL;
    317             break;
    318           }
    319         } // StringSegmentEnd loop
    320 
    321         //
    322         // Now write out as much as had the same Attributes
    323         //
    324 
    325         ConsoleInfo->OldConOut->SetAttribute(ConsoleInfo->OldConOut, CurrentAttrib);
    326         ConsoleInfo->OldConOut->SetCursorPosition(ConsoleInfo->OldConOut, CurrentColumn, CurrentRow);
    327         Status = ConsoleInfo->OldConOut->OutputString(ConsoleInfo->OldConOut, StringSegment);
    328 
    329         if (EFI_ERROR(Status)) {
    330           ASSERT(FALSE);
    331           RetVal = Status;
    332         }
    333 
    334         //
    335         // If we found a change in attribute put the character back and decrement the column
    336         // so when it increments it will point at that character and we will start printing
    337         // a segment with that new attribute
    338         //
    339         if (StringSegmentEndChar != CHAR_NULL) {
    340           *StringSegmentEnd = StringSegmentEndChar;
    341           StringSegmentEndChar = CHAR_NULL;
    342           Column--;
    343         }
    344       }
    345     } // column for loop
    346 
    347     //
    348     // If we removed the last char and this was the last row put it back
    349     //
    350     if (TempCharHolder != CHAR_NULL) {
    351       Screen[ConsoleInfo->ColsPerScreen - 1] = TempCharHolder;
    352       TempCharHolder = CHAR_NULL;
    353     }
    354   } // row for loop
    355 
    356   //
    357   // If we are setting the screen back to original turn on the cursor and make it visible
    358   // and set the attributes back to what they were
    359   //
    360   if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) {
    361     ConsoleInfo->OldConOut->SetAttribute (
    362                                 ConsoleInfo->OldConOut,
    363                                 ConsoleInfo->HistoryMode.Attribute
    364                                );
    365     ConsoleInfo->OldConOut->SetCursorPosition (
    366                                 ConsoleInfo->OldConOut,
    367                                 ConsoleInfo->HistoryMode.CursorColumn,
    368                                 ConsoleInfo->HistoryMode.CursorRow - ConsoleInfo->OriginalStartRow
    369                                );
    370 
    371     Status = ConsoleInfo->OldConOut->EnableCursor (
    372                                 ConsoleInfo->OldConOut,
    373                                 ConsoleInfo->HistoryMode.CursorVisible
    374                                );
    375     if (EFI_ERROR (Status)) {
    376       RetVal = Status;
    377     }
    378   } else {
    379     ConsoleInfo->OldConOut->SetAttribute (
    380                                 ConsoleInfo->OldConOut,
    381                                 OrigAttribute
    382                                );
    383   }
    384 
    385   return (RetVal);
    386 }
    387 
    388 /**
    389   Reset the text output device hardware and optionaly run diagnostics
    390 
    391   @param  This                pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
    392   @param ExtendedVerification Indicates that a more extensive test may be performed
    393 
    394   @retval EFI_SUCCESS         The text output device was reset.
    395   @retval EFI_DEVICE_ERROR    The text output device is not functioning correctly and
    396                               could not be reset.
    397 **/
    398 EFI_STATUS
    399 EFIAPI
    400 ConsoleLoggerReset (
    401   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
    402   IN  BOOLEAN                         ExtendedVerification
    403   )
    404 {
    405   EFI_STATUS                  Status;
    406   CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
    407   ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
    408 
    409   //
    410   // Forward the request to the original ConOut
    411   //
    412   Status = ConsoleInfo->OldConOut->Reset (ConsoleInfo->OldConOut, ExtendedVerification);
    413 
    414   //
    415   // Check that the buffers are still correct for logging
    416   //
    417   if (!EFI_ERROR (Status)) {
    418     ConsoleLoggerResetBuffers(ConsoleInfo);
    419     if (ExtendedVerification) {
    420       ConsoleInfo->OriginalStartRow = 0;
    421       ConsoleInfo->CurrentStartRow = 0;
    422     }
    423   }
    424 
    425   return Status;
    426 }
    427 
    428 /**
    429   Appends a string to the history buffer.  If the buffer is full then the oldest
    430   information in the buffer will be dropped.  Information is added in a line by
    431   line manner such that an empty line takes up just as much space as a full line.
    432 
    433   @param[in] String       String pointer to add.
    434   @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
    435 **/
    436 EFI_STATUS
    437 EFIAPI
    438 AppendStringToHistory(
    439   IN CONST CHAR16 *String,
    440   IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
    441   )
    442 {
    443   CONST CHAR16  *Walker;
    444   UINTN         CopySize;
    445   UINTN         PrintIndex;
    446   UINTN         Index;
    447 
    448   ASSERT(ConsoleInfo != NULL);
    449 
    450   for ( Walker = String
    451       ; Walker != NULL && *Walker != CHAR_NULL
    452       ; Walker++
    453      ){
    454     switch (*Walker) {
    455     case (CHAR_BACKSPACE):
    456       if (ConsoleInfo->HistoryMode.CursorColumn > 0) {
    457         ConsoleInfo->HistoryMode.CursorColumn--;
    458       }
    459       break;
    460     case (CHAR_LINEFEED):
    461       if (ConsoleInfo->HistoryMode.CursorRow >= (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1)) {
    462         //
    463         // Should never be bigger
    464         //
    465         ASSERT(ConsoleInfo->HistoryMode.CursorRow == (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1));
    466 
    467         //
    468         // scroll history attributes 'up' 1 row and set the last row to default attribute
    469         //
    470         CopySize = ConsoleInfo->ColsPerScreen
    471                  * ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1)
    472                  * sizeof(ConsoleInfo->Attributes[0]);
    473         ASSERT(CopySize < ConsoleInfo->AttribSize);
    474         CopyMem(
    475           ConsoleInfo->Attributes,
    476           ConsoleInfo->Attributes + ConsoleInfo->ColsPerScreen,
    477           CopySize
    478          );
    479 
    480         for ( Index = 0
    481             ; Index < ConsoleInfo->ColsPerScreen
    482             ; Index++
    483            ){
    484           *(ConsoleInfo->Attributes + (CopySize/sizeof(ConsoleInfo->Attributes[0])) + Index) = ConsoleInfo->HistoryMode.Attribute;
    485         }
    486 
    487         //
    488         // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
    489         //
    490         CopySize = (ConsoleInfo->ColsPerScreen + 2)
    491                  * ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1)
    492                  * sizeof(ConsoleInfo->Buffer[0]);
    493         ASSERT(CopySize < ConsoleInfo->BufferSize);
    494         CopyMem(
    495           ConsoleInfo->Buffer,
    496           ConsoleInfo->Buffer + (ConsoleInfo->ColsPerScreen + 2),
    497           CopySize
    498          );
    499 
    500         //
    501         // Set that last row of chars to spaces
    502         //
    503         SetMem16(((UINT8*)ConsoleInfo->Buffer)+CopySize, ConsoleInfo->ColsPerScreen*sizeof(CHAR16), L' ');
    504       } else {
    505         //
    506         // we are not on the last row
    507         //
    508 
    509         //
    510         // We should not be scrolling history
    511         //
    512         ASSERT (ConsoleInfo->OriginalStartRow == ConsoleInfo->CurrentStartRow);
    513         //
    514         // are we at the end of a row?
    515         //
    516         if (ConsoleInfo->HistoryMode.CursorRow == (INT32) (ConsoleInfo->OriginalStartRow + ConsoleInfo->RowsPerScreen - 1)) {
    517           ConsoleInfo->OriginalStartRow++;
    518           ConsoleInfo->CurrentStartRow++;
    519         }
    520         ConsoleInfo->HistoryMode.CursorRow++;
    521       }
    522       break;
    523     case (CHAR_CARRIAGE_RETURN):
    524       //
    525       // Move the cursor to the beginning of the current row.
    526       //
    527       ConsoleInfo->HistoryMode.CursorColumn = 0;
    528       break;
    529     default:
    530       //
    531       // Acrtually print characters into the history buffer
    532       //
    533 
    534       PrintIndex = ConsoleInfo->HistoryMode.CursorRow * ConsoleInfo->ColsPerScreen + ConsoleInfo->HistoryMode.CursorColumn;
    535 
    536       for ( // no initializer needed
    537           ; ConsoleInfo->HistoryMode.CursorColumn < (INT32) ConsoleInfo->ColsPerScreen
    538           ; ConsoleInfo->HistoryMode.CursorColumn++
    539           , PrintIndex++
    540           , Walker++
    541          ){
    542         if (*Walker == CHAR_NULL
    543           ||*Walker == CHAR_BACKSPACE
    544           ||*Walker == CHAR_LINEFEED
    545           ||*Walker == CHAR_CARRIAGE_RETURN
    546          ){
    547             Walker--;
    548             break;
    549         }
    550         //
    551         // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
    552         //
    553 
    554         ASSERT(PrintIndex + ConsoleInfo->HistoryMode.CursorRow < ConsoleInfo->BufferSize);
    555         ConsoleInfo->Buffer[PrintIndex + (2*ConsoleInfo->HistoryMode.CursorRow)] = *Walker;
    556         ASSERT(PrintIndex < ConsoleInfo->AttribSize);
    557         ConsoleInfo->Attributes[PrintIndex] = ConsoleInfo->HistoryMode.Attribute;
    558       } // for loop
    559 
    560       //
    561       // Add the carriage return and line feed at the end of the lines
    562       //
    563       if (ConsoleInfo->HistoryMode.CursorColumn >= (INT32)ConsoleInfo->ColsPerScreen) {
    564         AppendStringToHistory(L"\r\n", ConsoleInfo);
    565         Walker--;
    566       }
    567 
    568       break;
    569     } // switch for character
    570   } // for loop
    571 
    572   return (EFI_SUCCESS);
    573 }
    574 
    575 /**
    576   Worker function to handle printing the output to the screen
    577   and the history buffer
    578 
    579   @param[in] String               The string to output
    580   @param[in] ConsoleInfo          The pointer to the instance of the console logger information.
    581 
    582   @retval EFI_SUCCESS             The string was printed
    583   @retval EFI_DEVICE_ERROR        The device reported an error while attempting to output
    584                                   the text.
    585   @retval EFI_UNSUPPORTED         The output device's mode is not currently in a
    586                                   defined text mode.
    587   @retval EFI_WARN_UNKNOWN_GLYPH  This warning code indicates that some of the
    588                                   characters in the Unicode string could not be
    589                                   rendered and were skipped.
    590 **/
    591 EFI_STATUS
    592 EFIAPI
    593 ConsoleLoggerOutputStringSplit(
    594   IN CONST CHAR16   *String,
    595   IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
    596   )
    597 {
    598   EFI_STATUS    Status;
    599 
    600   //
    601   // Forward the request to the original ConOut
    602   //
    603   Status = ConsoleInfo->OldConOut->OutputString (ConsoleInfo->OldConOut, (CHAR16*)String);
    604 
    605   if (EFI_ERROR(Status)) {
    606     return (Status);
    607   }
    608 
    609   return (AppendStringToHistory(String, ConsoleInfo));
    610 }
    611 
    612 /**
    613   Function to handle page break mode.
    614 
    615   This function will prompt for continue or break.
    616 
    617   @retval EFI_SUCCESS   Continue was choosen
    618   @return other         Break was choosen
    619 **/
    620 EFI_STATUS
    621 EFIAPI
    622 ConsoleLoggerDoPageBreak(
    623   VOID
    624   )
    625 {
    626   SHELL_PROMPT_RESPONSE *Resp;
    627   EFI_STATUS            Status;
    628 
    629   Resp = NULL;
    630   ASSERT(ShellInfoObject.PageBreakEnabled);
    631   ShellInfoObject.PageBreakEnabled = FALSE;
    632   Status = ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue, STRING_TOKEN(STR_SHELL_QUIT_CONT), ShellInfoObject.HiiHandle, (VOID**)&Resp);
    633   ShellInfoObject.PageBreakEnabled = TRUE;
    634   ASSERT(Resp != NULL);
    635   if (Resp == NULL) {
    636     return (EFI_NOT_FOUND);
    637   }
    638   if (EFI_ERROR(Status)) {
    639     if (Resp != NULL) {
    640       FreePool(Resp);
    641     }
    642     return (Status);
    643   }
    644   if (*Resp == ShellPromptResponseContinue) {
    645     FreePool(Resp);
    646     ShellInfoObject.ConsoleInfo->RowCounter                   = 0;
    647 //    ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorRow    = 0;
    648 //    ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
    649 
    650     return (EFI_SUCCESS);
    651   } else if (*Resp == ShellPromptResponseQuit) {
    652     FreePool(Resp);
    653     ShellInfoObject.ConsoleInfo->Enabled = FALSE;
    654     //
    655     // When user wants to quit, the shell should stop running the command.
    656     //
    657     gBS->SignalEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak);
    658     return (EFI_DEVICE_ERROR);
    659   } else {
    660     ASSERT(FALSE);
    661   }
    662   return (EFI_SUCCESS);
    663 }
    664 /**
    665   Worker function to handle printing the output with page breaks.
    666 
    667   @param[in] String               The string to output
    668   @param[in] ConsoleInfo          The pointer to the instance of the console logger information.
    669 
    670   @retval EFI_SUCCESS             The string was printed
    671   @retval EFI_DEVICE_ERROR        The device reported an error while attempting to output
    672                                   the text.
    673   @retval EFI_UNSUPPORTED         The output device's mode is not currently in a
    674                                   defined text mode.
    675   @retval EFI_WARN_UNKNOWN_GLYPH  This warning code indicates that some of the
    676                                   characters in the Unicode string could not be
    677                                   rendered and were skipped.
    678 **/
    679 EFI_STATUS
    680 EFIAPI
    681 ConsoleLoggerPrintWithPageBreak(
    682   IN CONST CHAR16   *String,
    683   IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
    684   )
    685 {
    686   CONST CHAR16  *Walker;
    687   CONST CHAR16  *LineStart;
    688   CHAR16        *StringCopy;
    689   CHAR16        TempChar;
    690 
    691   StringCopy = NULL;
    692   StringCopy = StrnCatGrow(&StringCopy, NULL, String, 0);
    693   if (StringCopy == NULL) {
    694     return (EFI_OUT_OF_RESOURCES);
    695   }
    696 
    697   for ( Walker = StringCopy
    698       , LineStart = StringCopy
    699       ; Walker != NULL && *Walker != CHAR_NULL
    700       ; Walker++
    701      ){
    702     switch (*Walker) {
    703     case (CHAR_BACKSPACE):
    704       if (ConsoleInfo->OurConOut.Mode->CursorColumn > 0) {
    705         ConsoleInfo->OurConOut.Mode->CursorColumn--;
    706       }
    707       break;
    708     case (CHAR_LINEFEED):
    709       //
    710       // add a temp NULL terminator
    711       //
    712       TempChar = *(Walker + 1);
    713       *((CHAR16*)(Walker+1)) = CHAR_NULL;
    714 
    715       //
    716       // output the string
    717       //
    718       ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);
    719 
    720       //
    721       // restore the temp NULL terminator to it's original character
    722       //
    723       *((CHAR16*)(Walker+1)) = TempChar;
    724 
    725       //
    726       // Update LineStart Variable
    727       //
    728       LineStart = Walker + 1;
    729 
    730       //
    731       // increment row count
    732       //
    733       ShellInfoObject.ConsoleInfo->RowCounter++;
    734       ConsoleInfo->OurConOut.Mode->CursorRow++;
    735 
    736       break;
    737     case (CHAR_CARRIAGE_RETURN):
    738       //
    739       // Move the cursor to the beginning of the current row.
    740       //
    741       ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
    742       break;
    743     default:
    744       //
    745       // increment column count
    746       //
    747       ConsoleInfo->OurConOut.Mode->CursorColumn++;
    748       //
    749       // check if that is the last column
    750       //
    751       if ((INTN)ConsoleInfo->ColsPerScreen == ConsoleInfo->OurConOut.Mode->CursorColumn + 1) {
    752         //
    753         // output a line similar to the linefeed character.
    754         //
    755 
    756         //
    757         // add a temp NULL terminator
    758         //
    759         TempChar = *(Walker + 1);
    760         *((CHAR16*)(Walker+1)) = CHAR_NULL;
    761 
    762         //
    763         // output the string
    764         //
    765         ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);
    766 
    767         //
    768         // restore the temp NULL terminator to it's original character
    769         //
    770         *((CHAR16*)(Walker+1)) = TempChar;
    771 
    772         //
    773         // Update LineStart Variable
    774         //
    775         LineStart = Walker + 1;
    776 
    777         //
    778         // increment row count and zero the column
    779         //
    780         ShellInfoObject.ConsoleInfo->RowCounter++;
    781         ConsoleInfo->OurConOut.Mode->CursorRow++;
    782         ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
    783       } // last column on line
    784       break;
    785     } // switch for character
    786 
    787     //
    788     // check if that was the last printable row.  If yes handle PageBreak mode
    789     //
    790     if ((ConsoleInfo->RowsPerScreen) -1 == ShellInfoObject.ConsoleInfo->RowCounter) {
    791       if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
    792         //
    793         // We got an error which means 'break' and halt the printing
    794         //
    795         SHELL_FREE_NON_NULL(StringCopy);
    796         return (EFI_DEVICE_ERROR);
    797       }
    798     }
    799   } // for loop
    800 
    801   if (LineStart != NULL && *LineStart != CHAR_NULL) {
    802     ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);
    803   }
    804 
    805   SHELL_FREE_NON_NULL(StringCopy);
    806   return (EFI_SUCCESS);
    807 }
    808 
    809 /**
    810   Write a Unicode string to the output device.
    811 
    812   @param[in] This                 Protocol instance pointer.
    813   @param[in] WString              The NULL-terminated Unicode string to be displayed on the output
    814                                   device(s). All output devices must also support the Unicode
    815                                   drawing defined in this file.
    816   @retval EFI_SUCCESS             The string was output to the device.
    817   @retval EFI_DEVICE_ERROR        The device reported an error while attempting to output
    818                                   the text.
    819   @retval EFI_UNSUPPORTED         The output device's mode is not currently in a
    820                                   defined text mode.
    821   @retval EFI_WARN_UNKNOWN_GLYPH  This warning code indicates that some of the
    822                                   characters in the Unicode string could not be
    823                                   rendered and were skipped.
    824 **/
    825 EFI_STATUS
    826 EFIAPI
    827 ConsoleLoggerOutputString (
    828   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
    829   IN  CHAR16                          *WString
    830   )
    831 {
    832   EFI_STATUS                        Status;
    833   EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;
    834   EFI_KEY_DATA                      KeyData;
    835   UINTN                             EventIndex;
    836   CONSOLE_LOGGER_PRIVATE_DATA       *ConsoleInfo;
    837 
    838   ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
    839   if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
    840     return (EFI_UNSUPPORTED);
    841   }
    842   ASSERT(ShellInfoObject.ConsoleInfo == ConsoleInfo);
    843 
    844   Status = gBS->HandleProtocol (gST->ConsoleInHandle, &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);
    845   if (!EFI_ERROR (Status)) {
    846     while (ShellInfoObject.HaltOutput) {
    847 
    848       ShellInfoObject.HaltOutput = FALSE;
    849       //
    850       // just get some key
    851       //
    852       Status = gBS->WaitForEvent (1, &TxtInEx->WaitForKeyEx, &EventIndex);
    853       ASSERT_EFI_ERROR (Status);
    854       Status = TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData);
    855       if (EFI_ERROR(Status)) {
    856         break;
    857       }
    858 
    859       if ((KeyData.Key.UnicodeChar == L's') && (KeyData.Key.ScanCode == SCAN_NULL) &&
    860           ((KeyData.KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED)) ||
    861            (KeyData.KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID | EFI_RIGHT_CONTROL_PRESSED))
    862           )
    863          ) {
    864         ShellInfoObject.HaltOutput = TRUE;
    865       }
    866     }
    867   }
    868 
    869   if (!ShellInfoObject.ConsoleInfo->Enabled) {
    870     return (EFI_DEVICE_ERROR);
    871   } else if (ShellInfoObject.PageBreakEnabled) {
    872     return (ConsoleLoggerPrintWithPageBreak(WString, ConsoleInfo));
    873   } else {
    874     return (ConsoleLoggerOutputStringSplit(WString, ConsoleInfo));
    875   }
    876 }
    877 
    878 /**
    879   Verifies that all characters in a Unicode string can be output to the
    880   target device.
    881 
    882   @param[in] This     Protocol instance pointer.
    883   @param[in] WString  The NULL-terminated Unicode string to be examined for the output
    884                       device(s).
    885 
    886   @retval EFI_SUCCESS           The device(s) are capable of rendering the output string.
    887   @retval EFI_UNSUPPORTED       Some of the characters in the Unicode string cannot be
    888                                 rendered by one or more of the output devices mapped
    889                                 by the EFI handle.
    890 
    891 **/
    892 EFI_STATUS
    893 EFIAPI
    894 ConsoleLoggerTestString (
    895   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
    896   IN  CHAR16                        *WString
    897   )
    898 {
    899   CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
    900   ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
    901   //
    902   // Forward the request to the original ConOut
    903   //
    904   return (ConsoleInfo->OldConOut->TestString (ConsoleInfo->OldConOut, WString));
    905 }
    906 
    907 /**
    908   Returns information for an available text mode that the output device(s)
    909   supports.
    910 
    911   @param[in] This               Protocol instance pointer.
    912   @param[in] ModeNumber         The mode number to return information on.
    913   @param[out] Columns           Upon return, the number of columns in the selected geometry
    914   @param[out] Rows              Upon return, the number of rows in the selected geometry
    915 
    916   @retval EFI_SUCCESS           The requested mode information was returned.
    917   @retval EFI_DEVICE_ERROR      The device had an error and could not
    918                                 complete the request.
    919   @retval EFI_UNSUPPORTED       The mode number was not valid.
    920 **/
    921 EFI_STATUS
    922 EFIAPI
    923 ConsoleLoggerQueryMode (
    924   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
    925   IN  UINTN                         ModeNumber,
    926   OUT UINTN                         *Columns,
    927   OUT UINTN                         *Rows
    928   )
    929 {
    930   CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
    931   ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
    932   //
    933   // Forward the request to the original ConOut
    934   //
    935   return (ConsoleInfo->OldConOut->QueryMode (
    936     ConsoleInfo->OldConOut,
    937     ModeNumber,
    938     Columns,
    939     Rows
    940    ));
    941 }
    942 
    943 /**
    944   Sets the output device(s) to a specified mode.
    945 
    946   @param[in] This               Protocol instance pointer.
    947   @param[in] ModeNumber         The mode number to set.
    948 
    949 
    950   @retval EFI_SUCCESS           The requested text mode was set.
    951   @retval EFI_DEVICE_ERROR      The device had an error and
    952                                 could not complete the request.
    953   @retval EFI_UNSUPPORTED       The mode number was not valid.
    954 **/
    955 EFI_STATUS
    956 EFIAPI
    957 ConsoleLoggerSetMode (
    958   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *This,
    959   IN  UINTN                             ModeNumber
    960   )
    961 {
    962   EFI_STATUS                  Status;
    963 
    964   CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
    965   ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
    966 
    967   //
    968   // Forward the request to the original ConOut
    969   //
    970   Status = ConsoleInfo->OldConOut->SetMode (ConsoleInfo->OldConOut, ModeNumber);
    971 
    972   //
    973   // Check that the buffers are still correct for logging
    974   //
    975   if (!EFI_ERROR (Status)) {
    976     ConsoleInfo->OurConOut.Mode = ConsoleInfo->OldConOut->Mode;
    977     ConsoleLoggerResetBuffers(ConsoleInfo);
    978     ConsoleInfo->OriginalStartRow = 0;
    979     ConsoleInfo->CurrentStartRow = 0;
    980     ConsoleInfo->OurConOut.ClearScreen (&ConsoleInfo->OurConOut);
    981   }
    982 
    983   return Status;
    984 }
    985 
    986 /**
    987   Sets the background and foreground colors for the OutputString () and
    988   ClearScreen () functions.
    989 
    990   @param[in] This               Protocol instance pointer.
    991   @param[in] Attribute          The attribute to set. Bits 0..3 are the foreground color, and
    992                                 bits 4..6 are the background color. All other bits are undefined
    993                                 and must be zero. The valid Attributes are defined in this file.
    994 
    995   @retval EFI_SUCCESS           The attribute was set.
    996   @retval EFI_DEVICE_ERROR      The device had an error and
    997                                 could not complete the request.
    998   @retval EFI_UNSUPPORTED       The attribute requested is not defined.
    999 
   1000 **/
   1001 EFI_STATUS
   1002 EFIAPI
   1003 ConsoleLoggerSetAttribute (
   1004   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
   1005   IN  UINTN                           Attribute
   1006   )
   1007 {
   1008   EFI_STATUS                  Status;
   1009 
   1010   CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
   1011   ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
   1012 
   1013   //
   1014   // Forward the request to the original ConOut
   1015   //
   1016   Status = ConsoleInfo->OldConOut->SetAttribute (ConsoleInfo->OldConOut, Attribute);
   1017 
   1018   //
   1019   // Record console output history
   1020   //
   1021   if (!EFI_ERROR (Status)) {
   1022     ConsoleInfo->HistoryMode.Attribute = (INT32) Attribute;
   1023   }
   1024 
   1025   return Status;
   1026 }
   1027 
   1028 /**
   1029   Clears the output device(s) display to the currently selected background
   1030   color.
   1031 
   1032   @param[in] This               Protocol instance pointer.
   1033 
   1034   @retval EFI_SUCCESS           The operation completed successfully.
   1035   @retval EFI_DEVICE_ERROR      The device had an error and
   1036                                 could not complete the request.
   1037   @retval EFI_UNSUPPORTED       The output device is not in a valid text mode.
   1038 **/
   1039 EFI_STATUS
   1040 EFIAPI
   1041 ConsoleLoggerClearScreen (
   1042   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This
   1043   )
   1044 {
   1045   EFI_STATUS        Status;
   1046   CHAR16            *Screen;
   1047   INT32             *Attributes;
   1048   UINTN             Row;
   1049   UINTN             Column;
   1050   CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
   1051 
   1052   if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
   1053     return (EFI_UNSUPPORTED);
   1054   }
   1055 
   1056   ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
   1057 
   1058   //
   1059   // Forward the request to the original ConOut
   1060   //
   1061   Status = ConsoleInfo->OldConOut->ClearScreen (ConsoleInfo->OldConOut);
   1062 
   1063   //
   1064   // Record console output history
   1065   //
   1066   if (!EFI_ERROR (Status)) {
   1067     Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow];
   1068     Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow];
   1069     for ( Row = ConsoleInfo->OriginalStartRow
   1070         ; Row < (ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)
   1071         ; Row++
   1072        ){
   1073       for ( Column = 0
   1074           ; Column < ConsoleInfo->ColsPerScreen
   1075           ; Column++
   1076           , Screen++
   1077           , Attributes++
   1078          ){
   1079         *Screen = L' ';
   1080         *Attributes = ConsoleInfo->OldConOut->Mode->Attribute;
   1081       }
   1082       //
   1083       // Skip the NULL on each column end in text buffer only
   1084       //
   1085       Screen += 2;
   1086     }
   1087     ConsoleInfo->HistoryMode.CursorColumn = 0;
   1088     ConsoleInfo->HistoryMode.CursorRow    = 0;
   1089   }
   1090 
   1091   return Status;
   1092 }
   1093 
   1094 /**
   1095   Sets the current coordinates of the cursor position
   1096 
   1097   @param[in] This               Protocol instance pointer.
   1098   @param[in] Column             Column to put the cursor in.  Must be between zero and Column returned from QueryMode
   1099   @param[in] Row                Row to put the cursor in.  Must be between zero and Row returned from QueryMode
   1100 
   1101   @retval EFI_SUCCESS           The operation completed successfully.
   1102   @retval EFI_DEVICE_ERROR      The device had an error and
   1103                                 could not complete the request.
   1104   @retval EFI_UNSUPPORTED       The output device is not in a valid text mode, or the
   1105                                 cursor position is invalid for the current mode.
   1106 **/
   1107 EFI_STATUS
   1108 EFIAPI
   1109 ConsoleLoggerSetCursorPosition (
   1110   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
   1111   IN  UINTN                         Column,
   1112   IN  UINTN                         Row
   1113   )
   1114 {
   1115   EFI_STATUS                  Status;
   1116   CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
   1117 
   1118   if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
   1119     return (EFI_UNSUPPORTED);
   1120   }
   1121 
   1122   ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
   1123   //
   1124   // Forward the request to the original ConOut
   1125   //
   1126   Status = ConsoleInfo->OldConOut->SetCursorPosition (
   1127     ConsoleInfo->OldConOut,
   1128     Column,
   1129     Row
   1130    );
   1131 
   1132   //
   1133   // Record console output history
   1134   //
   1135   if (!EFI_ERROR (Status)) {
   1136     ConsoleInfo->HistoryMode.CursorColumn = (INT32)Column;
   1137     ConsoleInfo->HistoryMode.CursorRow    = (INT32)(ConsoleInfo->OriginalStartRow + Row);
   1138   }
   1139 
   1140   return Status;
   1141 }
   1142 
   1143 /**
   1144   Makes the cursor visible or invisible
   1145 
   1146   @param[in] This       Protocol instance pointer.
   1147   @param[in] Visible    If TRUE, the cursor is set to be visible. If FALSE, the cursor is
   1148                         set to be invisible.
   1149 
   1150   @retval EFI_SUCCESS           The operation completed successfully.
   1151   @retval EFI_DEVICE_ERROR      The device had an error and could not complete the
   1152                                 request, or the device does not support changing
   1153                                 the cursor mode.
   1154   @retval EFI_UNSUPPORTED       The output device is not in a valid text mode.
   1155 **/
   1156 EFI_STATUS
   1157 EFIAPI
   1158 ConsoleLoggerEnableCursor (
   1159   IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
   1160   IN  BOOLEAN                       Visible
   1161   )
   1162 {
   1163   EFI_STATUS                  Status;
   1164 
   1165   CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
   1166   ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
   1167   //
   1168   // Forward the request to the original ConOut
   1169   //
   1170   Status = ConsoleInfo->OldConOut->EnableCursor (ConsoleInfo->OldConOut, Visible);
   1171 
   1172   //
   1173   // Record console output history
   1174   //
   1175   if (!EFI_ERROR (Status)) {
   1176     ConsoleInfo->HistoryMode.CursorVisible = Visible;
   1177   }
   1178 
   1179   return Status;
   1180 }
   1181 
   1182 /**
   1183   Function to update and verify that the current buffers are correct.
   1184 
   1185   @param[in] ConsoleInfo  The pointer to the instance of the console logger information.
   1186 
   1187   This will be used when a mode has changed or a reset ocurred to verify all
   1188   history buffers.
   1189 **/
   1190 EFI_STATUS
   1191 EFIAPI
   1192 ConsoleLoggerResetBuffers(
   1193   IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
   1194   )
   1195 {
   1196   EFI_STATUS Status;
   1197 
   1198   if (ConsoleInfo->Buffer != NULL) {
   1199     FreePool(ConsoleInfo->Buffer);
   1200     ConsoleInfo->Buffer     = NULL;
   1201     ConsoleInfo->BufferSize = 0;
   1202   }
   1203   if (ConsoleInfo->Attributes != NULL) {
   1204     FreePool(ConsoleInfo->Attributes);
   1205     ConsoleInfo->Attributes = NULL;
   1206     ConsoleInfo->AttribSize = 0;
   1207   }
   1208 
   1209   Status = gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &ConsoleInfo->ColsPerScreen, &ConsoleInfo->RowsPerScreen);
   1210   if (EFI_ERROR(Status)){
   1211     return (Status);
   1212   }
   1213 
   1214   ConsoleInfo->BufferSize = (ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof(ConsoleInfo->Buffer[0]);
   1215   ConsoleInfo->AttribSize = ConsoleInfo->ColsPerScreen * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof(ConsoleInfo->Attributes[0]);
   1216 
   1217   ConsoleInfo->Buffer = (CHAR16*)AllocateZeroPool(ConsoleInfo->BufferSize);
   1218 
   1219   if (ConsoleInfo->Buffer == NULL) {
   1220     return (EFI_OUT_OF_RESOURCES);
   1221   }
   1222 
   1223   ConsoleInfo->Attributes = (INT32*)AllocateZeroPool(ConsoleInfo->AttribSize);
   1224   if (ConsoleInfo->Attributes == NULL) {
   1225     FreePool(ConsoleInfo->Buffer);
   1226     ConsoleInfo->Buffer     = NULL;
   1227     return (EFI_OUT_OF_RESOURCES);
   1228   }
   1229 
   1230   CopyMem (&ConsoleInfo->HistoryMode, ConsoleInfo->OldConOut->Mode, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE));
   1231 
   1232   return (EFI_SUCCESS);
   1233 }
   1234