/*++ Copyright (c) 2000 Microsoft Corporation Module Name: efidisp.c Author: Create It. 21-Nov-2000 (andrewr) Abstract: This file contains utility routines for manipulating the EFI SIMPLE_CONSOLE_OUTPUT interface --*/ #include "bldr.h" #include "bootefi.h" #include "efi.h" #include "efip.h" #include "flop.h" // // Externals // extern EFI_HANDLE EfiImageHandle; extern EFI_SYSTEM_TABLE *EfiST; extern EFI_BOOT_SERVICES *EfiBS; extern EFI_RUNTIME_SERVICES *EfiRS; extern BOOLEAN GoneVirtual; BOOLEAN gInverse = FALSE; ULONG BlEfiGetLinesPerRow( VOID ) /*++ Routine Description: Gets the number of lines per EFI console row. Arguments: None. Return Value: ULONG - number of lines. --*/ { // // TODO: read the modes to determine lines/row. // // for now we just support 80x25 // return 25; } ULONG BlEfiGetColumnsPerLine( VOID ) /*++ Routine Description: Gets the number of columns per EFI console line. Arguments: None. Return Value: ULONG - number of columns. --*/ { // // TODO: read the modes to determine columns/line. // // for now we just support 80x25 // return 80; } BOOLEAN BlEfiClearDisplay( VOID ) /*++ Routine Description: Clears the display. Arguments: None. Return Value: BOOLEAN - TRUE if the call succeeded. --*/ { EFI_STATUS Status; // // you must be in physical mode to call EFI // FlipToPhysical(); Status = EfiST->ConOut->ClearScreen(EfiST->ConOut); FlipToVirtual(); return (Status == EFI_SUCCESS); } BOOLEAN BlEfiClearToEndOfDisplay( VOID ) /*++ Routine Description: Clears from the current cursor position to the end of the display. Arguments: None. Return Value: BOOLEAN - TRUE if the call succeeded. --*/ { ULONG i,j, LinesPerRow,ColumnsPerLine; BOOLEAN FirstTime = TRUE; // // you must be in physical mode to call EFI // FlipToPhysical(); LinesPerRow = BlEfiGetLinesPerRow(); ColumnsPerLine = BlEfiGetColumnsPerLine(); for (i = EfiST->ConOut->Mode->CursorRow; i<= LinesPerRow; i++) { j = FirstTime ? EfiST->ConOut->Mode->CursorColumn : 0 ; FirstTime = FALSE; for (; j <= ColumnsPerLine; j++) { EfiST->ConOut->SetCursorPosition( EfiST->ConOut, i, j); // // outputting a space should clear the current character // EfiST->ConOut->OutputString( EfiST->ConOut, L" " ); } } // // flip back into virtual mode and return // FlipToVirtual(); return(TRUE); } BOOLEAN BlEfiClearToEndOfLine( VOID ) /*++ Routine Description: Clears from the current cursor position to the end of the line. Arguments: None. Return Value: BOOLEAN - TRUE if the call succeeded. --*/ { ULONG i, ColumnsPerLine; ULONG x, y; ColumnsPerLine = BlEfiGetColumnsPerLine(); // // save current cursor position // BlEfiGetCursorPosition( &x, &y ); FlipToPhysical(); for (i = EfiST->ConOut->Mode->CursorColumn; i <= ColumnsPerLine; i++) { EfiST->ConOut->SetCursorPosition( EfiST->ConOut, i, EfiST->ConOut->Mode->CursorRow); // // outputting a space should clear the current character // EfiST->ConOut->OutputString( EfiST->ConOut, L" " ); } // // restore the current cursor position // EfiST->ConOut->SetCursorPosition( EfiST->ConOut, x, y ); FlipToVirtual(); return(TRUE); } BOOLEAN BlEfiGetCursorPosition( OUT PULONG x, OPTIONAL OUT PULONG y OPTIONAL ) /*++ Routine Description: retrieves the current cursor position Arguments: x - if specified, receives the current cursor column. y - if specified, receives the current cursor row. Return Value: BOOLEAN - TRUE if the call succeeded. --*/ { FlipToPhysical(); if (x) { *x = EfiST->ConOut->Mode->CursorColumn; } if (y) { *y = EfiST->ConOut->Mode->CursorRow; } FlipToVirtual(); return(TRUE); } BOOLEAN BlEfiPositionCursor( IN ULONG Column, IN ULONG Row ) /*++ Routine Description: Sets the current cursor position. Arguments: Column - column to set (x coordinate) Row - row to set (y coordinate) Return Value: BOOLEAN - TRUE if the call succeeded. --*/ { EFI_STATUS Status; FlipToPhysical(); Status = EfiST->ConOut->SetCursorPosition(EfiST->ConOut,Column,Row); FlipToVirtual(); return (Status == EFI_SUCCESS); } BOOLEAN BlEfiEnableCursor( BOOLEAN bVisible ) /*++ Routine Description: Turns on or off the input cursor. Arguments: bVisible - TRUE indicates that the cursor should be made visible. Return Value: BOOLEAN - TRUE if the call succeeded. --*/ { EFI_STATUS Status; FlipToPhysical(); Status = EfiST->ConOut->EnableCursor( EfiST->ConOut, bVisible ); FlipToVirtual(); return (Status == EFI_SUCCESS); } BOOLEAN BlEfiSetAttribute( ULONG Attribute ) /*++ Routine Description: Sets the current attribute for the console. This routines switches between the ATT_* constants into the EFI_* display constants. Not all of the ATT_ flags can be supported under EFI, so we make a best guess. Arguments: None. Return Value: BOOLEAN - TRUE if the call succeeded. --*/ { EFI_STATUS Status; UINTN foreground,background; UINTN EfiAttribute; switch (Attribute & 0xf) { case ATT_FG_BLACK: foreground = EFI_BLACK; break; case ATT_FG_RED: foreground = EFI_RED; break; case ATT_FG_GREEN: foreground = EFI_GREEN; break; case ATT_FG_YELLOW: foreground = EFI_YELLOW; break; case ATT_FG_BLUE: foreground = EFI_BLUE; break; case ATT_FG_MAGENTA: foreground = EFI_MAGENTA; break; case ATT_FG_CYAN: foreground = EFI_CYAN; break; case ATT_FG_WHITE: foreground = EFI_LIGHTGRAY; // this is a best guess break; case ATT_FG_INTENSE: foreground = EFI_WHITE; // this is a best guess break; default: // you may fall into this for blinking attribute, etc. foreground = EFI_WHITE; } switch ( Attribute & ( 0xf << 4)) { case ATT_BG_BLACK: background = EFI_BACKGROUND_BLACK; break; case ATT_BG_RED: background = EFI_BACKGROUND_RED; break; case ATT_BG_GREEN: background = EFI_BACKGROUND_GREEN; break; case ATT_BG_YELLOW: // there is no yellow background in EFI background = EFI_BACKGROUND_CYAN; break; case ATT_BG_BLUE: background = EFI_BACKGROUND_BLUE; break; case ATT_BG_MAGENTA: background = EFI_BACKGROUND_MAGENTA; break; case ATT_BG_CYAN: background = EFI_BACKGROUND_CYAN; break; case ATT_BG_WHITE: // there is no white background in EFI background = EFI_BACKGROUND_LIGHTGRAY; break; case ATT_BG_INTENSE: // there is no intense (or white) background in EFI background = EFI_BACKGROUND_LIGHTGRAY; break; default: background = EFI_BACKGROUND_LIGHTGRAY; break; } EfiAttribute = foreground | background ; FlipToPhysical(); Status = EfiST->ConOut->SetAttribute(EfiST->ConOut,EfiAttribute); FlipToVirtual(); return (Status == EFI_SUCCESS); } BOOLEAN BlEfiSetInverseMode( BOOLEAN fInverseOn ) /*++ Routine Description: Sets the console text to an inverse attribute. Since EFI doesn't support the concept of inverse, we have to make a best guess at this. Note that if you clear the display, etc., then the entire display will be set to this attribute. Arguments: None. Return Value: BOOLEAN - TRUE if the call succeeded. --*/ { EFI_STATUS Status; UINTN EfiAttribute,foreground,background; // // if it's already on, then just return. // if (fInverseOn && gInverse) { return(TRUE); } // // if it's already off, then just return. // if (!fInverseOn && !gInverse) { return(TRUE); } FlipToPhysical(); // // get the current attribute and switch it. // EfiAttribute = EfiST->ConOut->Mode->Attribute; foreground = EfiAttribute & 0xf; background = (EfiAttribute & 0xf0) >> 4 ; EfiAttribute = background | foreground; Status = EfiST->ConOut->SetAttribute(EfiST->ConOut,EfiAttribute); FlipToVirtual(); gInverse = !gInverse; return (Status == EFI_SUCCESS); } // // Array of EFI drawing characters. // // This array MUST MATCH the GraphicsChar enumerated type in bldr.h. // USHORT EfiDrawingArray[GraphicsCharMax] = { BOXDRAW_DOUBLE_DOWN_RIGHT, BOXDRAW_DOUBLE_DOWN_LEFT, BOXDRAW_DOUBLE_UP_RIGHT, BOXDRAW_DOUBLE_UP_LEFT, BOXDRAW_DOUBLE_VERTICAL, BOXDRAW_DOUBLE_HORIZONTAL, BLOCKELEMENT_FULL_BLOCK, BLOCKELEMENT_LIGHT_SHADE }; USHORT BlEfiGetGraphicsChar( IN GraphicsChar WhichOne ) /*++ Routine Description: Gets the appropriate mapping character. Arguments: GraphicsChar - enumerated type indicating character to be retrieved. Return Value: USHORT - EFI drawing character. --*/ { // // just return a space if the input it out of range // if (WhichOne >= GraphicsCharMax) { return(L' '); } return(EfiDrawingArray[WhichOne]); } #if DBG VOID DBG_EFI_PAUSE( VOID ) { EFI_EVENT EventArray[2]; EFI_INPUT_KEY Key; UINTN num; if (GoneVirtual) { FlipToPhysical(); } EventArray[0] = EfiST->ConIn->WaitForKey; EventArray[1] = NULL; EfiBS->WaitForEvent(1,EventArray,&num); // // reset the event // EfiST->ConIn->ReadKeyStroke( EfiST->ConIn, &Key ); if (GoneVirtual) { FlipToVirtual(); } } #else VOID DBG_EFI_PAUSE( VOID ) { NOTHING; } #endif