/*++ Copyright (c) 1990 Microsoft Corporation Module Name: display.c Author: Thomas Parslow [TomP] Feb-13-1991 Reworked substantially in Tokyo 7-July-95 (tedm) Port from ARC-BIOS to EFI 22-Nov-2000 (andrewr) Abstract: This file contains an interface to the screen that is independent of the screen type actually being written to. The module serves as a layer between OS loader applications and the EFI services that do the actual legwork of writing to the default console handlers. --*/ #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 EFI_GUID EfiDevicePathProtocol; extern EFI_GUID EfiBlockIoProtocol; extern BOOLEAN GoneVirtual; #define ZLEN_SHORT(x) ((x < 0x10) + (x < 0x100) + (x < 0x1000)) #define ZLEN_LONG(x) ((x < 0x10) + (x < 0x100) + (x < 0x1000) + \ (x < 0x10000) + (x < 0x100000)+(x < 0x1000000)+(x < 0x10000000)) // // Current screen position. // USHORT TextColumn = 0; USHORT TextRow = 0; // // Current text attribute // UCHAR TextCurrentAttribute = 0x07; // start with white on black. // // Internal routines // VOID puti( LONG ); VOID putx( ULONG ); VOID putu( ULONG ); VOID putwS( PUNICODE_STRING String ); VOID putS( PCWSTR String ); VOID puts( PCSTR String ); VOID BlPrint( PTCHAR cp, ... ) /*++ Routine Description: Standard printf function with a subset of formating features supported. Currently handles %d, %ld - signed short, signed long %u, %lu - unsigned short, unsigned long %c, %s - character, string %x, %lx - unsigned print in hex, unsigned long print in hex %C, %S - ansi character, string %wS - counted UNICODE_STRING Does not do: - field width specification - floating point. Arguments: cp - pointer to the format string, text string. Returns: Nothing --*/ { ULONG l; ULONG Count; TCHAR ch; ULONG DeviceId; TCHAR b,c; PTSTR FormatString; va_list args; FormatString = cp; DeviceId = BlConsoleOutDeviceId; va_start(args, cp); // // Process the arguments using the descriptor string // while(*FormatString != TEXT('\0')) { b = *FormatString; FormatString += 1; if(b == TEXT('%')) { c = *FormatString; FormatString += 1; switch (c) { case TEXT('d'): puti((LONG)va_arg(args, LONG)); break; case TEXT('s'): putS((PCWSTR)va_arg(args, PWSTR)); break; case TEXT('S'): puts((PCSTR)va_arg(args, PSTR)); break; case TEXT('c'): ch = (WCHAR)va_arg( args, WCHAR ); ArcWrite(DeviceId, &ch, 1*sizeof(WCHAR), &Count); break; case TEXT('C'): ch = (CHAR)va_arg( args, CHAR ); ArcWrite(DeviceId, &ch, 1*sizeof(CHAR), &Count); break; case TEXT('x'): //note that this doesn't currently support zero padding. putx((ULONG)va_arg( args, ULONG)); break; case TEXT('u'): putu( (ULONG)va_arg( args, ULONG )); break; case TEXT('w'): c = *FormatString; FormatString += 1; switch (c) { case TEXT('S'): case TEXT('Z'): putwS((PUNICODE_STRING)va_arg( args, PUNICODE_STRING)); break; } break; case TEXT('l'): c = *FormatString; FormatString += 1; switch(c) { case TEXT('0'): break; case TEXT('u'): putu(va_arg( args, ULONG)); break; case TEXT('x'): //note that this doesn't currently support zero padding putx(va_arg( args, ULONG)); break; case TEXT('d'): puti(va_arg( args, ULONG)); break; } break; default : ch = (TCHAR)b; ArcWrite(DeviceId, &ch, 1*sizeof(TCHAR), &Count); ch = (TCHAR)c; ArcWrite(DeviceId, &ch, 1*sizeof(TCHAR), &Count); } } else { ArcWrite(DeviceId, FormatString - 1, 1*sizeof(TCHAR), &Count); } } va_end(args); #if 0 // // This code pauses the system after each BlPrint. You must enter // a character to continue. This is used for debugging // ArcRead(BlConsoleInDeviceId, &l, 1, &Count); #endif } VOID putwS( PUNICODE_STRING String ) /*++ Routine Description: Writes counted unicode string to the display at the current cursor position. Arguments: String - pointer to unicode string to display Returns: Nothing --*/ { ULONG i; ULONG Count; for(i=0; i < String->Length; i++) { ArcWrite(BlConsoleOutDeviceId, &String->Buffer[i], 1*sizeof(WCHAR), &Count); } } VOID puts( PCSTR AnsiString ) /*++ Routine Description: Writes an ANSI string to the display at the current cursor position. Arguments: String - pointer to ANSI string to display Returns: Nothing --*/ { ULONG i; ULONG Count; WCHAR Char; PCSTR p; p = AnsiString; while (*p != '\0') { Char = (WCHAR)*p; ArcWrite(BlConsoleOutDeviceId, &Char, sizeof(WCHAR), &Count); p += 1; } } VOID putS( PCWSTR UnicodeString ) /*++ Routine Description: Writes an ANSI string to the display at the current cursor position. Arguments: String - pointer to ANSI string to display Returns: Nothing --*/ { ULONG i; ULONG Count; WCHAR Char; PCWSTR p; p = UnicodeString; while (*p != L'\0') { Char = *p; ArcWrite(BlConsoleOutDeviceId, &Char, sizeof(WCHAR), &Count); p += 1; } } VOID putx( ULONG x ) /*++ Routine Description: Writes hex long to the display at the current cursor position. Arguments: x - ulong to write Returns: Nothing --*/ { ULONG j; ULONG Count; _TUCHAR ch; if(x/16) { putx(x/16); } if((j=x%16) > 9) { ch = (_TUCHAR)(j+TEXT('A')-10); ArcWrite(BlConsoleOutDeviceId, &ch, 1*sizeof(_TUCHAR), &Count); } else { ch = (_TUCHAR)(j+TEXT('0')); ArcWrite(BlConsoleOutDeviceId, &ch, 1*sizeof(_TUCHAR), &Count); } } VOID puti( LONG i ) /*++ Routine Description: Writes a long integer on the display at the current cursor position. Arguments: i - the integer to write to the display. Returns: Nothing --*/ { ULONG Count; _TUCHAR ch; if(i<0) { i = -i; ch = TEXT('-'); ArcWrite(BlConsoleOutDeviceId, &ch, 1*sizeof(_TUCHAR), &Count); } if(i/10) { puti(i/10); } ch = (_TUCHAR)((i%10)+TEXT('0')); ArcWrite(BlConsoleOutDeviceId, &ch, 1*sizeof(_TUCHAR), &Count); } VOID putu( ULONG u ) /*++ Routine Description: Write an unsigned long to display Arguments: u - unsigned Returns: Nothing --*/ { ULONG Count; _TUCHAR ch; if(u/10) { putu(u/10); } ch = (_TUCHAR)((u%10)+TEXT('0')); ArcWrite(BlConsoleOutDeviceId, &ch, 1*sizeof(_TUCHAR), &Count); } #if 0 VOID pTextCharOut( IN UCHAR c ) { if(DbcsLangId) { // // Single-byte only // TextGrCharOut(&c); } else { TextTmCharOut(&c); } } #endif VOID TextCharOut( IN PWCHAR pc ) { WCHAR Text[2]; Text[0] = *pc; Text[1] = L'\0'; if (GoneVirtual) { FlipToPhysical(); } EfiST->ConOut->OutputString(EfiST->ConOut,Text); if (GoneVirtual) { FlipToVirtual(); } #if 0 if(DbcsLangId) { return(TextGrCharOut(pc)); } else { return(TextTmCharOut(pc)); } #endif } VOID TextStringOut( IN PWCHAR String ) { PWCHAR p = String; while (*p) { TextCharOut(p); p += 1; } #if 0 if(DbcsLangId) { TextGrStringOut(String); } else { TextTmStringOut(String); } #endif } VOID TextSetCurrentAttribute( IN UCHAR Attribute ) /*++ Routine Description: Sets the character attribute to be used for subsequent text display. Arguments: Returns: Nothing. --*/ { TextCurrentAttribute = Attribute; #ifdef EFI BlEfiSetAttribute( Attribute ); #else if(DbcsLangId) { TextGrSetCurrentAttribute(Attribute); } else { TextTmSetCurrentAttribute(Attribute); } #endif } UCHAR TextGetCurrentAttribute( VOID ) { return(TextCurrentAttribute); } VOID TextFillAttribute( IN UCHAR Attribute, IN ULONG Length ) /*++ Routine Description: Changes the screen attribute starting at the current cursor position. The cursor is not moved. Arguments: Attribute - Supplies the new attribute Length - Supplies the length of the area to change (in bytes) Return Value: None. --*/ { #ifdef EFI ULONG x,y, OrigX, OrigY; BOOLEAN FirstTime = TRUE; BlEfiGetCursorPosition( &OrigX, &OrigY ); x = OrigX; y = OrigY; for (y = OrigY; y < BlEfiGetLinesPerRow() ; y++) { x = FirstTime ? OrigX : 0 ; FirstTime = FALSE; for (; x <= BlEfiGetColumnsPerLine(); x++) { BlEfiPositionCursor( y, x ); BlEfiSetAttribute( Attribute ); } } BlEfiPositionCursor( OrigY, OrigX ); #else if(DbcsLangId) { TextGrFillAttribute(Attribute,Length); } else { TextTmFillAttribute(Attribute,Length); } #endif } _TUCHAR TextGetGraphicsCharacter( IN GraphicsChar WhichOne ) { #ifdef EFI return(BlEfiGetGraphicsChar( WhichOne )); #else return((WhichOne < GraphicsCharMax) ? (DbcsLangId ? TextGrGetGraphicsChar(WhichOne) : TextTmGetGraphicsChar(WhichOne)) : TEXT(' ')); #endif }